From d3a4de34af8cb1b332e8609a9655b6a8d0ea5732 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mon, 24 Feb 2020 06:35:32 -0500 Subject: [PATCH] import python-pillow-5.1.1-10.el8_1 --- SOURCES/CVE-2020-5311.patch | 83 ++++++++++ SOURCES/CVE-2020-5312_CVE-2019-16865.patch | 183 +++++++++++++++++++++ SPECS/python-pillow.spec | 29 +++- 3 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 SOURCES/CVE-2020-5311.patch create mode 100644 SOURCES/CVE-2020-5312_CVE-2019-16865.patch diff --git a/SOURCES/CVE-2020-5311.patch b/SOURCES/CVE-2020-5311.patch new file mode 100644 index 0000000..de0439b --- /dev/null +++ b/SOURCES/CVE-2020-5311.patch @@ -0,0 +1,83 @@ +From 1dd0fb64bd3cc221b5877ece4ce2f300245b638f Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Mon, 17 Feb 2020 14:19:32 +0100 +Subject: [PATCH] CVE-2020-5311 + +--- + src/libImaging/SgiRleDecode.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c +index 39e7b3a..6367ae7 100644 +--- a/src/libImaging/SgiRleDecode.c ++++ b/src/libImaging/SgiRleDecode.c +@@ -25,7 +25,7 @@ static void read4B(UINT32* dest, UINT8* buf) + *dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); + } + +-static int expandrow(UINT8* dest, UINT8* src, int n, int z) ++static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + { + UINT8 pixel, count; + +@@ -37,6 +37,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z) + count = pixel & RLE_MAX_RUN; + if (!count) + return count; ++ if (count > xsize) { ++ return -1; ++ } + if (pixel & RLE_COPY_FLAG) { + while(count--) { + *dest = *src++; +@@ -56,7 +59,7 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z) + return 0; + } + +-static int expandrow2(UINT16* dest, UINT16* src, int n, int z) ++static int expandrow2(UINT16* dest, UINT16* src, int n, int z, int xsize) + { + UINT8 pixel, count; + +@@ -70,6 +73,9 @@ static int expandrow2(UINT16* dest, UINT16* src, int n, int z) + count = pixel & RLE_MAX_RUN; + if (!count) + return count; ++ if (count > xsize) { ++ return -1; ++ } + if (pixel & RLE_COPY_FLAG) { + while(count--) { + *dest = *src++; +@@ -95,6 +101,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + UINT8 *ptr; + SGISTATE *c; + int err = 0; ++ int status; + + /* Get all data from File descriptor */ + c = (SGISTATE*)state->context; +@@ -163,12 +170,16 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + + /* row decompression */ + if (c->bpc ==1) { +- if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands)) +- goto sgi_finish_decode; ++ status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); + } + else { +- if(expandrow2((UINT16*)&state->buffer[c->channo * 2], (UINT16*)&ptr[c->rleoffset], c->rlelength, im->bands)) +- goto sgi_finish_decode; ++ status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); ++ } ++ if (status == -1) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } else if (status == 1) { ++ goto sgi_finish_decode; + } + + state->count += c->rlelength; +-- +2.24.1 + diff --git a/SOURCES/CVE-2020-5312_CVE-2019-16865.patch b/SOURCES/CVE-2020-5312_CVE-2019-16865.patch new file mode 100644 index 0000000..e9fca85 --- /dev/null +++ b/SOURCES/CVE-2020-5312_CVE-2019-16865.patch @@ -0,0 +1,183 @@ +From cc9658731ba1ea291f83ea959acc27ac28384a2c Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Fri, 14 Feb 2020 11:14:53 +0100 +Subject: [PATCH] Combined fix for CVE-2020-5312 and CVE-2019-16865 + +--- + src/PIL/GifImagePlugin.py | 1 + + src/PIL/IcoImagePlugin.py | 1 + + src/PIL/PsdImagePlugin.py | 6 ++++-- + src/PIL/TiffImagePlugin.py | 4 ++-- + src/libImaging/FliDecode.c | 14 +++++++++++--- + src/libImaging/PcxDecode.c | 8 ++++++++ + src/libImaging/RawDecode.c | 11 +++++++++-- + src/libImaging/SgiRleDecode.c | 5 +++++ + 8 files changed, 41 insertions(+), 9 deletions(-) + +diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py +index c01adff..99af4a5 100644 +--- a/src/PIL/GifImagePlugin.py ++++ b/src/PIL/GifImagePlugin.py +@@ -251,6 +251,7 @@ class GifImageFile(ImageFile.ImageFile): + self.dispose = None + elif self.disposal_method == 2: + # replace with background colour ++ Image._decompression_bomb_check(self.size) + self.dispose = Image.core.fill("P", self.size, + self.info["background"]) + else: +diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py +index 428fdd4..2b6d1e0 100644 +--- a/src/PIL/IcoImagePlugin.py ++++ b/src/PIL/IcoImagePlugin.py +@@ -167,6 +167,7 @@ class IcoFile(object): + else: + # XOR + AND mask bmp frame + im = BmpImagePlugin.DibImageFile(self.buf) ++ Image._decompression_bomb_check(im.size) + + # change tile dimension to only encompass XOR image + im.size = (im.size[0], int(im.size[1] / 2)) +diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py +index f6e04f7..fe2a2ff 100644 +--- a/src/PIL/PsdImagePlugin.py ++++ b/src/PIL/PsdImagePlugin.py +@@ -209,9 +209,11 @@ def _layerinfo(file): + # skip over blend flags and extra information + filler = read(12) + name = "" +- size = i32(read(4)) ++ size = i32(read(4)) # length of the extra data field + combined = 0 + if size: ++ data_end = file.tell() + size ++ + length = i32(read(4)) + if length: + mask_y = i32(read(4)) +@@ -233,7 +235,7 @@ def _layerinfo(file): + name = read(length).decode('latin-1', 'replace') + combined += length + 1 + +- file.seek(size - combined, 1) ++ file.seek(data_end) + layers.append((name, mode, (x0, y0, x1, y1))) + + # get tiles +diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py +index f903918..b9a1ef7 100644 +--- a/src/PIL/TiffImagePlugin.py ++++ b/src/PIL/TiffImagePlugin.py +@@ -1170,8 +1170,8 @@ class TiffImageFile(ImageFile.ImageFile): + print("- fill_order:", fillorder) + + # size +- xsize = self.tag_v2.get(IMAGEWIDTH) +- ysize = self.tag_v2.get(IMAGELENGTH) ++ xsize = int(self.tag_v2.get(IMAGEWIDTH)) ++ ysize = int(self.tag_v2.get(IMAGELENGTH)) + self.size = xsize, ysize + + if DEBUG: +diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c +index 6d22c6c..a99aca8 100644 +--- a/src/libImaging/FliDecode.c ++++ b/src/libImaging/FliDecode.c +@@ -30,7 +30,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + { + UINT8* ptr; + int framesize; +- int c, chunks; ++ int c, chunks, advance; + int l, lines; + int i, j, x = 0, y, ymax; + +@@ -59,10 +59,16 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + + chunks = I16(ptr+6); + ptr += 16; ++ bytes -= 16; + + /* Process subchunks */ + for (c = 0; c < chunks; c++) { +- UINT8 *data = ptr + 6; ++ UINT8* data; ++ if (bytes < 10) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } ++ data = ptr + 6; + switch (I16(ptr+4)) { + case 4: case 11: + /* FLI COLOR chunk */ +@@ -198,7 +204,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + state->errcode = IMAGING_CODEC_UNKNOWN; + return -1; + } +- ptr += I32(ptr); ++ advance = I32(ptr); ++ ptr += advance; ++ bytes -= advance; + } + + return -1; /* end of frame */ +diff --git a/src/libImaging/PcxDecode.c b/src/libImaging/PcxDecode.c +index e5417f1..aaf5867 100644 +--- a/src/libImaging/PcxDecode.c ++++ b/src/libImaging/PcxDecode.c +@@ -22,6 +22,14 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + UINT8 n; + UINT8* ptr; + ++ if (strcmp(im->mode, "1") == 0 && state->xsize > state->bytes * 8) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } else if (strcmp(im->mode, "P") == 0 && state->xsize > state->bytes) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } ++ + ptr = buf; + + for (;;) { +diff --git a/src/libImaging/RawDecode.c b/src/libImaging/RawDecode.c +index 40c0cb7..d4b7994 100644 +--- a/src/libImaging/RawDecode.c ++++ b/src/libImaging/RawDecode.c +@@ -33,8 +33,15 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + + /* get size of image data and padding */ + state->bytes = (state->xsize * state->bits + 7) / 8; +- rawstate->skip = (rawstate->stride) ? +- rawstate->stride - state->bytes : 0; ++ if (rawstate->stride) { ++ rawstate->skip = rawstate->stride - state->bytes; ++ if (rawstate->skip < 0) { ++ state->errcode = IMAGING_CODEC_CONFIG; ++ return -1; ++ } ++ } else { ++ rawstate->skip = 0; ++ } + + /* check image orientation */ + if (state->ystep < 0) { +diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c +index 9d8e563..39e7b3a 100644 +--- a/src/libImaging/SgiRleDecode.c ++++ b/src/libImaging/SgiRleDecode.c +@@ -156,6 +156,11 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize]; + c->rleoffset -= SGI_HEADER_SIZE; + ++ if (c->rleoffset + c->rlelength > c->bufsize) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } ++ + /* row decompression */ + if (c->bpc ==1) { + if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands)) +-- +2.24.1 + diff --git a/SPECS/python-pillow.spec b/SPECS/python-pillow.spec index 804f5b3..2d786ca 100644 --- a/SPECS/python-pillow.spec +++ b/SPECS/python-pillow.spec @@ -8,7 +8,7 @@ Name: python-%{srcname} Version: 5.1.1 -Release: 7%{?dist} +Release: 10%{?dist} Summary: Python image processing library # License: see http://www.pythonware.com/products/pil/license.htm @@ -18,6 +18,20 @@ Source0: https://github.com/python-pillow/Pillow/archive/%{version}/Pillo Patch0: 0001-Fix-potential-un-terminated-buffer-problem-CWE-120.patch Patch1: 0002-Fix-potential-leaked-storage-issues-CWE-772.patch Patch2: 0003-Fix-dereferencing-type-punned-pointer.patch +# Combined fixes for CVE-2020-5312 improperly restricted operations on memory buffer in libImaging/PcxDecode.c +# https://bugzilla.redhat.com/show_bug.cgi?id=1789533 +# https://github.com/python-pillow/Pillow/commit/93b22b846e0269ee9594ff71a72bec02d2bea8fd +# and for CVE-2019-16865 reading specially crafted image files leads to allocation of large amounts of memory and denial of service +# https://bugzilla.redhat.com/show_bug.cgi?id=1774066 +# https://github.com/python-pillow/Pillow/commit/cc16025e234b7a7a4dd3a86d2fdc0980698db9cc +# https://github.com/python-pillow/Pillow/commit/b36c1bc943d554ba223086c7efb502d080f73905 +# https://github.com/python-pillow/Pillow/commit/f228d0ccbf6bf9392d7fcd51356ef2cfda80c75a +# https://github.com/python-pillow/Pillow/commit/b9693a51c99c260bd66d1affeeab4a226cf7e5a5 +Patch3: CVE-2020-5312_CVE-2019-16865.patch +# Fix for CVE-2020-5311 - out-of-bounds write in expandrow in libImaging/SgiRleDecode.c +# https://bugzilla.redhat.com/show_bug.cgi?id=1789535 +# https://github.com/python-pillow/Pillow/commit/a79b65c47c7dc6fe623aadf09aa6192fc54548f3 +Patch4: CVE-2020-5311.patch BuildRequires: freetype-devel BuildRequires: gcc @@ -162,6 +176,19 @@ popd %changelog +* Mon Feb 17 2020 Lumír Balhar - 5.1.1-10 +- Bump and rebuild for gating to deliver CVE fixes +Resolves: rhbz#1789535 + +* Mon Feb 17 2020 Lumír Balhar - 5.1.1-9 +- Fix for CVE-2020-5311 - out-of-bounds write in expandrow +Resolves: rhbz#1789535 + +* Fri Feb 14 2020 Lumír Balhar - 5.1.1-8 +- Combined fixes for CVE-2020-5312 and CVE-2019-16865 +Resolves: rhbz#1789533 +Resolves: rhbz#1774066 + * Tue Nov 27 2018 Lumír Balhar - 5.1.1-7 - Add upstream patch to solve build-time warning - Move patches to dist-git