]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
smbios: move validation of SMBIOS table sizes fully into get_smbios_table()
authorLennart Poettering <lennart@poettering.net>
Fri, 11 Oct 2024 09:11:50 +0000 (11:11 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 11 Oct 2024 09:54:02 +0000 (11:54 +0200)
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

index 7d7d0d138272ef0c0e6aa35fb421c0edb0d446b8..5d20b3a195b598ccea866c5174a56a9bb600c621 100644 (file)
@@ -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; ) {