summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksandermj@chromium.org>2023-10-30 12:56:26 +0000
committerAleksander Morgado <aleksandermj@chromium.org>2023-10-30 14:12:33 +0000
commit128f63528614aaa07b60c8e7bc5627e8bb6f4717 (patch)
tree30d086d31791dd6530ed58695ed39fc60c0f2970
parent158111dacc25679718b0b54ac3eb49cf7269dbaa (diff)
mbim-codegen,struct: support 'unsized-byte-array' as part of a struct with known length
Fixes segfault when parsing "Terminal Capability" response messages with invalid data. ==2083974==ERROR: MemorySanitizer: SEGV on unknown address 0x704100000143 (pc 0x7f2c1fcb71fd bp 0x7fffdf329090 sp 0x7fffdf328848 T2083974) ==2083974==The signal is caused by a READ memory access. #0 0x7f2c1fcb71fd in memcpy@GLIBC_2.2.5 /var/tmp/portage/cross-x86_64-cros-linux-gnu/glibc-2.35-r25/work/glibc-2.35/string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:222 #1 0x55d6c6e9b270 in _mbim_message_read_mbim_terminal_capability_info_struct /build/amd64-generic/tmp/portage/net-libs/libmbim-9999/work/libmbim-9999-build/src/libmbim-glib/generated/mbim-ms-uicc-low-level-access.c:69:9 #2 0x55d6c6e9b270 in _mbim_message_read_mbim_terminal_capability_info_ref_struct_array /build/amd64-generic/tmp/portage/net-libs/libmbim-9999/work/libmbim-9999-build/src/libmbim-glib/generated/mbim-ms-uicc-low-level-access.c:114:22 #3 0x55d6c6ea3375 in mbim_message_ms_uicc_low_level_access_terminal_capability_set_get_printable /build/amd64-generic/tmp/portage/net-libs/libmbim-9999/work/libmbim-9999-build/src/libmbim-glib/generated/mbim-ms-uicc-low-level-access.c:1364:14 #4 0x55d6c6df9e42 in mbim_message_get_printable_full /build/amd64-generic/tmp/portage/net-libs/libmbim-9999/work/libmbim-9999-build/../libmbim-9999/src/libmbim-glib/mbim-message.c:2229:32 #5 0x55d6c6defd27 in LLVMFuzzerTestOneInput /build/amd64-generic/tmp/portage/net-libs/libmbim-9999/work/libmbim-9999-build/../libmbim-9999/src/libmbim-glib/test/test-message-fuzzer.c:31:17 #6 0x55d6c6d3ae30 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/usr/libexec/fuzzers/test-mbim-message-fuzzer+0x87e30) (BuildId: 7be533406832bc29) #7 0x55d6c6d25750 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/usr/libexec/fuzzers/test-mbim-message-fuzzer+0x72750) (BuildId: 7be533406832bc29) #8 0x55d6c6d2ab84 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/usr/libexec/fuzzers/test-mbim-message-fuzzer+0x77b84) (BuildId: 7be533406832bc29) #9 0x55d6c6d560f2 in main (/usr/libexec/fuzzers/test-mbim-message-fuzzer+0xa30f2) (BuildId: 7be533406832bc29) #10 0x7f2c1fc3f6c5 in __libc_start_call_main /var/tmp/portage/cross-x86_64-cros-linux-gnu/glibc-2.35-r25/work/glibc-2.35/csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #11 0x7f2c1fc3f781 in __libc_start_main@GLIBC_2.2.5 /var/tmp/portage/cross-x86_64-cros-linux-gnu/glibc-2.35-r25/work/glibc-2.35/csu/../csu/libc-start.c:389:3 #12 0x55d6c6d1cb70 in _start (/usr/libexec/fuzzers/test-mbim-message-fuzzer+0x69b70) (BuildId: 7be533406832bc29)
-rw-r--r--build-aux/mbim-codegen/Struct.py21
-rw-r--r--src/libmbim-glib/test/test-message-fuzzer-samples.c16
2 files changed, 32 insertions, 5 deletions
diff --git a/build-aux/mbim-codegen/Struct.py b/build-aux/mbim-codegen/Struct.py
index 8222940..95ae16a 100644
--- a/build-aux/mbim-codegen/Struct.py
+++ b/build-aux/mbim-codegen/Struct.py
@@ -579,17 +579,28 @@ class Struct:
# fro the variable buffer, which is currently not implemented for this type.
if self.ms_struct_array_member == True:
raise ValueError('type unsupported in \'ms-struct-array\'')
-
inner_template += (
'\n'
' {\n'
' const guint8 *tmp;\n'
- '\n'
- ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, FALSE, FALSE, 0, &tmp, &(out->${field_name_underscore}_size), error, FALSE))\n'
- ' goto out;\n'
+ '\n')
+ if self.ref_struct_array_member == True:
+ # When the unsized-byte-array is given inside a struct, its length may already be known, e.g. if the
+ # array is a ref-struct-array of OL pairs (the 'L' length of the array item implicitly defines the
+ # length of the byte array. In this case, we must provide an explicit_array_size and avoid trying
+ # to read until the end of the message.
+ inner_template += (
+ ' out->${field_name_underscore}_size = explicit_struct_size - (offset - relative_offset);\n'
+ ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, FALSE, FALSE, out->${field_name_underscore}_size, &tmp, NULL, error, FALSE))\n'
+ ' goto out;\n')
+ else:
+ inner_template += (
+ ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, FALSE, FALSE, 0, &tmp, &(out->${field_name_underscore}_size), error, FALSE))\n'
+ ' goto out;\n')
+ inner_template += (
' out->${field_name_underscore} = g_malloc (out->${field_name_underscore}_size);\n'
' memcpy (out->${field_name_underscore}, tmp, out->${field_name_underscore}_size);\n'
- ' /* no offset update expected, this should be the last field */\n'
+ ' /* no offset update expected, this should be the last field in the struct */\n'
' }\n')
elif field['format'] == 'byte-array':
translations['array_size'] = field['array-size']
diff --git a/src/libmbim-glib/test/test-message-fuzzer-samples.c b/src/libmbim-glib/test/test-message-fuzzer-samples.c
index 63f0dcb..c80f3ca 100644
--- a/src/libmbim-glib/test/test-message-fuzzer-samples.c
+++ b/src/libmbim-glib/test/test-message-fuzzer-samples.c
@@ -78,6 +78,21 @@ test_fuzzer_sample_ms_struct_array_with_string (void)
g_assert_cmpuint (LLVMFuzzerTestOneInput (data, G_N_ELEMENTS (data)), ==, 0);
}
+static void
+test_fuzzer_sample_ref_struct_array_with_unsized_bytearrays (void)
+{
+ const guint8 data[] = {
+ 0x3,0x0,0x0,0x80,0x33,0x0,0x0,0x0,0x0,0x0,0x55,0x8,0x1,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0xc2,0xf6,0x58,0x8e,0xf0,0x37,0x4b,0xc9,0x86,
+ 0x65,0xf4,0xd4,0x4b,0xd0,0x93,0x67,0x5,0x0,0x0,0x0,0x32,0x0,0x0,
+ 0x0,0x1,0x0,0x0,0x0,0x0,0x1,0x0,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0xb0,0x13,0x12,0x0,0xca,0xca,0xca,0x0,0x0,0xe8
+ };
+
+ g_assert_cmpuint (LLVMFuzzerTestOneInput (data, G_N_ELEMENTS (data)), ==, 0);
+}
+
int main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
@@ -87,6 +102,7 @@ int main (int argc, char **argv)
g_test_add_func (PREFIX "invalid-arraysize", test_fuzzer_sample_invalid_array_size);
g_test_add_func (PREFIX "invalid-offset-unbound-bytearray", test_fuzzer_sample_invalid_offset_unbound_bytearray);
g_test_add_func (PREFIX "ms-struct-array-with-string", test_fuzzer_sample_ms_struct_array_with_string);
+ g_test_add_func (PREFIX "ref-struct-array-with-unsized-bytearrays", test_fuzzer_sample_ref_struct_array_with_unsized_bytearrays);
#undef PREFIX
return g_test_run ();
}