diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2023-10-30 12:56:26 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksandermj@chromium.org> | 2023-10-30 14:12:33 +0000 |
commit | 128f63528614aaa07b60c8e7bc5627e8bb6f4717 (patch) | |
tree | 30d086d31791dd6530ed58695ed39fc60c0f2970 | |
parent | 158111dacc25679718b0b54ac3eb49cf7269dbaa (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.py | 21 | ||||
-rw-r--r-- | src/libmbim-glib/test/test-message-fuzzer-samples.c | 16 |
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 (); } |