@samitouri / QOSamiQemu / commits / 80776c4df9

hw/intc/loongarch_pch_pic: Validate htmsi_vector before indexing parent_irq

pch_pic_update_irq() used the guest-writable htmsi_vector[irq] value as an index into parent_irq[] without checking bounds. A value >= irq_num (64 in the array, but only 32 are used by the virt machine) causes an out-of-bounds read and a guest-triggerable QEMU crash. Validate the vector before calling qemu_set_irq() in both the raise and lower paths and log a guest error if it is out of range. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4114 Cc: qemu-stable@nongnu.org Signed-off-by: Bin Guo <guobin@linux.alibaba.com> Signed-off-by: Bibo Mao <maobibo@loongson.cn> Reviewed-by: Bibo Mao <maobibo@loongson.cn>

Bin Guo committed Aug 4, 2026 at 15:34 UTC 80776c4df92c3d58f89608b61e355092a7d524ed
1 file changed +17 -2
hw/intc/loongarch_pch_pic.c
+17 -2
@@ -19,13 +19,21 @@ static void pch_pic_update_irq(LoongArchPICCommonState *s, uint64_t mask,
19 {
20 uint64_t val;
21 int irq;
22 + uint8_t vector;
23
24 if (level) {
25 val = mask & s->intirr & ~s->int_mask;
26 if (val) {
27 irq = ctz64(val);
28 + vector = s->htmsi_vector[irq];
29 + if (vector >= s->irq_num) {
30 + qemu_log_mask(LOG_GUEST_ERROR,
31 + "%s: htmsi_vector[%d]=%u out of range\n",
32 + __func__, irq, vector);
33 + return;
34 + }
35 s->intisr |= MAKE_64BIT_MASK(irq, 1);
28 - qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
36 + qemu_set_irq(s->parent_irq[vector], 1);
37 }
38 } else {
39 /*
@@ -35,8 +43,15 @@ static void pch_pic_update_irq(LoongArchPICCommonState *s, uint64_t mask,
43 val = mask & s->intisr & ~s->intirr;
44 if (val) {
45 irq = ctz64(val);
46 + vector = s->htmsi_vector[irq];
47 + if (vector >= s->irq_num) {
48 + qemu_log_mask(LOG_GUEST_ERROR,
49 + "%s: htmsi_vector[%d]=%u out of range\n",
50 + __func__, irq, vector);
51 + return;
52 + }
53 s->intisr &= ~MAKE_64BIT_MASK(irq, 1);
39 - qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
54 + qemu_set_irq(s->parent_irq[vector], 0);
55 }
56 }
57 }