| From 034bf5fef22c3f47dcd6584928c31dccdb96cd01 Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Fri, 6 Mar 2020 14:03:44 +0100 |
| Subject: [PATCH] x86/apic/vector: Force interupt handler invocation to irq |
| context |
| |
| commit 008f1d60fe25810d4554916744b0975d76601b64 upstream. |
| |
| Sathyanarayanan reported that the PCI-E AER error injection mechanism |
| can result in a NULL pointer dereference in apic_ack_edge(): |
| |
| BUG: unable to handle kernel NULL pointer dereference at 0000000000000078 |
| RIP: 0010:apic_ack_edge+0x1e/0x40 |
| Call Trace: |
| handle_edge_irq+0x7d/0x1e0 |
| generic_handle_irq+0x27/0x30 |
| aer_inject_write+0x53a/0x720 |
| |
| It crashes in irq_complete_move() which dereferences get_irq_regs() which |
| is obviously NULL when this is called from non interrupt context. |
| |
| Of course the pointer could be checked, but that just papers over the real |
| issue. Invoking the low level interrupt handling mechanism from random code |
| can wreckage the fragile interrupt affinity mechanism of x86 as interrupts |
| can only be moved in interrupt context or with special care when a CPU goes |
| offline and the move has to be enforced. |
| |
| In the best case this triggers the warning in the MSI affinity setter, but |
| if the call happens on the correct CPU it just corrupts state and might |
| prevent further interrupt delivery for the affected device. |
| |
| Mark the APIC interrupts as unsuitable for being invoked in random contexts. |
| |
| This prevents the AER injection from proliferating the wreckage, but that's |
| less broken than the current state of affairs and more correct than just |
| papering over the problem by sprinkling random checks all over the place |
| and silently corrupting state. |
| |
| Reported-by: sathyanarayanan.kuppuswamy@linux.intel.com |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Link: https://lkml.kernel.org/r/20200306130623.684591280@linutronix.de |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c |
| index 18c0dca08163..c1857c08706e 100644 |
| --- a/arch/x86/kernel/apic/vector.c |
| +++ b/arch/x86/kernel/apic/vector.c |
| @@ -554,6 +554,12 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq, |
| irqd->chip_data = apicd; |
| irqd->hwirq = virq + i; |
| irqd_set_single_target(irqd); |
| + /* |
| + * Prevent that any of these interrupts is invoked in |
| + * non interrupt context via e.g. generic_handle_irq() |
| + * as that can corrupt the affinity move state. |
| + */ |
| + irqd_set_handle_enforce_irqctx(irqd); |
| /* |
| * Legacy vectors are already assigned when the IOAPIC |
| * takes them over. They stay on the same vector. This is |
| -- |
| 2.27.0 |
| |