From 0280dd9858c7ff34d3d4a80d2551a957cb8d4686 Mon Sep 17 00:00:00 2001 From: starlet-dx <15929766099@163.com> Date: Fri, 20 Dec 2024 14:31:46 +0800 Subject: [PATCH] Fix CVE-2024-47544,CVE-2024-47545,CVE-2024-47599 and CVE-2024-47603 (cherry picked from commit c91da9c62a183f0b0978fa2fb56c05b2a9dbde40) --- CVE-2024-47544.patch | 32 +++ CVE-2024-47545-pre1.patch | 223 ++++++++++++++++++++ CVE-2024-47545-pre2.patch | 102 +++++++++ CVE-2024-47545.patch | 388 +++++++++++++++++++++++++++++++++++ CVE-2024-47599.patch | 95 +++++++++ CVE-2024-47603.patch | 32 +++ gstreamer1-plugins-good.spec | 11 +- 7 files changed, 882 insertions(+), 1 deletion(-) create mode 100644 CVE-2024-47544.patch create mode 100644 CVE-2024-47545-pre1.patch create mode 100644 CVE-2024-47545-pre2.patch create mode 100644 CVE-2024-47545.patch create mode 100644 CVE-2024-47599.patch create mode 100644 CVE-2024-47603.patch diff --git a/CVE-2024-47544.patch b/CVE-2024-47544.patch new file mode 100644 index 0000000..d51344b --- /dev/null +++ b/CVE-2024-47544.patch @@ -0,0 +1,32 @@ +Backport of: + +From 8e884e4e31649a9fc19095d6501a1143b074aba8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Fri, 27 Sep 2024 09:47:50 +0300 +Subject: [PATCH] qtdemux: Fix error handling when parsing cenc sample groups + fails + +Thanks to Antonio Morales for finding and reporting the issue. + +Fixes GHSL-2024-238, GHSL-2024-239, GHSL-2024-240 +Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3846 + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 25 ++++++++++++++----- + 1 file changed, 19 insertions(+), 6 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -10705,8 +10705,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + * with the same type */ + GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc); + stream->protected = TRUE; +- if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc)) ++ if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc)) { + GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info"); ++ goto corrupt_file; ++ } + } + + if (stream->subtype == FOURCC_vide) { diff --git a/CVE-2024-47545-pre1.patch b/CVE-2024-47545-pre1.patch new file mode 100644 index 0000000..7de3fa4 --- /dev/null +++ b/CVE-2024-47545-pre1.patch @@ -0,0 +1,223 @@ +Backport of: + +From fd96fc23c53dcd95becfcca06d471e92923265ab Mon Sep 17 00:00:00 2001 +From: Justin Chadwell +Date: Wed, 2 Sep 2020 10:49:40 +0100 +Subject: [PATCH] qtdemux: use unsigned int types to store result of QT_UINT32 + +In a few cases throughout qtdemux, the results of QT_UINT32 were being +stored in a signed integer, which could cause subtle bugs in the case of +an integer overflow, even allowing the the result to equal a negative +number! + +This patch prevents this by simply storing the results of this function +call properly in an unsigned integer type. Additionally, we fix up the +length checking with stsd parsing to prevent cases of child atoms +exceeding their parent atom sizes. + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 76 ++++++++++++------- + 1 file changed, 47 insertions(+), 29 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -9772,8 +9772,8 @@ qtdemux_parse_segments (GstQTDemux * qtd + stream->segments = NULL; + if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) { + GNode *elst; +- gint n_segments; +- gint segment_number, entry_size; ++ guint n_segments; ++ guint segment_number, entry_size; + guint64 time; + GstClockTime stime; + const guint8 *buffer; +@@ -10449,6 +10449,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + guint8 tkhd_version = 0; + guint32 w = 0, h = 0; + guint value_size, stsd_len, len; ++ guint32 lenb; + guint32 track_id; + guint32 dummy; + +@@ -10789,7 +10790,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + break; + } + } else { +- gint i, j, start, end; ++ guint i, j, start, end; + + if (len < 94) + goto corrupt_file; +@@ -10905,7 +10906,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + if (pasp) { + const guint8 *pasp_data = (const guint8 *) pasp->data; +- gint len = QT_UINT32 (pasp_data); ++ guint len = QT_UINT32 (pasp_data); + + if (len == 16) { + CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8); +@@ -10921,7 +10922,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + if (fiel) { + const guint8 *fiel_data = (const guint8 *) fiel->data; +- gint len = QT_UINT32 (fiel_data); ++ guint len = QT_UINT32 (fiel_data); + + if (len == 10) { + CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8); +@@ -10931,7 +10932,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + if (colr) { + const guint8 *colr_data = (const guint8 *) colr->data; +- gint len = QT_UINT32 (colr_data); ++ guint len = QT_UINT32 (colr_data); + + if (len == 19 || len == 18) { + guint32 color_type = GST_READ_UINT32_LE (colr_data + 8); +@@ -11017,14 +11018,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_avc1: + case FOURCC_avc3: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *avc_data = stsd_entry_data + 0x56; + + /* find avcC */ + while (len >= 0x8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (avc_data) <= len) ++ if (QT_UINT32 (avc_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (avc_data) <= len) + size = QT_UINT32 (avc_data) - 0x8; + else + size = len - 0x8; +@@ -11129,14 +11133,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_hvc1: + case FOURCC_hev1: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *hevc_data = stsd_entry_data + 0x56; + + /* find hevc */ + while (len >= 0x8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (hevc_data) <= len) ++ if (QT_UINT32 (hevc_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (hevc_data) <= len) + size = QT_UINT32 (hevc_data) - 0x8; + else + size = len - 0x8; +@@ -11192,7 +11199,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + if (glbl) { + guint8 *data; + GstBuffer *buf; +- gint len; ++ guint len; + + GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd"); + data = glbl->data; +@@ -11376,7 +11383,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + /* add codec_data if provided */ + if (prefix) { + GstBuffer *buf; +- gint len; ++ guint len; + + GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd"); + data = prefix->data; +@@ -11398,7 +11405,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + GstBuffer *buf; + GstBuffer *seqh = NULL; + const guint8 *gamma_data = NULL; +- gint len = QT_UINT32 (stsd_data); /* FIXME review - why put the whole stsd in codec data? */ ++ guint len = QT_UINT32 (stsd_data); /* FIXME review - why put the whole stsd in codec data? */ + + qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data, + &seqh); +@@ -11550,14 +11557,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_vc_1: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *vc1_data = stsd_entry_data + 0x56; + + /* find dvc1 */ + while (len >= 8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (vc1_data) <= len) ++ if (QT_UINT32 (vc1_data) <= 8) ++ size = 0; ++ else if (QT_UINT32 (vc1_data) <= len) + size = QT_UINT32 (vc1_data) - 8; + else + size = len - 8; +@@ -11589,14 +11599,17 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_av01: + { +- gint len = QT_UINT32 (stsd_entry_data) - 0x56; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *av1_data = stsd_entry_data + 0x56; + + /* find av1C */ + while (len >= 0x8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (av1_data) <= len) ++ if (QT_UINT32 (av1_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (av1_data) <= len) + size = QT_UINT32 (av1_data) - 0x8; + else + size = len - 0x8; +@@ -11673,7 +11686,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + } else if (stream->subtype == FOURCC_soun) { + GNode *wave; +- int version, samplesize; ++ guint version, samplesize; + guint16 compression_id; + gboolean amrwb = FALSE; + +@@ -11920,7 +11933,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_wma_: + { +- gint len = QT_UINT32 (stsd_entry_data) - offset; ++ guint len = QT_UINT32 (stsd_entry_data); ++ len = len <= offset ? 0 : len - offset; + const guint8 *wfex_data = stsd_entry_data + offset; + const gchar *codec_name = NULL; + gint version = 1; +@@ -11944,9 +11958,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + /* find wfex */ + while (len >= 8) { +- gint size; ++ guint size; + +- if (QT_UINT32 (wfex_data) <= len) ++ if (QT_UINT32 (wfex_data) <= 0x8) ++ size = 0; ++ else if (QT_UINT32 (wfex_data) <= len) + size = QT_UINT32 (wfex_data) - 8; + else + size = len - 8; diff --git a/CVE-2024-47545-pre2.patch b/CVE-2024-47545-pre2.patch new file mode 100644 index 0000000..4e6d09f --- /dev/null +++ b/CVE-2024-47545-pre2.patch @@ -0,0 +1,102 @@ +Backport of: + +From d4bab55077c6a77bd80cb12a8b0d28020ef412a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Tue, 24 Sep 2024 09:50:34 +0300 +Subject: [PATCH] qtdemux: Skip zero-sized boxes instead of stopping to look at + further boxes + +A zero-sized box is not really a problem and can be skipped to look at any +possibly following ones. + +BMD ATEM devices specifically write a zero-sized bmdc box in the sample +description, followed by the avcC box in case of h264. Previously the avcC box +would simply not be read at all and the file would be unplayable. + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 54 ++++++++++++------- + 1 file changed, 36 insertions(+), 18 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -11033,9 +11033,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 0x8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ avc_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (avc_data + 0x4)) { + case FOURCC_avcC: +@@ -11148,9 +11151,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 0x8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ hevc_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (hevc_data + 0x4)) { + case FOURCC_hvcC: +@@ -11572,9 +11578,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ vc1_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (vc1_data + 0x4)) { + case GST_MAKE_FOURCC ('d', 'v', 'c', '1'): +@@ -11614,9 +11623,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 0x8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ av1_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (av1_data + 0x4)) { + case FOURCC_av1C: +@@ -11967,9 +11979,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + else + size = len - 8; + +- if (size < 1) +- /* No real data, so break out */ +- break; ++ /* No real data, so skip */ ++ if (size < 1) { ++ len -= 8; ++ wfex_data += 8; ++ continue; ++ } + + switch (QT_FOURCC (wfex_data + 4)) { + case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'): diff --git a/CVE-2024-47545.patch b/CVE-2024-47545.patch new file mode 100644 index 0000000..cb795f9 --- /dev/null +++ b/CVE-2024-47545.patch @@ -0,0 +1,388 @@ +Backport of: + +From fe9d5d37234aca04fef7248184177168905a7a69 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Fri, 27 Sep 2024 00:12:57 +0300 +Subject: [PATCH] qtdemux: Fix length checks and offsets in stsd entry parsing + +Thanks to Antonio Morales for finding and reporting the issue. + +Fixes GHSL-2024-242 +Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3845 + +Part-of: +--- + .../gst-plugins-good/gst/isomp4/qtdemux.c | 218 +++++++----------- + 1 file changed, 79 insertions(+), 139 deletions(-) + +--- a/gst/isomp4/qtdemux.c ++++ b/gst/isomp4/qtdemux.c +@@ -11018,43 +11018,35 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_avc1: + case FOURCC_avc3: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *avc_data = stsd_entry_data + 0x56; + + /* find avcC */ +- while (len >= 0x8) { +- guint size; ++ while (len >= 8) { ++ guint32 size = QT_UINT32 (avc_data); + +- if (QT_UINT32 (avc_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (avc_data) <= len) +- size = QT_UINT32 (avc_data) - 0x8; +- else +- size = len - 0x8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- avc_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (avc_data + 0x4)) { ++ switch (QT_FOURCC (avc_data + 4)) { + case FOURCC_avcC: + { + /* parse, if found */ + GstBuffer *buf; + ++ if (size < 8 + 1) ++ break; ++ + GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd"); + + /* First 4 bytes are the length of the atom, the next 4 bytes + * are the fourcc, the next 1 byte is the version, and the + * subsequent bytes are profile_tier_level structure like data. */ + gst_codec_utils_h264_caps_set_level_and_profile (entry->caps, +- avc_data + 8 + 1, size - 1); +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, avc_data + 0x8, size); ++ avc_data + 8 + 1, size - 8 - 1); ++ buf = gst_buffer_new_and_alloc (size - 8); ++ gst_buffer_fill (buf, 0, avc_data + 8, size - 8); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -11065,6 +11057,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + { + GstBuffer *buf; + ++ if (size < 8 + 40 + 1) ++ break; ++ + GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd"); + + /* First 4 bytes are the length of the atom, the next 4 bytes +@@ -11072,17 +11067,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + * next 1 byte is the version, and the + * subsequent bytes are sequence parameter set like data. */ + +- size -= 40; /* we'll be skipping BITMAPINFOHEADER */ +- if (size > 1) { +- gst_codec_utils_h264_caps_set_level_and_profile +- (entry->caps, avc_data + 8 + 40 + 1, size - 1); ++ gst_codec_utils_h264_caps_set_level_and_profile ++ (entry->caps, avc_data + 8 + 40 + 1, size - 8 - 40 - 1); + +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, avc_data + 8 + 40, size); +- gst_caps_set_simple (entry->caps, +- "codec_data", GST_TYPE_BUFFER, buf, NULL); +- gst_buffer_unref (buf); +- } ++ buf = gst_buffer_new_and_alloc (size - 8 - 40); ++ gst_buffer_fill (buf, 0, avc_data + 8 + 40, size - 8 - 40); ++ gst_caps_set_simple (entry->caps, ++ "codec_data", GST_TYPE_BUFFER, buf, NULL); ++ gst_buffer_unref (buf); + break; + } + case FOURCC_btrt: +@@ -11090,11 +11082,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + guint avg_bitrate, max_bitrate; + + /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */ +- if (size < 12) ++ if (size < 8 + 12) + break; + +- max_bitrate = QT_UINT32 (avc_data + 0xc); +- avg_bitrate = QT_UINT32 (avc_data + 0x10); ++ max_bitrate = QT_UINT32 (avc_data + 8 + 4); ++ avg_bitrate = QT_UINT32 (avc_data + 8 + 8); + + if (!max_bitrate && !avg_bitrate) + break; +@@ -11126,8 +11118,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + break; + } + +- len -= size + 8; +- avc_data += size + 8; ++ len -= size; ++ avc_data += size; + } + + break; +@@ -11136,44 +11128,36 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + case FOURCC_hvc1: + case FOURCC_hev1: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *hevc_data = stsd_entry_data + 0x56; + + /* find hevc */ +- while (len >= 0x8) { +- guint size; ++ while (len >= 8) { ++ guint32 size = QT_UINT32 (hevc_data); + +- if (QT_UINT32 (hevc_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (hevc_data) <= len) +- size = QT_UINT32 (hevc_data) - 0x8; +- else +- size = len - 0x8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- hevc_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (hevc_data + 0x4)) { ++ switch (QT_FOURCC (hevc_data + 4)) { + case FOURCC_hvcC: + { + /* parse, if found */ + GstBuffer *buf; + ++ if (size < 8 + 1) ++ break; ++ + GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd"); + + /* First 4 bytes are the length of the atom, the next 4 bytes + * are the fourcc, the next 1 byte is the version, and the + * subsequent bytes are sequence parameter set like data. */ + gst_codec_utils_h265_caps_set_level_tier_and_profile +- (entry->caps, hevc_data + 8 + 1, size - 1); ++ (entry->caps, hevc_data + 8 + 1, size - 8 - 1); + +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, hevc_data + 0x8, size); ++ buf = gst_buffer_new_and_alloc (size - 8); ++ gst_buffer_fill (buf, 0, hevc_data + 8, size - 8); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -11182,8 +11166,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + default: + break; + } +- len -= size + 8; +- hevc_data += size + 8; ++ len -= size; ++ hevc_data += size; + } + break; + } +@@ -11563,36 +11547,25 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_vc_1: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *vc1_data = stsd_entry_data + 0x56; + + /* find dvc1 */ + while (len >= 8) { +- guint size; ++ guint32 size = QT_UINT32 (vc1_data); + +- if (QT_UINT32 (vc1_data) <= 8) +- size = 0; +- else if (QT_UINT32 (vc1_data) <= len) +- size = QT_UINT32 (vc1_data) - 8; +- else +- size = len - 8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- vc1_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (vc1_data + 0x4)) { ++ switch (QT_FOURCC (vc1_data + 4)) { + case GST_MAKE_FOURCC ('d', 'v', 'c', '1'): + { + GstBuffer *buf; + + GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd"); +- buf = gst_buffer_new_and_alloc (size); +- gst_buffer_fill (buf, 0, vc1_data + 8, size); ++ buf = gst_buffer_new_and_alloc (size - 8); ++ gst_buffer_fill (buf, 0, vc1_data + 8, size - 8); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -11601,36 +11574,25 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + default: + break; + } +- len -= size + 8; +- vc1_data += size + 8; ++ len -= size; ++ vc1_data += size; + } + break; + } + case FOURCC_av01: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= 0x56 ? 0 : len - 0x56; + const guint8 *av1_data = stsd_entry_data + 0x56; + + /* find av1C */ +- while (len >= 0x8) { +- guint size; ++ while (len >= 8) { ++ guint32 size = QT_UINT32 (av1_data); + +- if (QT_UINT32 (av1_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (av1_data) <= len) +- size = QT_UINT32 (av1_data) - 0x8; +- else +- size = len - 0x8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- av1_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + +- switch (QT_FOURCC (av1_data + 0x4)) { ++ switch (QT_FOURCC (av1_data + 4)) { + case FOURCC_av1C: + { + /* parse, if found */ +@@ -11641,7 +11603,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + "found av1C codec_data in stsd of size %d", size); + + /* not enough data, just ignore and hope for the best */ +- if (size < 5) ++ if (size < 8 + 5) + break; + + /* Content is: +@@ -11667,10 +11629,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + "presentation-delay", G_TYPE_INT, + (gint) (pres_delay_field & 0x0F) + 1, NULL); + } +- if (size > 5) { +- buf = gst_buffer_new_and_alloc (size - 5); ++ if (size > 8 + 5) { ++ buf = gst_buffer_new_and_alloc (size - 8 - 5); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER); +- gst_buffer_fill (buf, 0, av1_data + 13, size - 5); ++ gst_buffer_fill (buf, 0, av1_data + 13, size - 8 - 5); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -11681,8 +11643,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + break; + } + +- len -= size + 8; +- av1_data += size + 8; ++ len -= size; ++ av1_data += size; + } + + break; +@@ -11945,7 +11907,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + } + case FOURCC_wma_: + { +- guint len = QT_UINT32 (stsd_entry_data); ++ guint32 len = QT_UINT32 (stsd_entry_data); + len = len <= offset ? 0 : len - offset; + const guint8 *wfex_data = stsd_entry_data + offset; + const gchar *codec_name = NULL; +@@ -11970,21 +11932,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + + /* find wfex */ + while (len >= 8) { +- guint size; ++ guint32 size = QT_UINT32 (wfex_data); + +- if (QT_UINT32 (wfex_data) <= 0x8) +- size = 0; +- else if (QT_UINT32 (wfex_data) <= len) +- size = QT_UINT32 (wfex_data) - 8; +- else +- size = len - 8; +- +- /* No real data, so skip */ +- if (size < 1) { +- len -= 8; +- wfex_data += 8; +- continue; +- } ++ if (size < 8 || size > len) ++ break; + + switch (QT_FOURCC (wfex_data + 4)) { + case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'): +@@ -12029,12 +11980,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + "width", G_TYPE_INT, wfex.wBitsPerSample, + "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL); + +- if (size > wfex.cbSize) { ++ if (size > 8 + wfex.cbSize) { + GstBuffer *buf; + +- buf = gst_buffer_new_and_alloc (size - wfex.cbSize); ++ buf = gst_buffer_new_and_alloc (size - 8 - wfex.cbSize); + gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize, +- size - wfex.cbSize); ++ size - 8 - wfex.cbSize); + gst_caps_set_simple (entry->caps, + "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); +@@ -12051,8 +12002,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux + default: + break; + } +- len -= size + 8; +- wfex_data += size + 8; ++ len -= size; ++ wfex_data += size; + } + break; + } diff --git a/CVE-2024-47599.patch b/CVE-2024-47599.patch new file mode 100644 index 0000000..4ef4362 --- /dev/null +++ b/CVE-2024-47599.patch @@ -0,0 +1,95 @@ +From 8b1c866e93749fd42d1908ec77a4f339343acbb2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Mon, 30 Sep 2024 16:22:19 +0300 +Subject: [PATCH] jpegdec: Directly error out on negotiation failures + +Thanks to Antonio Morales for finding and reporting the issue. + +Fixes GHSL-2024-247 +Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3862 + +Part-of: +--- + ext/jpeg/gstjpegdec.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c +index 5442168..3374e18 100644 +--- a/ext/jpeg/gstjpegdec.c ++++ b/ext/jpeg/gstjpegdec.c +@@ -947,13 +947,14 @@ format_not_supported: + } + } + +-static void ++static gboolean + gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc, + gboolean interlaced) + { + GstVideoCodecState *outstate; + GstVideoInfo *info; + GstVideoFormat format; ++ gboolean res; + + switch (clrspc) { + case JCS_RGB: +@@ -976,7 +977,7 @@ gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc, + height == GST_VIDEO_INFO_HEIGHT (info) && + format == GST_VIDEO_INFO_FORMAT (info)) { + gst_video_codec_state_unref (outstate); +- return; ++ return TRUE; + } + gst_video_codec_state_unref (outstate); + } +@@ -984,6 +985,8 @@ gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc, + outstate = + gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), format, + width, height, dec->input_state); ++ if (!outstate) ++ return FALSE; + + switch (clrspc) { + case JCS_RGB: +@@ -1005,10 +1008,12 @@ gst_jpeg_dec_negotiate (GstJpegDec * dec, gint width, gint height, gint clrspc, + + gst_video_codec_state_unref (outstate); + +- gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec)); ++ res = gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec)); + + GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor); + GST_DEBUG_OBJECT (dec, "max_h_samp_factor=%d", dec->cinfo.max_h_samp_factor); ++ ++ return res; + } + + static GstFlowReturn +@@ -1274,8 +1279,9 @@ gst_jpeg_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame) + num_fields = 1; + } + +- gst_jpeg_dec_negotiate (dec, width, output_height, +- dec->cinfo.jpeg_color_space, num_fields == 2); ++ if (!gst_jpeg_dec_negotiate (dec, width, output_height, ++ dec->cinfo.jpeg_color_space, num_fields == 2)) ++ goto negotiation_failed; + + state = gst_video_decoder_get_output_state (bdec); + ret = gst_video_decoder_allocate_output_frame (bdec, frame); +@@ -1392,6 +1398,12 @@ need_more_data: + ret = GST_FLOW_OK; + goto exit; + } ++negotiation_failed: ++ { ++ GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), ("failed to negotiate")); ++ ret = GST_FLOW_NOT_NEGOTIATED; ++ goto exit; ++ } + /* ERRORS */ + decode_error: + { +-- +2.33.0 + diff --git a/CVE-2024-47603.patch b/CVE-2024-47603.patch new file mode 100644 index 0000000..3442c23 --- /dev/null +++ b/CVE-2024-47603.patch @@ -0,0 +1,32 @@ +Backport of: + +From 09803e225de515c8881fd13ed464c23771a4d1a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= +Date: Mon, 30 Sep 2024 19:19:42 +0300 +Subject: [PATCH] matroskademux: Skip over zero-sized Xiph stream headers + +Thanks to Antonio Morales for finding and reporting the issue. + +Fixes GHSL-2024-251 +Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3867 + +Part-of: +--- + gst/matroska/matroska-ids.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/gst/matroska/matroska-ids.c ++++ b/gst/matroska/matroska-ids.c +@@ -184,8 +184,10 @@ gst_matroska_parse_xiph_stream_headers ( + if (offset + length[i] > codec_data_size) + goto error; + +- hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]); +- gst_buffer_list_add (list, hdr); ++ if (length[i] > 0) { ++ hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]); ++ gst_buffer_list_add (list, hdr); ++ } + + offset += length[i]; + } diff --git a/gstreamer1-plugins-good.spec b/gstreamer1-plugins-good.spec index 31e11fe..7f46dac 100644 --- a/gstreamer1-plugins-good.spec +++ b/gstreamer1-plugins-good.spec @@ -3,7 +3,7 @@ Name: gstreamer1-plugins-good Version: 1.16.2 -Release: 7 +Release: 8 Summary: GStreamer plugins with good code and licensing License: LGPLv2+ URL: http://gstreamer.freedesktop.org/ @@ -41,6 +41,12 @@ Patch0022: CVE-2024-47546.patch Patch0023: matroskademux-Fix-off-by-one-when-parsing-multi-channel-WavPack.patch Patch0024: qtdemux-Do-not-iterate-over-all-trun-entries-if-none.patch Patch0025: qtdemux-Fix-debug-output-during-trun-parsing.patch +Patch0026: CVE-2024-47599.patch +Patch0027: CVE-2024-47603.patch +Patch0028: CVE-2024-47545-pre1.patch +Patch0029: CVE-2024-47545-pre2.patch +Patch0030: CVE-2024-47545.patch +Patch0031: CVE-2024-47544.patch BuildRequires: gcc gcc-c++ gstreamer1-devel gstreamer1-plugins-base-devel flac-devel BuildRequires: gdk-pixbuf2-devel libjpeg-devel libpng-devel libshout-devel orc-devel @@ -125,6 +131,9 @@ echo "%{_libdir}" > %{buildroot}/etc/ld.so.conf.d/%{name}-%{_arch}.conf %doc %{_datadir}/gtk-doc/html/* %changelog +* Fri Dec 20 2024 yaoxin - 1.16.2-8 +- Fix CVE-2024-47544,CVE-2024-47545,CVE-2024-47599 and CVE-2024-47603 + * Wed Dec 18 2024 yaoxin - 1.16.2-7 - Fix cves: CVE-2024-47606,CVE-2024-47613,CVE-2024-47775,CVE-2024-47776 -- Gitee