From 14df9f8d70dabe9b9a6858772df9e4805c717d05 Mon Sep 17 00:00:00 2001 From: RHEL Packaging Agent Date: Thu, 13 Aug 2026 14:36:59 +0000 Subject: [PATCH] Fix CVE-2026-18649 in H.264/H.265 RTP depayloaders Backport CVE-2026-18649 fix from upstream GStreamer MR 12244 to gstreamer1-plugins-good 1.16.1. The patch adds a max-fragmentation-unit-size property (default 32 MB) to both H.264 and H.265 RTP depayloaders. If a fragmentation unit exceeds this limit while being assembled, it is dropped and the depayloader state is reset, preventing excessive memory usage from crafted RTP streams. CVE: CVE-2026-18649 Upstream patches: - https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12244.patch Resolves: RHEL-224145 This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent. Assisted-by: Ymir --- ...1-plugins-good-1.16.1-CVE-2026-18649.patch | 296 ++++++++++++++++++ gstreamer1-plugins-good.spec | 10 +- 2 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 gstreamer1-plugins-good-1.16.1-CVE-2026-18649.patch diff --git a/gstreamer1-plugins-good-1.16.1-CVE-2026-18649.patch b/gstreamer1-plugins-good-1.16.1-CVE-2026-18649.patch new file mode 100644 index 0000000..81ccae0 --- /dev/null +++ b/gstreamer1-plugins-good-1.16.1-CVE-2026-18649.patch @@ -0,0 +1,296 @@ +From 07cbde0479905b968c54f6ca22999aa9b62bd653 Mon Sep 17 00:00:00 2001 +From: RHEL Packaging Agent +Date: Fri, 7 Aug 2026 14:34:04 +0000 +Subject: [PATCH] rtph264depay: rtph265depay: Limit the maximum fragmentation + unit size + +Adds a max-fragmentation-unit-size property (default 32 MB) to both +H.264 and H.265 RTP depayloaders. If a fragmentation unit exceeds +this limit while being assembled, it is dropped and the depayloader +state is reset to prevent excessive memory usage. + +Adapted from upstream commits: +- 5cd490c125e04676659593b0f5b19130fc2face7 +- 820bd15585b13af8be9b0131699655194ae68a5b + +Fixes: CVE-2026-18649 +--- + gst/rtp/gstrtph264depay.c | 79 ++++++++++++++++++++++++++++++++++++++- + gst/rtp/gstrtph264depay.h | 2 + + gst/rtp/gstrtph265depay.c | 75 +++++++++++++++++++++++++++++++++++++ + gst/rtp/gstrtph265depay.h | 2 + + 4 files changed, 157 insertions(+), 1 deletion(-) + +diff --git a/gst/rtp/gstrtph264depay.c b/gst/rtp/gstrtph264depay.c +index 275a9a0..625244f 100644 +--- a/gst/rtp/gstrtph264depay.c ++++ b/gst/rtp/gstrtph264depay.c +@@ -38,6 +38,13 @@ GST_DEBUG_CATEGORY_STATIC (rtph264depay_debug); + * expressed a restriction or preference via caps */ + #define DEFAULT_BYTE_STREAM TRUE + #define DEFAULT_ACCESS_UNIT FALSE ++#define DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE (32 * 1024 * 1024) ++ ++enum ++{ ++ PROP_0, ++ PROP_MAX_FRAGMENTATION_UNIT_SIZE, ++}; + + /* 3 zero bytes syncword */ + static const guint8 sync_bytes[] = { 0, 0, 0, 1 }; +@@ -83,6 +90,10 @@ G_DEFINE_TYPE (GstRtpH264Depay, gst_rtp_h264_depay, + GST_TYPE_RTP_BASE_DEPAYLOAD); + + static void gst_rtp_h264_depay_finalize (GObject * object); ++static void gst_rtp_h264_depay_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec); ++static void gst_rtp_h264_depay_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * pspec); + + static GstStateChangeReturn gst_rtp_h264_depay_change_state (GstElement * + element, GstStateChange transition); +@@ -111,6 +122,24 @@ gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass) + gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass; + + gobject_class->finalize = gst_rtp_h264_depay_finalize; ++ gobject_class->set_property = gst_rtp_h264_depay_set_property; ++ gobject_class->get_property = gst_rtp_h264_depay_get_property; ++ ++ /** ++ * GstRtpH264Depay:max-fragmentation-unit-size: ++ * ++ * Maximum size in bytes for a fragmentation unit. Larger units ++ * will be dropped to prevent excessive memory usage. ++ * ++ * Use 0 for automatic. ++ */ ++ g_object_class_install_property (gobject_class, ++ PROP_MAX_FRAGMENTATION_UNIT_SIZE, ++ g_param_spec_uint ("max-fragmentation-unit-size", ++ "Max Fragmentation Unit Size", ++ "Maximum size in bytes for a fragmentation unit (0 = auto)", 0, ++ G_MAXUINT, DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_h264_depay_src_template); +@@ -128,6 +157,38 @@ gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass) + gstrtpbasedepayload_class->handle_event = gst_rtp_h264_depay_handle_event; + } + ++static void ++gst_rtp_h264_depay_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec) ++{ ++ GstRtpH264Depay *self = GST_RTP_H264_DEPAY (object); ++ ++ switch (prop_id) { ++ case PROP_MAX_FRAGMENTATION_UNIT_SIZE: ++ self->max_fragmentation_unit_size = g_value_get_uint (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gst_rtp_h264_depay_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * pspec) ++{ ++ GstRtpH264Depay *self = GST_RTP_H264_DEPAY (object); ++ ++ switch (prop_id) { ++ case PROP_MAX_FRAGMENTATION_UNIT_SIZE: ++ g_value_set_uint (value, self->max_fragmentation_unit_size); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ + static void + gst_rtp_h264_depay_init (GstRtpH264Depay * rtph264depay) + { +@@ -139,6 +200,8 @@ gst_rtp_h264_depay_init (GstRtpH264Depay * rtph264depay) + (GDestroyNotify) gst_buffer_unref); + rtph264depay->pps = g_ptr_array_new_with_free_func ( + (GDestroyNotify) gst_buffer_unref); ++ rtph264depay->max_fragmentation_unit_size = ++ DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE; + } + + static void +@@ -1241,8 +1304,22 @@ gst_rtp_h264_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp) + rtph264depay->fu_marker = marker; + + /* if NAL unit ends, flush the adapter */ +- if (E) ++ if (E) { + gst_rtp_h264_finish_fragmentation_unit (rtph264depay); ++ GST_DEBUG_OBJECT (rtph264depay, "End of Fragmentation Unit"); ++ } else { ++ guint limit = rtph264depay->max_fragmentation_unit_size ? ++ rtph264depay->max_fragmentation_unit_size : ++ DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE; ++ if (gst_adapter_available (rtph264depay->adapter) > limit) { ++ GST_WARNING_OBJECT (rtph264depay, ++ "Too big (> %u bytes) fragmentation unit, dropping.", limit); ++ rtph264depay->wait_start = TRUE; ++ rtph264depay->current_fu_type = 0; ++ gst_adapter_clear (rtph264depay->adapter); ++ return NULL; ++ } ++ } + break; + } + default: +diff --git a/gst/rtp/gstrtph264depay.h b/gst/rtp/gstrtph264depay.h +index ba41312..a02a65d 100644 +--- a/gst/rtp/gstrtph264depay.h ++++ b/gst/rtp/gstrtph264depay.h +@@ -62,6 +62,8 @@ struct _GstRtpH264Depay + GstClockTime fu_timestamp; + gboolean fu_marker; + ++ guint max_fragmentation_unit_size; ++ + /* misc */ + GPtrArray *sps; + GPtrArray *pps; +diff --git a/gst/rtp/gstrtph265depay.c b/gst/rtp/gstrtph265depay.c +index 551e08a..b046030 100644 +--- a/gst/rtp/gstrtph265depay.c ++++ b/gst/rtp/gstrtph265depay.c +@@ -38,6 +38,13 @@ GST_DEBUG_CATEGORY_STATIC (rtph265depay_debug); + * expressed a restriction or preference via caps */ + #define DEFAULT_STREAM_FORMAT GST_H265_STREAM_FORMAT_BYTESTREAM + #define DEFAULT_ACCESS_UNIT FALSE ++#define DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE (32 * 1024 * 1024) ++ ++enum ++{ ++ PROP_0, ++ PROP_MAX_FRAGMENTATION_UNIT_SIZE, ++}; + + /* 3 zero bytes syncword */ + static const guint8 sync_bytes[] = { 0, 0, 0, 1 }; +@@ -99,6 +106,10 @@ G_DEFINE_TYPE (GstRtpH265Depay, gst_rtp_h265_depay, + GST_TYPE_RTP_BASE_DEPAYLOAD); + + static void gst_rtp_h265_depay_finalize (GObject * object); ++static void gst_rtp_h265_depay_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec); ++static void gst_rtp_h265_depay_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * pspec); + + static GstStateChangeReturn gst_rtp_h265_depay_change_state (GstElement * + element, GstStateChange transition); +@@ -128,6 +139,24 @@ gst_rtp_h265_depay_class_init (GstRtpH265DepayClass * klass) + gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass; + + gobject_class->finalize = gst_rtp_h265_depay_finalize; ++ gobject_class->set_property = gst_rtp_h265_depay_set_property; ++ gobject_class->get_property = gst_rtp_h265_depay_get_property; ++ ++ /** ++ * GstRtpH265Depay:max-fragmentation-unit-size: ++ * ++ * Maximum size in bytes for a fragmentation unit. Larger units ++ * will be dropped to prevent excessive memory usage. ++ * ++ * Use 0 for automatic. ++ */ ++ g_object_class_install_property (gobject_class, ++ PROP_MAX_FRAGMENTATION_UNIT_SIZE, ++ g_param_spec_uint ("max-fragmentation-unit-size", ++ "Max Fragmentation Unit Size", ++ "Maximum size in bytes for a fragmentation unit (0 = auto)", 0, ++ G_MAXUINT, DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_h265_depay_src_template); +@@ -145,6 +174,38 @@ gst_rtp_h265_depay_class_init (GstRtpH265DepayClass * klass) + gstrtpbasedepayload_class->handle_event = gst_rtp_h265_depay_handle_event; + } + ++static void ++gst_rtp_h265_depay_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec) ++{ ++ GstRtpH265Depay *self = GST_RTP_H265_DEPAY (object); ++ ++ switch (prop_id) { ++ case PROP_MAX_FRAGMENTATION_UNIT_SIZE: ++ self->max_fragmentation_unit_size = g_value_get_uint (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gst_rtp_h265_depay_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * pspec) ++{ ++ GstRtpH265Depay *self = GST_RTP_H265_DEPAY (object); ++ ++ switch (prop_id) { ++ case PROP_MAX_FRAGMENTATION_UNIT_SIZE: ++ g_value_set_uint (value, self->max_fragmentation_unit_size); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ + static void + gst_rtp_h265_depay_init (GstRtpH265Depay * rtph265depay) + { +@@ -161,6 +222,8 @@ gst_rtp_h265_depay_init (GstRtpH265Depay * rtph265depay) + (GDestroyNotify) gst_buffer_unref); + rtph265depay->pps = g_ptr_array_new_with_free_func ( + (GDestroyNotify) gst_buffer_unref); ++ rtph265depay->max_fragmentation_unit_size = ++ DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE; + } + + static void +@@ -1520,6 +1583,18 @@ gst_rtp_h265_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp) + if (E) { + gst_rtp_h265_finish_fragmentation_unit (rtph265depay); + GST_DEBUG_OBJECT (rtph265depay, "End of Fragmentation Unit"); ++ } else { ++ guint limit = rtph265depay->max_fragmentation_unit_size ? ++ rtph265depay->max_fragmentation_unit_size : ++ DEFAULT_MAX_FRAGMENTATION_UNIT_SIZE; ++ if (gst_adapter_available (rtph265depay->adapter) > limit) { ++ GST_WARNING_OBJECT (rtph265depay, ++ "Too big (> %u bytes) fragmentation unit, dropping.", limit); ++ rtph265depay->wait_start = TRUE; ++ rtph265depay->current_fu_type = 0; ++ gst_adapter_clear (rtph265depay->adapter); ++ return NULL; ++ } + } + break; + } +diff --git a/gst/rtp/gstrtph265depay.h b/gst/rtp/gstrtph265depay.h +index cf17694..e851d3b 100644 +--- a/gst/rtp/gstrtph265depay.h ++++ b/gst/rtp/gstrtph265depay.h +@@ -76,6 +76,8 @@ struct _GstRtpH265Depay + GstClockTime fu_timestamp; + gboolean fu_marker; + ++ guint max_fragmentation_unit_size; ++ + /* misc */ + GPtrArray *vps; + GPtrArray *sps; diff --git a/gstreamer1-plugins-good.spec b/gstreamer1-plugins-good.spec index 168bc8c..a962775 100644 --- a/gstreamer1-plugins-good.spec +++ b/gstreamer1-plugins-good.spec @@ -15,7 +15,7 @@ Name: gstreamer1-plugins-good Version: 1.16.1 -Release: 7%{?gitcommit:.git%{shortcommit}}%{?dist}.1 +Release: 7%{?gitcommit:.git%{shortcommit}}%{?dist}.2 Summary: GStreamer plugins with good code and licensing License: LGPLv2+ @@ -45,6 +45,9 @@ Patch10: gstreamer1-plugins-good-1.16.1-CVE-2026-53705.patch # https://issues.redhat.com/browse/RHEL-239068 # https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12231 Patch11: gstreamer1-plugins-good-1.16.1-CVE-2026-73433.patch +# https://issues.redhat.com/browse/RHEL-224145 +# https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12244 +Patch12: gstreamer1-plugins-good-1.16.1-CVE-2026-18649.patch BuildRequires: gcc BuildRequires: gcc-c++ @@ -190,6 +193,7 @@ to be installed. %patch9 -p1 %patch10 -p1 %patch11 -p1 +%patch12 -p1 %build %configure --disable-silent-rules --disable-fatal-warnings \ @@ -374,6 +378,10 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %changelog +* Thu Aug 13 2026 RHEL Packaging Agent - 1.16.1-7.2 +- Fix CVE-2026-18649 in H.264/H.265 RTP depayloaders + Resolves: RHEL-224145 + * Thu Aug 13 2026 RHEL Packaging Agent - 1.16.1-7.1 - Fix multiple security issues in AVI demuxer (CVE-2026-73433) Resolves: RHEL-239068