summaryrefslogtreecommitdiff
path: root/gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch')
-rw-r--r--gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch319
1 files changed, 319 insertions, 0 deletions
diff --git a/gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch b/gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch
new file mode 100644
index 0000000000..f77dca2cd6
--- /dev/null
+++ b/gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch
@@ -0,0 +1,319 @@
+Fix CVE-2016-{9634,9635,9636}.
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9634
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9635
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9636
+
+This fixes upstream bug #774834 (flic decoder: Buffer overflow in
+flx_decode_delta_fli):
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774834
+
+Patch copied from upstream source repository:
+
+https://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=2e203a79b7d9af4029307c1a845b3c148d5f5e62
+
+From 2e203a79b7d9af4029307c1a845b3c148d5f5e62 Mon Sep 17 00:00:00 2001
+From: Matthew Waters <matthew@centricular.com>
+Date: Tue, 22 Nov 2016 19:05:00 +1100
+Subject: [PATCH] flxdec: add some write bounds checking
+
+Without checking the bounds of the frame we are writing into, we can
+write off the end of the destination buffer.
+
+https://scarybeastsecurity.blogspot.dk/2016/11/0day-exploit-advancing-exploitation.html
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774834
+---
+ gst/flx/gstflxdec.c | 116 +++++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 91 insertions(+), 25 deletions(-)
+
+diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
+index 604be2f..d51a8e6 100644
+--- a/gst/flx/gstflxdec.c
++++ b/gst/flx/gstflxdec.c
+@@ -74,9 +74,9 @@ static gboolean gst_flxdec_src_query_handler (GstPad * pad, GstObject * parent,
+ GstQuery * query);
+
+ static void flx_decode_color (GstFlxDec *, guchar *, guchar *, gint);
+-static void flx_decode_brun (GstFlxDec *, guchar *, guchar *);
+-static void flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
+-static void flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
++static gboolean flx_decode_brun (GstFlxDec *, guchar *, guchar *);
++static gboolean flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
++static gboolean flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
+
+ #define rndalign(off) ((off) + ((off) & 1))
+
+@@ -203,13 +203,14 @@ gst_flxdec_sink_event_handler (GstPad * pad, GstObject * parent,
+ return ret;
+ }
+
+-static void
++static gboolean
+ flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+ guchar * dest)
+ {
+ FlxFrameChunk *hdr;
++ gboolean ret = TRUE;
+
+- g_return_if_fail (data != NULL);
++ g_return_val_if_fail (data != NULL, FALSE);
+
+ while (count--) {
+ hdr = (FlxFrameChunk *) data;
+@@ -228,17 +229,17 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+ break;
+
+ case FLX_BRUN:
+- flx_decode_brun (flxdec, data, dest);
++ ret = flx_decode_brun (flxdec, data, dest);
+ data += rndalign (hdr->size) - FlxFrameChunkSize;
+ break;
+
+ case FLX_LC:
+- flx_decode_delta_fli (flxdec, data, dest);
++ ret = flx_decode_delta_fli (flxdec, data, dest);
+ data += rndalign (hdr->size) - FlxFrameChunkSize;
+ break;
+
+ case FLX_SS2:
+- flx_decode_delta_flc (flxdec, data, dest);
++ ret = flx_decode_delta_flc (flxdec, data, dest);
+ data += rndalign (hdr->size) - FlxFrameChunkSize;
+ break;
+
+@@ -256,7 +257,12 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+ data += rndalign (hdr->size) - FlxFrameChunkSize;
+ break;
+ }
++
++ if (!ret)
++ break;
+ }
++
++ return ret;
+ }
+
+
+@@ -289,13 +295,13 @@ flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale)
+ }
+ }
+
+-static void
++static gboolean
+ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ {
+ gulong count, lines, row;
+ guchar x;
+
+- g_return_if_fail (flxdec != NULL);
++ g_return_val_if_fail (flxdec != NULL, FALSE);
+
+ lines = flxdec->hdr.height;
+ while (lines--) {
+@@ -313,12 +319,21 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ if (count > 0x7f) {
+ /* literal run */
+ count = 0x100 - count;
++ if ((glong) row - count < 0) {
++ GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
++ return FALSE;
++ }
+ row -= count;
+
+ while (count--)
+ *dest++ = *data++;
+
+ } else {
++ if ((glong) row - count < 0) {
++ GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
++ return FALSE;
++ }
++
+ /* replicate run */
+ row -= count;
+ x = *data++;
+@@ -328,22 +343,28 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ }
+ }
+ }
++
++ return TRUE;
+ }
+
+-static void
++static gboolean
+ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ {
+ gulong count, packets, lines, start_line;
+ guchar *start_p, x;
+
+- g_return_if_fail (flxdec != NULL);
+- g_return_if_fail (flxdec->delta_data != NULL);
++ g_return_val_if_fail (flxdec != NULL, FALSE);
++ g_return_val_if_fail (flxdec->delta_data != NULL, FALSE);
+
+ /* use last frame for delta */
+ memcpy (dest, flxdec->delta_data, flxdec->size);
+
+ start_line = (data[0] + (data[1] << 8));
+ lines = (data[2] + (data[3] << 8));
++ if (start_line + lines > flxdec->hdr.height) {
++ GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. too many lines.");
++ return FALSE;
++ }
+ data += 4;
+
+ /* start position of delta */
+@@ -356,7 +377,8 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+
+ while (packets--) {
+ /* skip count */
+- dest += *data++;
++ guchar skip = *data++;
++ dest += skip;
+
+ /* RLE count */
+ count = *data++;
+@@ -364,12 +386,24 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ if (count > 0x7f) {
+ /* literal run */
+ count = 0x100 - count;
+- x = *data++;
+
++ if (skip + count > flxdec->hdr.width) {
++ GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
++ "line too long.");
++ return FALSE;
++ }
++
++ x = *data++;
+ while (count--)
+ *dest++ = x;
+
+ } else {
++ if (skip + count > flxdec->hdr.width) {
++ GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
++ "line too long.");
++ return FALSE;
++ }
++
+ /* replicate run */
+ while (count--)
+ *dest++ = *data++;
+@@ -378,21 +412,27 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ start_p += flxdec->hdr.width;
+ dest = start_p;
+ }
++
++ return TRUE;
+ }
+
+-static void
++static gboolean
+ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ {
+ gulong count, lines, start_l, opcode;
+ guchar *start_p;
+
+- g_return_if_fail (flxdec != NULL);
+- g_return_if_fail (flxdec->delta_data != NULL);
++ g_return_val_if_fail (flxdec != NULL, FALSE);
++ g_return_val_if_fail (flxdec->delta_data != NULL, FALSE);
+
+ /* use last frame for delta */
+ memcpy (dest, flxdec->delta_data, flxdec->size);
+
+ lines = (data[0] + (data[1] << 8));
++ if (lines > flxdec->hdr.height) {
++ GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. too many lines.");
++ return FALSE;
++ }
+ data += 2;
+
+ start_p = dest;
+@@ -405,9 +445,15 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ while ((opcode = (data[0] + (data[1] << 8))) & 0xc000) {
+ data += 2;
+ if ((opcode & 0xc000) == 0xc000) {
+- /* skip count */
+- start_l += (0x10000 - opcode);
+- dest += flxdec->hdr.width * (0x10000 - opcode);
++ /* line skip count */
++ gulong skip = (0x10000 - opcode);
++ if (skip > flxdec->hdr.height) {
++ GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
++ "skip line count too big.");
++ return FALSE;
++ }
++ start_l += skip;
++ dest += flxdec->hdr.width * skip;
+ } else {
+ /* last pixel */
+ dest += flxdec->hdr.width;
+@@ -419,7 +465,8 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ /* last opcode is the packet count */
+ while (opcode--) {
+ /* skip count */
+- dest += *data++;
++ guchar skip = *data++;
++ dest += skip;
+
+ /* RLE count */
+ count = *data++;
+@@ -427,12 +474,25 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ if (count > 0x7f) {
+ /* replicate word run */
+ count = 0x100 - count;
++
++ if (skip + count > flxdec->hdr.width) {
++ GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
++ "line too long.");
++ return FALSE;
++ }
++
+ while (count--) {
+ *dest++ = data[0];
+ *dest++ = data[1];
+ }
+ data += 2;
+ } else {
++ if (skip + count > flxdec->hdr.width) {
++ GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
++ "line too long.");
++ return FALSE;
++ }
++
+ /* literal word run */
+ while (count--) {
+ *dest++ = *data++;
+@@ -442,6 +502,8 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ }
+ lines--;
+ }
++
++ return TRUE;
+ }
+
+ static GstFlowReturn
+@@ -571,9 +633,13 @@ gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+ out = gst_buffer_new_and_alloc (flxdec->size * 4);
+
+ /* decode chunks */
+- flx_decode_chunks (flxdec,
+- ((FlxFrameType *) chunk)->chunks,
+- chunk + FlxFrameTypeSize, flxdec->frame_data);
++ if (!flx_decode_chunks (flxdec,
++ ((FlxFrameType *) chunk)->chunks,
++ chunk + FlxFrameTypeSize, flxdec->frame_data)) {
++ GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++ ("%s", "Could not decode chunk"), NULL);
++ return GST_FLOW_ERROR;
++ }
+
+ /* save copy of the current frame for possible delta. */
+ memcpy (flxdec->delta_data, flxdec->frame_data, flxdec->size);
+--
+2.10.2
+