* [PATCH] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers
@ 2025-12-02 10:53 zhuling0805
2025-12-02 11:44 ` Marc Zyngier
0 siblings, 1 reply; 4+ messages in thread
From: zhuling0805 @ 2025-12-02 10:53 UTC (permalink / raw)
To: Marc Zyngier; +Cc: Thomas Gleixner, linux-arm-kernel, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2529 bytes --]
Hi,
When running a kernel built with UBSAN enabled, enabling a GPIO
controller that uses a GIC interrupt as its parent triggers several
shift-out-of-bounds warnings in the GIC helpers.
This patch fixes the issue by using unsigned constants so that the
left shifts are well-defined and UBSAN stays quiet.
Thanks,
Zhu Ling
---
From: Zhu Ling <zhuling0805@proton.me>
Date: Tue, 2 Dec 2025 17:54:10 +0800
Subject: [PATCH] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers
When running with UBSAN enabled, enabling a GPIO controller that uses
a GIC interrupt as its parent triggers several shift-out-of-bounds
warnings:
UBSAN: shift-out-of-bounds in drivers/irqchip/irq-gic-common.c:50:21
left shift of 2 by 30 places cannot be represented in type 'int'
and similar reports in gic_poke_irq() and gic_peek_irq() in
drivers/irqchip/irq-gic-v3.c.
These come from shifting signed integer constants. Use unsigned
constants (0x2U and 1U) so that the behavior is well-defined and the
UBSAN warnings go away.
Signed-off-by: Zhu Ling <zhuling0805@proton.me>
---
drivers/irqchip/irq-gic-common.c | 2 +-
drivers/irqchip/irq-gic-v3.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index c776f9142..d4f0afd9e 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -48,7 +48,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base)
{
- u32 confmask = 0x2 << ((irq % 16) * 2);
+ u32 confmask = 0x2U << ((irq % 16) * 2);
u32 confoff = (irq / 16) * 4;
u32 val, oldval;
int ret = 0;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 3de351e66..f5226c03f 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -457,7 +457,7 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
u32 index, mask;
offset = convert_offset_index(d, offset, &index);
- mask = 1 << (index % 32);
+ mask = 1U << (index % 32);
if (gic_irq_in_rdist(d))
base = gic_data_rdist_sgi_base();
@@ -473,7 +473,7 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
u32 index, mask;
offset = convert_offset_index(d, offset, &index);
- mask = 1 << (index % 32);
+ mask = 1U << (index % 32);
if (gic_irq_in_rdist(d))
base = gic_data_rdist_sgi_base();
--
2.17.1
[-- Attachment #2: 0001-irqchip-gic-Fix-UBSAN-shift-out-of-bounds-in-GIC-hel.patch --]
[-- Type: application/octet-stream, Size: 2200 bytes --]
From 6b46e4ce40ddd3f18a73d9c66bebf22a167bd5f3 Mon Sep 17 00:00:00 2001
From: Zhu Ling <zhuling0805@proton.me>
Date: Tue, 2 Dec 2025 17:54:10 +0800
Subject: [PATCH] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers
When running with UBSAN enabled, enabling a GPIO controller that uses
a GIC interrupt as its parent triggers several shift-out-of-bounds
warnings:
UBSAN: shift-out-of-bounds in drivers/irqchip/irq-gic-common.c:50:21
left shift of 2 by 30 places cannot be represented in type 'int'
and similar reports in gic_poke_irq() and gic_peek_irq() in
drivers/irqchip/irq-gic-v3.c.
These come from shifting signed integer constants. Use unsigned
constants (0x2U and 1U) so that the behavior is well-defined and the
UBSAN warnings go away.
Signed-off-by: Zhu Ling <zhuling0805@proton.me>
---
drivers/irqchip/irq-gic-common.c | 2 +-
drivers/irqchip/irq-gic-v3.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index c776f9142..d4f0afd9e 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -48,7 +48,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base)
{
- u32 confmask = 0x2 << ((irq % 16) * 2);
+ u32 confmask = 0x2U << ((irq % 16) * 2);
u32 confoff = (irq / 16) * 4;
u32 val, oldval;
int ret = 0;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 3de351e66..f5226c03f 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -457,7 +457,7 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
u32 index, mask;
offset = convert_offset_index(d, offset, &index);
- mask = 1 << (index % 32);
+ mask = 1U << (index % 32);
if (gic_irq_in_rdist(d))
base = gic_data_rdist_sgi_base();
@@ -473,7 +473,7 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
u32 index, mask;
offset = convert_offset_index(d, offset, &index);
- mask = 1 << (index % 32);
+ mask = 1U << (index % 32);
if (gic_irq_in_rdist(d))
base = gic_data_rdist_sgi_base();
--
2.17.1
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers
2025-12-02 10:53 [PATCH] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers zhuling0805
@ 2025-12-02 11:44 ` Marc Zyngier
2026-09-21 2:21 ` [PATCH v2] " Zhu Ling
0 siblings, 1 reply; 4+ messages in thread
From: Marc Zyngier @ 2025-12-02 11:44 UTC (permalink / raw)
To: zhuling0805; +Cc: Thomas Gleixner, linux-arm-kernel, linux-kernel
On Tue, 02 Dec 2025 10:53:24 +0000,
zhuling0805 <zhuling0805@proton.me> wrote:
>
> Hi,
>
> When running a kernel built with UBSAN enabled, enabling a GPIO
> controller that uses a GIC interrupt as its parent triggers several
> shift-out-of-bounds warnings in the GIC helpers.
>
> This patch fixes the issue by using unsigned constants so that the
> left shifts are well-defined and UBSAN stays quiet.
Next time, please put additional notes *after* the commit message. In
this case, you are simply repeating what is already in the commit
message, so just sending the patch without anything else would have
been better.
>
> Thanks,
> Zhu Ling
>
> ---
> From: Zhu Ling <zhuling0805@proton.me>
> Date: Tue, 2 Dec 2025 17:54:10 +0800
> Subject: [PATCH] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers
>
> When running with UBSAN enabled, enabling a GPIO controller that uses
> a GIC interrupt as its parent triggers several shift-out-of-bounds
> warnings:
>
> UBSAN: shift-out-of-bounds in drivers/irqchip/irq-gic-common.c:50:21
> left shift of 2 by 30 places cannot be represented in type 'int'
>
> and similar reports in gic_poke_irq() and gic_peek_irq() in
> drivers/irqchip/irq-gic-v3.c.
>
> These come from shifting signed integer constants. Use unsigned
> constants (0x2U and 1U) so that the behavior is well-defined and the
> UBSAN warnings go away.
I think a better approach would be to convert all of this to
primitives that are designed for bit mask generation, rather than
reinventing the wheel. See below for some (untested) suggestions.
>
> Signed-off-by: Zhu Ling <zhuling0805@proton.me>
> ---
> drivers/irqchip/irq-gic-common.c | 2 +-
> drivers/irqchip/irq-gic-v3.c | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
> index c776f9142..d4f0afd9e 100644
> --- a/drivers/irqchip/irq-gic-common.c
> +++ b/drivers/irqchip/irq-gic-common.c
> @@ -48,7 +48,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
> int gic_configure_irq(unsigned int irq, unsigned int type,
> void __iomem *base)
> {
> - u32 confmask = 0x2 << ((irq % 16) * 2);
> + u32 confmask = 0x2U << ((irq % 16) * 2);
This really should be written as:
u32 confmask = BIT(((irq % 16) * 2) + 1);
> u32 confoff = (irq / 16) * 4;
> u32 val, oldval;
> int ret = 0;
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 3de351e66..f5226c03f 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -457,7 +457,7 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
> u32 index, mask;
>
> offset = convert_offset_index(d, offset, &index);
> - mask = 1 << (index % 32);
> + mask = 1U << (index % 32);
and this as BIT(index % 32).
>
> if (gic_irq_in_rdist(d))
> base = gic_data_rdist_sgi_base();
> @@ -473,7 +473,7 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
> u32 index, mask;
>
> offset = convert_offset_index(d, offset, &index);
> - mask = 1 << (index % 32);
> + mask = 1U << (index % 32);
Same here.
>
> if (gic_irq_in_rdist(d))
> base = gic_data_rdist_sgi_base();
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v2] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers
2025-12-02 11:44 ` Marc Zyngier
@ 2026-09-21 2:21 ` Zhu Ling
2026-09-21 9:31 ` Zenghui Yu
0 siblings, 1 reply; 4+ messages in thread
From: Zhu Ling @ 2026-09-21 2:21 UTC (permalink / raw)
To: maz, tglx; +Cc: radu, linux-arm-kernel, linux-kernel, Zhu Ling
When running with UBSAN enabled, enabling a GPIO controller that uses a
GIC interrupt as its parent triggers several shift-out-of-bounds warnings:
shift-out-of-bounds in drivers/irqchip/irq-gic-common.c:50:21
left shift of 2 by 30 places cannot be represented in type 'int'
Similar reports are emitted from gic_poke_irq() and gic_peek_irq() in
drivers/irqchip/irq-gic-v3.c. These masks are generated by shifting
signed integer constants, which invokes undefined behavior when bit 31
is selected.
Use BIT() to generate the masks with an unsigned type and make their
intent explicit.
Signed-off-by: Zhu Ling <zhuling2709@phytium.com.cn>
---
Changes in v2:
- Use BIT() instead of explicit unsigned shifts, as suggested by Marc.
- Drop the redundant introductory text from the email.
- Update the author email address.
Link: https://lore.kernel.org/r/2fJDwUUYdEf2_eaRa041L9xkT8RkSWFeo7euOnqMbbPhUatLlEaAvGfB6sOspDmXaxO87Eh7bQLV9UolyjbMtZBT1wB2UGypjPOo0Z-RC0Q=@proton.me
---
drivers/irqchip/irq-gic-common.c | 2 +-
drivers/irqchip/irq-gic-v3.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index c776f9142610..8bd1eaa54295 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -48,7 +48,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base)
{
- u32 confmask = 0x2 << ((irq % 16) * 2);
+ u32 confmask = BIT(((irq % 16) * 2) + 1);
u32 confoff = (irq / 16) * 4;
u32 val, oldval;
int ret = 0;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 6e1fa5b247fc..15110d47ddb0 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -457,7 +457,7 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
u32 index, mask;
offset = convert_offset_index(d, offset, &index);
- mask = 1 << (index % 32);
+ mask = BIT(index % 32);
if (gic_irq_in_rdist(d))
base = gic_data_rdist_sgi_base();
@@ -473,7 +473,7 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
u32 index, mask;
offset = convert_offset_index(d, offset, &index);
- mask = 1 << (index % 32);
+ mask = BIT(index % 32);
if (gic_irq_in_rdist(d))
base = gic_data_rdist_sgi_base();
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v2] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers
2026-09-21 2:21 ` [PATCH v2] " Zhu Ling
@ 2026-09-21 9:31 ` Zenghui Yu
0 siblings, 0 replies; 4+ messages in thread
From: Zenghui Yu @ 2026-09-21 9:31 UTC (permalink / raw)
To: Zhu Ling; +Cc: maz, tglx, radu, linux-arm-kernel, linux-kernel
On 9/21/26 10:21 AM, Zhu Ling wrote:
> When running with UBSAN enabled, enabling a GPIO controller that uses a
> GIC interrupt as its parent triggers several shift-out-of-bounds warnings:
>
> shift-out-of-bounds in drivers/irqchip/irq-gic-common.c:50:21
> left shift of 2 by 30 places cannot be represented in type 'int'
>
> Similar reports are emitted from gic_poke_irq() and gic_peek_irq() in
> drivers/irqchip/irq-gic-v3.c. These masks are generated by shifting
> signed integer constants, which invokes undefined behavior when bit 31
> is selected.
>
> Use BIT() to generate the masks with an unsigned type and make their
> intent explicit.
>
> Signed-off-by: Zhu Ling <zhuling2709@phytium.com.cn>
> ---
> Changes in v2:
> - Use BIT() instead of explicit unsigned shifts, as suggested by Marc.
> - Drop the redundant introductory text from the email.
> - Update the author email address.
>
> Link: https://lore.kernel.org/r/2fJDwUUYdEf2_eaRa041L9xkT8RkSWFeo7euOnqMbbPhUatLlEaAvGfB6sOspDmXaxO87Eh7bQLV9UolyjbMtZBT1wB2UGypjPOo0Z-RC0Q=@proton.me
> ---
> drivers/irqchip/irq-gic-common.c | 2 +-
> drivers/irqchip/irq-gic-v3.c | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
> index c776f9142610..8bd1eaa54295 100644
> --- a/drivers/irqchip/irq-gic-common.c
> +++ b/drivers/irqchip/irq-gic-common.c
> @@ -48,7 +48,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
> int gic_configure_irq(unsigned int irq, unsigned int type,
> void __iomem *base)
> {
> - u32 confmask = 0x2 << ((irq % 16) * 2);
> + u32 confmask = BIT(((irq % 16) * 2) + 1);
> u32 confoff = (irq / 16) * 4;
> u32 val, oldval;
> int ret = 0;
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 6e1fa5b247fc..15110d47ddb0 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -457,7 +457,7 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
> u32 index, mask;
>
> offset = convert_offset_index(d, offset, &index);
> - mask = 1 << (index % 32);
> + mask = BIT(index % 32);
>
> if (gic_irq_in_rdist(d))
> base = gic_data_rdist_sgi_base();
> @@ -473,7 +473,7 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
> u32 index, mask;
>
> offset = convert_offset_index(d, offset, &index);
> - mask = 1 << (index % 32);
> + mask = BIT(index % 32);
>
> if (gic_irq_in_rdist(d))
> base = gic_data_rdist_sgi_base();
gic_{poke,peek}_irq in drivers/irqchip/irq-gic.c have a similar pattern.
|static void gic_poke_irq(struct irq_data *d, u32 offset)
|{
| u32 mask = 1 << (irqd_to_hwirq(d) % 32);
Mind fixing them as well?
Thanks,
Zenghui
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-21 9:31 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-02 10:53 [PATCH] irqchip/gic: Fix UBSAN shift-out-of-bounds in GIC helpers zhuling0805
2025-12-02 11:44 ` Marc Zyngier
2026-09-21 2:21 ` [PATCH v2] " Zhu Ling
2026-09-21 9:31 ` Zenghui Yu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®