[PATCH] hw/intc/bcm2835_ic: reject out-of-range FIQ source values

Bin Guo posted 1 patch 3 weeks, 5 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260831081709.77725-1-guobin@linux.alibaba.com
Maintainers: Peter Maydell <peter.maydell@linaro.org>, "Philippe Mathieu-Daudé" <philmd@mailo.com>, Fabiano Rosas <farosas@suse.de>, Laurent Vivier <lvivier@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>
hw/intc/bcm2835_ic.c          | 13 +++++--
tests/qtest/bcm2835-ic-test.c | 66 +++++++++++++++++++++++++++++++++++
tests/qtest/meson.build       |  2 +-
3 files changed, 78 insertions(+), 3 deletions(-)
create mode 100644 tests/qtest/bcm2835-ic-test.c
[PATCH] hw/intc/bcm2835_ic: reject out-of-range FIQ source values
Posted by Bin Guo 3 weeks, 5 days ago
The FIQ_CONTROL register accepts a 7-bit source selector, but only
sources 0..71 (64 GPU + 8 ARM IRQs) exist.  Values 96..127 cause
bcm2835_ic_update() to call extract32(arm_irq_level, start, 1) with
start >= 32, which trips the assertion in bitops.h and aborts QEMU.

Reject writes that select a non-existent source and log a guest error,
so that a malicious or buggy guest cannot kill the emulator.

Add a qtest that verifies both valid and out-of-range FIQ source
selections on raspi3b.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4368
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
---
 hw/intc/bcm2835_ic.c          | 13 +++++--
 tests/qtest/bcm2835-ic-test.c | 66 +++++++++++++++++++++++++++++++++++
 tests/qtest/meson.build       |  2 +-
 3 files changed, 78 insertions(+), 3 deletions(-)
 create mode 100644 tests/qtest/bcm2835-ic-test.c

diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
index 71bf671761..262a620968 100644
--- a/hw/intc/bcm2835_ic.c
+++ b/hw/intc/bcm2835_ic.c
@@ -139,10 +139,19 @@ static void bcm2835_ic_write(void *opaque, hwaddr offset, uint64_t val,
     BCM2835ICState *s = opaque;
 
     switch (offset) {
-    case FIQ_CONTROL:
-        s->fiq_select = extract32(val, 0, 7);
+    case FIQ_CONTROL: {
+        unsigned fiq_select = extract32(val, 0, 7);
+
+        if (fiq_select >= GPU_IRQS + ARM_IRQS) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: FIQ select %u out of range\n",
+                          __func__, fiq_select);
+            return;
+        }
+        s->fiq_select = fiq_select;
         s->fiq_enable = extract32(val, 7, 1);
         break;
+    }
     case IRQ_ENABLE_1:
         s->gpu_irq_enable |= val;
         break;
