diff --git a/SOURCES/9efd93e20dd7789e4172ad6c8f4108271b3fb1ee.patch b/SOURCES/9efd93e20dd7789e4172ad6c8f4108271b3fb1ee.patch new file mode 100644 index 0000000..52c3e9a --- /dev/null +++ b/SOURCES/9efd93e20dd7789e4172ad6c8f4108271b3fb1ee.patch @@ -0,0 +1,201 @@ +From 9efd93e20dd7789e4172ad6c8f4108271b3fb1ee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Thu, 4 Mar 2021 13:05:19 +0200 +Subject: [PATCH] matroskademux: Fix extraction of multichannel WavPack + +The old code had a couple of issues that all lead to potential memory +safety bugs. + + - Use a constant for the Wavpack4Header size instead of using sizeof. + It's written out into the data and not from the struct and who knows + what special alignment/padding requirements some C compilers have. + - gst_buffer_set_size() does not realloc the buffer when setting a + bigger size than allocated, it only allows growing up to the maximum + allocated size. Instead use a GstAdapter to collect all the blocks + and take out everything at once in the end. + - Check that enough data is actually available in the input and + otherwise handle it an error in all cases instead of silently + ignoring it. + +Among other things this fixes out of bounds writes because the code +assumed gst_buffer_set_size() can grow the buffer and simply wrote after +the end of the buffer. + +Thanks to Natalie Silvanovich for reporting. + +Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/859 + +Part-of: +--- + gst/matroska/matroska-demux.c | 99 +++++++++++++++++++---------------- + gst/matroska/matroska-ids.h | 2 + + 2 files changed, 55 insertions(+), 46 deletions(-) + +diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c +index 4eb3d2a9f..f890ae611 100644 +--- a/gst/matroska/matroska-demux.c ++++ b/gst/matroska/matroska-demux.c +@@ -3706,6 +3706,12 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, + guint32 block_samples, tmp; + gsize size = gst_buffer_get_size (*buf); + ++ if (size < 4) { ++ GST_ERROR_OBJECT (element, "Too small wavpack buffer"); ++ gst_buffer_unmap (*buf, &map); ++ return GST_FLOW_ERROR; ++ } ++ + gst_buffer_extract (*buf, 0, &tmp, sizeof (guint32)); + block_samples = GUINT32_FROM_LE (tmp); + /* we need to reconstruct the header of the wavpack block */ +@@ -3713,10 +3719,10 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, + /* -20 because ck_size is the size of the wavpack block -8 + * and lace_size is the size of the wavpack block + 12 + * (the three guint32 of the header that already are in the buffer) */ +- wvh.ck_size = size + sizeof (Wavpack4Header) - 20; ++ wvh.ck_size = size + WAVPACK4_HEADER_SIZE - 20; + + /* block_samples, flags and crc are already in the buffer */ +- newbuf = gst_buffer_new_allocate (NULL, sizeof (Wavpack4Header) - 12, NULL); ++ newbuf = gst_buffer_new_allocate (NULL, WAVPACK4_HEADER_SIZE - 12, NULL); + + gst_buffer_map (newbuf, &outmap, GST_MAP_WRITE); + data = outmap.data; +@@ -3741,9 +3747,11 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, + audiocontext->wvpk_block_index += block_samples; + } else { + guint8 *outdata = NULL; +- guint outpos = 0; +- gsize buf_size, size, out_size = 0; ++ gsize buf_size, size; + guint32 block_samples, flags, crc, blocksize; ++ GstAdapter *adapter; ++ ++ adapter = gst_adapter_new (); + + gst_buffer_map (*buf, &map, GST_MAP_READ); + buf_data = map.data; +@@ -3752,6 +3760,7 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, + if (buf_size < 4) { + GST_ERROR_OBJECT (element, "Too small wavpack buffer"); + gst_buffer_unmap (*buf, &map); ++ g_object_unref (adapter); + return GST_FLOW_ERROR; + } + +@@ -3773,59 +3782,57 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, + data += 4; + size -= 4; + +- if (blocksize == 0 || size < blocksize) +- break; +- +- g_assert ((newbuf == NULL) == (outdata == NULL)); ++ if (blocksize == 0 || size < blocksize) { ++ GST_ERROR_OBJECT (element, "Too small wavpack buffer"); ++ gst_buffer_unmap (*buf, &map); ++ g_object_unref (adapter); ++ return GST_FLOW_ERROR; ++ } + +- if (newbuf == NULL) { +- out_size = sizeof (Wavpack4Header) + blocksize; +- newbuf = gst_buffer_new_allocate (NULL, out_size, NULL); ++ g_assert (newbuf == NULL); + +- gst_buffer_copy_into (newbuf, *buf, +- GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS, 0, -1); ++ newbuf = ++ gst_buffer_new_allocate (NULL, WAVPACK4_HEADER_SIZE + blocksize, ++ NULL); ++ gst_buffer_map (newbuf, &outmap, GST_MAP_WRITE); ++ outdata = outmap.data; ++ ++ outdata[0] = 'w'; ++ outdata[1] = 'v'; ++ outdata[2] = 'p'; ++ outdata[3] = 'k'; ++ outdata += 4; ++ ++ GST_WRITE_UINT32_LE (outdata, blocksize + WAVPACK4_HEADER_SIZE - 8); ++ GST_WRITE_UINT16_LE (outdata + 4, wvh.version); ++ GST_WRITE_UINT8 (outdata + 6, wvh.track_no); ++ GST_WRITE_UINT8 (outdata + 7, wvh.index_no); ++ GST_WRITE_UINT32_LE (outdata + 8, wvh.total_samples); ++ GST_WRITE_UINT32_LE (outdata + 12, wvh.block_index); ++ GST_WRITE_UINT32_LE (outdata + 16, block_samples); ++ GST_WRITE_UINT32_LE (outdata + 20, flags); ++ GST_WRITE_UINT32_LE (outdata + 24, crc); ++ outdata += 28; ++ ++ memcpy (outdata, data, blocksize); + +- outpos = 0; +- gst_buffer_map (newbuf, &outmap, GST_MAP_WRITE); +- outdata = outmap.data; +- } else { +- gst_buffer_unmap (newbuf, &outmap); +- out_size += sizeof (Wavpack4Header) + blocksize; +- gst_buffer_set_size (newbuf, out_size); +- gst_buffer_map (newbuf, &outmap, GST_MAP_WRITE); +- outdata = outmap.data; +- } ++ gst_buffer_unmap (newbuf, &outmap); ++ gst_adapter_push (adapter, newbuf); ++ newbuf = NULL; + +- outdata[outpos] = 'w'; +- outdata[outpos + 1] = 'v'; +- outdata[outpos + 2] = 'p'; +- outdata[outpos + 3] = 'k'; +- outpos += 4; +- +- GST_WRITE_UINT32_LE (outdata + outpos, +- blocksize + sizeof (Wavpack4Header) - 8); +- GST_WRITE_UINT16_LE (outdata + outpos + 4, wvh.version); +- GST_WRITE_UINT8 (outdata + outpos + 6, wvh.track_no); +- GST_WRITE_UINT8 (outdata + outpos + 7, wvh.index_no); +- GST_WRITE_UINT32_LE (outdata + outpos + 8, wvh.total_samples); +- GST_WRITE_UINT32_LE (outdata + outpos + 12, wvh.block_index); +- GST_WRITE_UINT32_LE (outdata + outpos + 16, block_samples); +- GST_WRITE_UINT32_LE (outdata + outpos + 20, flags); +- GST_WRITE_UINT32_LE (outdata + outpos + 24, crc); +- outpos += 28; +- +- memmove (outdata + outpos, data, blocksize); +- outpos += blocksize; + data += blocksize; + size -= blocksize; + } + gst_buffer_unmap (*buf, &map); +- gst_buffer_unref (*buf); + +- if (newbuf) +- gst_buffer_unmap (newbuf, &outmap); ++ newbuf = gst_adapter_take_buffer (adapter, gst_adapter_available (adapter)); ++ g_object_unref (adapter); + ++ gst_buffer_copy_into (newbuf, *buf, ++ GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS, 0, -1); ++ gst_buffer_unref (*buf); + *buf = newbuf; ++ + audiocontext->wvpk_block_index += block_samples; + } + +diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h +index 9b263d8a1..a0d68343f 100644 +--- a/gst/matroska/matroska-ids.h ++++ b/gst/matroska/matroska-ids.h +@@ -667,6 +667,8 @@ typedef struct _Wavpack4Header { + guint32 crc; /* crc for actual decoded data */ + } Wavpack4Header; + ++#define WAVPACK4_HEADER_SIZE (32) ++ + typedef enum { + GST_MATROSKA_TRACK_ENCODING_SCOPE_FRAME = (1<<0), + GST_MATROSKA_TRACK_ENCODING_SCOPE_CODEC_DATA = (1<<1), +-- +GitLab + diff --git a/SOURCES/d62cecf193d6bf3b16fe91d725f4514161f602c3.patch b/SOURCES/d62cecf193d6bf3b16fe91d725f4514161f602c3.patch new file mode 100644 index 0000000..bd0ff4d --- /dev/null +++ b/SOURCES/d62cecf193d6bf3b16fe91d725f4514161f602c3.patch @@ -0,0 +1,38 @@ +From d62cecf193d6bf3b16fe91d725f4514161f602c3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Wed, 3 Mar 2021 11:31:52 +0200 +Subject: [PATCH] matroskademux: Initialize track context out parameter to NULL + before parsing + +Various error return paths don't set it to NULL and callers are only +checking if the pointer is NULL. As it's allocated on the stack this +usually contains random stack memory, and more often than not the memory +of a previously parsed track. + +This then causes all kinds of memory corruptions further down the line. + +Thanks to Natalie Silvanovich for reporting. + +Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/858 + +Part-of: +--- + gst/matroska/matroska-demux.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c +index b2cd9b5d4..4eb3d2a9f 100644 +--- a/gst/matroska/matroska-demux.c ++++ b/gst/matroska/matroska-demux.c +@@ -660,6 +660,8 @@ gst_matroska_demux_parse_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml, + + DEBUG_ELEMENT_START (demux, ebml, "TrackEntry"); + ++ *dest_context = NULL; ++ + /* start with the master */ + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "TrackEntry", ret); +-- +GitLab + diff --git a/SPECS/gstreamer1-plugins-good.spec b/SPECS/gstreamer1-plugins-good.spec index 31579af..5d2429a 100644 --- a/SPECS/gstreamer1-plugins-good.spec +++ b/SPECS/gstreamer1-plugins-good.spec @@ -15,7 +15,7 @@ Name: gstreamer1-plugins-good Version: 1.16.1 -Release: 2%{?gitcommit:.git%{shortcommit}}%{?dist} +Release: 3%{?gitcommit:.git%{shortcommit}}%{?dist} Summary: GStreamer plugins with good code and licensing License: LGPLv2+ @@ -29,6 +29,9 @@ Source0: gst-plugins-good-%{version}.tar.xz Source0: http://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-%{version}.tar.xz %endif +Patch0: d62cecf193d6bf3b16fe91d725f4514161f602c3.patch +Patch1: 9efd93e20dd7789e4172ad6c8f4108271b3fb1ee.patch + BuildRequires: gcc BuildRequires: gcc-c++ BuildRequires: gstreamer1-devel >= %{version} @@ -161,6 +164,8 @@ to be installed. %prep %setup -q -n gst-plugins-good-%{version} +%patch0 -p1 +%patch1 -p1 %build %configure --disable-silent-rules --disable-fatal-warnings \ @@ -345,6 +350,10 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %changelog +* Thu Jul 14 2022 Wim Taymans - 1.16.1-3 +- Add patches for matroskademux. CVE-2021-3497 +- Resolves: rhbz#1948942 + * Wed Dec 9 2020 Wim Taymans - 1.16.1-2 - Suppress documentation in Flatpak builds - Resolves: rhbz#1895938