[PATCH 3/6] LoongArch: KVM: Load dmsintc pointer once in pch_msi_set_irq

From: Tao Cui

Date: Sun Sep 27 2026 - 03:53:44 EST


From: Tao Cui <cuitao@xxxxxxxxxx>

pch_msi_set_irq() reads kvm->arch.dmsintc several times: the non-NULL
check and the address-window comparison each reload the pointer, so a
concurrent device removal can be observed between them and the
following dereference hits a freed object.

Load the pointer once at the top of pch_msi_set_irq(); also use the
local in dmsintc_set_irq() for its own cpu_mask read.

Fixes: 03de5eecb0f0 ("LoongArch: KVM: Add DMSINTC inject msi to vCPU")
Signed-off-by: Tao Cui <cuitao@xxxxxxxxxx>
---
arch/loongarch/kvm/intc/dmsintc.c | 6 ++++--
arch/loongarch/kvm/intc/pch_pic.c | 7 ++++---
2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c
index e27f448bb54f..d42567eba3ed 100644
--- a/arch/loongarch/kvm/intc/dmsintc.c
+++ b/arch/loongarch/kvm/intc/dmsintc.c
@@ -70,11 +70,13 @@ int dmsintc_set_irq(struct kvm *kvm, u64 addr, int data, int level)
unsigned int irq, cpu;
struct kvm_vcpu *vcpu;

- if (!kvm->arch.dmsintc)
+ struct loongarch_dmsintc *s = kvm->arch.dmsintc;
+
+ if (!s)
return -EINVAL;

irq = (addr >> AVEC_IRQ_SHIFT) & AVEC_IRQ_MASK;
- cpu = (addr >> AVEC_CPU_SHIFT) & kvm->arch.dmsintc->cpu_mask;
+ cpu = (addr >> AVEC_CPU_SHIFT) & s->cpu_mask;
if (cpu >= KVM_MAX_VCPUS)
return -EINVAL;
vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu);
diff --git a/arch/loongarch/kvm/intc/pch_pic.c b/arch/loongarch/kvm/intc/pch_pic.c
index 88666425d800..e33d6693c37c 100644
--- a/arch/loongarch/kvm/intc/pch_pic.c
+++ b/arch/loongarch/kvm/intc/pch_pic.c
@@ -74,10 +74,11 @@ void pch_pic_set_irq(struct loongarch_pch_pic *s, int irq, int level)
int pch_msi_set_irq(struct kvm *kvm, struct kvm_kernel_irq_routing_entry *e, int level)
{
u64 msg_addr = (((u64)e->msi.address_hi) << 32) | e->msi.address_lo;
+ struct loongarch_dmsintc *dmsintc = kvm->arch.dmsintc;

- if (cpu_has_msgint && kvm->arch.dmsintc &&
- msg_addr >= kvm->arch.dmsintc->msg_addr_base &&
- msg_addr < (kvm->arch.dmsintc->msg_addr_base + kvm->arch.dmsintc->msg_addr_size)) {
+ if (cpu_has_msgint && dmsintc &&
+ msg_addr >= dmsintc->msg_addr_base &&
+ msg_addr < (dmsintc->msg_addr_base + dmsintc->msg_addr_size)) {
return dmsintc_set_irq(kvm, msg_addr, e->msi.data, level);
}

--
2.43.0