Bug 1284421 (CVE-2015-7507, CVE-2015-7508)

Summary: CVE-2015-7507 CVE-2015-7508 libnsbmp: Heap overflow in bmp_decode_rle() and out-of-bounds read in bmp_decode_rle()/bmp_decode_rgb()
Product: [Other] Security Response Reporter: Adam Mariš <amaris>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED UPSTREAM QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: carnil, security-response-team
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-06-08 02:45:46 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:
Bug Depends On: 1292162    
Bug Blocks:    

Description Adam Mariš 2015-11-23 10:14:13 UTC
1. CVE-2015-7508:
A heap-based buffer overflow vulnerability was found in bmp_decode_rle function when processing run-length endoded BMP data, that can expand beyond the allocated buffer.

Vulnerable code:

951: static bmp_result bmp_decode_rle(bmp_image *bmp, uint8_t *data, int bytes, int size) {
[...]
962: swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
963: top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
[...]
973: length = *data++;
[...]
1048: /* NN means perform RLE for NN pixels */
1049: if (bmp->reversed) {
1050: pixels_left = (y + 1) * bmp->width - x;
1051: scanline = (void *)(top + (y * swidth));
1052: } else {
1053: pixels_left = (bmp->height - y + 1) * bmp->width - x;
1054: scanline = (void *)(bottom - (y * swidth));
1055: }
1056: if (length > pixels_left)
1057: length = pixels_left;
[...]
1078: pixel2 = *data++;
1079: pixel = bmp->colour_table[pixel2 >> 4];
1080: pixel2 = bmp->colour_table[pixel2 & 0xf];
1081: for (i = 0; i < length; i++) {
1082: if (x >= bmp->width) {
1083: x = 0;
1084: if (++y > bmp->height)
1085: return BMP_DATA_ERROR;
1086: scanline -= bmp->width;
1087: }
1088: if ((i & 1) == 0)
1089: scanline[x++] = pixel;
1090: else
1091: scanline[x++] = pixel2;
1092: }

libnsbmp expects that the user-supplied `bmp_bitmap_cb_create` callback allocates enough memory to accommodate for `bmp->width * bmp->height * bmp->bpp` bytes of data. Due to the way `pixels_left` is calculated, the last row of BMP-encoded data may expand beyond the end of `bmp->bitmap`.

2. CVE-2015-7508:
An out-of-bounds read due to a lack of boundary checking before  dereferencing `bmp->colour_table` in `bmp_decode_rgb()` and `bmp_decode_rle()` with an index based on a user-supplied value was found.

Vulnerable code:

306: static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) {
[...]
319: header_size = read_uint32(data, 0);
[...]
322: if (header_size == 12) {
323: /* the following header is for os/2 and windows 2.x and consists of:
324: *
325: * +0 UINT32 size of this header (in bytes)
326: * +4 INT16 image width (in pixels)
327: * +6 INT16 image height (in pixels)
328: * +8 UINT16 number of colour planes (always 1)
329: * +10 UINT16 number of bits per pixel
330: */
[...]
358: bmp->bpp = read_uint16(data, 10);
359: /**
360: * The bpp value should be in the range 1-32, but the only
361: * values considered legal are:
362: * RGB ENCODING: 1, 4, 8, 16, 24 and 32
363: */
364: if ((bmp->bpp != 1) && (bmp->bpp != 4) &&
365: (bmp->bpp != 8) &&
366: (bmp->bpp != 16) &&
367: (bmp->bpp != 24) &&
368: (bmp->bpp != 32))
369: return BMP_DATA_ERROR;
370: bmp->colours = (1 << bmp->bpp);
[...]
374: } else {
[...]
501: bmp->colours = read_uint32(data, 32);
502: if (bmp->colours == 0)
503: bmp->colours = (1 << bmp->bpp);
504: palette_size = 4;
505: }
[...]
515: if (bmp->bpp < 16) {
[...]
531: bmp->colour_table = (uint32_t *)malloc(bmp->colours * 4);
532: if (!bmp->colour_table)
533: return BMP_INSUFFICIENT_MEMORY;
534: for (i = 0; i < bmp->colours; i++) {
535: bmp->colour_table[i] = data[2] | (data[1] << 8) | (data[0] << 16);
536: if (bmp->opaque)
537: bmp->colour_table[i] |= (0xff << 24);
538: data += palette_size;
539: bmp->colour_table[i] = read_uint32((uint8_t *)&bmp->colour_table[i],0);
540: }
541: }
[...]

844: static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes) {
845: uint8_t *top, *bottom, *end, *data;
846: uint32_t *scanline;
847: intptr_t addr;
848: uint32_t x, y, swidth;
849: uint8_t bit_shifts[8];
850: uint8_t ppb = 8 / bmp->bpp;
851: uint8_t bit_mask = (1 << bmp->bpp) - 1;
852: uint8_t cur_byte = 0, bit, i;
853:
854: for (i = 0; i < ppb; i++)
855: bit_shifts[i] = 8 - ((i + 1) * bmp->bpp);
856: data = *start;
[..]
868: if (bmp->limited_trans)
869: bmp->transparent_index = bmp->colour_table[(*data >> bit_shifts[0]) & bit_mask];
[...]
871: for (y = 0; y < bmp->height; y++) {
[...]
874: bit = 8;
[...]
881: for (x = 0; x < bmp->width; x++) {
882: if (bit >= ppb) {
883: bit = 0;
884: cur_byte = *data++;
885: }
886: scanline[x] = bmp->colour_table[(cur_byte >> bit_shifts[bit++]) & bit_mask];
[...]

These issues affect libnsbmp <= 0.1.2

Comment 3 Martin Prpič 2015-12-16 15:37:04 UTC
Created libnsbmp tracking bugs for this issue:

Affects: fedora-all [bug 1292162]

Comment 4 Martin Prpič 2015-12-16 15:37:28 UTC
External References:

http://seclists.org/bugtraq/2015/Dec/87

Comment 5 Product Security DevOps Team 2019-06-08 02:45:46 UTC
This CVE Bugzilla entry is for community support informational purposes only as it does not affect a package in a commercially supported Red Hat product. Refer to the dependent bugs for status of those individual community products.