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..5133b47 --- /dev/null +++ b/SOURCES/CVE-2020-5312_CVE-2019-16865.patch @@ -0,0 +1,124 @@ +From 6cad2f6857ab669139e5d417139b5795fae4afdf Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Fri, 14 Feb 2020 09:43:57 +0100 +Subject: [PATCH] CVE-2020-5312_CVE-2019-16865 + +--- + .../PIL/PsdImagePlugin.py | 6 ++++-- + .../libImaging/FliDecode.c | 14 +++++++++++--- + .../libImaging/PcxDecode.c | 8 ++++++++ + .../libImaging/RawDecode.c | 11 +++++++++-- + 4 files changed, 32 insertions(+), 7 deletions(-) + +diff --git a/python-imaging-Pillow-d1c6db8/PIL/PsdImagePlugin.py b/python-imaging-Pillow-d1c6db8/PIL/PsdImagePlugin.py +index 2192015..9072875 100644 +--- a/python-imaging-Pillow-d1c6db8/PIL/PsdImagePlugin.py ++++ b/python-imaging-Pillow-d1c6db8/PIL/PsdImagePlugin.py +@@ -202,9 +202,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)); mask_x = i32(read(4)) +@@ -223,7 +225,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/python-imaging-Pillow-d1c6db8/libImaging/FliDecode.c b/python-imaging-Pillow-d1c6db8/libImaging/FliDecode.c +index 75eebe8..940171f 100644 +--- a/python-imaging-Pillow-d1c6db8/libImaging/FliDecode.c ++++ b/python-imaging-Pillow-d1c6db8/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/python-imaging-Pillow-d1c6db8/libImaging/PcxDecode.c b/python-imaging-Pillow-d1c6db8/libImaging/PcxDecode.c +index ab82b23..4a1d92a 100644 +--- a/python-imaging-Pillow-d1c6db8/libImaging/PcxDecode.c ++++ b/python-imaging-Pillow-d1c6db8/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/python-imaging-Pillow-d1c6db8/libImaging/RawDecode.c b/python-imaging-Pillow-d1c6db8/libImaging/RawDecode.c +index 5aadb2b..b8b667e 100644 +--- a/python-imaging-Pillow-d1c6db8/libImaging/RawDecode.c ++++ b/python-imaging-Pillow-d1c6db8/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) { +-- +2.24.1 + diff --git a/SPECS/python-pillow.spec b/SPECS/python-pillow.spec index bb1381b..0e91629 100644 --- a/SPECS/python-pillow.spec +++ b/SPECS/python-pillow.spec @@ -23,7 +23,7 @@ Name: python-pillow Version: 2.0.0 -Release: 19%{?snap}%{?dist} +Release: 20%{?snap}%{?dist} Summary: Python image processing library # License: see http://www.pythonware.com/products/pil/license.htm @@ -40,6 +40,15 @@ Patch0: python-pillow-archs.patch Patch1: python-pillow_endian.patch Patch2: python-pillow-2.0.0_bytearray.patch Patch3: python-pillow-2.0.0_memleaks.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 +# this one is implemented only partially because this old version of Pillow does not support all vulnerable file types +# 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 +Patch4: CVE-2020-5312_CVE-2019-16865.patch BuildRequires: python2-devel BuildRequires: python-setuptools @@ -207,6 +216,7 @@ PIL image wrapper for Qt. %patch1 -p1 -b .endian %patch2 -p1 -b .byte_array %patch3 -p1 -b .memleaks +%patch4 -p2 -b .cves %if %{with_python3} # Create Python 3 source tree @@ -364,6 +374,11 @@ popd %endif %changelog +* Wed Feb 12 2020 Lumír Balhar - 2.0.0-20gitd1c6db8 +- Combined fixes for CVE-2020-5312 and CVE-2019-16865 +Resolves: rhbz#1789533 +Resolves: rhbz#1774066 + * Mon Oct 06 2014 Michal Minar 2.0.0-19gitd1c6db8 - Reenabled webp support on little endian archs.