[PATCH 3.19 068/101] firmware: dmi_scan: Prevent dmi_num integer overflow
3.19-stable review patch. If anyone has any objections, please let me know. -- From: Jean Delvare commit bfbaafae8519d82d10da6abe75f5766dd5b20475 upstream. dmi_num is a u16, dmi_len is a u32, so this construct: dmi_num = dmi_len / 4; would result in an integer overflow for a DMI table larger than 256 kB. I've never see such a large table so far, but SMBIOS 3.0 makes it possible so maybe we'll see such tables in the future. So instead of faking a structure count when the entry point does not provide it, adjust the loop condition in dmi_table() to properly deal with the case where dmi_num is not set. This bug was introduced with the initial SMBIOS 3.0 support in commit fc43026278b2 ("dmi: add support for SMBIOS 3.0 64-bit entry point"). Signed-off-by: Jean Delvare Cc: Matt Fleming Cc: Ivan Khoronzhuk Acked-by: Ard Biesheuvel Signed-off-by: Matt Fleming Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi_scan.c | 22 +++--- 1 file changed, 7 insertions(+), 15 deletions(-) --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -86,10 +86,13 @@ static void dmi_table(u8 *buf, u32 len, int i = 0; /* -* Stop when we see all the items the table claimed to have -* OR we run off the end of the table (also happens) +* Stop when we have seen all the items the table claimed to have +* (SMBIOS < 3.0 only) OR we reach an end-of-table marker OR we run +* off the end of the table (should never happen but sometimes does +* on bogus implementations.) */ - while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { + while ((!num || i < num) && + (data - buf + sizeof(struct dmi_header)) <= len) { const struct dmi_header *dm = (const struct dmi_header *)data; /* @@ -529,21 +532,10 @@ static int __init dmi_smbios3_present(co if (memcmp(buf, "_SM3_", 5) == 0 && buf[6] < 32 && dmi_checksum(buf, buf[6])) { dmi_ver = get_unaligned_be16(buf + 7); + dmi_num = 0;/* No longer specified */ dmi_len = get_unaligned_le32(buf + 12); dmi_base = get_unaligned_le64(buf + 16); - /* -* The 64-bit SMBIOS 3.0 entry point no longer has a field -* containing the number of structures present in the table. -* Instead, it defines the table size as a maximum size, and -* relies on the end-of-table structure type (#127) to be used -* to signal the end of the table. -* So let's define dmi_num as an upper bound as well: each -* structure has a 4 byte header, so dmi_len / 4 is an upper -* bound for the number of structures in the table. -*/ - dmi_num = dmi_len / 4; - if (dmi_walk_early(dmi_decode) == 0) { pr_info("SMBIOS %d.%d present.\n", dmi_ver >> 8, dmi_ver & 0xFF); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3.19 068/101] firmware: dmi_scan: Prevent dmi_num integer overflow
3.19-stable review patch. If anyone has any objections, please let me know. -- From: Jean Delvare jdelv...@suse.de commit bfbaafae8519d82d10da6abe75f5766dd5b20475 upstream. dmi_num is a u16, dmi_len is a u32, so this construct: dmi_num = dmi_len / 4; would result in an integer overflow for a DMI table larger than 256 kB. I've never see such a large table so far, but SMBIOS 3.0 makes it possible so maybe we'll see such tables in the future. So instead of faking a structure count when the entry point does not provide it, adjust the loop condition in dmi_table() to properly deal with the case where dmi_num is not set. This bug was introduced with the initial SMBIOS 3.0 support in commit fc43026278b2 (dmi: add support for SMBIOS 3.0 64-bit entry point). Signed-off-by: Jean Delvare jdelv...@suse.de Cc: Matt Fleming matt.flem...@intel.com Cc: Ivan Khoronzhuk ivan.khoronz...@linaro.org Acked-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Matt Fleming matt.flem...@intel.com Signed-off-by: Greg Kroah-Hartman gre...@linuxfoundation.org --- drivers/firmware/dmi_scan.c | 22 +++--- 1 file changed, 7 insertions(+), 15 deletions(-) --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -86,10 +86,13 @@ static void dmi_table(u8 *buf, u32 len, int i = 0; /* -* Stop when we see all the items the table claimed to have -* OR we run off the end of the table (also happens) +* Stop when we have seen all the items the table claimed to have +* (SMBIOS 3.0 only) OR we reach an end-of-table marker OR we run +* off the end of the table (should never happen but sometimes does +* on bogus implementations.) */ - while ((i num) (data - buf + sizeof(struct dmi_header)) = len) { + while ((!num || i num) + (data - buf + sizeof(struct dmi_header)) = len) { const struct dmi_header *dm = (const struct dmi_header *)data; /* @@ -529,21 +532,10 @@ static int __init dmi_smbios3_present(co if (memcmp(buf, _SM3_, 5) == 0 buf[6] 32 dmi_checksum(buf, buf[6])) { dmi_ver = get_unaligned_be16(buf + 7); + dmi_num = 0;/* No longer specified */ dmi_len = get_unaligned_le32(buf + 12); dmi_base = get_unaligned_le64(buf + 16); - /* -* The 64-bit SMBIOS 3.0 entry point no longer has a field -* containing the number of structures present in the table. -* Instead, it defines the table size as a maximum size, and -* relies on the end-of-table structure type (#127) to be used -* to signal the end of the table. -* So let's define dmi_num as an upper bound as well: each -* structure has a 4 byte header, so dmi_len / 4 is an upper -* bound for the number of structures in the table. -*/ - dmi_num = dmi_len / 4; - if (dmi_walk_early(dmi_decode) == 0) { pr_info(SMBIOS %d.%d present.\n, dmi_ver 8, dmi_ver 0xFF); -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/