Marc Schoenefeld found an invalid pointer dereference flaw, present in Python's RGB image processing module. An attacker could provide a specially-crafted black-and-white (B/W) RGB image, which once processed by Python's RGB module would lead to denial of service (Python VM crash).
This issue affects the versions of python package, as shipped with Red Hat Enterprise Linux 3, 4, and 5.
I will refer to this SGI image format spec below: ftp://ftp.sgi.com/graphics/SGIIMAGESPEC The crash triggered by Marc's reproducer is a buffer underflow caused by an unexpectedly large ZSIZE (number of channels) value. The spec defines certain typical ZSIZE values (1 for B/W, 3 for RGB, 4 for RGB+Alpha), but it does not forbid greater values. ZSIZE is read as 16bit value from the image header, so values up to 0xffff can be specified. rgbimgmodule implementation assumes that ZSIZE <= 4, but does not check that. It uses 32bit value to store info for one pixel (so up to 4 channels, module only supports 1 byte per channel, BPC == 2 images are not supported) and uses pattern 3-z (for z in 0 .. ZSIZE-1) to adjust the pointer position within a 32bit value used to store one pixel to write particular channel data. Therefore, interleaverow() can be called with its third argument having a negative value, resulting in buffer underflow. In case of Marc's reproducer, input file was truncated after YSIZE and ZSIZE was not specified in the file at all. rgbimgmodule does not have EOF / file truncation checks, so ZSIZE value was rather unpredictable and possibly different for each run. In addition, there is also an integer overflow leading to buffer under-allocation and overflow: rv = PyString_FromStringAndSize((char *) 0, (xsize*ysize+TAGLEN)*sizeof(Py_Int32)); There was and attempt to fix in as part of CVE-2008-3143 (bug #455013): http://svn.python.org/view?view=rev&revision=60793 http://svn.python.org/view/python/branches/release25-maint/Modules/rgbimgmodule.c?r1=60793&r2=60792 using the code: new_size = xsize * ysize + TAGLEN; if (new_size < 0 || (new_size * sizeof(Py_Int32)) < 0) { PyErr_NoMemory(); This check is insufficient though (e.g. for xsize = ysize = 0x8000, new_size is 0x40000000 and new_size * sizeof(Py_Int32) is 0).
Two more bonus flaws in RLE decoder: longimagedata() contains two copies of this: fread(rledat, lengthtab[idx], 1, inf); where lengthtab[idx] is 32bit value read form the image file. rledat size (rlebuflen) is derived form XSIZE. On one of the code paths, there's a check to ensure that lengthtab[idx] does not exceed rlebuflen, but not on the other one. Another issue is in expandrow(). The amount of uncompressed / decoded data written to the output buffer is only controlled by the input from the file, not checking any output buffer boundaries.
Created attachment 411489 [details] Patch It adds following: - checks that ZSIZE does not exceed 4 - corrects broken integer overflow checks, unneeded check are dropped / replaced by comment indicating no overflow can happen - check against rlebuflen before reading data to rledat - only allow expandrow() to write XSIZE bytes (one scanline) It adds basic sanity check to longstoimage() (image writing) too. This patch should be applied after reverting rgbimgmodule.c changes from CVE-2008-3143 patch.
CVE assignments: CVE-2009-4134 - for the original issue - buffer underflow caused by unexpected ZSIZE value, as pointed out in comment #0 and further detailed in comment #9 CVE-2010-1449 - incorrect integer overflow checks, incomplete fix for rgbimg part of the CVE-2008-3143, detailed in comment #9 CVE-2010-1450 - multiple RLE decoder buffer overflows, detailed in comment #10
Making the bug public.
Upstream bug report: http://bugs.python.org/issue8678
Statement: The Red Hat Security Response Team has rated this issue as having low security impact, a future update may address this flaw.
This issue has been addressed in following products: Red Hat Enterprise Linux 5 Via RHSA-2011:0027 https://rhn.redhat.com/errata/RHSA-2011-0027.html
This issue has been addressed in following products: Red Hat Enterprise Linux 4 Via RHSA-2011:0260 https://rhn.redhat.com/errata/RHSA-2011-0260.html