summaryrefslogtreecommitdiffstats
path: root/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/CVE-2022-1922-1923-1924-1925.patch
blob: ebffbc473d7328f114f65e088e98d8362ca22f12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
From ad6012159acf18c6b5c0f4edf037e8c9a2dbc966 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Wed, 18 May 2022 11:24:37 +0300
Subject: [PATCH] matroskademux: Fix integer overflows in zlib/bz2/etc
 decompression code

Various variables were of smaller types than needed and there were no
checks for any overflows when doing additions on the sizes. This is all
checked now.

In addition the size of the decompressed data is limited to 120MB now as
any larger sizes are likely pathological and we can avoid out of memory
situations in many cases like this.

Also fix a bug where the available output size on the next iteration in
the zlib/bz2 decompression code was provided too large and could
potentially lead to out of bound writes.

Thanks to Adam Doupe for analyzing and reporting the issue.

CVE: CVE-2022-1922, CVE-2022-1923, CVE-2022-1924, CVE-2022-1925

https://gstreamer.freedesktop.org/security/sa-2022-0002.html

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1225

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2610>

CVE: CVE-2022-1922 CVE-2022-1923 CVE-2022-1924 CVE-2022-1925
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/ad6012159acf18c6b5c0f4edf037e8c9a2dbc966
Upstream-Status: Backport
Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
---
 .../gst/matroska/matroska-read-common.c       | 76 +++++++++++++++----
 1 file changed, 61 insertions(+), 15 deletions(-)

diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c
index eb317644cc5..6fadbba9567 100644
--- a/gst/matroska/matroska-read-common.c
+++ b/gst/matroska/matroska-read-common.c
@@ -70,6 +70,10 @@ typedef struct
   gboolean audio_only;
 } TargetTypeContext;
 
+/* 120MB as maximum decompressed data size. Anything bigger is likely
+ * pathological, and like this we avoid out of memory situations in many cases
+ */
+#define MAX_DECOMPRESS_SIZE (120 * 1024 * 1024)
 
 static gboolean
 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
@@ -77,19 +81,23 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
     GstMatroskaTrackCompressionAlgorithm algo)
 {
   guint8 *new_data = NULL;
-  guint new_size = 0;
+  gsize new_size = 0;
   guint8 *data = *data_out;
-  guint size = *size_out;
+  const gsize size = *size_out;
   gboolean ret = TRUE;
 
+  if (size > G_MAXUINT32) {
+    GST_WARNING ("too large compressed data buffer.");
+    ret = FALSE;
+    goto out;
+  }
+
   if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
 #ifdef HAVE_ZLIB
     /* zlib encoded data */
     z_stream zstream;
-    guint orig_size;
     int result;
 
-    orig_size = size;
     zstream.zalloc = (alloc_func) 0;
     zstream.zfree = (free_func) 0;
     zstream.opaque = (voidpf) 0;
@@ -99,8 +107,8 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
       goto out;
     }
     zstream.next_in = (Bytef *) data;
-    zstream.avail_in = orig_size;
-    new_size = orig_size;
+    zstream.avail_in = size;
+    new_size = size;
     new_data = g_malloc (new_size);
     zstream.avail_out = new_size;
     zstream.next_out = (Bytef *) new_data;
@@ -114,10 +122,18 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
         break;
       }
 
+      if (new_size > G_MAXSIZE - 4096 || new_size + 4096 > MAX_DECOMPRESS_SIZE) {
+        GST_WARNING ("too big decompressed data");
+        result = Z_MEM_ERROR;
+        break;
+      }
+
       new_size += 4096;
       new_data = g_realloc (new_data, new_size);
       zstream.next_out = (Bytef *) (new_data + zstream.total_out);
-      zstream.avail_out += 4096;
+      /* avail_out is an unsigned int */
+      g_assert (new_size - zstream.total_out <= G_MAXUINT);
+      zstream.avail_out = new_size - zstream.total_out;
     } while (zstream.avail_in > 0);
 
     if (result != Z_STREAM_END) {
@@ -137,13 +153,11 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
 #ifdef HAVE_BZ2
     /* bzip2 encoded data */
     bz_stream bzstream;
-    guint orig_size;
     int result;
 
     bzstream.bzalloc = NULL;
     bzstream.bzfree = NULL;
     bzstream.opaque = NULL;
-    orig_size = size;
 
     if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
       GST_WARNING ("bzip2 initialization failed.");
@@ -152,8 +166,8 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
     }
 
     bzstream.next_in = (char *) data;
-    bzstream.avail_in = orig_size;
-    new_size = orig_size;
+    bzstream.avail_in = size;
+    new_size = size;
     new_data = g_malloc (new_size);
     bzstream.avail_out = new_size;
     bzstream.next_out = (char *) new_data;
@@ -167,17 +181,31 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
         break;
       }
 
+      if (new_size > G_MAXSIZE - 4096 || new_size + 4096 > MAX_DECOMPRESS_SIZE) {
+        GST_WARNING ("too big decompressed data");
+        result = BZ_MEM_ERROR;
+        break;
+      }
+
       new_size += 4096;
       new_data = g_realloc (new_data, new_size);
-      bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
-      bzstream.avail_out += 4096;
+      bzstream.next_out =
+          (char *) (new_data + ((guint64) bzstream.total_out_hi32 << 32) +
+          bzstream.total_out_lo32);
+      /* avail_out is an unsigned int */
+      g_assert (new_size - ((guint64) bzstream.total_out_hi32 << 32) +
+          bzstream.total_out_lo32 <= G_MAXUINT);
+      bzstream.avail_out =
+          new_size - ((guint64) bzstream.total_out_hi32 << 32) +
+          bzstream.total_out_lo32;
     } while (bzstream.avail_in > 0);
 
     if (result != BZ_STREAM_END) {
       ret = FALSE;
       g_free (new_data);
     } else {
-      new_size = bzstream.total_out_lo32;
+      new_size =
+          ((guint64) bzstream.total_out_hi32 << 32) + bzstream.total_out_lo32;
     }
     BZ2_bzDecompressEnd (&bzstream);
 
@@ -189,7 +217,13 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
     /* lzo encoded data */
     int result;
-    int orig_size, out_size;
+    gint orig_size, out_size;
+
+    if (size > G_MAXINT) {
+      GST_WARNING ("too large compressed data buffer.");
+      ret = FALSE;
+      goto out;
+    }
 
     orig_size = size;
     out_size = size;
@@ -203,6 +237,11 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
       result = lzo1x_decode (new_data, &out_size, data, &orig_size);
 
       if (orig_size > 0) {
+        if (new_size > G_MAXINT - 4096 || new_size + 4096 > MAX_DECOMPRESS_SIZE) {
+          GST_WARNING ("too big decompressed data");
+          result = LZO_ERROR;
+          break;
+        }
         new_size += 4096;
         new_data = g_realloc (new_data, new_size);
       }
@@ -221,6 +260,13 @@ gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
     /* header stripped encoded data */
     if (enc->comp_settings_length > 0) {
+      if (size > G_MAXSIZE - enc->comp_settings_length
+          || size + enc->comp_settings_length > MAX_DECOMPRESS_SIZE) {
+        GST_WARNING ("too big decompressed data");
+        ret = FALSE;
+        goto out;
+      }
+
       new_data = g_malloc (size + enc->comp_settings_length);
       new_size = size + enc->comp_settings_length;
 
-- 
GitLab