Commit 5d64089a authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Thomas Gleixner

x86/PCI: Add PIRQ routing table range checks

Verify that the PCI IRQ Routing Table header as well as individual slot 
entries are all wholly contained within the BIOS memory area.  Do not 
even call the checksum calculator if the header would overrun the area 
and then bail out early if any slot would.
Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203301735510.22465@angie.orcam.me.uk
parent fe62bc23
...@@ -68,7 +68,8 @@ void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq; ...@@ -68,7 +68,8 @@ void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq;
* and perform checksum verification. * and perform checksum verification.
*/ */
static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr) static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr,
u8 *limit)
{ {
struct irq_routing_table *rt; struct irq_routing_table *rt;
int i; int i;
...@@ -78,7 +79,8 @@ static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr) ...@@ -78,7 +79,8 @@ static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr)
if (rt->signature != PIRQ_SIGNATURE || if (rt->signature != PIRQ_SIGNATURE ||
rt->version != PIRQ_VERSION || rt->version != PIRQ_VERSION ||
rt->size % 16 || rt->size % 16 ||
rt->size < sizeof(struct irq_routing_table)) rt->size < sizeof(struct irq_routing_table) ||
(limit && rt->size > limit - addr))
return NULL; return NULL;
sum = 0; sum = 0;
for (i = 0; i < rt->size; i++) for (i = 0; i < rt->size; i++)
...@@ -99,17 +101,22 @@ static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr) ...@@ -99,17 +101,22 @@ static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr)
static struct irq_routing_table * __init pirq_find_routing_table(void) static struct irq_routing_table * __init pirq_find_routing_table(void)
{ {
u8 * const bios_start = (u8 *)__va(0xf0000);
u8 * const bios_end = (u8 *)__va(0x100000);
u8 *addr; u8 *addr;
struct irq_routing_table *rt; struct irq_routing_table *rt;
if (pirq_table_addr) { if (pirq_table_addr) {
rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr)); rt = pirq_check_routing_table((u8 *)__va(pirq_table_addr),
NULL);
if (rt) if (rt)
return rt; return rt;
printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
} }
for (addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { for (addr = bios_start;
rt = pirq_check_routing_table(addr); addr < bios_end - sizeof(struct irq_routing_table);
addr += 16) {
rt = pirq_check_routing_table(addr, bios_end);
if (rt) if (rt)
return rt; return rt;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment