diff options
author | Daniel P. Berrangé <berrange@redhat.com> | 2020-09-23 14:38:03 +0100 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2020-09-29 02:15:24 -0400 |
commit | 10c3666658f53c5ec8fd9ec27cdf5c393ff814a0 (patch) | |
tree | 0dd1200517eecd64ff50274d4133b3a2874035b0 | |
parent | bb99f4772f54017490e3356ecbb3df25c5d4537f (diff) |
hw/smbios: report error if table size is too large
The SMBIOS 2.1 entry point uses a uint16 data type for reporting the
total length of the tables. If the user passes -smbios configuration to
QEMU that causes the table size to exceed this limit then various bad
behaviours result, including
- firmware hangs in an infinite loop
- firmware triggers a KVM crash on bad memory access
- firmware silently discards user's SMBIOS data replacing it with
a generic data set.
Limiting the size to 0xffff in QEMU avoids triggering most of these
problems. There is a remaining bug in SeaBIOS which tries to prepend its
own data for table 0, and does not check whether there is sufficient
space before attempting this.
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20200923133804.2089190-3-berrange@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r-- | hw/smbios/smbios.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index d993448087..8b30906e50 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -365,6 +365,13 @@ static void smbios_register_config(void) opts_init(smbios_register_config); +/* + * The SMBIOS 2.1 "structure table length" field in the + * entry point uses a 16-bit integer, so we're limited + * in total table size + */ +#define SMBIOS_21_MAX_TABLES_LEN 0xffff + static void smbios_validate_table(MachineState *ms) { uint32_t expect_t4_count = smbios_legacy ? @@ -375,6 +382,13 @@ static void smbios_validate_table(MachineState *ms) expect_t4_count, smbios_type4_count); exit(1); } + + if (smbios_ep_type == SMBIOS_ENTRY_POINT_21 && + smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) { + error_report("SMBIOS 2.1 table length %zu exceeds %d", + smbios_tables_len, SMBIOS_21_MAX_TABLES_LEN); + exit(1); + } } |