Blame SOURCES/0002-matroskademux-Fix-integer-overflows-in-zlib-bz2-etc-.patch

27715b
From 22eb3dc56d8cb71af2c2d413ae587cc401704780 Mon Sep 17 00:00:00 2001
27715b
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
27715b
Date: Wed, 18 May 2022 11:24:37 +0300
27715b
Subject: [PATCH 2/4] matroskademux: Fix integer overflows in zlib/bz2/etc
27715b
 decompression code
27715b
27715b
Various variables were of smaller types than needed and there were no
27715b
checks for any overflows when doing additions on the sizes. This is all
27715b
checked now.
27715b
27715b
In addition the size of the decompressed data is limited to 120MB now as
27715b
any larger sizes are likely pathological and we can avoid out of memory
27715b
situations in many cases like this.
27715b
27715b
Also fix a bug where the available output size on the next iteration in
27715b
the zlib/bz2 decompression code was provided too large and could
27715b
potentially lead to out of bound writes.
27715b
27715b
Thanks to Adam Doupe for analyzing and reporting the issue.
27715b
27715b
CVE: CVE-2022-1922, CVE-2022-1923, CVE-2022-1924, CVE-2022-1925
27715b
27715b
https://gstreamer.freedesktop.org/security/sa-2022-0002.html
27715b
27715b
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1225
27715b
27715b
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2610>
27715b
---
27715b
 gst/matroska/matroska-read-common.c | 76 +++++++++++++++++++++++------
27715b
 1 file changed, 61 insertions(+), 15 deletions(-)
27715b
27715b
diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c
27715b
index 90d6e38e17..0ee9a787a4 100644
27715b
--- a/gst/matroska/matroska-read-common.c
27715b
+++ b/gst/matroska/matroska-read-common.c
27715b
@@ -70,6 +70,10 @@ typedef struct
27715b
   gboolean audio_only;
27715b
 } TargetTypeContext;
27715b
 
27715b
+/* 120MB as maximum decompressed data size. Anything bigger is likely
27715b
+ * pathological, and like this we avoid out of memory situations in many cases
27715b
+ */
27715b
+#define MAX_DECOMPRESS_SIZE (120 * 1024 * 1024)
27715b
 
27715b
 static gboolean
27715b
 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
@@ -77,19 +81,23 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
     GstMatroskaTrackCompressionAlgorithm algo)
27715b
 {
27715b
   guint8 *new_data = NULL;
27715b
-  guint new_size = 0;
27715b
+  gsize new_size = 0;
27715b
   guint8 *data = *data_out;
27715b
-  guint size = *size_out;
27715b
+  const gsize size = *size_out;
27715b
   gboolean ret = TRUE;
27715b
 
27715b
+  if (size > G_MAXUINT32) {
27715b
+    GST_WARNING ("too large compressed data buffer.");
27715b
+    ret = FALSE;
27715b
+    goto out;
27715b
+  }
27715b
+
27715b
   if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
27715b
 #ifdef HAVE_ZLIB
27715b
     /* zlib encoded data */
27715b
     z_stream zstream;
27715b
-    guint orig_size;
27715b
     int result;
27715b
 
27715b
-    orig_size = size;
27715b
     zstream.zalloc = (alloc_func) 0;
27715b
     zstream.zfree = (free_func) 0;
27715b
     zstream.opaque = (voidpf) 0;
27715b
@@ -99,8 +107,8 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
       goto out;
27715b
     }
27715b
     zstream.next_in = (Bytef *) data;
27715b
-    zstream.avail_in = orig_size;
27715b
-    new_size = orig_size;
27715b
+    zstream.avail_in = size;
27715b
+    new_size = size;
27715b
     new_data = g_malloc (new_size);
27715b
     zstream.avail_out = new_size;
27715b
     zstream.next_out = (Bytef *) new_data;
27715b
@@ -114,10 +122,18 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
         break;
27715b
       }
27715b
 
27715b
+      if (new_size > G_MAXSIZE - 4096 || new_size + 4096 > MAX_DECOMPRESS_SIZE) {
27715b
+        GST_WARNING ("too big decompressed data");
27715b
+        result = Z_MEM_ERROR;
27715b
+        break;
27715b
+      }
27715b
+
27715b
       new_size += 4096;
27715b
       new_data = g_realloc (new_data, new_size);
27715b
       zstream.next_out = (Bytef *) (new_data + zstream.total_out);
27715b
-      zstream.avail_out += 4096;
27715b
+      /* avail_out is an unsigned int */
27715b
+      g_assert (new_size - zstream.total_out <= G_MAXUINT);
27715b
+      zstream.avail_out = new_size - zstream.total_out;
27715b
     } while (zstream.avail_in > 0);
