[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#991628: buster-pu: package pillow/5.4.1-2+deb10u2



Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian.org@packages.debian.org
Usertags: pu

Fix for CVE-2021-34552 (#991293) is mitigated by FORTIFY_SOURCE, so
this upload targets proposed-updates instead of security after
discussion with Moritz.

Other pending CVEs in pillow for buster have been set to ignored as 
the patches would be too intrusive in buster due mainly to binary 
changes in the test suite support files.

Debdiff is attached.

 pillow (5.4.1-2+deb10u3) buster; urgency=medium
 .
   * Non-maintainer upload by the Security Team.
 .
   [ Moritz Mühlenhoff ]
   * CVE-2020-35653 CVE-2020-35655 CVE-2021-27921 CVE-2021-27922
     CVE-2021-27923 CVE-2021-25290 CVE-2021-25292 CVE-2021-28677
     CVE-2021-28678
 .
   [ Neil Williams ]
   * CVE-2021-34552


-- System Information:
Debian Release: 10.10
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.19.0-17-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE=en_GB:en (charmap=UTF-8)
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diffstat for pillow-5.4.1 pillow-5.4.1

 changelog                                                                                                              |   13 
 patches/CVE-2020-35653.patch                                                                                           |   26 +
 patches/CVE-2020-35655.patch                                                                                           |   87 ++++
 patches/CVE-2021-27921_CVE-2021-27922_CVE-2021-27923_CVE-2021-25290_CVE-2021-25292_CVE-2021-28677_CVE-2021-28678.patch |  209 ++++++++++
 patches/CVE-2021-34552.patch                                                                                           |   40 +
 patches/series                                                                                                         |    4 
 6 files changed, 379 insertions(+)

diff -Nru pillow-5.4.1/debian/changelog pillow-5.4.1/debian/changelog
--- pillow-5.4.1/debian/changelog	2020-07-22 16:25:31.000000000 +0100
+++ pillow-5.4.1/debian/changelog	2021-07-20 07:21:31.000000000 +0100
@@ -1,3 +1,16 @@
+pillow (5.4.1-2+deb10u3) buster; urgency=medium
+  * Non-maintainer upload by the Security Team.
+
+  [ Moritz Mühlenhoff ]
+  * CVE-2020-35653 CVE-2020-35655 CVE-2021-27921 CVE-2021-27922
+    CVE-2021-27923 CVE-2021-25290 CVE-2021-25292 CVE-2021-28677
+    CVE-2021-28678
+
+  [ Neil Williams ]
+  * CVE-2021-34552
+
+ -- Neil Williams <codehelp@debian.org>  Tue, 20 Jul 2021 07:21:31 +0100
+
 pillow (5.4.1-2+deb10u2) buster; urgency=medium
 
   * CVE-2020-11538 CVE-2020-10378 CVE-2020-10177
diff -Nru pillow-5.4.1/debian/patches/CVE-2020-35653.patch pillow-5.4.1/debian/patches/CVE-2020-35653.patch
--- pillow-5.4.1/debian/patches/CVE-2020-35653.patch	1970-01-01 01:00:00.000000000 +0100
+++ pillow-5.4.1/debian/patches/CVE-2020-35653.patch	2021-07-20 07:21:31.000000000 +0100
@@ -0,0 +1,26 @@
+--- a/src/PIL/PcxImagePlugin.py
++++ b/src/PIL/PcxImagePlugin.py
+@@ -63,9 +63,9 @@
+         version = i8(s[1])
+         bits = i8(s[3])
+         planes = i8(s[65])
+-        stride = i16(s, 66)
++        ignored_stride = i16(s, 66)
+         logger.debug("PCX version %s, bits %s, planes %s, stride %s",
+-                     version, bits, planes, stride)
++                     version, bits, planes, ignored_stride)
+ 
+         self.info["dpi"] = i16(s, 12), i16(s, 14)
+ 
+@@ -102,6 +102,11 @@
+         self.mode = mode
+         self._size = bbox[2]-bbox[0], bbox[3]-bbox[1]
+ 
++        # don't trust the passed in stride. Calculate for ourselves.
++        # CVE-2020-35655
++        stride = (self._size[0] * bits + 7) // 8
++        stride += stride % 2
++
+         bbox = (0, 0) + self.size
+         logger.debug("size: %sx%s", *self.size)
+ 
diff -Nru pillow-5.4.1/debian/patches/CVE-2020-35655.patch pillow-5.4.1/debian/patches/CVE-2020-35655.patch
--- pillow-5.4.1/debian/patches/CVE-2020-35655.patch	1970-01-01 01:00:00.000000000 +0100
+++ pillow-5.4.1/debian/patches/CVE-2020-35655.patch	2021-07-20 07:18:32.000000000 +0100
@@ -0,0 +1,87 @@
+2f409261eb1228e166868f8f0b5da5cda52e55bf and 9a2c9f722f78773e608d44710873437baf3f17d1
+upstream
+
+--- pillow-5.4.1.orig/src/libImaging/SgiRleDecode.c
++++ pillow-5.4.1/src/libImaging/SgiRleDecode.c
+@@ -107,14 +107,33 @@ ImagingSgiRleDecode(Imaging im, ImagingC
+     int err = 0;
+     int status;
+ 
++    /* size check */
++    if (im->xsize > INT_MAX / im->bands ||
++        im->ysize > INT_MAX / im->bands) {
++        state->errcode = IMAGING_CODEC_MEMORY;
++        return -1;
++    }
++
+     /* Get all data from File descriptor */
+     c = (SGISTATE*)state->context;
+     _imaging_seek_pyFd(state->fd, 0L, SEEK_END);
+     c->bufsize = _imaging_tell_pyFd(state->fd);
+     c->bufsize -= SGI_HEADER_SIZE;
++
++    c->tablen = im->bands * im->ysize;
++    /* below, we populate the starttab and lentab into the bufsize,
++       each with 4 bytes per element of tablen
++       Check here before we allocate any memory
++    */
++    if (c->bufsize < 8*c->tablen) {
++        state->errcode = IMAGING_CODEC_OVERRUN;
++        return -1;
++    }
++
+     ptr = malloc(sizeof(UINT8) * c->bufsize);
+     if (!ptr) {
+-        return IMAGING_CODEC_MEMORY;
++        state->errcode = IMAGING_CODEC_MEMORY;
++        return -1;
+     }
+     _imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET);
+     _imaging_read_pyFd(state->fd, (char*)ptr, c->bufsize);
+@@ -129,18 +148,11 @@ ImagingSgiRleDecode(Imaging im, ImagingC
+         state->ystep = 1;
+     }
+ 
+-    if (im->xsize > INT_MAX / im->bands ||
+-        im->ysize > INT_MAX / im->bands) {
+-        err = IMAGING_CODEC_MEMORY;
+-        goto sgi_finish_decode;
+-    }
+-
+     /* Allocate memory for RLE tables and rows */
+     free(state->buffer);
+     state->buffer = NULL;
+     /* malloc overflow check above */
+     state->buffer = calloc(im->xsize * im->bands, sizeof(UINT8) * 2);
+-    c->tablen = im->bands * im->ysize;
+     c->starttab = calloc(c->tablen, sizeof(UINT32));
+     c->lengthtab = calloc(c->tablen, sizeof(UINT32));
+     if (!state->buffer ||
+@@ -169,7 +181,7 @@ ImagingSgiRleDecode(Imaging im, ImagingC
+ 
+             if (c->rleoffset + c->rlelength > c->bufsize) {
+                 state->errcode = IMAGING_CODEC_OVERRUN;
+-                return -1;
++                goto sgi_finish_decode;
+             }
+ 
+             /* row decompression */
+@@ -181,7 +193,7 @@ ImagingSgiRleDecode(Imaging im, ImagingC
+             }
+             if (status == -1) {
+                 state->errcode = IMAGING_CODEC_OVERRUN;
+-                return -1;
++                goto sgi_finish_decode;
+             } else if (status == 1) {
+                 goto sgi_finish_decode;
+             }
+@@ -202,7 +214,8 @@ sgi_finish_decode: ;
+     free(c->lengthtab);
+     free(ptr);
+     if (err != 0){
+-        return err;
++        state->errcode=err;
++        return -1;
+     }
+     return state->count - c->bufsize;
+ }
diff -Nru pillow-5.4.1/debian/patches/CVE-2021-27921_CVE-2021-27922_CVE-2021-27923_CVE-2021-25290_CVE-2021-25292_CVE-2021-28677_CVE-2021-28678.patch pillow-5.4.1/debian/patches/CVE-2021-27921_CVE-2021-27922_CVE-2021-27923_CVE-2021-25290_CVE-2021-25292_CVE-2021-28677_CVE-2021-28678.patch
--- pillow-5.4.1/debian/patches/CVE-2021-27921_CVE-2021-27922_CVE-2021-27923_CVE-2021-25290_CVE-2021-25292_CVE-2021-28677_CVE-2021-28678.patch	1970-01-01 01:00:00.000000000 +0100
+++ pillow-5.4.1/debian/patches/CVE-2021-27921_CVE-2021-27922_CVE-2021-27923_CVE-2021-25290_CVE-2021-25292_CVE-2021-28677_CVE-2021-28678.patch	2021-07-20 07:18:32.000000000 +0100
@@ -0,0 +1,209 @@
+Fixes the following CVE IDs:
+CVE-2021-25290
+CVE-2021-25292
+CVE-2021-27921
+CVE-2021-27922
+CVE-2021-27923
+CVE-2021-28677
+CVE-2021-28678
+
+Based on the following commits:
+86f02f7c70862a0954bfe8133736d352db978eaa
+3bce145966374dd39ce58a6fc0083f8d1890719c
+480f6819b592d7f07b9a9a52a7656c10bbe07442
+5a5e6db0abf4e7a638fb1b3408c4e495a096cb92
+496245aa4365d0827390bd0b6fbd11287453b3a1
+
+--- pillow-5.4.1.orig/src/PIL/BlpImagePlugin.py
++++ pillow-5.4.1/src/PIL/BlpImagePlugin.py
+@@ -294,33 +294,36 @@ class _BLPBaseDecoder(ImageFile.PyDecode
+             raise IOError("Truncated Blp file")
+         return 0, 0
+ 
++    def _safe_read(self, length):
++        return ImageFile._safe_read(self.fd, length)
++
+     def _read_palette(self):
+         ret = []
+         for i in range(256):
+             try:
+-                b, g, r, a = struct.unpack("<4B", self.fd.read(4))
++                b, g, r, a = struct.unpack("<4B", self._safe_read(4))
+             except struct.error:
+                 break
+             ret.append((b, g, r, a))
+         return ret
+ 
+     def _read_blp_header(self):
+-        self._blp_compression, = struct.unpack("<i", self.fd.read(4))
++        (self._blp_compression,) = struct.unpack("<i", self._safe_read(4))
+ 
+-        self._blp_encoding, = struct.unpack("<b", self.fd.read(1))
+-        self._blp_alpha_depth, = struct.unpack("<b", self.fd.read(1))
+-        self._blp_alpha_encoding, = struct.unpack("<b", self.fd.read(1))
+-        self._blp_mips, = struct.unpack("<b", self.fd.read(1))
++        (self._blp_encoding,) = struct.unpack("<b", self._safe_read(1))
++        (self._blp_alpha_depth,) = struct.unpack("<b", self._safe_read(1))
++        (self._blp_alpha_encoding,) = struct.unpack("<b", self._safe_read(1))
++        (self._blp_mips,) = struct.unpack("<b", self._safe_read(1))
+ 
+-        self.size = struct.unpack("<II", self.fd.read(8))
++        self.size = struct.unpack("<II", self._safe_read(8))
+ 
+         if self.magic == b"BLP1":
+             # Only present for BLP1
+-            self._blp_encoding, = struct.unpack("<i", self.fd.read(4))
+-            self._blp_subtype, = struct.unpack("<i", self.fd.read(4))
++            (self._blp_encoding,) = struct.unpack("<i", self._safe_read(4))
++            (self._blp_subtype,) = struct.unpack("<i", self._safe_read(4))
+ 
+-        self._blp_offsets = struct.unpack("<16I", self.fd.read(16 * 4))
+-        self._blp_lengths = struct.unpack("<16I", self.fd.read(16 * 4))
++        self._blp_offsets = struct.unpack("<16I", self._safe_read(16 * 4))
++        self._blp_lengths = struct.unpack("<16I", self._safe_read(16 * 4))
+ 
+ 
+ class BLP1Decoder(_BLPBaseDecoder):
+@@ -333,7 +336,7 @@ class BLP1Decoder(_BLPBaseDecoder):
+             if self._blp_encoding in (4, 5):
+                 data = bytearray()
+                 palette = self._read_palette()
+-                _data = BytesIO(self.fd.read(self._blp_lengths[0]))
++                _data = BytesIO(self._safe_read(self._blp_lengths[0]))
+                 while True:
+                     try:
+                         offset, = struct.unpack("<B", _data.read(1))
+@@ -355,13 +358,14 @@ class BLP1Decoder(_BLPBaseDecoder):
+     def _decode_jpeg_stream(self):
+         from PIL.JpegImagePlugin import JpegImageFile
+ 
+-        jpeg_header_size, = struct.unpack("<I", self.fd.read(4))
+-        jpeg_header = self.fd.read(jpeg_header_size)
+-        self.fd.read(self._blp_offsets[0] - self.fd.tell())  # What IS this?
+-        data = self.fd.read(self._blp_lengths[0])
++        (jpeg_header_size,) = struct.unpack("<I", self._safe_read(4))
++        jpeg_header = self._safe_read(jpeg_header_size)
++        self._safe_read(self._blp_offsets[0] - self.fd.tell())  # What IS this?
++        data = self._safe_read(self._blp_lengths[0])
+         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
+@@ -379,7 +383,7 @@ class BLP2Decoder(_BLPBaseDecoder):
+             # Uncompressed or DirectX compression
+ 
+             if self._blp_encoding == BLP_ENCODING_UNCOMPRESSED:
+-                _data = BytesIO(self.fd.read(self._blp_lengths[0]))
++                _data = BytesIO(self._safe_read(self._blp_lengths[0]))
+                 while True:
+                     try:
+                         offset, = struct.unpack("<B", _data.read(1))
+@@ -393,7 +397,7 @@ class BLP2Decoder(_BLPBaseDecoder):
+                     linesize = (self.size[0] + 3) // 4 * 8
+                     for yb in range((self.size[1] + 3) // 4):
+                         for d in decode_dxt1(
+-                            self.fd.read(linesize),
++                            self._safe_read(linesize),
+                             alpha=bool(self._blp_alpha_depth)
+                         ):
+                             data += d
+@@ -401,13 +405,13 @@ class BLP2Decoder(_BLPBaseDecoder):
+                 elif self._blp_alpha_encoding == BLP_ALPHA_ENCODING_DXT3:
+                     linesize = (self.size[0] + 3) // 4 * 16
+                     for yb in range((self.size[1] + 3) // 4):
+-                        for d in decode_dxt3(self.fd.read(linesize)):
++                        for d in decode_dxt3(self._safe_read(linesize)):
+                             data += d
+ 
+                 elif self._blp_alpha_encoding == BLP_ALPHA_ENCODING_DXT5:
+                     linesize = (self.size[0] + 3) // 4 * 16
+                     for yb in range((self.size[1] + 3) // 4):
+-                        for d in decode_dxt5(self.fd.read(linesize)):
++                        for d in decode_dxt5(self._safe_read(linesize)):
+                             data += d
+                 else:
+                     raise BLPFormatError("Unsupported alpha encoding %r" % (
+--- pillow-5.4.1.orig/src/PIL/EpsImagePlugin.py
++++ pillow-5.4.1/src/PIL/EpsImagePlugin.py
+@@ -172,12 +172,12 @@ class PSFile(object):
+         self.fp.seek(offset, whence)
+ 
+     def readline(self):
+-        s = self.char or b""
++        s = [self.char or b""]
+         self.char = None
+ 
+         c = self.fp.read(1)
+-        while c not in b"\r\n":
+-            s = s + c
++        while (c not in b"\r\n") and len(c):
++            s.append(c)
+             c = self.fp.read(1)
+ 
+         self.char = self.fp.read(1)
+@@ -185,7 +185,7 @@ class PSFile(object):
+         if self.char in b"\r\n":
+             self.char = None
+ 
+-        return s.decode('latin-1')
++        return b"".join(s).decode("latin-1")
+ 
+ 
+ def _accept(prefix):
+--- pillow-5.4.1.orig/src/PIL/IcnsImagePlugin.py
++++ pillow-5.4.1/src/PIL/IcnsImagePlugin.py
+@@ -110,6 +110,7 @@ def read_png_or_jpeg2000(fobj, start_len
+     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_len
+         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}
+--- pillow-5.4.1.orig/src/PIL/IcoImagePlugin.py
++++ pillow-5.4.1/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)
+--- pillow-5.4.1.orig/src/PIL/PdfParser.py
++++ pillow-5.4.1/src/PIL/PdfParser.py
+@@ -616,8 +616,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]+)" +
+--- pillow-5.4.1.orig/src/libImaging/TiffDecode.c
++++ pillow-5.4.1/src/libImaging/TiffDecode.c
+@@ -36,6 +36,10 @@ tsize_t _tiffReadProc(thandle_t hdata, t
+     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));
+ 
diff -Nru pillow-5.4.1/debian/patches/CVE-2021-34552.patch pillow-5.4.1/debian/patches/CVE-2021-34552.patch
--- pillow-5.4.1/debian/patches/CVE-2021-34552.patch	1970-01-01 01:00:00.000000000 +0100
+++ pillow-5.4.1/debian/patches/CVE-2021-34552.patch	2021-07-20 07:18:42.000000000 +0100
@@ -0,0 +1,40 @@
+From 5f4504bb03f4edeeef8c2633dc5ba03a4c2a8a97 Mon Sep 17 00:00:00 2001
+From: Andrew Murray <radarhere@users.noreply.github.com>
+Date: Tue, 15 Jun 2021 15:14:26 +1000
+Subject: [PATCH 1/2] Limit sprintf modes to 10 characters
+
+From 518ee3722a99d7f7d890db82a20bd81c1c0327fb Mon Sep 17 00:00:00 2001
+From: Andrew Murray <radarhere@users.noreply.github.com>
+Date: Wed, 30 Jun 2021 23:47:10 +1000
+Subject: [PATCH 2/2] Use snprintf instead of sprintf
+
+* https://github.com/python-pillow/Pillow/pull/5567/files
+* Replace sprintf with snprintf in src/libImaging/Convert.c
+
+---
+--- a/src/libImaging/Convert.c
++++ b/src/libImaging/Convert.c
+@@ -1337,9 +1337,8 @@
+         return (Imaging) ImagingError_ValueError("conversion not supported");
+ #else
+     {
+-      static char buf[256];
+-      /* FIXME: may overflow if mode is too large */
+-      sprintf(buf, "conversion from %s to %s not supported", imIn->mode, mode);
++      static char buf[100];
++      snprintf(buf, 100, "conversion from %.10s to %.10s not supported", imIn->mode, mode);
+       return (Imaging) ImagingError_ValueError(buf);
+     }
+ #endif
+@@ -1393,9 +1392,8 @@
+     }
+ #else
+     {
+-      static char buf[256];
+-      /* FIXME: may overflow if mode is too large */
+-      sprintf(buf, "conversion from %s to %s not supported in convert_transparent", imIn->mode, mode);
++      static char buf[100];
++      snprintf(buf, 100, "conversion from %.10s to %.10s not supported in convert_transparent", imIn->mode, mode);
+       return (Imaging) ImagingError_ValueError(buf);
+     }
+ #endif
diff -Nru pillow-5.4.1/debian/patches/series pillow-5.4.1/debian/patches/series
--- pillow-5.4.1/debian/patches/series	2020-07-22 16:22:53.000000000 +0100
+++ pillow-5.4.1/debian/patches/series	2021-07-20 07:21:31.000000000 +0100
@@ -10,3 +10,7 @@
 CVE-2020-10177.patch
 CVE-2020-10378.patch
 CVE-2020-11538.patch
+CVE-2020-35653.patch
+CVE-2020-35655.patch
+CVE-2021-27921_CVE-2021-27922_CVE-2021-27923_CVE-2021-25290_CVE-2021-25292_CVE-2021-28677_CVE-2021-28678.patch
+CVE-2021-34552.patch

Reply to: