diff options
author | Olivier Certner <olce@FreeBSD.org> | 2025-03-04 11:17:45 +0000 |
---|---|---|
committer | Olivier Certner <olce@FreeBSD.org> | 2025-03-11 13:54:09 +0000 |
commit | 7e61fc76400cce08de39adde99b879f0bca21b7d (patch) | |
tree | 222239e61ef241632cb087dd8b725500365eb09a | |
parent | d1f351fcb22f46805ff0a0cecf6ce787f84d31d5 (diff) |
libsa: smbios: Stop parsing on an End-of-Table structure
This structure exists since SMBIOS v2.2 and indicates that there are no
structures to be parsed beyond this point. For backwards compatibility,
the standard recommends that system software ensures that this structure
covers the rest of the SMBIOS structure table area as reported by the
Structure Table Address, and the Structure Table Maximum Size (64-bit
entry point) or the Structure Table Length (32-bit entry point), which
makes existing parsers continue to work correctly as they usually ignore
unknown structure types. However, this is not a requirement, so be
bullet proof and immediately stop parsing in this case.
Reviewed by: imp, markj
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D49285
-rw-r--r-- | stand/libsa/smbios.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/stand/libsa/smbios.c b/stand/libsa/smbios.c index e726dfeb7af3..50cab3eee939 100644 --- a/stand/libsa/smbios.c +++ b/stand/libsa/smbios.c @@ -92,6 +92,7 @@ #define SMBIOS_SIG "_SM_" #define SMBIOS3_SIG "_SM3_" #define SMBIOS_DMI_SIG "_DMI_" +#define SMBIOS_EOT_TYPE 0x7f /* * 5.1 General @@ -504,6 +505,9 @@ smbios_parse_table(const caddr_t addr) (size & 0x7fff) : (size << 10); break; + case SMBIOS_EOT_TYPE: /* 3.3.42 End-of-Table (Type 127) */ + return (NULL); + default: /* skip other types */ break; } @@ -529,15 +533,19 @@ smbios_find_struct(int type) ep = smbios.addr + smbios.length; for (dmi = smbios.addr, i = 0; dmi < ep && i < smbios.count; i++) { - if (SMBIOS_GET8(dmi, 0) == type) { - return dmi; - } + const uint8_t seen_type = SMBIOS_GET8(dmi, 0); + + if (seen_type == type) + return (dmi); + if (seen_type == SMBIOS_EOT_TYPE) + /* End of table. */ + break; /* Find structure terminator. */ dmi = SMBIOS_GETSTR(dmi); - while (SMBIOS_GET16(dmi, 0) != 0 && dmi < ep) { + while (SMBIOS_GET16(dmi, 0) != 0 && dmi < ep) dmi++; - } - dmi += 2; /* For checksum */ + /* Skip it. */ + dmi += 2; } return (NULL); @@ -632,8 +640,8 @@ smbios_detect(const caddr_t addr) if (smbios.addr == NULL) return; - for (dmi = smbios.addr, i = 0; - dmi < smbios.addr + smbios.length && i < smbios.count; i++) + for (dmi = smbios.addr, i = 0; dmi != NULL && + dmi < smbios.addr + smbios.length && i < smbios.count; i++) dmi = smbios_parse_table(dmi); setenv("smbios.entry_point_type", |