27715b
 
27715b
     if (result != Z_STREAM_END) {
27715b
@@ -137,13 +153,11 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
 #ifdef HAVE_BZ2
27715b
     /* bzip2 encoded data */
27715b
     bz_stream bzstream;
27715b
-    guint orig_size;
27715b
     int result;
27715b
 
27715b
     bzstream.bzalloc = NULL;
27715b
     bzstream.bzfree = NULL;
27715b
     bzstream.opaque = NULL;
27715b
-    orig_size = size;
27715b
 
27715b
     if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
27715b
       GST_WARNING ("bzip2 initialization failed.");
27715b
@@ -152,8 +166,8 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
     }
27715b
 
27715b
     bzstream.next_in = (char *) data;
27715b
-    bzstream.avail_in = orig_size;
27715b
-    new_size = orig_size;
27715b
+    bzstream.avail_in = size;
27715b
+    new_size = size;
27715b
     new_data = g_malloc (new_size);
27715b
     bzstream.avail_out = new_size;
27715b
     bzstream.next_out = (char *) new_data;
27715b
@@ -167,17 +181,31 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
         break;
27715b
       }
27715b
 
27715b
+      if (new_size > G_MAXSIZE - 4096 || new_size + 4096 > MAX_DECOMPRESS_SIZE) {
27715b
+        GST_WARNING ("too big decompressed data");
27715b
+        result = BZ_MEM_ERROR;
27715b
+        break;
27715b
+      }
27715b
+
27715b
       new_size += 4096;
27715b
       new_data = g_realloc (new_data, new_size);
27715b
-      bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
27715b
-      bzstream.avail_out += 4096;
27715b
+      bzstream.next_out =
27715b
+          (char *) (new_data + ((guint64) bzstream.total_out_hi32 << 32) +
27715b
+          bzstream.total_out_lo32);
27715b
+      /* avail_out is an unsigned int */
27715b
+      g_assert (new_size - ((guint64) bzstream.total_out_hi32 << 32) +
27715b
+          bzstream.total_out_lo32 <= G_MAXUINT);
27715b
+      bzstream.avail_out =
27715b
+          new_size - ((guint64) bzstream.total_out_hi32 << 32) +
27715b
+          bzstream.total_out_lo32;
27715b
     } while (bzstream.avail_in > 0);
27715b
 
27715b
     if (result != BZ_STREAM_END) {
27715b
       ret = FALSE;
27715b
       g_free (new_data);
27715b
     } else {
27715b
-      new_size = bzstream.total_out_lo32;
27715b
+      new_size =
27715b
+          ((guint64) bzstream.total_out_hi32 << 32) + bzstream.total_out_lo32;
27715b
     }
27715b
     BZ2_bzDecompressEnd (&bzstream);
27715b
 
27715b
@@ -189,7 +217,13 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
27715b
     /* lzo encoded data */
27715b
     int result;
27715b
-    int orig_size, out_size;
27715b
+    gint orig_size, out_size;
27715b
+
27715b
+    if (size > G_MAXINT) {
27715b
+      GST_WARNING ("too large compressed data buffer.");
27715b
+      ret = FALSE;
27715b
+      goto out;
27715b
+    }
27715b
 
27715b
     orig_size = size;
27715b
     out_size = size;
27715b
@@ -203,6 +237,11 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
       result = lzo1x_decode (new_data, &out_size, data, &orig_size);
27715b
 
27715b
       if (orig_size > 0) {
27715b
+        if (new_size > G_MAXINT - 4096 || new_size + 4096 > MAX_DECOMPRESS_SIZE) {
27715b
+          GST_WARNING ("too big decompressed data");
27715b
+          result = LZO_ERROR;
27715b
+          break;
27715b
+        }
27715b
         new_size += 4096;
27715b
         new_data = g_realloc (new_data, new_size);
27715b
       }
27715b
@@ -221,6 +260,13 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
27715b
   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
27715b
     /* header stripped encoded data */
27715b
     if (enc->comp_settings_length > 0) {
27715b
+      if (size > G_MAXSIZE - enc->comp_settings_length
27715b
+          || size + enc->comp_settings_length > MAX_DECOMPRESS_SIZE) {
27715b
+        GST_WARNING ("too big decompressed data");
27715b
+        ret = FALSE;
27715b
+        goto out;
27715b
+      }
27715b
+
27715b
       new_data = g_malloc (size + enc->comp_settings_length);
27715b
       new_size = size + enc->comp_settings_length;
27715b
 
27715b
-- 
27715b
2.38.1
27715b