diff options
authorRasmus Villemoes <linux@rasmusvillemoes.dk>2017-10-30 22:35:47 +0100
committerThomas Gleixner <tglx@linutronix.de>2017-11-12 23:25:40 +0100
commitffc661c99f621152d5fdcf53f9df0d48c326318b (patch)
parent306eb5a38dfc1a4c8a5c910c9844da6a97f2b9a4 (diff)
genirq: Fix type of shifting literal 1 in __setup_irq()
If ffz() ever returns a value >= 31 then the following shift is undefined behaviour because the literal 1 which gets shifted is treated as signed integer. In practice, the bug is probably harmless, since the first undefined shift count is 31 which results - ignoring UB - in (int)(0x80000000). This gets sign extended so bit 32-63 will be set as well and all subsequent __setup_irq() calls would just end up hitting the -EBUSY branch. However, a sufficiently aggressive optimizer may use the UB of 1<<31 to decide that doesn't happen, and hence elide the sign-extension code, so that subsequent calls can indeed get ffz > 31. In any case, the right thing to do is to make the literal 1UL. [ tglx: For this to happen a single interrupt would have to be shared by 32 devices. Hardware like that does not exist and would have way more problems than that. ] Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20171030213548.16831-1-linux@rasmusvillemoes.dk
1 files changed, 1 insertions, 1 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index c65f282cbc9a..6a1bf9dc7a6a 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1289,7 +1289,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
* thread_mask assigned. See the loop above which or's
* all existing action->thread_mask bits.
- new->thread_mask = 1 << ffz(thread_mask);
+ new->thread_mask = 1UL << ffz(thread_mask);
} else if (new->handler == irq_default_primary_handler &&
!(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) {

Privacy Policy