[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <alpine.DEB.2.21.2203301735510.22465@angie.orcam.me.uk>
Date: Thu, 31 Mar 2022 08:10:55 +0100 (BST)
From: "Maciej W. Rozycki" <macro@...am.me.uk>
To: Bjorn Helgaas <bhelgaas@...gle.com>,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
"H. Peter Anvin" <hpa@...or.com>
cc: Arnd Bergmann <arnd@...nel.org>, Nikolai Zhubr <zhubr.2@...il.com>,
Michal Necasek <mnecasek@...oo.com>,
Dmitry Osipenko <dmitry.osipenko@...labora.com>,
Linus Torvalds <torvalds@...ux-foundation.org>, x86@...nel.org,
linux-pci@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH v4 1/5] 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: Maciej W. Rozycki <macro@...am.me.uk>
---
New change in v4.
---
arch/x86/pci/irq.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
linux-x86-pirq-range-check.diff
Index: linux-macro/arch/x86/pci/irq.c
===================================================================
--- linux-macro.orig/arch/x86/pci/irq.c
+++ linux-macro/arch/x86/pci/irq.c
@@ -68,7 +68,8 @@ void (*pcibios_disable_irq)(struct pci_d
* 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;
int i;
@@ -78,7 +79,8 @@ static inline struct irq_routing_table *
if (rt->signature != PIRQ_SIGNATURE ||
rt->version != PIRQ_VERSION ||
rt->size % 16 ||
- rt->size < sizeof(struct irq_routing_table))
+ rt->size < sizeof(struct irq_routing_table) ||
+ (limit && rt->size > limit - addr))
return NULL;
sum = 0;
for (i = 0; i < rt->size; i++)
@@ -99,17 +101,22 @@ static inline struct irq_routing_table *
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;
struct irq_routing_table *rt;
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)
return rt;
printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
}
- for (addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
- rt = pirq_check_routing_table(addr);
+ for (addr = bios_start;
+ addr < bios_end - sizeof(struct irq_routing_table);
+ addr += 16) {
+ rt = pirq_check_routing_table(addr, bios_end);
if (rt)
return rt;
}
Powered by blists - more mailing lists