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

Configure Feed

Select the types of activity you want to include in your feed.

Fix crash with irqpoll due to the IRQF_IRQPOLL flag testing

With irqpoll enabled, trying to test the IRQF_IRQPOLL flag in the
actions would cause a NULL pointer dereference if no action was
installed (for example, the driver might have been unloaded with
interrupts still pending).

So be a bit more careful about testing the flag by making sure to test
for that case.

(The actual _change_ is trivial, the patch is more than a one-liner
because I rewrote the testing to also be much more readable.

Original (discarded) bugfix by Bernhard Walle.

Cc: Bernhard Walle <bwalle@suse.de>
Tested-by: Vivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+37 -9
+37 -9
kernel/irq/spurious.c
··· 135 135 } 136 136 } 137 137 138 + static inline int try_misrouted_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) 139 + { 140 + struct irqaction *action; 141 + 142 + if (!irqfixup) 143 + return 0; 144 + 145 + /* We didn't actually handle the IRQ - see if it was misrouted? */ 146 + if (action_ret == IRQ_NONE) 147 + return 1; 148 + 149 + /* 150 + * But for 'irqfixup == 2' we also do it for handled interrupts if 151 + * they are marked as IRQF_IRQPOLL (or for irq zero, which is the 152 + * traditional PC timer interrupt.. Legacy) 153 + */ 154 + if (irqfixup < 2) 155 + return 0; 156 + 157 + if (!irq) 158 + return 1; 159 + 160 + /* 161 + * Since we don't get the descriptor lock, "action" can 162 + * change under us. We don't really care, but we don't 163 + * want to follow a NULL pointer. So tell the compiler to 164 + * just load it once by using a barrier. 165 + */ 166 + action = desc->action; 167 + barrier(); 168 + return action && (action->flags & IRQF_IRQPOLL); 169 + } 170 + 138 171 void note_interrupt(unsigned int irq, struct irq_desc *desc, 139 172 irqreturn_t action_ret) 140 173 { ··· 177 144 report_bad_irq(irq, desc, action_ret); 178 145 } 179 146 180 - if (unlikely(irqfixup)) { 181 - /* Don't punish working computers */ 182 - if ((irqfixup == 2 && ((irq == 0) || 183 - (desc->action->flags & IRQF_IRQPOLL))) || 184 - action_ret == IRQ_NONE) { 185 - int ok = misrouted_irq(irq); 186 - if (action_ret == IRQ_NONE) 187 - desc->irqs_unhandled -= ok; 188 - } 147 + if (unlikely(try_misrouted_irq(irq, desc, action_ret))) { 148 + int ok = misrouted_irq(irq); 149 + if (action_ret == IRQ_NONE) 150 + desc->irqs_unhandled -= ok; 189 151 } 190 152 191 153 desc->irq_count++;