From 699c67bdb011afdacad42b1591c4cc9a0041b876 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 21 2021 14:15:40 +0000 Subject: import python-pillow-5.1.1-14.el8 --- diff --git a/SOURCES/CVE-2021-25290.patch b/SOURCES/CVE-2021-25290.patch new file mode 100644 index 0000000..39af8bd --- /dev/null +++ b/SOURCES/CVE-2021-25290.patch @@ -0,0 +1,28 @@ +From c558baf01a97aed376a67ff4641f1c3c864ae3f0 Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Thu, 8 Apr 2021 17:55:26 +0200 +Subject: [PATCH 1/4] CVE-2021-25290 + +--- + src/libImaging/TiffDecode.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/libImaging/TiffDecode.c b/src/libImaging/TiffDecode.c +index f292da3..d17b557 100644 +--- a/src/libImaging/TiffDecode.c ++++ b/src/libImaging/TiffDecode.c +@@ -36,6 +36,11 @@ tsize_t _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) { + TRACE(("_tiffReadProc: %d \n", (int)size)); + dump_state(state); + ++ if (state->loc > state->eof) { ++ TIFFError("_tiffReadProc", "Invalid Read at loc %d, eof: %d", state->loc, state->eof); ++ return 0; ++ } ++ + to_read = min(size, min(state->size, (tsize_t)state->eof) - (tsize_t)state->loc); + TRACE(("to_read: %d\n", (int)to_read)); + +-- +2.30.2 + diff --git a/SOURCES/CVE-2021-25292.patch b/SOURCES/CVE-2021-25292.patch new file mode 100644 index 0000000..452609b --- /dev/null +++ b/SOURCES/CVE-2021-25292.patch @@ -0,0 +1,27 @@ +From f60b6ae79d3c2e759f54bb4acb62b4c49f89fef2 Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Thu, 8 Apr 2021 17:59:21 +0200 +Subject: [PATCH 2/4] CVE-2021-25292 + +--- + src/PIL/PdfParser.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py +index b6938fd..189aed8 100644 +--- a/src/PIL/PdfParser.py ++++ b/src/PIL/PdfParser.py +@@ -562,8 +562,9 @@ class PdfParser: + whitespace_or_hex = br"[\000\011\012\014\015\0400-9a-fA-F]" + whitespace_optional = whitespace + b"*" + whitespace_mandatory = whitespace + b"+" ++ whitespace_optional_no_nl = br"[\000\011\014\015\040]*" # no "\012" aka "\n" + newline_only = br"[\r\n]+" +- newline = whitespace_optional + newline_only + whitespace_optional ++ newline = whitespace_optional_no_nl + newline_only + whitespace_optional_no_nl + re_trailer_end = re.compile(whitespace_mandatory + br"trailer" + whitespace_optional + br"\<\<(.*\>\>)" + newline + + br"startxref" + newline + br"([0-9]+)" + newline + br"%%EOF" + whitespace_optional + br"$", re.DOTALL) + re_trailer_prev = re.compile(whitespace_optional + br"trailer" + whitespace_optional + br"\<\<(.*?\>\>)" + newline +-- +2.30.2 + diff --git a/SOURCES/CVE-2021-25293.patch b/SOURCES/CVE-2021-25293.patch new file mode 100644 index 0000000..0361ed6 --- /dev/null +++ b/SOURCES/CVE-2021-25293.patch @@ -0,0 +1,207 @@ +From 1312c5426e7dd84e396ef2ff35aa09b64d92d382 Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Fri, 9 Apr 2021 19:33:55 +0200 +Subject: [PATCH 3/4] CVE-2021-25293 + +--- + src/libImaging/SgiRleDecode.c | 88 +++++++++++++++++++++++++++++------ + 1 file changed, 75 insertions(+), 13 deletions(-) + +diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c +index 2259159..85af456 100644 +--- a/src/libImaging/SgiRleDecode.c ++++ b/src/libImaging/SgiRleDecode.c +@@ -25,13 +25,60 @@ 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, int xsize) ++/* ++ SgiRleDecoding is done in a single channel row oriented set of RLE chunks. ++ ++ * The file is arranged as ++ - SGI Header ++ - Rle Offset Table ++ - Rle Length Table ++ - Scanline Data ++ ++ * Each RLE atom is c->bpc bytes wide (1 or 2) ++ ++ * Each RLE Chunk is [specifier atom] [ 1 or n data atoms ] ++ ++ * Copy Atoms are a byte with the high bit set, and the low 7 are ++ the number of bytes to copy from the source to the ++ destination. e.g. ++ ++ CBBBBBBBB or 0CHLHLHLHLHLHL (B=byte, H/L = Hi low bytes) ++ ++ * Run atoms do not have the high bit set, and the low 7 bits are ++ the number of copies of the next atom to copy to the ++ destination. e.g.: ++ ++ RB -> BBBBB or RHL -> HLHLHLHLHL ++ ++ The upshot of this is, there is no way to determine the required ++ length of the input buffer from reloffset and rlelength without ++ going through the data at that scan line. ++ ++ Furthermore, there's no requirement that individual scan lines ++ pointed to from the rleoffset table are in any sort of order or ++ used only once, or even disjoint. There's also no requirement that ++ all of the data in the scan line area of the image file be used ++ ++ */ ++ ++static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize, UINT8 *end_of_buffer) + { ++ /* ++ * n here is the number of rlechunks ++ * z is the number of channels, for calculating the interleave ++ * offset to go to RGBA style pixels ++ * xsize is the row width ++ * end_of_buffer is the address of the end of the input buffer ++ */ ++ + UINT8 pixel, count; + int x = 0; + + for (;n > 0; n--) + { ++ if (src > end_of_buffer) { ++ return -1; ++ } + pixel = *src++; + if (n == 1 && pixel != 0) + return n; +@@ -43,6 +90,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + } + x += count; + if (pixel & RLE_COPY_FLAG) { ++ if (src + count > end_of_buffer) { ++ return -1; ++ } + while(count--) { + *dest = *src++; + dest += z; +@@ -50,6 +100,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + + } + else { ++ if (src > end_of_buffer) { ++ return -1; ++ } + pixel = *src++; + while (count--) { + *dest = pixel; +@@ -61,7 +114,7 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + return 0; + } + +-static int expandrow2(UINT16* dest, UINT16* src, int n, int z, int xsize) ++static int expandrow2(UINT16* dest, UINT16* src, int n, int z, int xsize, UINT8 *end_of_buffer) + { + UINT8 pixel, count; + +@@ -69,6 +122,9 @@ static int expandrow2(UINT16* dest, UINT16* src, int n, int z, int xsize) + + for (;n > 0; n--) + { ++ if (src + 1 > end_of_buffer) { ++ return -1; ++ } + pixel = ((UINT8*)src)[1]; + ++src; + if (n == 1 && pixel != 0) +@@ -81,12 +137,18 @@ static int expandrow2(UINT16* dest, UINT16* src, int n, int z, int xsize) + } + x += count; + if (pixel & RLE_COPY_FLAG) { ++ if (src + 2 * count > end_of_buffer) { ++ return -1; ++ } + while(count--) { + *dest = *src++; + dest += z; + } + } + else { ++ if (src + 2 > end_of_buffer) { ++ return -1; ++ } + while (count--) { + *dest = *src; + dest += z; +@@ -136,8 +198,10 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + return -1; + } + _imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET); +- _imaging_read_pyFd(state->fd, (char*)ptr, c->bufsize); +- ++ if (_imaging_read_pyFd(state->fd, (char *)ptr, c->bufsize) != c->bufsize) { ++ state->errcode = IMAGING_CODEC_UNKNOWN; ++ return -1; ++ } + + /* decoder initialization */ + state->count = 0; +@@ -168,8 +232,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + for (c->tabindex = 0, c->bufindex = c->tablen * sizeof(UINT32); c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) + read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]); + +- state->count += c->tablen * sizeof(UINT32) * 2; +- + /* read compressed rows */ + for (c->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep) + { +@@ -177,19 +239,21 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + { + c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize]; + c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize]; +- c->rleoffset -= SGI_HEADER_SIZE; + +- if (c->rleoffset + c->rlelength > c->bufsize) { ++ // Check for underflow of rleoffset-SGI_HEADER_SIZE ++ if (c->rleoffset < SGI_HEADER_SIZE) { + state->errcode = IMAGING_CODEC_OVERRUN; + goto sgi_finish_decode; + } + ++ c->rleoffset -= SGI_HEADER_SIZE; ++ + /* row decompression */ + if (c->bpc ==1) { +- status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); ++ status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize, &ptr[c->bufsize-1]); + } + else { +- status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); ++ status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize, &ptr[c->bufsize-1]); + } + if (status == -1) { + state->errcode = IMAGING_CODEC_OVERRUN; +@@ -198,7 +262,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + goto sgi_finish_decode; + } + +- state->count += c->rlelength; + } + + /* store decompressed data in image */ +@@ -206,7 +269,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + + } + +- c->bufsize++; + + sgi_finish_decode: ; + +@@ -217,5 +279,5 @@ sgi_finish_decode: ; + state->errcode=err; + return -1; + } +- return state->count - c->bufsize; ++ return 0; + } +-- +2.30.2 + diff --git a/SOURCES/CVE-2021-27921_27922_27923.patch b/SOURCES/CVE-2021-27921_27922_27923.patch new file mode 100644 index 0000000..0cdb073 --- /dev/null +++ b/SOURCES/CVE-2021-27921_27922_27923.patch @@ -0,0 +1,58 @@ +From 357fef8b4bd076e3a15e7ffc58a475626794c7e3 Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Fri, 9 Apr 2021 19:41:58 +0200 +Subject: [PATCH 4/4] CVE-2021-27921_27922_27923 + +--- + src/PIL/BlpImagePlugin.py | 1 + + src/PIL/IcnsImagePlugin.py | 2 ++ + src/PIL/IcoImagePlugin.py | 1 + + 3 files changed, 4 insertions(+) + +diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py +index ec358db..d56d46c 100644 +--- a/src/PIL/BlpImagePlugin.py ++++ b/src/PIL/BlpImagePlugin.py +@@ -362,6 +362,7 @@ class BLP1Decoder(_BLPBaseDecoder): + data = jpeg_header + data + data = BytesIO(data) + image = JpegImageFile(data) ++ Image._decompression_bomb_check(image.size) + self.tile = image.tile # :/ + self.fd = image.fp + self.mode = image.mode +diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py +index b382a73..2292584 100644 +--- a/src/PIL/IcnsImagePlugin.py ++++ b/src/PIL/IcnsImagePlugin.py +@@ -110,6 +110,7 @@ def read_png_or_jpeg2000(fobj, start_length, size): + if sig[:8] == b'\x89PNG\x0d\x0a\x1a\x0a': + fobj.seek(start) + im = PngImagePlugin.PngImageFile(fobj) ++ Image._decompression_bomb_check(im.size) + return {"RGBA": im} + elif sig[:4] == b'\xff\x4f\xff\x51' \ + or sig[:4] == b'\x0d\x0a\x87\x0a' \ +@@ -122,6 +123,7 @@ def read_png_or_jpeg2000(fobj, start_length, size): + jp2kstream = fobj.read(length) + f = io.BytesIO(jp2kstream) + im = Jpeg2KImagePlugin.Jpeg2KImageFile(f) ++ Image._decompression_bomb_check(im.size) + if im.mode != 'RGBA': + im = im.convert('RGBA') + return {"RGBA": im} +diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py +index 2b6d1e0..30412ad 100644 +--- a/src/PIL/IcoImagePlugin.py ++++ b/src/PIL/IcoImagePlugin.py +@@ -164,6 +164,7 @@ class IcoFile(object): + if data[:8] == PngImagePlugin._MAGIC: + # png frame + im = PngImagePlugin.PngImageFile(self.buf) ++ Image._decompression_bomb_check(im.size) + else: + # XOR + AND mask bmp frame + im = BmpImagePlugin.DibImageFile(self.buf) +-- +2.30.2 + diff --git a/SPECS/python-pillow.spec b/SPECS/python-pillow.spec index 19678fa..01703a2 100644 --- a/SPECS/python-pillow.spec +++ b/SPECS/python-pillow.spec @@ -8,7 +8,7 @@ Name: python-%{srcname} Version: 5.1.1 -Release: 13%{?dist} +Release: 14%{?dist} Summary: Python image processing library # License: see http://www.pythonware.com/products/pil/license.htm @@ -49,6 +49,27 @@ Patch7: CVE-2020-35653.patch # Upstream fix: https://github.com/python-pillow/Pillow/commit/120eea2e4547a7d1826afdf01563035844f0b7d5 # Tracking bug: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2020-35653 Patch8: CVE-2020-35655.patch +# CVE-2021-25290 negative-offset memcpy with an invalid size in TiffDecode.c +# Upstream fix: https://github.com/python-pillow/Pillow/commit/86f02f7c70862a0954bfe8133736d352db978eaa +# Tracking bug: https://bugzilla.redhat.com/show_bug.cgi?id=1934685 +Patch9: CVE-2021-25290.patch +# CVE-2021-25292 backtracking regex in PDF parser could be used as a DOS attack +# Upstream fix: https://github.com/python-pillow/Pillow/commit/3bce145966374dd39ce58a6fc0083f8d1890719c +# Tracking bug: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2021-25292 +Patch10: CVE-2021-25292.patch +# CVE-2021-25293 out-of-bounds read in SGIRleDecode.c +# Upstream fix: https://github.com/python-pillow/Pillow/commit/4853e522bddbec66022c0915b9a56255d0188bf9 +# Tracking bug: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2021-25293 +Patch11: CVE-2021-25293.patch +# CVE-2021-27921 reported size of a contained image is not properly checked for a BLP container +# CVE-2021-27922 reported size of a contained image is not properly checked for an ICNS container +# CVE-2021-27923 reported size of a contained image is not properly checked for an ICO container +# Upstream fix: https://github.com/python-pillow/Pillow/commit/480f6819b592d7f07b9a9a52a7656c10bbe07442 +# Tracking bugs: +# - https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2021-27921 +# - https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2021-27922 +# - https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2021-27923 +Patch12: CVE-2021-27921_27922_27923.patch BuildRequires: freetype-devel BuildRequires: gcc @@ -193,6 +214,11 @@ popd %changelog +* Fri Apr 09 2021 Lumír Balhar - 5.1.1-14 +- Fixes for CVE-2021-25290, CVE-2021-25292, CVE-2021-25293, CVE-2021-27921 +CVE-2021-27922, and CVE-2021-27923 +Resolves: rhbz#1934685 rhbz#1934699 rhbz#1934705 rhbz#1935384 rhbz#1935396 rhbz#1935401 + * Thu Feb 18 2021 Lumír Balhar - 5.1.1-13 - Fixes for CVE-2020-35653 and CVE-2020-35655 Resolves: rhbz#1915420 rhbz#1915432