From: Maintainers of GStreamer packages Date: Fri, 27 Oct 2023 20:55:02 +0000 (+0200) Subject: CVE-2023-40474 X-Git-Tag: archive/raspbian/1.14.4-1+rvt+deb10u5^2^2~3 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=46562b77e9eb53e4fe536f759ad253d85c1def80;p=gst-plugins-bad1.0.git CVE-2023-40474 commit f73fc41f2ca6a0cd4e883aee64bf8e1c15ff68ce Author: Sebastian Dröge Date: Thu Aug 10 15:45:01 2023 +0300 mxfdemux: Fix integer overflow causing out of bounds writes when handling invalid uncompressed video Check ahead of time when parsing the track information whether width, height and bpp are valid and usable without overflows. Fixes ZDI-CAN-21660, CVE-2023-40474 Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2896 Part-of: Gbp-Pq: Name CVE-2023-40474.patch --- diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index d8b6664..b8c9cae 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -100,6 +100,64 @@ typedef struct guint32 image_end_offset; } MXFUPMappingData; +/*----------- start of new functions -----------*/ +/* + * add some functions that are needed for CVE-2023-40474.patch + * but are only added later to gstreamer + */ +void gst_clear_caps (GstCaps ** caps_ptr); +void gst_clear_mini_object (GstMiniObject ** object_ptr); + +/** + * gst_clear_caps: (skip) + * @caps_ptr: a pointer to a #GstCaps reference + * + * Clears a reference to a #GstCaps. + * + * @caps_ptr must not be %NULL. + * + * If the reference is %NULL then this function does nothing. Otherwise, the + * reference count of the caps is decreased and the pointer is set to %NULL. + * + * Since: 1.16 + */ +void +gst_clear_caps (GstCaps ** caps_ptr) +{ + gst_clear_mini_object ((GstMiniObject **) caps_ptr); +} + + +/** + * gst_clear_mini_object: (skip) + * @object_ptr: a pointer to a #GstMiniObject reference + * + * Clears a reference to a #GstMiniObject. + * + * @object_ptr must not be %NULL. + * + * If the reference is %NULL then this function does nothing. + * Otherwise, the reference count of the object is decreased using + * gst_mini_object_unref() and the pointer is set to %NULL. + * + * A macro is also included that allows this function to be used without + * pointer casts. + * + * Since: 1.16 + **/ +#undef gst_clear_mini_object +void +gst_clear_mini_object (GstMiniObject ** object_ptr) +{ + g_clear_pointer (object_ptr, gst_mini_object_unref); +} +/*----------- end of new functions -----------*/ + + + + + + static gboolean mxf_is_up_essence_track (const MXFMetadataTimelineTrack * track) { @@ -134,6 +192,8 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer, gpointer mapping_data, GstBuffer ** outbuf) { MXFUPMappingData *data = mapping_data; + gsize expected_in_stride = 0, out_stride = 0; + gsize expected_in_size = 0, out_size = 0; /* SMPTE 384M 7.1 */ if (key->u[12] != 0x15 || (key->u[14] != 0x01 && key->u[14] != 0x02 @@ -162,22 +222,25 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer, } } - if (gst_buffer_get_size (buffer) != data->bpp * data->width * data->height) { + // Checked for overflows when parsing the descriptor + expected_in_stride = data->bpp * data->width; + out_stride = GST_ROUND_UP_4 (expected_in_stride); + expected_in_size = expected_in_stride * data->height; + out_size = out_stride * data->height; + + if (gst_buffer_get_size (buffer) != expected_in_size) { GST_ERROR ("Invalid buffer size"); gst_buffer_unref (buffer); return GST_FLOW_ERROR; } - if (data->bpp != 4 - || GST_ROUND_UP_4 (data->width * data->bpp) != data->width * data->bpp) { + if (data->bpp != 4 || out_stride != expected_in_stride) { guint y; GstBuffer *ret; GstMapInfo inmap, outmap; guint8 *indata, *outdata; - ret = - gst_buffer_new_and_alloc (GST_ROUND_UP_4 (data->width * data->bpp) * - data->height); + ret = gst_buffer_new_and_alloc (out_size); gst_buffer_map (buffer, &inmap, GST_MAP_READ); gst_buffer_map (ret, &outmap, GST_MAP_WRITE); indata = inmap.data; @@ -185,8 +248,8 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer, for (y = 0; y < data->height; y++) { memcpy (outdata, indata, data->width * data->bpp); - outdata += GST_ROUND_UP_4 (data->width * data->bpp); - indata += data->width * data->bpp; + outdata += out_stride; + indata += expected_in_stride; } gst_buffer_unmap (buffer, &inmap); @@ -394,6 +457,36 @@ mxf_up_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags, return NULL; } + if (caps) { + MXFUPMappingData *data = *mapping_data; + gsize expected_in_stride = 0, out_stride = 0; + gsize expected_in_size = 0, out_size = 0; + + // Do some checking of the parameters to see if they're valid and + // we can actually work with them. + if (data->image_start_offset > data->image_end_offset) { + GST_WARNING ("Invalid image start/end offset"); + g_free (data); + *mapping_data = NULL; + gst_clear_caps (&caps); + + return NULL; + } + + if (!g_size_checked_mul (&expected_in_stride, data->bpp, data->width) || + (out_stride = GST_ROUND_UP_4 (expected_in_stride)) < expected_in_stride + || !g_size_checked_mul (&expected_in_size, expected_in_stride, + data->height) + || !g_size_checked_mul (&out_size, out_stride, data->height)) { + GST_ERROR ("Invalid resolution or bit depth"); + g_free (data); + *mapping_data = NULL; + gst_clear_caps (&caps); + + return NULL; + } + } + return caps; }