summaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
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)
tree541eeda902b4a35a7fab7fd92cdf9691a3e691f1 /kernel/irq
parent306eb5a38dfc1a4c8a5c910c9844da6a97f2b9a4 (diff)
downloadlinux-ffc661c99f621152d5fdcf53f9df0d48c326318b.tar.gz
linux-ffc661c99f621152d5fdcf53f9df0d48c326318b.tar.bz2
linux-ffc661c99f621152d5fdcf53f9df0d48c326318b.zip
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
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/manage.c2
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)) {