gnu: gst-plugins-good: Fix CVE-2016-{9634,9635,9636} and other security issues.

* gnu/packages/patches/gst-plugins-good-fix-crashes.patch,
gnu/packages/patches/gst-plugins-good-fix-invalid-read.patch,
gnu/packages/patches/gst-plugins-good-fix-signedness.patch,
gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch: New files.
* gnu/local.mk (dist_patch_DATA): Add them.
* gnu/packages/gstreamer.scm (gst-plugins-good): Use them.
master
Leo Famulari 2016-11-25 01:47:14 -05:00
parent 5305ed2002
commit 9e46245b89
No known key found for this signature in database
GPG Key ID: 2646FA30BACA7F08
6 changed files with 1470 additions and 0 deletions

View File

@ -585,6 +585,10 @@ dist_patch_DATA = \
%D%/packages/patches/grub-gets-undeclared.patch \
%D%/packages/patches/grub-freetype.patch \
%D%/packages/patches/gsl-test-i686.patch \
%D%/packages/patches/gst-plugins-good-fix-crashes.patch \
%D%/packages/patches/gst-plugins-good-fix-invalid-read.patch \
%D%/packages/patches/gst-plugins-good-fix-signedness.patch \
%D%/packages/patches/gst-plugins-good-flic-bounds-check.patch \
%D%/packages/patches/guile-1.8-cpp-4.5.patch \
%D%/packages/patches/guile-arm-fixes.patch \
%D%/packages/patches/guile-default-utf8.patch \

View File

@ -4,6 +4,7 @@
;;; Copyright © 2015, 2016 Sou Bunnbu <iyzsong@gmail.com>
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
;;;
;;; This file is part of GNU Guix.
;;;
@ -207,6 +208,10 @@ for the GStreamer multimedia library.")
(uri (string-append
"https://gstreamer.freedesktop.org/src/" name "/"
name "-" version ".tar.xz"))
(patches (search-patches "gst-plugins-good-flic-bounds-check.patch"
"gst-plugins-good-fix-signedness.patch"
"gst-plugins-good-fix-invalid-read.patch"
"gst-plugins-good-fix-crashes.patch"))
(sha256
(base32
"1hkcap9l2603266gyi6jgvx7frbvfmb7xhfhjizbczy1wykjwr57"))))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
Fixes upstream bug #774897 (flxdec: Unreferences itself one time too many on
invalid files):
https://bugzilla.gnome.org/show_bug.cgi?id=774897
Patch copied from upstream source repository:
https://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=b31c504645a814c59d91d49e4fe218acaf93f4ca
From b31c504645a814c59d91d49e4fe218acaf93f4ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Wed, 23 Nov 2016 11:20:49 +0200
Subject: [PATCH] flxdec: Don't unref() parent in the chain function
We don't own the reference here, it is owned by the caller and given to
us for the scope of this function. Leftover mistake from 0.10 porting.
https://bugzilla.gnome.org/show_bug.cgi?id=774897
---
gst/flx/gstflxdec.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
index e675c99..a237976 100644
--- a/gst/flx/gstflxdec.c
+++ b/gst/flx/gstflxdec.c
@@ -677,7 +677,6 @@ wrong_type:
{
GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
("not a flx file (type %x)", flxh->type));
- gst_object_unref (flxdec);
return GST_FLOW_ERROR;
}
}
--
2.10.2

View File

@ -0,0 +1,58 @@
This is a followup fix for upstream bug #774834 (flic decoder: Buffer overflow
in flx_decode_delta_fli):
https://bugzilla.gnome.org/show_bug.cgi?id=774834#c2
Patch copied from upstream source repository:
https://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=1ab2b26193861b124426e2f8eb62b75b59ec5488
From 1ab2b26193861b124426e2f8eb62b75b59ec5488 Mon Sep 17 00:00:00 2001
From: Matthew Waters <matthew@centricular.com>
Date: Tue, 22 Nov 2016 23:46:00 +1100
Subject: [PATCH] flxdec: fix some warnings comparing unsigned < 0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
bf43f44fcfada5ec4a3ce60cb374340486fe9fac was comparing an unsigned
expression to be < 0 which was always false.
gstflxdec.c: In function flx_decode_brun:
gstflxdec.c:322:33: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
if ((glong) row - count < 0) {
^
gstflxdec.c:332:33: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
if ((glong) row - count < 0) {
^
https://bugzilla.gnome.org/show_bug.cgi?id=774834
---
gst/flx/gstflxdec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
index d51a8e6..e675c99 100644
--- a/gst/flx/gstflxdec.c
+++ b/gst/flx/gstflxdec.c
@@ -319,7 +319,7 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
if (count > 0x7f) {
/* literal run */
count = 0x100 - count;
- if ((glong) row - count < 0) {
+ if ((glong) row - (glong) count < 0) {
GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
return FALSE;
}
@@ -329,7 +329,7 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
*dest++ = *data++;
} else {
- if ((glong) row - count < 0) {
+ if ((glong) row - (glong) count < 0) {
GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
return FALSE;
}
--
2.10.2

View File

@ -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