* [PATCH v5 0/5] LoongArch: KVM: Harden interrupt injection
@ 2026-07-14 7:25 Bibo Mao
2026-07-14 7:25 ` [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc Bibo Mao
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Bibo Mao @ 2026-07-14 7:25 UTC (permalink / raw)
To: Huacai Chen; +Cc: Song Gao, kvm, loongarch, linux-kernel
API kvm_vcpu_ioctl_interrupt() is mainly to used to deliver interrupt
from user mode, and internal APIs kvm_queue_irq() and kvm_dequeue_irq()
are used in kernel mode, also moves IPI interrupt handling within lock
protection.
Also this patch replaces kvm_err() with WARN_ONCE() to avoid noise
kernel log.
---
v4 ... v5:
1. Add one new patch and fix uninitialized stack variable issue with
dmsintc.
2. In patch 2, set return value with 0 to prevent information leak
where return directly with non-aligned address in IPI irqchip.
v3 ... v4:
1. From AI assist, replace kvm_err() with kvm_pr_unimpl() rather than
WARN_ONCE(), since host may crash with WARN_ONCE() when kernel
parameter panic_on_warn=1 is set.
2. Add one new patch 3 which returns directly when IPI address is not
aligned, rather than only print WARN_ON_ONCE() and continue to run.
v2 ... v3:
1. Split the patches into three smaller ones, the first patch removes
old default case and kvm_err() since it is impossible to happen.
And the second patch replaces kvm_err() with WARN_ONCE().
v1 ... v2:
1. Add border check with ipnum in eiointc_set_sw_coreisr() and
eiointc_update_irq(), so that injected interrupt vector is valid.
2. Move IPI inject and ack within lock to avoid contention in
ipi_set() and ipi_clear().
3. Add kvm_arch_irqchip_in_kernel() check in user mode irq injection
in function kvm_vcpu_ioctl_interrupt(), contention of user mode irq
injection is assured from user mode VMM.
---
Bibo Mao (5):
LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc
LoongArch: KVM: Return directly when IPI address is not aligned
LoongArch: KVM: Set default MAILBOX access size with 8
LoongArch: KVM: Replace kvm_err() with kvm_pr_unimpl()
LoongArch: KVM: Use internal API to deliver interrupt in kernel mode
arch/loongarch/kvm/exit.c | 16 +++----
arch/loongarch/kvm/intc/dmsintc.c | 17 ++++---
arch/loongarch/kvm/intc/eiointc.c | 32 ++++++++------
arch/loongarch/kvm/intc/ipi.c | 73 ++++++++++++++-----------------
arch/loongarch/kvm/intc/pch_pic.c | 12 ++---
arch/loongarch/kvm/vcpu.c | 5 ++-
6 files changed, 80 insertions(+), 75 deletions(-)
base-commit: a13c140cc289c0b7b3770bce5b3ad42ab35074aa
--
2.39.3
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc 2026-07-14 7:25 [PATCH v5 0/5] LoongArch: KVM: Harden interrupt injection Bibo Mao @ 2026-07-14 7:25 ` Bibo Mao 2026-07-14 7:44 ` sashiko-bot 2026-07-14 7:25 ` [PATCH v5 2/5] LoongArch: KVM: Return directly when IPI address is not aligned Bibo Mao ` (3 subsequent siblings) 4 siblings, 1 reply; 10+ messages in thread From: Bibo Mao @ 2026-07-14 7:25 UTC (permalink / raw) To: Huacai Chen; +Cc: Song Gao, kvm, loongarch, linux-kernel, stable Variable vector[] is declared on stack in function dmsintc_inject_irq() and sometimes it is used without initialized. Here fix this issue. Fixes: 03de5eecb0f0 ("LoongArch: KVM: Add DMSINTC inject msi to vCPU") Cc: stable@vger.kernel.org Signed-off-by: Bibo Mao <maobibo@loongson.cn> --- arch/loongarch/kvm/intc/dmsintc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c index de25735ce039..0a8492c4394c 100644 --- a/arch/loongarch/kvm/intc/dmsintc.c +++ b/arch/loongarch/kvm/intc/dmsintc.c @@ -21,6 +21,8 @@ void dmsintc_inject_irq(struct kvm_vcpu *vcpu) old = atomic64_read(&(ds->vector_map[i])); if (old) vector[i] = atomic64_xchg(&(ds->vector_map[i]), 0); + else + vector[i] = 0; } if (vector[0]) { -- 2.39.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc 2026-07-14 7:25 ` [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc Bibo Mao @ 2026-07-14 7:44 ` sashiko-bot 0 siblings, 0 replies; 10+ messages in thread From: sashiko-bot @ 2026-07-14 7:44 UTC (permalink / raw) To: Bibo Mao; +Cc: kvm Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Missing memory barriers in lockless MSI injection between `vector_map` and `irq_pending` can cause lost interrupts. -- --- Patch [1]: [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc --- commit 9139baa9157d8865599df0b5b9ceaace254286a5 Author: Bibo Mao <maobibo@loongson.cn> LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc This commit fixes an uninitialized stack variable array in dmsintc_inject_irq() by explicitly initializing it to 0 when no pending interrupts are found in the vector map. > diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c > index de25735ce0394..0a8492c4394c7 100644 > --- a/arch/loongarch/kvm/intc/dmsintc.c > +++ b/arch/loongarch/kvm/intc/dmsintc.c > @@ -21,6 +21,8 @@ void dmsintc_inject_irq(struct kvm_vcpu *vcpu) > old = atomic64_read(&(ds->vector_map[i])); > if (old) > vector[i] = atomic64_xchg(&(ds->vector_map[i]), 0); [Severity: High] This is a pre-existing issue, but is there a missing memory barrier in the lockless MSI injection mechanism that synchronizes vector_map and irq_pending? On the producer side, dmsintc_deliver_msi_to_vcpu() lacks a memory barrier (e.g., smp_wmb()) between setting the payload (vector_map) and the notification flag (irq_pending): arch/loongarch/kvm/intc/dmsintc.c:dmsintc_deliver_msi_to_vcpu() { ... set_bit(vector, (unsigned long *)&ds->vector_map); kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq); ... } Since set_bit() does not imply a memory barrier, the host CPU could reorder these stores. If reordered, the consumer side might observe the irq_pending flag but read a stale 0 from vector_map, especially since it uses xchg_relaxed(): arch/loongarch/kvm/interrupt.c:kvm_deliver_intr() { ... mask = READ_ONCE(vcpu->arch.irq_pending); if (mask) { mask = xchg_relaxed(&vcpu->arch.irq_pending, 0); kvm_irq_deliver(vcpu, mask); } ... } Could this lead to the VCPU clearing irq_pending and skipping the injection, permanently losing the interrupt and causing a guest VM hang? > + else > + vector[i] = 0; > } > > if (vector[0]) { -- Sashiko AI review · https://sashiko.dev/#/patchset/20260714072520.2745942-1-maobibo@loongson.cn?part=1 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 2/5] LoongArch: KVM: Return directly when IPI address is not aligned 2026-07-14 7:25 [PATCH v5 0/5] LoongArch: KVM: Harden interrupt injection Bibo Mao 2026-07-14 7:25 ` [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc Bibo Mao @ 2026-07-14 7:25 ` Bibo Mao 2026-07-14 7:45 ` sashiko-bot 2026-07-14 7:25 ` [PATCH v5 3/5] LoongArch: KVM: Set default MAILBOX access size with 8 Bibo Mao ` (2 subsequent siblings) 4 siblings, 1 reply; 10+ messages in thread From: Bibo Mao @ 2026-07-14 7:25 UTC (permalink / raw) To: Huacai Chen; +Cc: Song Gao, kvm, loongarch, linux-kernel When IPI address is not aligned with its access size, it should return directly in read/write operations, rather than only print WARN_ON_ONCE(). The method is the same with in kernel extioi and pch_pic operations. Signed-off-by: Bibo Mao <maobibo@loongson.cn> --- arch/loongarch/kvm/intc/ipi.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 4fa0897d7bdb..928f9bd5e1f1 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -186,9 +186,13 @@ static int loongarch_ipi_readl(struct kvm_vcpu *vcpu, gpa_t addr, int len, void uint32_t offset; uint64_t res = 0; - offset = (uint32_t)(addr & 0x1ff); - WARN_ON_ONCE(offset & (len - 1)); + if (addr & (len - 1)) { + *(uint64_t *)val = res; + kvm_pr_unimpl("%s: ipi not aligned addr %llx len %d\n", __func__, addr, len); + return 0; + } + offset = addr - IOCSR_IPI_BASE; switch (offset) { case IOCSR_IPI_STATUS: spin_lock(&vcpu->arch.ipi_state.lock); @@ -204,11 +208,6 @@ static int loongarch_ipi_readl(struct kvm_vcpu *vcpu, gpa_t addr, int len, void case IOCSR_IPI_CLEAR: break; case IOCSR_IPI_BUF_20 ... IOCSR_IPI_BUF_38 + 7: - if (offset + len > IOCSR_IPI_BUF_38 + 8) { - kvm_err("%s: invalid offset or len: offset = %d, len = %d\n", - __func__, offset, len); - break; - } res = read_mailbox(vcpu, offset, len); break; default: @@ -227,9 +226,12 @@ static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, cons data = *(uint64_t *)val; - offset = (uint32_t)(addr & 0x1ff); - WARN_ON_ONCE(offset & (len - 1)); + if (addr & (len - 1)) { + kvm_pr_unimpl("%s: ipi not aligned addr %llx len %d\n", __func__, addr, len); + return 0; + } + offset = addr - IOCSR_IPI_BASE; switch (offset) { case IOCSR_IPI_STATUS: break; -- 2.39.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5 2/5] LoongArch: KVM: Return directly when IPI address is not aligned 2026-07-14 7:25 ` [PATCH v5 2/5] LoongArch: KVM: Return directly when IPI address is not aligned Bibo Mao @ 2026-07-14 7:45 ` sashiko-bot 0 siblings, 0 replies; 10+ messages in thread From: sashiko-bot @ 2026-07-14 7:45 UTC (permalink / raw) To: Bibo Mao; +Cc: kvm Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Guest-triggerable host log spam (Denial of Service) via un-ratelimited `kvm_err` calls across multiple IPI and interrupt controller handlers. -- --- Patch [2]: [PATCH v5 2/5] LoongArch: KVM: Return directly when IPI address is not aligned --- commit ee58d22f0a0ca959fcdaed9af721908e0d1dcd00 Author: Bibo Mao <maobibo@loongson.cn> LoongArch: KVM: Return directly when IPI address is not aligned When an IPI address is not aligned with its access size, the code now returns directly in read/write operations and prints a ratelimited message instead of emitting a warning. This matches the behavior of in-kernel extioi and pch_pic operations. > diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c > index 4fa0897d7bdb0..928f9bd5e1f12 100644 > --- a/arch/loongarch/kvm/intc/ipi.c > +++ b/arch/loongarch/kvm/intc/ipi.c > @@ -186,9 +186,13 @@ static int loongarch_ipi_readl(struct kvm_vcpu *vcpu, gpa_t addr, int len, void > uint32_t offset; > uint64_t res = 0; > > - offset = (uint32_t)(addr & 0x1ff); > - WARN_ON_ONCE(offset & (len - 1)); > + if (addr & (len - 1)) { > + *(uint64_t *)val = res; > + kvm_pr_unimpl("%s: ipi not aligned addr %llx len %d\n", __func__, addr, len); > + return 0; > + } [Severity: High] This is a pre-existing issue, but while you are using the ratelimited kvm_pr_unimpl() here, there appear to be other un-ratelimited error prints triggered by guest actions in these handlers. For example, when a guest performs accesses to unknown offsets or provides invalid CPU IDs, the code uses kvm_err(): arch/loongarch/kvm/intc/ipi.c:loongarch_ipi_readl() and loongarch_ipi_writel() kvm_err("%s: unknown addr: %llx\n", __func__, addr); arch/loongarch/kvm/intc/ipi.c:any_send() kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); arch/loongarch/kvm/intc/eiointc.c:kvm_eiointc_read() kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); Can an untrusted guest flood the host's dmesg by repeatedly triggering these conditions, potentially causing a host denial of service? Would it be safer to convert these to ratelimited prints as well? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260714072520.2745942-1-maobibo@loongson.cn?part=2 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 3/5] LoongArch: KVM: Set default MAILBOX access size with 8 2026-07-14 7:25 [PATCH v5 0/5] LoongArch: KVM: Harden interrupt injection Bibo Mao 2026-07-14 7:25 ` [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc Bibo Mao 2026-07-14 7:25 ` [PATCH v5 2/5] LoongArch: KVM: Return directly when IPI address is not aligned Bibo Mao @ 2026-07-14 7:25 ` Bibo Mao 2026-07-14 7:51 ` sashiko-bot 2026-07-14 7:25 ` [PATCH v5 4/5] LoongArch: KVM: Replace kvm_err() with kvm_pr_unimpl() Bibo Mao 2026-07-14 7:25 ` [PATCH v5 5/5] LoongArch: KVM: Use internal API to deliver interrupt in kernel mode Bibo Mao 4 siblings, 1 reply; 10+ messages in thread From: Bibo Mao @ 2026-07-14 7:25 UTC (permalink / raw) To: Huacai Chen; +Cc: Song Gao, kvm, loongarch, linux-kernel With IOCSR instruction emulation in function kvm_emu_iocsr(), the possible size combination is 1/2/4/8 and no other combinations. Here remove the old default case and replace the default case with 8 in read_mailbox() and write_mailbox(). Signed-off-by: Bibo Mao <maobibo@loongson.cn> --- arch/loongarch/kvm/intc/ipi.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 928f9bd5e1f1..3871a6953a64 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -67,11 +67,8 @@ static uint64_t read_mailbox(struct kvm_vcpu *vcpu, int offset, int len) return data & 0xffff; case 4: return data & 0xffffffff; - case 8: - return data; default: - kvm_err("%s: unknown data len: %d\n", __func__, len); - return 0; + return data; } } @@ -92,11 +89,9 @@ static void write_mailbox(struct kvm_vcpu *vcpu, int offset, uint64_t data, int case 4: *(unsigned int *)pbuf = (unsigned int)data; break; - case 8: + default: *(unsigned long *)pbuf = (unsigned long)data; break; - default: - kvm_err("%s: unknown data len: %d\n", __func__, len); } spin_unlock(&vcpu->arch.ipi_state.lock); } -- 2.39.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/5] LoongArch: KVM: Set default MAILBOX access size with 8 2026-07-14 7:25 ` [PATCH v5 3/5] LoongArch: KVM: Set default MAILBOX access size with 8 Bibo Mao @ 2026-07-14 7:51 ` sashiko-bot 0 siblings, 0 replies; 10+ messages in thread From: sashiko-bot @ 2026-07-14 7:51 UTC (permalink / raw) To: Bibo Mao; +Cc: kvm Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Non-atomic read-modify-write of IPI mailbox in `mail_send()` and `send_ipi_data()` can lead to lost mailbox updates. -- --- Patch [3]: [PATCH v5 3/5] LoongArch: KVM: Set default MAILBOX access size with 8 --- commit 41b08f9f42313b6881c240343f238221b9928a3a Author: Bibo Mao <maobibo@loongson.cn> LoongArch: KVM: Set default MAILBOX access size with 8 This commit updates the IOCSR instruction emulation in KVM LoongArch. It removes the explicit case for 8-byte lengths and instead uses the default case to handle 8-byte access in the mailbox read and write functions. > diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c > index 928f9bd5e1f12..3871a6953a649 100644 > --- a/arch/loongarch/kvm/intc/ipi.c > +++ b/arch/loongarch/kvm/intc/ipi.c [ ... ] > @@ -92,11 +89,9 @@ static void write_mailbox(struct kvm_vcpu *vcpu, int offset, uint64_t data, int > case 4: > *(unsigned int *)pbuf = (unsigned int)data; > break; > - case 8: > + default: > *(unsigned long *)pbuf = (unsigned long)data; > break; > - default: > - kvm_err("%s: unknown data len: %d\n", __func__, len); > } > spin_unlock(&vcpu->arch.ipi_state.lock); > } [Severity: High] This is a pre-existing issue, but looking at how read_mailbox() and write_mailbox() are used together, is there a potential race condition when multiple vCPUs send IPIs concurrently? In mail_send(), the read and write operations are performed independently: arch/loongarch/kvm/intc/ipi.c:mail_send() { ... if ((data >> 27) & 0xf) { val = read_mailbox(vcpu, offset, 4); for (i = 0; i < 4; i++) if (data & (BIT(27 + i))) mask |= (0xff << (i * 8)); val &= mask; } val |= ((uint32_t)(data >> 32) & ~mask); write_mailbox(vcpu, offset, val, 4); ... } Since ipi_state.lock is acquired and released inside both read_mailbox() and write_mailbox(), could two sender vCPUs read the same initial state, apply their masks, and write back, causing one of the updates to be lost? A similar pattern appears in send_ipi_data(), where kvm_io_bus_read() and kvm_io_bus_write() are used with the SRCU lock being dropped in between. Could this lead to dropped IPI data and guest hangs under concurrent workloads? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260714072520.2745942-1-maobibo@loongson.cn?part=3 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 4/5] LoongArch: KVM: Replace kvm_err() with kvm_pr_unimpl() 2026-07-14 7:25 [PATCH v5 0/5] LoongArch: KVM: Harden interrupt injection Bibo Mao ` (2 preceding siblings ...) 2026-07-14 7:25 ` [PATCH v5 3/5] LoongArch: KVM: Set default MAILBOX access size with 8 Bibo Mao @ 2026-07-14 7:25 ` Bibo Mao 2026-07-14 7:25 ` [PATCH v5 5/5] LoongArch: KVM: Use internal API to deliver interrupt in kernel mode Bibo Mao 4 siblings, 0 replies; 10+ messages in thread From: Bibo Mao @ 2026-07-14 7:25 UTC (permalink / raw) To: Huacai Chen; +Cc: Song Gao, kvm, loongarch, linux-kernel Since guest kernel and ioctl parameter from user mode is untrusted, there may be noise kernel log output in host hypervisor with abnormal state. Here replace kvm_err() with kvm_pr_unimpl() to reduce this kind of noise kernel log, and there is no function change. Signed-off-by: Bibo Mao <maobibo@loongson.cn> --- arch/loongarch/kvm/exit.c | 16 ++++++++-------- arch/loongarch/kvm/intc/dmsintc.c | 8 ++++---- arch/loongarch/kvm/intc/eiointc.c | 18 +++++++++--------- arch/loongarch/kvm/intc/ipi.c | 30 +++++++++++++++--------------- arch/loongarch/kvm/intc/pch_pic.c | 12 ++++++------ arch/loongarch/kvm/vcpu.c | 2 +- 6 files changed, 43 insertions(+), 43 deletions(-) diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c index 8572b63478bb..590580d0303e 100644 --- a/arch/loongarch/kvm/exit.c +++ b/arch/loongarch/kvm/exit.c @@ -252,7 +252,7 @@ int kvm_complete_iocsr_read(struct kvm_vcpu *vcpu, struct kvm_run *run) *gpr = *(s64 *)run->iocsr_io.data; break; default: - kvm_err("Bad IOCSR length: %d, addr is 0x%lx\n", + kvm_pr_unimpl("Bad IOCSR length: %d, addr is 0x%lx\n", run->iocsr_io.len, vcpu->arch.badv); er = EMULATE_FAIL; break; @@ -326,7 +326,7 @@ static int kvm_trap_handle_gspr(struct kvm_vcpu *vcpu) /* Rollback PC only if emulation was unsuccessful */ if (er == EMULATE_FAIL) { - kvm_err("[%#lx]%s: unsupported gspr instruction 0x%08x\n", + kvm_pr_unimpl("[%#lx]%s: unsupported gspr instruction 0x%08x\n", curr_pc, __func__, inst.word); kvm_arch_vcpu_dump_regs(vcpu); @@ -491,7 +491,7 @@ int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst) return EMULATE_DO_MMIO; } - kvm_err("Read not supported Inst=0x%08x @%lx BadVaddr:%#lx\n", + kvm_pr_unimpl("Read not supported Inst=0x%08x @%lx BadVaddr:%#lx\n", inst.word, vcpu->arch.pc, vcpu->arch.badv); kvm_arch_vcpu_dump_regs(vcpu); vcpu->mmio_needed = 0; @@ -529,7 +529,7 @@ int kvm_complete_mmio_read(struct kvm_vcpu *vcpu, struct kvm_run *run) *gpr = *(s64 *)run->mmio.data; break; default: - kvm_err("Bad MMIO length: %d, addr is 0x%lx\n", + kvm_pr_unimpl("Bad MMIO length: %d, addr is 0x%lx\n", run->mmio.len, vcpu->arch.badv); er = EMULATE_FAIL; break; @@ -656,7 +656,7 @@ int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst) } vcpu->arch.pc = curr_pc; - kvm_err("Write not supported Inst=0x%08x @%lx BadVaddr:%#lx\n", + kvm_pr_unimpl("Write not supported Inst=0x%08x @%lx BadVaddr:%#lx\n", inst.word, vcpu->arch.pc, vcpu->arch.badv); kvm_arch_vcpu_dump_regs(vcpu); /* Rollback PC if emulation was unsuccessful */ @@ -748,8 +748,8 @@ static int kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu, int ecode) * treated as a reserved instruction! * If FPU already in use, we shouldn't get this at all. */ - if (WARN_ON(vcpu->arch.aux_inuse & KVM_LARCH_FPU)) { - kvm_err("%s internal error\n", __func__); + if (vcpu->arch.aux_inuse & KVM_LARCH_FPU) { + kvm_pr_unimpl("%s internal error\n", __func__); run->exit_reason = KVM_EXIT_INTERNAL_ERROR; return RESUME_HOST; } @@ -943,7 +943,7 @@ static int kvm_fault_ni(struct kvm_vcpu *vcpu, int ecode) /* Fetch the instruction */ inst = vcpu->arch.badi; badv = vcpu->arch.badv; - kvm_err("ECode: %d PC=%#lx Inst=0x%08x BadVaddr=%#lx ESTAT=%#lx\n", + kvm_pr_unimpl("ECode: %d PC=%#lx Inst=0x%08x BadVaddr=%#lx ESTAT=%#lx\n", ecode, vcpu->arch.pc, inst, badv, read_gcsr_estat()); kvm_arch_vcpu_dump_regs(vcpu); kvm_queue_exception(vcpu, EXCCODE_INE, 0); diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c index 0a8492c4394c..5797ef17cd71 100644 --- a/arch/loongarch/kvm/intc/dmsintc.c +++ b/arch/loongarch/kvm/intc/dmsintc.c @@ -116,7 +116,7 @@ static int kvm_dmsintc_ctrl_access(struct kvm_device *dev, } break; default: - kvm_err("%s: unknown dmsintc register, addr = %d\n", __func__, addr); + kvm_pr_unimpl("%s: unknown dmsintc register, addr = %d\n", __func__, addr); return -ENXIO; } @@ -130,7 +130,7 @@ static int kvm_dmsintc_set_attr(struct kvm_device *dev, case KVM_DEV_LOONGARCH_DMSINTC_GRP_CTRL: return kvm_dmsintc_ctrl_access(dev, attr, true); default: - kvm_err("%s: unknown group (%d)\n", __func__, attr->group); + kvm_pr_unimpl("%s: unknown group (%d)\n", __func__, attr->group); return -EINVAL; } } @@ -141,13 +141,13 @@ static int kvm_dmsintc_create(struct kvm_device *dev, u32 type) struct loongarch_dmsintc *s; if (!dev) { - kvm_err("%s: kvm_device ptr is invalid!\n", __func__); + kvm_pr_unimpl("%s: kvm_device ptr is invalid!\n", __func__); return -EINVAL; } kvm = dev->kvm; if (kvm->arch.dmsintc) { - kvm_err("%s: LoongArch DMSINTC has already been created!\n", __func__); + kvm_pr_unimpl("%s: LoongArch DMSINTC has already been created!\n", __func__); return -EINVAL; } diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c index 2b14485d14a7..fd089d54da10 100644 --- a/arch/loongarch/kvm/intc/eiointc.c +++ b/arch/loongarch/kvm/intc/eiointc.c @@ -47,7 +47,7 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) cpu = s->sw_coremap[irq]; vcpu = kvm_get_vcpu_by_id(s->kvm, cpu); if (unlikely(vcpu == NULL)) { - kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); + kvm_pr_unimpl("%s: invalid target cpu: %d\n", __func__, cpu); return; } @@ -165,12 +165,12 @@ static int kvm_eiointc_read(struct kvm_vcpu *vcpu, struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc; if (!eiointc) { - kvm_err("%s: eiointc irqchip not valid!\n", __func__); + kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__); return 0; } if (addr & (len - 1)) { - kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); + kvm_pr_unimpl("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); return 0; } @@ -297,12 +297,12 @@ static int kvm_eiointc_write(struct kvm_vcpu *vcpu, struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc; if (!eiointc) { - kvm_err("%s: eiointc irqchip not valid!\n", __func__); + kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__); return 0; } if (addr & (len - 1)) { - kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); + kvm_pr_unimpl("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); return 0; } @@ -345,7 +345,7 @@ static int kvm_eiointc_virt_read(struct kvm_vcpu *vcpu, struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc; if (!eiointc) { - kvm_err("%s: eiointc irqchip not valid!\n", __func__); + kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__); return 0; } @@ -375,7 +375,7 @@ static int kvm_eiointc_virt_write(struct kvm_vcpu *vcpu, struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc; if (!eiointc) { - kvm_err("%s: eiointc irqchip not valid!\n", __func__); + kvm_pr_unimpl("%s: eiointc irqchip not valid!\n", __func__); return 0; } @@ -502,7 +502,7 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev, p = (void *)s->coremap + offset * 4; break; default: - kvm_err("%s: unknown eiointc register, addr = %d\n", __func__, addr); + kvm_pr_unimpl("%s: unknown eiointc register, addr = %d\n", __func__, addr); return -EINVAL; } @@ -546,7 +546,7 @@ static int kvm_eiointc_sw_status_access(struct kvm_device *dev, p = &s->status; break; default: - kvm_err("%s: unknown eiointc register, addr = %d\n", __func__, addr); + kvm_pr_unimpl("%s: unknown eiointc register, addr = %d\n", __func__, addr); return -EINVAL; } spin_lock_irqsave(&s->lock, flags); diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 3871a6953a64..0edaa124a61e 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -30,7 +30,7 @@ static void ipi_send(struct kvm *kvm, uint64_t data) cpu = ((data & 0xffffffff) >> 16) & 0x3ff; vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu); if (unlikely(vcpu == NULL)) { - kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); + kvm_pr_unimpl("%s: invalid target cpu: %d\n", __func__, cpu); return; } @@ -105,7 +105,7 @@ static int mail_send(struct kvm *kvm, uint64_t data) cpu = ((data & 0xffffffff) >> 16) & 0x3ff; vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu); if (unlikely(vcpu == NULL)) { - kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); + kvm_pr_unimpl("%s: invalid target cpu: %d\n", __func__, cpu); return 0; } mailbox = ((data & 0xffffffff) >> 2) & 0x7; @@ -139,7 +139,7 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data) ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, 4, &val); srcu_read_unlock(&vcpu->kvm->srcu, idx); if (unlikely(ret)) { - kvm_err("%s: : read data from addr %llx failed\n", __func__, addr); + kvm_pr_unimpl("%s: : read data from addr %llx failed\n", __func__, addr); return 0; } /* Construct the mask by scanning the bit 27-30 */ @@ -155,7 +155,7 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data) ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, 4, &val); srcu_read_unlock(&vcpu->kvm->srcu, idx); if (unlikely(ret)) - kvm_err("%s: : write data to addr %llx failed\n", __func__, addr); + kvm_pr_unimpl("%s: : write data to addr %llx failed\n", __func__, addr); return 0; } @@ -168,7 +168,7 @@ static int any_send(struct kvm *kvm, uint64_t data) cpu = ((data & 0xffffffff) >> 16) & 0x3ff; vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu); if (unlikely(vcpu == NULL)) { - kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); + kvm_pr_unimpl("%s: invalid target cpu: %d\n", __func__, cpu); return 0; } offset = data & 0xffff; @@ -206,7 +206,7 @@ static int loongarch_ipi_readl(struct kvm_vcpu *vcpu, gpa_t addr, int len, void res = read_mailbox(vcpu, offset, len); break; default: - kvm_err("%s: unknown addr: %llx\n", __func__, addr); + kvm_pr_unimpl("%s: unknown addr: %llx\n", __func__, addr); break; } *(uint64_t *)val = res; @@ -244,7 +244,7 @@ static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, cons break; case IOCSR_IPI_BUF_20 ... IOCSR_IPI_BUF_38 + 7: if (offset + len > IOCSR_IPI_BUF_38 + 8) { - kvm_err("%s: invalid offset or len: offset = %d, len = %d\n", + kvm_pr_unimpl("%s: invalid offset or len: offset = %d, len = %d\n", __func__, offset, len); break; } @@ -260,7 +260,7 @@ static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, cons any_send(vcpu->kvm, data); break; default: - kvm_err("%s: unknown addr: %llx\n", __func__, addr); + kvm_pr_unimpl("%s: unknown addr: %llx\n", __func__, addr); break; } @@ -303,7 +303,7 @@ static int kvm_ipi_regs_access(struct kvm_device *dev, vcpu = kvm_get_vcpu_by_id(dev->kvm, cpu); if (unlikely(vcpu == NULL)) { - kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); + kvm_pr_unimpl("%s: invalid target cpu: %d\n", __func__, cpu); return -EINVAL; } @@ -337,7 +337,7 @@ static int kvm_ipi_regs_access(struct kvm_device *dev, len = 8; break; default: - kvm_err("%s: unknown ipi register, addr = %d\n", __func__, addr); + kvm_pr_unimpl("%s: unknown ipi register, addr = %d\n", __func__, addr); return -EINVAL; } @@ -371,7 +371,7 @@ static int kvm_ipi_get_attr(struct kvm_device *dev, case KVM_DEV_LOONGARCH_IPI_GRP_REGS: return kvm_ipi_regs_access(dev, attr, false); default: - kvm_err("%s: unknown group (%d)\n", __func__, attr->group); + kvm_pr_unimpl("%s: unknown group (%d)\n", __func__, attr->group); return -EINVAL; } } @@ -383,7 +383,7 @@ static int kvm_ipi_set_attr(struct kvm_device *dev, case KVM_DEV_LOONGARCH_IPI_GRP_REGS: return kvm_ipi_regs_access(dev, attr, true); default: - kvm_err("%s: unknown group (%d)\n", __func__, attr->group); + kvm_pr_unimpl("%s: unknown group (%d)\n", __func__, attr->group); return -EINVAL; } } @@ -396,13 +396,13 @@ static int kvm_ipi_create(struct kvm_device *dev, u32 type) struct loongarch_ipi *s; if (!dev) { - kvm_err("%s: kvm_device ptr is invalid!\n", __func__); + kvm_pr_unimpl("%s: kvm_device ptr is invalid!\n", __func__); return -EINVAL; } kvm = dev->kvm; if (kvm->arch.ipi) { - kvm_err("%s: LoongArch IPI has already been created!\n", __func__); + kvm_pr_unimpl("%s: LoongArch IPI has already been created!\n", __func__); return -EINVAL; } @@ -422,7 +422,7 @@ static int kvm_ipi_create(struct kvm_device *dev, u32 type) ret = kvm_io_bus_register_dev(kvm, KVM_IOCSR_BUS, IOCSR_IPI_BASE, IOCSR_IPI_SIZE, device); mutex_unlock(&kvm->slots_lock); if (ret < 0) { - kvm_err("%s: Initialize IOCSR dev failed, ret = %d\n", __func__, ret); + kvm_pr_unimpl("%s: Initialize IOCSR dev failed, ret = %d\n", __func__, ret); goto err; } diff --git a/arch/loongarch/kvm/intc/pch_pic.c b/arch/loongarch/kvm/intc/pch_pic.c index 175a630aceb4..e7b77705c516 100644 --- a/arch/loongarch/kvm/intc/pch_pic.c +++ b/arch/loongarch/kvm/intc/pch_pic.c @@ -151,12 +151,12 @@ static int kvm_pch_pic_read(struct kvm_vcpu *vcpu, struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic; if (!s) { - kvm_err("%s: pch pic irqchip not valid!\n", __func__); + kvm_pr_unimpl("%s: pch pic irqchip not valid!\n", __func__); return ret; } if (addr & (len - 1)) { - kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); + kvm_pr_unimpl("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); return ret; } @@ -250,12 +250,12 @@ static int kvm_pch_pic_write(struct kvm_vcpu *vcpu, struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic; if (!s) { - kvm_err("%s: pch pic irqchip not valid!\n", __func__); + kvm_pr_unimpl("%s: pch pic irqchip not valid!\n", __func__); return ret; } if (addr & (len - 1)) { - kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); + kvm_pr_unimpl("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); return ret; } @@ -390,13 +390,13 @@ static int kvm_pch_pic_set_attr(struct kvm_device *dev, return -EFAULT; if (!dev->kvm->arch.pch_pic) { - kvm_err("%s: please create pch_pic irqchip first!\n", __func__); + kvm_pr_unimpl("%s: pch_pic irqchip not created\n", __func__); return -ENODEV; } return kvm_pch_pic_init(dev, addr); default: - kvm_err("%s: unknown group (%d) attr (%lld)\n", __func__, attr->group, + kvm_pr_unimpl("%s: unknown group (%d) attr (%lld)\n", __func__, attr->group, attr->attr); return -EINVAL; } diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index 20c207d80e31..1a0cf6c81df6 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -1473,7 +1473,7 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) else if (intr < 0) kvm_dequeue_irq(vcpu, -intr); else { - kvm_err("%s: invalid interrupt ioctl %d\n", __func__, irq->irq); + kvm_pr_unimpl("%s: invalid interrupt ioctl %d\n", __func__, irq->irq); return -EINVAL; } -- 2.39.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 5/5] LoongArch: KVM: Use internal API to deliver interrupt in kernel mode 2026-07-14 7:25 [PATCH v5 0/5] LoongArch: KVM: Harden interrupt injection Bibo Mao ` (3 preceding siblings ...) 2026-07-14 7:25 ` [PATCH v5 4/5] LoongArch: KVM: Replace kvm_err() with kvm_pr_unimpl() Bibo Mao @ 2026-07-14 7:25 ` Bibo Mao 2026-07-14 7:53 ` sashiko-bot 4 siblings, 1 reply; 10+ messages in thread From: Bibo Mao @ 2026-07-14 7:25 UTC (permalink / raw) To: Huacai Chen; +Cc: Song Gao, kvm, loongarch, linux-kernel API kvm_vcpu_ioctl_interrupt() is mainly to used to deliver interrupt from user mode, and internal APIs kvm_queue_irq() and kvm_dequeue_irq() are used in kernel mode. Also move IPI inject and ack within lock protection to avoid contention in ipi_set() and ipi_clear(). Signed-off-by: Bibo Mao <maobibo@loongson.cn> --- arch/loongarch/kvm/intc/dmsintc.c | 7 ++++--- arch/loongarch/kvm/intc/eiointc.c | 14 +++++++++----- arch/loongarch/kvm/intc/ipi.c | 14 ++++++-------- arch/loongarch/kvm/vcpu.c | 3 +++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c index 5797ef17cd71..1c716e24c5b0 100644 --- a/arch/loongarch/kvm/intc/dmsintc.c +++ b/arch/loongarch/kvm/intc/dmsintc.c @@ -49,7 +49,6 @@ void dmsintc_inject_irq(struct kvm_vcpu *vcpu) int dmsintc_deliver_msi_to_vcpu(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 vector, int level) { - struct kvm_interrupt vcpu_irq; struct dmsintc_state *ds = &vcpu->arch.dmsintc_state; if (!level) @@ -59,9 +58,11 @@ int dmsintc_deliver_msi_to_vcpu(struct kvm *kvm, if (!ds) return -ENODEV; - vcpu_irq.irq = INT_AVEC; + if (!kvm_guest_has_msgint(&vcpu->arch)) + return -EINVAL; + set_bit(vector, (unsigned long *)&ds->vector_map); - kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq); + kvm_queue_irq(vcpu, INT_AVEC); kvm_vcpu_kick(vcpu); return 0; diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c index fd089d54da10..e04aadbd68db 100644 --- a/arch/loongarch/kvm/intc/eiointc.c +++ b/arch/loongarch/kvm/intc/eiointc.c @@ -17,7 +17,8 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s) if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) { ipnum = count_trailing_zeros(ipnum); ipnum = ipnum < 4 ? ipnum : 0; - } + } else if (ipnum >= LOONGSON_IP_NUM) + ipnum = 0; cpuid = ((u8 *)s->coremap)[irq]; vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid); @@ -36,13 +37,13 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) { int ipnum, cpu, found; struct kvm_vcpu *vcpu; - struct kvm_interrupt vcpu_irq; ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff; if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) { ipnum = count_trailing_zeros(ipnum); ipnum = ipnum < 4 ? ipnum : 0; - } + } else if (ipnum >= LOONGSON_IP_NUM) + ipnum = 0; cpu = s->sw_coremap[irq]; vcpu = kvm_get_vcpu_by_id(s->kvm, cpu); @@ -67,8 +68,11 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) if (found < EIOINTC_IRQS) return; /* other irq is handling, needn't update parent irq */ - vcpu_irq.irq = level ? (INT_HWI0 + ipnum) : -(INT_HWI0 + ipnum); - kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq); + if (level) + kvm_queue_irq(vcpu, INT_HWI0 + ipnum); + else + kvm_dequeue_irq(vcpu, INT_HWI0 + ipnum); + kvm_vcpu_kick(vcpu); } static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s, diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 0edaa124a61e..f30d0d13f54d 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -10,16 +10,15 @@ static void ipi_set(struct kvm_vcpu *vcpu, uint32_t data) { uint32_t status; - struct kvm_interrupt irq; spin_lock(&vcpu->arch.ipi_state.lock); status = vcpu->arch.ipi_state.status; vcpu->arch.ipi_state.status |= data; - spin_unlock(&vcpu->arch.ipi_state.lock); if ((status == 0) && data) { - irq.irq = LARCH_INT_IPI; - kvm_vcpu_ioctl_interrupt(vcpu, &irq); + kvm_queue_irq(vcpu, LARCH_INT_IPI); + kvm_vcpu_kick(vcpu); } + spin_unlock(&vcpu->arch.ipi_state.lock); } static void ipi_send(struct kvm *kvm, uint64_t data) @@ -40,16 +39,15 @@ static void ipi_send(struct kvm *kvm, uint64_t data) static void ipi_clear(struct kvm_vcpu *vcpu, uint64_t data) { uint32_t status; - struct kvm_interrupt irq; spin_lock(&vcpu->arch.ipi_state.lock); vcpu->arch.ipi_state.status &= ~data; status = vcpu->arch.ipi_state.status; - spin_unlock(&vcpu->arch.ipi_state.lock); if (status == 0) { - irq.irq = -LARCH_INT_IPI; - kvm_vcpu_ioctl_interrupt(vcpu, &irq); + kvm_dequeue_irq(vcpu, LARCH_INT_IPI); + kvm_vcpu_kick(vcpu); } + spin_unlock(&vcpu->arch.ipi_state.lock); } static uint64_t read_mailbox(struct kvm_vcpu *vcpu, int offset, int len) diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index 1a0cf6c81df6..f81dadc62c98 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -1465,6 +1465,9 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) if (vector >= EXCCODE_INT_NUM) return -EINVAL; + if (kvm_arch_irqchip_in_kernel(vcpu->kvm)) + return -EINVAL; + if (!kvm_guest_has_msgint(&vcpu->arch) && (vector == INT_AVEC)) return -EINVAL; -- 2.39.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5 5/5] LoongArch: KVM: Use internal API to deliver interrupt in kernel mode 2026-07-14 7:25 ` [PATCH v5 5/5] LoongArch: KVM: Use internal API to deliver interrupt in kernel mode Bibo Mao @ 2026-07-14 7:53 ` sashiko-bot 0 siblings, 0 replies; 10+ messages in thread From: sashiko-bot @ 2026-07-14 7:53 UTC (permalink / raw) To: Bibo Mao; +Cc: kvm Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: New issues: - [Medium] The commit silently includes a critical fix for a guest-triggerable out-of-bounds array access in the EIOINTC emulation. Pre-existing issues: - [Critical] Unvalidated 'msi.data' from userspace causes severe out-of-bounds memory accesses in 'eiointc_set_irq' and 'eiointc_update_irq'. -- --- Patch [5]: [PATCH v5 5/5] LoongArch: KVM: Use internal API to deliver interrupt in kernel mode --- commit f180398d8de8f24b25d2d879c17f336978ed95e1 Author: Bibo Mao <maobibo@loongson.cn> LoongArch: KVM: Use internal API to deliver interrupt in kernel mode API kvm_vcpu_ioctl_interrupt() is mainly to used to deliver interrupt from user mode, and internal APIs kvm_queue_irq() and kvm_dequeue_irq() are used in kernel mode. Also move IPI inject and ack within lock protection to avoid contention in ipi_set() and ipi_clear(). > diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c > index fd089d54da103..e04aadbd68db9 100644 > --- a/arch/loongarch/kvm/intc/eiointc.c > +++ b/arch/loongarch/kvm/intc/eiointc.c > @@ -17,7 +17,8 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s) > if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) { > ipnum = count_trailing_zeros(ipnum); > ipnum = ipnum < 4 ? ipnum : 0; > - } > + } else if (ipnum >= LOONGSON_IP_NUM) > + ipnum = 0; [Severity: Medium] This looks like a fix for an out-of-bounds array access, as ipnum is used to index into s->sw_coreisr[][] shortly after this. Should this fix be documented in the commit message or split into a separate patch so it can be properly tracked and backported? [ ... ] > @@ -36,13 +37,13 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) > { > int ipnum, cpu, found; > struct kvm_vcpu *vcpu; > > ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff; > if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) { > ipnum = count_trailing_zeros(ipnum); > ipnum = ipnum < 4 ? ipnum : 0; > - } > + } else if (ipnum >= LOONGSON_IP_NUM) > + ipnum = 0; > > cpu = s->sw_coremap[irq]; [Severity: Critical] This is a pre-existing issue, but does this code perform an out-of-bounds read or write if irq is greater than or equal to EIOINTC_IRQS (256)? In pch_msi_set_irq(), the untrusted 32-bit e->msi.data is passed directly as the irq index: arch/loongarch/kvm/intc/pch_pic.c:pch_msi_set_irq() { ... eiointc_set_irq(kvm->arch.eiointc, e->msi.data, level); ... } eiointc_set_irq() then performs a bitwise operation on the 256-bit isr array without bounds checking: arch/loongarch/kvm/intc/eiointc.c:eiointc_set_irq() { ... level ? __set_bit(irq, isr) : __clear_bit(irq, isr); eiointc_update_irq(s, irq, level); ... } And here in eiointc_update_irq(), it accesses s->sw_coremap[irq]. If e->msi.data from userspace or guest is >= 256, could this cause host kernel memory corruption? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260714072520.2745942-1-maobibo@loongson.cn?part=5 ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-07-14 7:53 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-14 7:25 [PATCH v5 0/5] LoongArch: KVM: Harden interrupt injection Bibo Mao 2026-07-14 7:25 ` [PATCH v5 1/5] LoongArch: KVM: Fix uninitialized stack variable issue with dmsintc Bibo Mao 2026-07-14 7:44 ` sashiko-bot 2026-07-14 7:25 ` [PATCH v5 2/5] LoongArch: KVM: Return directly when IPI address is not aligned Bibo Mao 2026-07-14 7:45 ` sashiko-bot 2026-07-14 7:25 ` [PATCH v5 3/5] LoongArch: KVM: Set default MAILBOX access size with 8 Bibo Mao 2026-07-14 7:51 ` sashiko-bot 2026-07-14 7:25 ` [PATCH v5 4/5] LoongArch: KVM: Replace kvm_err() with kvm_pr_unimpl() Bibo Mao 2026-07-14 7:25 ` [PATCH v5 5/5] LoongArch: KVM: Use internal API to deliver interrupt in kernel mode Bibo Mao 2026-07-14 7:53 ` sashiko-bot
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.