From dd3e1bf2433db47d1f808f3e2722332876285e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20V=C3=B6lcker?= Date: Mon, 6 Jul 2026 12:11:27 +0200 Subject: [PATCH] Sanity checks tag and length parameteters This fixes a potential read OOM vulnerability in the TLV structure. For example, an attacker could change the length value of a TLV forcing a read outside the size of the SEI. Updates ONVIF Media Signing to r25.12.4. The version is bumped to v2.3.7. --- lib/src/sv_internal.h | 2 +- lib/src/sv_tlv.c | 30 ++++++++++++++++++++++++------ media-signing-framework | 2 +- meson.build | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/src/sv_internal.h b/lib/src/sv_internal.h index 20a680f..73cdd38 100644 --- a/lib/src/sv_internal.h +++ b/lib/src/sv_internal.h @@ -50,7 +50,7 @@ #define DEFAULT_HASH_SIZE (256 / 8) #define SV_VERSION_BYTES 3 -#define SIGNED_VIDEO_VERSION "v2.3.6" +#define SIGNED_VIDEO_VERSION "v2.3.7" #define SV_VERSION_MAX_STRLEN 19 // Longest possible string including 'ONVIF' prefix #define DEFAULT_AUTHENTICITY_LEVEL SV_AUTHENTICITY_LEVEL_FRAME diff --git a/lib/src/sv_tlv.c b/lib/src/sv_tlv.c index 671e122..6c84103 100644 --- a/lib/src/sv_tlv.c +++ b/lib/src/sv_tlv.c @@ -177,7 +177,11 @@ get_decoder(sv_tlv_tag_t tag); static sv_tlv_tuple_t get_tlv_tuple(sv_tlv_tag_t tag); static svrc_t -decode_tlv_header(const uint8_t *data, size_t *data_bytes_read, sv_tlv_tag_t *tag, size_t *length); +decode_tlv_header(const uint8_t *data, + size_t bytes_left, + size_t *data_bytes_read, + sv_tlv_tag_t *tag, + size_t *length); /* Selects and returns the correct decoder from either |tlv_tuples| or |vendor_tlv_tuples|. */ static sv_tlv_decoder_t @@ -1097,10 +1101,14 @@ sv_tlv_list_encode_or_get_size(signed_video_t *self, } static svrc_t -decode_tlv_header(const uint8_t *data, size_t *data_bytes_read, sv_tlv_tag_t *tag, size_t *length) +decode_tlv_header(const uint8_t *data, + size_t bytes_left, + size_t *data_bytes_read, + sv_tlv_tag_t *tag, + size_t *length) { - // Sanity checks on input parameters. - if (!data || !data_bytes_read || !tag || !length) return SV_INVALID_PARAMETER; + // Sanity checks on input parameters. At least 2 bytes are needed to read a tag and a length. + if (!data || !data_bytes_read || !tag || !length || bytes_left < 2) return SV_INVALID_PARAMETER; const uint8_t *data_ptr = data; sv_tlv_tag_t tag_from_data = (sv_tlv_tag_t)(*data_ptr++); @@ -1112,12 +1120,20 @@ decode_tlv_header(const uint8_t *data, size_t *data_bytes_read, sv_tlv_tag_t *ta } *tag = tag_from_data; + if (bytes_left < (size_t)tlv.bytes_for_length + 1) return SV_INVALID_PARAMETER; if (tlv.bytes_for_length == 2) { data_ptr += sv_read_16bits(data_ptr, (uint16_t *)length); } else { *length = *data_ptr++; } + // Sanity check on the length. It should not exceed the remaining bytes in the data. + if (*length > bytes_left - tlv.bytes_for_length - 1) { + DEBUG_LOG("Parsed length (%zu) exceeds remaining bytes (%zu)", *length, + bytes_left - tlv.bytes_for_length - 1); + return SV_INVALID_PARAMETER; + } + *data_bytes_read = (data_ptr - data); return SV_OK; @@ -1135,7 +1151,8 @@ sv_tlv_decode(signed_video_t *self, const uint8_t *data, size_t data_size) sv_tlv_tag_t tag = 0; size_t tlv_header_size = 0; size_t length = 0; - status = decode_tlv_header(data_ptr, &tlv_header_size, &tag, &length); + status = + decode_tlv_header(data_ptr, data + data_size - data_ptr, &tlv_header_size, &tag, &length); if (status != SV_OK) { DEBUG_LOG("Could not decode TLV header (error %d)", status); break; @@ -1220,7 +1237,8 @@ sv_tlv_find_and_decode_tags(signed_video_t *self, size_t tlv_header_size = 0; size_t length = 0; sv_tlv_tag_t this_tag = UNDEFINED_TAG; - status = decode_tlv_header(tlv_data_ptr, &tlv_header_size, &this_tag, &length); + status = decode_tlv_header(tlv_data_ptr, tlv_data + tlv_data_size - tlv_data_ptr, + &tlv_header_size, &this_tag, &length); if (status != SV_OK) { DEBUG_LOG("Could not decode tlv header"); break; diff --git a/media-signing-framework b/media-signing-framework index 7634c1b..cd497c8 160000 --- a/media-signing-framework +++ b/media-signing-framework @@ -1 +1 @@ -Subproject commit 7634c1b6303263211650b533c81226d5653d1843 +Subproject commit cd497c85c5b072674e4465b7007c1e3db378a9c3 diff --git a/meson.build b/meson.build index e5073af..8b35c55 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('signed-video-framework', 'c', - version : '2.3.6', + version : '2.3.7', meson_version : '>= 0.53.0', default_options : [ 'warning_level=2', 'werror=true',