]> exis.tech > repos - linux.git/commitdiff
KVM: Move kvm_io_bus_get_dev() locking responsibilities to callers
authorMarc Zyngier <maz@kernel.org>
Sat, 27 Jun 2026 10:51:05 +0000 (11:51 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 6 Jul 2026 16:15:57 +0000 (17:15 +0100)
kvm_io_bus_get_dev() returns a device that is only matched by the
address, and nothing else. This can cause a lifetime issue if
the matched device is not the expected type, as by the time
the caller can introspect the object, it might be gone (the srcu
lock having been dropped).

Given that there is only a single user of this helper, the simplest
option is to move the locking responsibility to the caller, which
can keep the srcu lock held for as long as it wants.

Note that this aligns with other kvm_io_bus*() helpers, which
already require the srcu lock to be held by the callers.

Reported-by: Will Deacon <will@kernel.org>
Fixes: 8a39d00670f07 ("KVM: kvm_io_bus: Add kvm_io_bus_get_dev() call")
Link: https://lore.kernel.org/all/20260626111344.802555-1-maz@kernel.org
Cc: stable@vger.kernel.org
Reviewed-by: Oliver Upton <oupton@kernel.org>
Link: https://patch.msgid.link/20260627105105.1005990-1-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/vgic/vgic-its.c
virt/kvm/kvm_main.c

index 67d107e9a77d1447442ee38950b51d518c894a5d..c90abde39fb8e395037f5429ccf3ff428bf10ee9 100644 (file)
@@ -508,6 +508,8 @@ static struct vgic_its *__vgic_doorbell_to_its(struct kvm *kvm, gpa_t db)
        struct kvm_io_device *kvm_io_dev;
        struct vgic_io_device *iodev;
 
+       guard(srcu)(&kvm->srcu);
+
        kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, db);
        if (!kvm_io_dev)
                return ERR_PTR(-EINVAL);
index 89489996fbc1efbb6dab0e9581f98ec13b01c0ec..5788eac0ab81cc34c22bd7c2683eba8095c24d08 100644 (file)
@@ -6068,25 +6068,19 @@ struct kvm_io_device *kvm_io_bus_get_dev(struct kvm *kvm, enum kvm_bus bus_idx,
                                         gpa_t addr)
 {
        struct kvm_io_bus *bus;
-       int dev_idx, srcu_idx;
-       struct kvm_io_device *iodev = NULL;
+       int dev_idx;
 
-       srcu_idx = srcu_read_lock(&kvm->srcu);
+       lockdep_assert_held(&kvm->srcu);
 
        bus = kvm_get_bus_srcu(kvm, bus_idx);
        if (!bus)
-               goto out_unlock;
+               return NULL;
 
        dev_idx = kvm_io_bus_get_first_dev(bus, addr, 1);
        if (dev_idx < 0)
-               goto out_unlock;
-
-       iodev = bus->range[dev_idx].dev;
-
-out_unlock:
-       srcu_read_unlock(&kvm->srcu, srcu_idx);
+               return NULL;
 
-       return iodev;
+       return bus->range[dev_idx].dev;
 }
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_io_bus_get_dev);