From b7c544c759e8010d07dadd764d59703f3d839bb3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Oct 2024 11:11:50 +0200 Subject: [PATCH] smbios: move validation of SMBIOS table sizes fully into get_smbios_table() We do half a validation currently ourselves (i.e. check the header fits into the rest of the data), and leave the other half to the caller (i.e. check the table fits into the rest of the data). get_smbios_table() is changed to accept the minimum object size and validates it before returning a table. Based on a discussion with @anonymix007. --- src/boot/efi/vmm.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c index 7d7d0d13827..5d20b3a195b 100644 --- a/src/boot/efi/vmm.c +++ b/src/boot/efi/vmm.c @@ -213,7 +213,7 @@ static const void *find_smbios_configuration_table(uint64_t *ret_size) { return NULL; } -static const SmbiosHeader *get_smbios_table(uint8_t type, uint64_t *ret_size_left) { +static const SmbiosHeader *get_smbios_table(uint8_t type, size_t min_size, uint64_t *ret_size_left) { uint64_t size = 0; const uint8_t *p = find_smbios_configuration_table(&size); if (!p) @@ -233,6 +233,10 @@ static const SmbiosHeader *get_smbios_table(uint8_t type, uint64_t *ret_size_lef return NULL; if (header->type == type) { + /* Table is smaller than the minimum expected size? Refuse */ + if (header->length < min_size) + return NULL; + if (ret_size_left) *ret_size_left = size; return header; /* Yay! */ @@ -273,8 +277,8 @@ static const SmbiosHeader *get_smbios_table(uint8_t type, uint64_t *ret_size_lef static bool smbios_in_hypervisor(void) { /* Look up BIOS Information (Type 0). */ - const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0, NULL); - if (!type0 || type0->header.length < sizeof(SmbiosTableType0)) + const SmbiosTableType0 *type0 = (const SmbiosTableType0 *) get_smbios_table(0, sizeof(SmbiosTableType0), /* left= */ NULL); + if (!type0) return false; /* Bit 4 of 2nd BIOS characteristics extension bytes indicates virtualization. */ @@ -295,13 +299,13 @@ const char* smbios_find_oem_string(const char *name) { assert(name); - const SmbiosTableType11 *type11 = (const SmbiosTableType11 *) get_smbios_table(11, &left); - if (!type11 || type11->header.length < sizeof(SmbiosTableType11)) + const SmbiosTableType11 *type11 = (const SmbiosTableType11 *) get_smbios_table(11, sizeof(SmbiosTableType11), &left); + if (!type11) return NULL; - assert(left >= type11->header.length); - const char *s = type11->contents; + + assert(left >= type11->header.length); /* get_smbios_table() already validated this */ left -= type11->header.length; for (const char *p = s; p < s + left; ) { -- 2.47.3