Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Fix irq_free_virt by adjusting bounds before loop

Instead of looping over each irq and checking against the irq array
bounds, adjust the bounds before looping.

The old code will not free any irq if the irq + count is above
irq_virq_count because the test in the loop is testing irq + count
instead of irq + i.

This code checks the limits to avoid unsigned integer overflows.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Milton Miller and committed by
Benjamin Herrenschmidt
4dd60290 9b788251

+13 -4
+13 -4
arch/powerpc/kernel/irq.c
··· 1007 1007 WARN_ON (virq < NUM_ISA_INTERRUPTS); 1008 1008 WARN_ON (count == 0 || (virq + count) > irq_virq_count); 1009 1009 1010 + if (virq < NUM_ISA_INTERRUPTS) { 1011 + if (virq + count < NUM_ISA_INTERRUPTS) 1012 + return; 1013 + count =- NUM_ISA_INTERRUPTS - virq; 1014 + virq = NUM_ISA_INTERRUPTS; 1015 + } 1016 + 1017 + if (count > irq_virq_count || virq > irq_virq_count - count) { 1018 + if (virq > irq_virq_count) 1019 + return; 1020 + count = irq_virq_count - virq; 1021 + } 1022 + 1010 1023 raw_spin_lock_irqsave(&irq_big_lock, flags); 1011 1024 for (i = virq; i < (virq + count); i++) { 1012 1025 struct irq_host *host; 1013 - 1014 - if (i < NUM_ISA_INTERRUPTS || 1015 - (virq + count) > irq_virq_count) 1016 - continue; 1017 1026 1018 1027 host = irq_map[i].host; 1019 1028 irq_map[i].hwirq = host->inval_irq;