diff options
author | Jean Delvare <jdelvare@suse.de> | 2021-01-15 17:20:16 +0100 |
---|---|---|
committer | Jean Delvare <jdelvare@suse.de> | 2021-01-15 17:20:16 +0100 |
commit | 89efc6b9563a70da9f2a91c05455ba9e7b37e126 (patch) | |
tree | 5f399b6ed6aef438d3c5d84f510192ea9f6c0838 | |
parent | 1117390ccd9cea139638db6f460bb6de70e28f94 (diff) | |
download | dmidecode-git-89efc6b9563a70da9f2a91c05455ba9e7b37e126.tar.gz |
dmidecode: Set vendor early
If OEM type entries come before the type 1 entry (System
Information), we aren't able to decode them because we don't know
the vendor yet. To fix this, figure out the vendor during a first
pass, and walk the table again once we have the information.
Signed-off-by: Jean Delvare <jdelvare@suse.de>
Reported-by: Erwan Velu <e.velu@criteo.com>
-rw-r--r-- | dmidecode.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/dmidecode.c b/dmidecode.c index 864a193..344dce7 100644 --- a/dmidecode.c +++ b/dmidecode.c @@ -5182,6 +5182,51 @@ static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags) u8 *data; int i = 0; + /* First pass: Save the vendor so that so that we can decode OEM types */ + data = buf; + while ((i < num || !num) + && data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */ + { + u8 *next; + struct dmi_header h; + + to_dmi_header(&h, data); + + /* + * If a short entry is found (less than 4 bytes), not only it + * is invalid, but we cannot reliably locate the next entry. + * Also stop at end-of-table marker if so instructed. + */ + if (h.length < 4 || + (h.type == 127 && + (opt.flags & (FLAG_QUIET | FLAG_STOP_AT_EOT)))) + break; + i++; + + /* Look for the next handle */ + next = data + h.length; + while ((unsigned long)(next - buf + 1) < len + && (next[0] != 0 || next[1] != 0)) + next++; + next += 2; + + /* Make sure the whole structure fits in the table */ + if ((unsigned long)(next - buf) > len) + break; + + /* Assign vendor for vendor-specific decodes later */ + if (h.type == 1 && h.length >= 6) + { + dmi_set_vendor(_dmi_string(&h, data[0x04], 0), + _dmi_string(&h, data[0x05], 0)); + break; + } + + data = next; + } + + /* Second pass: Actually decode the data */ + i = 0; data = buf; while ((i < num || !num) && data + 4 <= buf + len) /* 4 is the length of an SMBIOS structure header */ @@ -5241,11 +5286,6 @@ static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags) break; } - /* assign vendor for vendor-specific decodes later */ - if (h.type == 1 && h.length >= 6) - dmi_set_vendor(_dmi_string(&h, data[0x04], 0), - _dmi_string(&h, data[0x05], 0)); - /* Fixup a common mistake */ if (h.type == 34) dmi_fixup_type_34(&h, display); |