mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
thunderbolt: Require complete DROM entry headers
tb_drom_parse_entries() checks for one byte remaining before reading a DROM entry header, but the header occupies two bytes. It also accepts a declared length of one byte. A one-byte tail consequently makes the parser read entry->len outside the DROM. A one-byte generic string entry reaches the subtype parser and underflows its payload-length calculation. Require a complete entry header before reading it and require the declared entry length to cover that header. Use subtraction-based bounds checks so the firmware-provided length cannot overflow the DROM extent calculation. While at it, use the actual const type instead of void * to make it clear we only read these. Assisted-by: Codex:gpt-5 Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
parent
ae35035da9
commit
b946f490be
|
|
@ -324,7 +324,7 @@ int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid)
|
|||
}
|
||||
|
||||
static int tb_drom_parse_entry_generic(struct tb_switch *sw,
|
||||
struct tb_drom_entry_header *header)
|
||||
const struct tb_drom_entry_header *header)
|
||||
{
|
||||
const struct tb_drom_entry_generic *entry =
|
||||
(const struct tb_drom_entry_generic *)header;
|
||||
|
|
@ -360,7 +360,7 @@ static int tb_drom_parse_entry_generic(struct tb_switch *sw,
|
|||
}
|
||||
|
||||
static int tb_drom_parse_entry_port(struct tb_switch *sw,
|
||||
struct tb_drom_entry_header *header)
|
||||
const struct tb_drom_entry_header *header)
|
||||
{
|
||||
struct tb_port *port;
|
||||
int res;
|
||||
|
|
@ -386,11 +386,13 @@ static int tb_drom_parse_entry_port(struct tb_switch *sw,
|
|||
type &= 0xffffff;
|
||||
|
||||
if (type == TB_TYPE_PORT) {
|
||||
struct tb_drom_entry_port *entry = (void *) header;
|
||||
const struct tb_drom_entry_port *entry =
|
||||
(const struct tb_drom_entry_port *)header;
|
||||
|
||||
if (header->len != sizeof(*entry)) {
|
||||
tb_sw_warn(sw,
|
||||
"port entry has size %#x (expected %#zx)\n",
|
||||
header->len, sizeof(struct tb_drom_entry_port));
|
||||
header->len, sizeof(*entry));
|
||||
return -EIO;
|
||||
}
|
||||
port->link_nr = entry->link_nr;
|
||||
|
|
@ -421,9 +423,16 @@ static int tb_drom_parse_entries(struct tb_switch *sw, size_t header_size)
|
|||
int res;
|
||||
|
||||
while (pos < drom_size) {
|
||||
struct tb_drom_entry_header *entry = (void *) (sw->drom + pos);
|
||||
if (pos + 1 == drom_size || pos + entry->len > drom_size
|
||||
|| !entry->len) {
|
||||
const struct tb_drom_entry_header *entry;
|
||||
|
||||
if (drom_size - pos < sizeof(*entry)) {
|
||||
tb_sw_warn(sw, "DROM buffer overrun\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
entry = (const struct tb_drom_entry_header *)(sw->drom + pos);
|
||||
if (entry->len < sizeof(*entry) ||
|
||||
entry->len > drom_size - pos) {
|
||||
tb_sw_warn(sw, "DROM buffer overrun\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user