3 From ec66c7c584f0b41c98e93758d9b53bd6dd582df2 Mon Sep 17 00:00:00 2001
4 From: Matthew Waters <matthew@centricular.com>
5 Date: Tue, 22 Nov 2016 19:05:00 +1100
6 Subject: flxdec: add some write bounds checking
8 Without checking the bounds of the frame we are writing into, we can
9 write off the end of the destination buffer.
11 https://scarybeastsecurity.blogspot.dk/2016/11/0day-exploit-advancing-exploitation.html
13 https://bugzilla.gnome.org/show_bug.cgi?id=774834
15 Index: gst-plugins-good0.10-0.10.31/gst/flx/gstflxdec.c
16 ===================================================================
17 --- gst-plugins-good0.10-0.10.31.orig/gst/flx/gstflxdec.c 2016-11-22 08:49:30.987370013 -0500
18 +++ gst-plugins-good0.10-0.10.31/gst/flx/gstflxdec.c 2016-11-22 08:52:35.889496961 -0500
20 static gboolean gst_flxdec_sink_event_handler (GstPad * pad, GstEvent * event);
22 static void flx_decode_color (GstFlxDec *, guchar *, guchar *, gint);
23 -static void flx_decode_brun (GstFlxDec *, guchar *, guchar *);
24 -static void flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
25 -static void flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
26 +static gboolean flx_decode_brun (GstFlxDec *, guchar *, guchar *);
27 +static gboolean flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
28 +static gboolean flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
30 #define rndalign(off) ((off) + ((off) & 1))
38 flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
42 + gboolean ret = TRUE;
44 - g_return_if_fail (data != NULL);
45 + g_return_val_if_fail (data != NULL, FALSE);
48 hdr = (FlxFrameChunk *) data;
53 - flx_decode_brun (flxdec, data, dest);
54 + ret = flx_decode_brun (flxdec, data, dest);
55 data += rndalign (hdr->size) - FlxFrameChunkSize;
59 - flx_decode_delta_fli (flxdec, data, dest);
60 + ret = flx_decode_delta_fli (flxdec, data, dest);
61 data += rndalign (hdr->size) - FlxFrameChunkSize;
65 - flx_decode_delta_flc (flxdec, data, dest);
66 + ret = flx_decode_delta_flc (flxdec, data, dest);
67 data += rndalign (hdr->size) - FlxFrameChunkSize;
71 data += rndalign (hdr->size) - FlxFrameChunkSize;
89 flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
91 gulong count, lines, row;
94 - g_return_if_fail (flxdec != NULL);
95 + g_return_val_if_fail (flxdec != NULL, FALSE);
97 lines = flxdec->hdr.height;
102 count = 0x100 - count;
103 + if ((glong) row - count < 0) {
104 + GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
113 + if ((glong) row - count < 0) {
114 + GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
121 @@ -350,16 +365,18 @@
131 flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
133 gulong count, packets, lines, start_line;
136 - g_return_if_fail (flxdec != NULL);
137 - g_return_if_fail (flxdec->delta != NULL);
138 + g_return_val_if_fail (flxdec != NULL, FALSE);
139 + g_return_val_if_fail (flxdec->delta != NULL, FALSE);
141 /* use last frame for delta */
142 memcpy (dest, GST_BUFFER_DATA (flxdec->delta),
145 start_line = (data[0] + (data[1] << 8));
146 lines = (data[2] + (data[3] << 8));
147 + if (start_line + lines > flxdec->hdr.height) {
148 + GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. too many lines.");
153 /* start position of delta */
159 + guchar skip = *data++;
164 @@ -387,12 +407,24 @@
167 count = 0x100 - count;
170 + if (skip + count > flxdec->hdr.width) {
171 + GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
181 + if (skip + count > flxdec->hdr.width) {
182 + GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
190 @@ -401,22 +433,28 @@
191 start_p += flxdec->hdr.width;
200 flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
202 gulong count, lines, start_l, opcode;
205 - g_return_if_fail (flxdec != NULL);
206 - g_return_if_fail (flxdec->delta != NULL);
207 + g_return_val_if_fail (flxdec != NULL, FALSE);
208 + g_return_val_if_fail (flxdec->delta != NULL, FALSE);
210 /* use last frame for delta */
211 memcpy (dest, GST_BUFFER_DATA (flxdec->delta),
212 GST_BUFFER_SIZE (flxdec->delta));
214 lines = (data[0] + (data[1] << 8));
215 + if (lines > flxdec->hdr.height) {
216 + GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. too many lines.");
223 while ((opcode = (data[0] + (data[1] << 8))) & 0xc000) {
225 if ((opcode & 0xc000) == 0xc000) {
227 - start_l += (0x10000 - opcode);
228 - dest += flxdec->hdr.width * (0x10000 - opcode);
229 + /* line skip count */
230 + gulong skip = (0x10000 - opcode);
231 + if (skip > flxdec->hdr.height) {
232 + GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
233 + "skip line count too big.");
237 + dest += flxdec->hdr.width * skip;
240 dest += flxdec->hdr.width;
242 /* last opcode is the packet count */
246 + guchar skip = *data++;
251 @@ -451,12 +496,25 @@
253 /* replicate word run */
254 count = 0x100 - count;
256 + if (skip + count > flxdec->hdr.width) {
257 + GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
268 + if (skip + count > flxdec->hdr.width) {
269 + GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
274 /* literal word run */
290 - flx_decode_chunks (flxdec,
291 - ((FlxFrameType *) chunk)->chunks,
292 - chunk + FlxFrameTypeSize, GST_BUFFER_DATA (flxdec->frame));
293 + if (!flx_decode_chunks (flxdec,
294 + ((FlxFrameType *) chunk)->chunks,
295 + chunk + FlxFrameTypeSize, GST_BUFFER_DATA (flxdec->frame))) {
296 + GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
297 + ("%s", "Could not decode chunk"), NULL);
298 + return GST_FLOW_ERROR;
301 /* save copy of the current frame for possible delta. */
302 memcpy (GST_BUFFER_DATA (flxdec->delta),