Bug 168278
Summary: | CAN-2005-2978 Crash running pnmtopng -trans on some pnm files | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Product: | Red Hat Enterprise Linux 4 | Reporter: | Bastien Nocera <bnocera> | ||||||||
Component: | netpbm | Assignee: | Jindrich Novy <jnovy> | ||||||||
Status: | CLOSED ERRATA | QA Contact: | Ben Levenson <benl> | ||||||||
Severity: | medium | Docs Contact: | |||||||||
Priority: | medium | ||||||||||
Version: | 4.0 | CC: | pknirsch, psplicha, security-response-team | ||||||||
Target Milestone: | --- | Keywords: | Security | ||||||||
Target Release: | --- | ||||||||||
Hardware: | x86_64 | ||||||||||
OS: | Linux | ||||||||||
Whiteboard: | impact=moderate,source=redhat,embargo=20051018,reported=20050914 | ||||||||||
Fixed In Version: | RHSA-2005-793 | Doc Type: | Bug Fix | ||||||||
Doc Text: | Story Points: | --- | |||||||||
Clone Of: | Environment: | ||||||||||
Last Closed: | 2005-10-18 15:41:58 UTC | Type: | --- | ||||||||
Regression: | --- | Mount Type: | --- | ||||||||
Documentation: | --- | CRM: | |||||||||
Verified Versions: | Category: | --- | |||||||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||||
Cloudforms Team: | --- | Target Upstream Version: | |||||||||
Embargoed: | |||||||||||
Attachments: |
|
Description
Bastien Nocera
2005-09-14 13:24:24 UTC
Created attachment 118793 [details]
well.pnm
Can be reproduced with netpbm-progs-10.29-1 from rawhide. Created attachment 118798 [details] sample.pnm.bz2 Another test file, bzipped2. btw. I see the crash elsewhere when compiled with -O0 -g3: gdb --args ./pnmtopng -trans '#ffffff' ~/well.pnm Program received signal SIGSEGV, Segmentation fault. 0x0000000000404952 in writeRaster (png_ptr=0x50a250, info_ptr=0x50c760, ifP=0x50a010, imagepos=12, cols=8, rows=32, maxval=255, format=20534, png_maxval=3, depth=2, alpha=0, alpha_mask=0x0, cht=0x2a95558010, caht=0x0) at pnmtopng.c:1693 1693 makePngLine(line, xelrow, cols, maxval, alpha, alpha_mask[row], (gdb) bt #0 0x0000000000404952 in writeRaster (png_ptr=0x50a250, info_ptr=0x50c760, ifP=0x50a010, imagepos=12, cols=8, rows=32, maxval=255, format=20534, png_maxval=3, depth=2, alpha=0, alpha_mask=0x0, cht=0x2a95558010, caht=0x0) at pnmtopng.c:1693 #1 0x0000000000405df0 in convertpnm (ifp=0x50a010, afp=0x0, pfp=0x0, tfp=0x0, gamma=-1, interlace=0, downscale=0, transparent_opt=1, transstring=0x7fbffffb17 "#ffffff", alpha_opt=0, alpha_file=0x0, background=-1, backstring=0x0, hist=0, chroma= {wx = -1, wy = -1, rx = -1, ry = -1, gx = -1, gy = -1, bx = -1, by = -1}, phys_x=-1, phys_y=-1, phys_unit=-1, text=0, ztxt=0, text_file=0x2a95583f88 "\uffff\017@", mtime=0, date_string=0x0, time_string=0x3436 <Address 0x3436 out of bounds>, filterSet=0, force=0, zlib_compression= {level = -1, mem_level = -1, strategy = -1, window_bits = -1, method = -1, buffer_size = -1}) at pnmtopng.c:2201 #2 0x0000000000407060 in main (argc=4, argv=0x7fbffff8b8) at pnmtopng.c:2520 and can reproduce the segfault on i386 as well. Jindrich, Can you paste the output of a "list" command in gdb at that crash? I'm not sure which version of netpbm you're running as the version shipped in RHEL4 doesn't seem to match up when I look at the line numbers gdb is reporting. Additionally, if this issue is caused by an OOB read and has no potential for exploitation, it will not be considered a security issue. We do not consider crashes of userland programs such as this security issues (the user is running it interactively so if it crashes a few times, they'll figure out it's just a broken image file). Josh, I discussed this with Bastien and it seems the error is present at least in RHEL4 and rawhide netpbm (10.29-1). The gdb dump above in comment #4 is done from pnmtopng present in netpbm-10.29-1, where something seems seriously broken, as the crash is caused by call of makePngLine(), but it segfaults even before the code within the makePngLine() is executed (likely somewhere in the calling convention stuff or similar). Consider this patch: --- pnmtopng.c.segfault 2005-08-06 19:26:55.000000000 +0200 +++ pnmtopng.c 2005-09-15 18:38:33.000000000 +0200 @@ -1605,6 +1605,9 @@ makePngLine(png_byte * const l unsigned int col; png_byte *pp; + + fprintf(stderr, "*** called\n"); + fflush(stderr); /* fflush() to be *sure* the above is displayed */ pp = line; /* start at beginning of line */ for (col = 0; col < cols; ++col) { @@ -1690,6 +1693,7 @@ writeRaster(png_struct * const p pnm_promoteformatrow(xelrow, cols, maxval, format, maxval, PPM_TYPE); + fprintf(stderr,"*** before call\n"); makePngLine(line, xelrow, cols, maxval, alpha, alpha_mask[row], cht, caht, info_ptr, png_maxval, depth); then: ./pnmtopng -trans '#ffffff' ~/well.pnm >/dev/null displays: pnmtopng: 3 colors found *** before call Segmentation fault /me is afraid it's needed to dig into assembly a bit I'll focus on the RHEL4 netpbm now. BTW. the images are completely sane. Got it... the pnmtopng in RHEL4 netpbm doesn't bother to initialize palette size when requesting encoding of a pixmap line to PNG... Furthermore it doesn't initialize bestIndex, so that in case paletteSize==0 (paletteSize is uninitialized) it returns uninitialized output to bestIndexP, what could be likely another source of segfault: unsigned int paletteIndex; unsigned int bestIndex; unsigned int bestMatch; bestMatch = UINT_MAX; for (paletteIndex = 0; paletteIndex < paletteSize; ++paletteIndex) { unsigned int const dist = PPM_DISTANCE(palette_pnm[paletteIndex], targetColor); if (dist < bestMatch) { bestMatch = dist; bestIndex = paletteIndex; } } if (bestIndexP != NULL) *bestIndexP = bestIndex; if (bestMatchP != NULL) *bestMatchP = bestMatch; Created attachment 118961 [details]
Patch to fix the segfault.
Josh, Mark,
maybe this is also dangerous from the security point of view. If you consider
that the palette array that is indexed by the uninitialized variable is not
allocated by malloc, but is a local array of convertpnm(), therefore it's
allocated on stack. If an attacker could make the uninitialized paletteSize=0
(what is likely the case of i386 - this is the reason why it doesn't segfault
there) and make bestIndex to be initialized by something he wants, he can swap
any pixel sized memory on the stack, because this code is executed right after
the closestColorInPalette() call that returns the uninitialized bestIndex in
transparentIndex variable:
/* Swap this with the first entry in the palette */
pixel tmp;
tmp = palette_pnm[transparentIndex];
palette_pnm[transparentIndex] = palette_pnm[0];
palette_pnm[0] = tmp;
One can make a lot by modifying the stack contents...
Yes, we're going to want to fix this as a security update. Does this affect everything we ship? There's a different implementation of pnmtopng in netpbm-9.24 RHEL3 and RHEL2.1 that doesn't seem to be broken (I tested this case on the both RHELs and everything is fine) so the only affected is RHEL4 from RHELs and all currently supported Fedora Cores. I applied patch to RHEL4 and errata is comming soon. Lifting embargo An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHSA-2005-793.html |