Source: libjpeg-turbo Version: 1:1.5.2-2 Severity: important Tags: security upstream Forwarded: https://github.com/libjpeg-turbo/libjpeg-turbo/issues/258
Hi, The following vulnerability was published for libjpeg-turbo. CVE-2018-14498[0]: | get_8bit_row in rdbmp.c in libjpeg-turbo through 1.5.90 and MozJPEG | through 3.3.1 allows attackers to cause a denial of service (heap-based | buffer over-read and application crash) via a crafted 8-bit BMP in | which one or more of the color indices is out of range for the number | of palette entries. If you fix the vulnerability please also make sure to include the CVE (Common Vulnerabilities & Exposures) id in your changelog entry. Build with ASAN one sees the issue as $ ASAN_OPTIONS="detect_leaks=0" ./cjpeg -outfile /dev/null ~/CVE-2018-14498 ================================================================= ==31997==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60d0000000d3 at pc 0x56029bfc9ff7 bp 0x7ffe52f5e400 sp 0x7ffe52f5e3f8 READ of size 1 at 0x60d0000000d3 thread T0 #0 0x56029bfc9ff6 in get_8bit_row /tmp/libjpeg-turbo-1.5.2/rdbmp.c:145 #1 0x56029bfcaf1b in preload_image /tmp/libjpeg-turbo-1.5.2/rdbmp.c:270 #2 0x56029bfc3c40 in main /tmp/libjpeg-turbo-1.5.2/cjpeg.c:616 #3 0x7f8be200109a in __libc_start_main ../csu/libc-start.c:308 #4 0x56029bfc1359 in _start (/tmp/libjpeg-turbo-1.5.2/.libs/cjpeg+0x5359) 0x60d0000000d3 is located 12 bytes to the right of 135-byte region [0x60d000000040,0x60d0000000c7) allocated by thread T0 here: #0 0x7f8be23d6350 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xe9350) #1 0x7f8be229b437 in jpeg_get_large /tmp/libjpeg-turbo-1.5.2/jmemnobs.c:56 #2 0x7f8be2296e9f in alloc_large /tmp/libjpeg-turbo-1.5.2/jmemmgr.c:393 #3 0x7f8be22971fc in alloc_sarray /tmp/libjpeg-turbo-1.5.2/jmemmgr.c:477 #4 0x56029bfcce5a in start_input_bmp /tmp/libjpeg-turbo-1.5.2/rdbmp.c:401 #5 0x56029bfc3b5d in main /tmp/libjpeg-turbo-1.5.2/cjpeg.c:595 #6 0x7f8be200109a in __libc_start_main ../csu/libc-start.c:308 SUMMARY: AddressSanitizer: heap-buffer-overflow /tmp/libjpeg-turbo-1.5.2/rdbmp.c:145 in get_8bit_row Shadow bytes around the buggy address: 0x0c1a7fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c1a7fff8000: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 =>0x0c1a7fff8010: 00 00 00 00 00 00 00 00 07 fa[fa]fa fa fa fa fa 0x0c1a7fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c1a7fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c1a7fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c1a7fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c1a7fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==31997==ABORTING For further information see: [0] https://security-tracker.debian.org/tracker/CVE-2018-14498 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-14498 [1] https://github.com/libjpeg-turbo/libjpeg-turbo/issues/258 Please adjust the affected versions in the BTS as needed. Attaching a preliminary backported patch which should apply on top of 1:1.5.2-2 (not yet checked it is fully correct backport). Regards, Salvatore
From: DRC <informat...@libjpeg-turbo.org> Date: Fri, 20 Jul 2018 17:21:36 -0500 Subject: cjpeg: Fix OOB read caused by malformed 8-bit BMP Origin: https://github.com/libjpeg-turbo/libjpeg-turbo/commit/9c78a04df4e44ef6487eee99c4258397f4fdca55 Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-14498 Bug: https://github.com/libjpeg-turbo/libjpeg-turbo/issues/258 ... in which one or more of the color indices is out of range for the number of palette entries. Fix partly borrowed from jpeg-9c. This commit also adopts Guido's JERR_PPM_OUTOFRANGE enum value in lieu of our project-specific JERR_PPM_TOOLARGE enum value. Fixes #258 --- ChangeLog.md | 5 +++++ cderror.h | 5 +++-- rdbmp.c | 13 ++++++++++++- rdppm.c | 12 ++++++------ 4 files changed, 26 insertions(+), 9 deletions(-) --- a/cderror.h +++ b/cderror.h @@ -49,6 +49,7 @@ JMESSAGE(JERR_BMP_COLORSPACE, "BMP outpu JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") +JMESSAGE(JERR_BMP_OUTOFRANGE, "Numeric value out of range in BMP file") JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") @@ -75,8 +76,8 @@ JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out o #ifdef PPM_SUPPORTED JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") -JMESSAGE(JERR_PPM_TOOLARGE, "Integer value too large in PPM file") JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") +JMESSAGE(JERR_PPM_OUTOFRANGE, "Numeric value out of range in PPM file") JMESSAGE(JTRC_PGM, "%ux%u PGM image") JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") JMESSAGE(JTRC_PPM, "%ux%u PPM image") --- a/rdbmp.c +++ b/rdbmp.c @@ -66,6 +66,7 @@ typedef struct _bmp_source_struct { JDIMENSION row_width; /* Physical width of scanlines in file */ int bits_per_pixel; /* remembers 8- or 24-bit format */ + int cmap_length; /* colormap length */ } bmp_source_struct; @@ -126,6 +127,7 @@ get_8bit_row (j_compress_ptr cinfo, cjpe { bmp_source_ptr source = (bmp_source_ptr) sinfo; register JSAMPARRAY colormap = source->colormap; + int cmaplen = source->cmap_length; JSAMPARRAY image_ptr; register int t; register JSAMPROW inptr, outptr; @@ -142,6 +144,8 @@ get_8bit_row (j_compress_ptr cinfo, cjpe outptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { t = GETJSAMPLE(*inptr++); + if (t >= cmaplen) + ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */ *outptr++ = colormap[1][t]; *outptr++ = colormap[2][t]; @@ -401,6 +405,7 @@ start_input_bmp (j_compress_ptr cinfo, c source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) biClrUsed, (JDIMENSION) 3); + source->cmap_length = (int)biClrUsed; /* and read it from the file */ read_colormap(source, (int) biClrUsed, mapentrysize); /* account for size of colormap */ --- a/rdppm.c +++ b/rdppm.c @@ -69,7 +69,7 @@ typedef struct { JSAMPROW pixrow; /* compressor input buffer */ size_t buffer_width; /* width of I/O buffer */ JSAMPLE *rescale; /* => maxval-remapping array, or NULL */ - int maxval; + unsigned int maxval; } ppm_source_struct; typedef ppm_source_struct *ppm_source_ptr; @@ -119,7 +119,7 @@ read_pbm_integer (j_compress_ptr cinfo, } if (val > maxval) - ERREXIT(cinfo, JERR_PPM_TOOLARGE); + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); return val; } @@ -255,7 +255,7 @@ get_word_gray_row (j_compress_ptr cinfo, temp = UCH(*bufferptr++) << 8; temp |= UCH(*bufferptr++); if (temp > maxval) - ERREXIT(cinfo, JERR_PPM_TOOLARGE); + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); *ptr++ = rescale[temp]; } return 1; @@ -282,17 +282,17 @@ get_word_rgb_row (j_compress_ptr cinfo, temp = UCH(*bufferptr++) << 8; temp |= UCH(*bufferptr++); if (temp > maxval) - ERREXIT(cinfo, JERR_PPM_TOOLARGE); + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); *ptr++ = rescale[temp]; temp = UCH(*bufferptr++) << 8; temp |= UCH(*bufferptr++); if (temp > maxval) - ERREXIT(cinfo, JERR_PPM_TOOLARGE); + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); *ptr++ = rescale[temp]; temp = UCH(*bufferptr++) << 8; temp |= UCH(*bufferptr++); if (temp > maxval) - ERREXIT(cinfo, JERR_PPM_TOOLARGE); + ERREXIT(cinfo, JERR_PPM_OUTOFRANGE); *ptr++ = rescale[temp]; } return 1;