diff --git a/tests/qtest/bcm2835-ic-test.c b/tests/qtest/bcm2835-ic-test.c
new file mode 100644
index 0000000000..1e171ee092
--- /dev/null
+++ b/tests/qtest/bcm2835-ic-test.c
@@ -0,0 +1,66 @@
+/*
+ * QTest testcase for the BCM2835 Interrupt Controller
+ *
+ * Copyright (c) 2026 Bin Guo <guobin@linux.alibaba.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+
+#define IC_BASE     0x3f00b200
+#define FIQ_CONTROL (IC_BASE + 0x0c)
+
+static void test_fiq_select_out_of_range(void)
+{
+    uint32_t val;
+
+    /*
+     * Only FIQ sources 0..71 exist.  Source 96 used to trigger an assertion
+     * in bcm2835_ic_update() because extract32(arm_irq_level, 32, 1) was
+     * called with start >= 32.  Make sure the write is rejected and QEMU
+     * keeps running.
+     */
+    writel(FIQ_CONTROL, 0xe0); /* fiq_select = 96, fiq_enable = 1 */
+    val = readl(FIQ_CONTROL);
+    g_assert_cmpint(val, ==, 0);
+
+    /* The first source past the ARM IRQ range should also be rejected. */
+    writel(FIQ_CONTROL, 0xc8); /* fiq_select = 72, fiq_enable = 1 */
+    val = readl(FIQ_CONTROL);
+    g_assert_cmpint(val, ==, 0);
+}
+
+static void test_fiq_select_valid(void)
+{
+    uint32_t val;
+
+    /* Select the highest valid ARM IRQ source (64 + 7 = 71). */
+    writel(FIQ_CONTROL, 0xc7); /* fiq_select = 71, fiq_enable = 1 */
+    val = readl(FIQ_CONTROL);
+    g_assert_cmpint(val, ==, 0xc7);
+
+    /* Select the highest valid GPU IRQ source. */
+    writel(FIQ_CONTROL, 0x3f); /* fiq_select = 63, fiq_enable = 0 */
+    val = readl(FIQ_CONTROL);
+    g_assert_cmpint(val, ==, 0x3f);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+
+    qtest_add_func("/bcm2835/bcm2835-ic/fiq-select-out-of-range",
+                   test_fiq_select_out_of_range);
+    qtest_add_func("/bcm2835/bcm2835-ic/fiq-select-valid",
+                   test_fiq_select_valid);
+
+    qtest_start("-machine raspi3b");
+    ret = g_test_run();
+    qtest_end();
+
+    return ret;
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index a13c4af989..149b395e53 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -274,7 +274,7 @@ qtests_aarch64 = \
     ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +                                         \
   (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \
   (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \
-  (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test', 'bcm2835-i2c-test'] : []) +  \
+  (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test', 'bcm2835-i2c-test', 'bcm2835-ic-test'] : []) +  \
   (config_all_accel.has_key('CONFIG_TCG') and                                            \
    config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test', 'tpm-tis-i2c-swtpm-test'] : []) + \
   (config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed64 : []) + \
-- 
2.50.1 (Apple Git-155)
Re: [PATCH] hw/intc/bcm2835_ic: reject out-of-range FIQ source values
Posted by Michael Tokarev 1 week, 3 days ago
On 8/31/26 11:17, Bin Guo wrote:
> The FIQ_CONTROL register accepts a 7-bit source selector, but only
> sources 0..71 (64 GPU + 8 ARM IRQs) exist.  Values 96..127 cause
> bcm2835_ic_update() to call extract32(arm_irq_level, start, 1) with
> start >= 32, which trips the assertion in bitops.h and aborts QEMU.
> 
> Reject writes that select a non-existent source and log a guest error,
> so that a malicious or buggy guest cannot kill the emulator.
> 
> Add a qtest that verifies both valid and out-of-range FIQ source
> selections on raspi3b.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4368
> Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
> ---
>   hw/intc/bcm2835_ic.c          | 13 +++++--
>   tests/qtest/bcm2835-ic-test.c | 66 +++++++++++++++++++++++++++++++++++
>   tests/qtest/meson.build       |  2 +-
>   3 files changed, 78 insertions(+), 3 deletions(-)
>   create mode 100644 tests/qtest/bcm2835-ic-test.c

I'm picking this up for currently active stable qemu series.
Please let me know if I shouldn't.

Thanks,

/mjt
Re: [PATCH] hw/intc/bcm2835_ic: reject out-of-range FIQ source values
Posted by Peter Maydell 2 weeks, 4 days ago
On Mon, 31 Aug 2026 at 09:17, Bin Guo <guobin@linux.alibaba.com> wrote:
>
> The FIQ_CONTROL register accepts a 7-bit source selector, but only
> sources 0..71 (64 GPU + 8 ARM IRQs) exist.  Values 96..127 cause
> bcm2835_ic_update() to call extract32(arm_irq_level, start, 1) with
> start >= 32, which trips the assertion in bitops.h and aborts QEMU.
>
> Reject writes that select a non-existent source and log a guest error,
> so that a malicious or buggy guest cannot kill the emulator.
>
> Add a qtest that verifies both valid and out-of-range FIQ source
> selections on raspi3b.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4368
> Signed-off-by: Bin Guo <guobin@linux.alibaba.com>



Applied to target-arm.next, thanks.

-- PMM
Re: [PATCH] hw/intc/bcm2835_ic: reject out-of-range FIQ source values
Posted by Philippe Mathieu-Daudé 3 weeks, 5 days ago
On 31/8/26 10:17, Bin Guo wrote:
> The FIQ_CONTROL register accepts a 7-bit source selector, but only
> sources 0..71 (64 GPU + 8 ARM IRQs) exist.  Values 96..127 cause
> bcm2835_ic_update() to call extract32(arm_irq_level, start, 1) with
> start >= 32, which trips the assertion in bitops.h and aborts QEMU.
> 
> Reject writes that select a non-existent source and log a guest error,
> so that a malicious or buggy guest cannot kill the emulator.
> 
> Add a qtest that verifies both valid and out-of-range FIQ source
> selections on raspi3b.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4368
> Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
> ---
>   hw/intc/bcm2835_ic.c          | 13 +++++--
>   tests/qtest/bcm2835-ic-test.c | 66 +++++++++++++++++++++++++++++++++++
>   tests/qtest/meson.build       |  2 +-
>   3 files changed, 78 insertions(+), 3 deletions(-)
>   create mode 100644 tests/qtest/bcm2835-ic-test.c

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>