]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Disassociate vcpus from redistributor region on teardown
authorMarc Zyngier <maz@kernel.org>
Wed, 5 Jun 2024 17:56:37 +0000 (18:56 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jun 2024 11:52:27 +0000 (13:52 +0200)
commit 0d92e4a7ffd5c42b9fa864692f82476c0bf8bcc8 upstream.

When tearing down a redistributor region, make sure we don't have
any dangling pointer to that region stored in a vcpu.

Fixes: e5a35635464b ("kvm: arm64: vgic-v3: Introduce vgic_v3_free_redist_region()")
Reported-by: Alexander Potapenko <glider@google.com>
Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240605175637.1635653-1-maz@kernel.org
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/kvm/vgic/vgic-init.c
arch/arm64/kvm/vgic/vgic-mmio-v3.c
arch/arm64/kvm/vgic/vgic.h

index f20941f83a077cbc2be093b487e4afe5a29f30ae..ce3bcff34b09b8217392d3559365e96e76389808 100644 (file)
@@ -355,7 +355,7 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
 
        if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
                list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list)
-                       vgic_v3_free_redist_region(rdreg);
+                       vgic_v3_free_redist_region(kvm, rdreg);
                INIT_LIST_HEAD(&dist->rd_regions);
        } else {
                dist->vgic_cpu_base = VGIC_ADDR_UNDEF;
index c15ee1df036a22b42d0059cfe546857450fb91d7..dad60b1e21d4de4271e6faf67f7fc75c5a119047 100644 (file)
@@ -919,8 +919,19 @@ free:
        return ret;
 }
 
-void vgic_v3_free_redist_region(struct vgic_redist_region *rdreg)
+void vgic_v3_free_redist_region(struct kvm *kvm, struct vgic_redist_region *rdreg)
 {
+       struct kvm_vcpu *vcpu;
+       unsigned long c;
+
+       lockdep_assert_held(&kvm->arch.config_lock);
+
+       /* Garbage collect the region */
+       kvm_for_each_vcpu(c, vcpu, kvm) {
+               if (vcpu->arch.vgic_cpu.rdreg == rdreg)
+                       vcpu->arch.vgic_cpu.rdreg = NULL;
+       }
+
        list_del(&rdreg->list);
        kfree(rdreg);
 }
@@ -945,7 +956,7 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count)
 
                mutex_lock(&kvm->arch.config_lock);
                rdreg = vgic_v3_rdist_region_from_index(kvm, index);
-               vgic_v3_free_redist_region(rdreg);
+               vgic_v3_free_redist_region(kvm, rdreg);
                mutex_unlock(&kvm->arch.config_lock);
                return ret;
        }
index 0c2b82de8fa3c723279695c8641de02e7775065d..08b4c09a0886d79dbad7abc98de7ae9d936fdcbe 100644 (file)
@@ -317,7 +317,7 @@ vgic_v3_rd_region_size(struct kvm *kvm, struct vgic_redist_region *rdreg)
 
 struct vgic_redist_region *vgic_v3_rdist_region_from_index(struct kvm *kvm,
                                                           u32 index);
-void vgic_v3_free_redist_region(struct vgic_redist_region *rdreg);
+void vgic_v3_free_redist_region(struct kvm *kvm, struct vgic_redist_region *rdreg);
 
 bool vgic_v3_rdist_overlap(struct kvm *kvm, gpa_t base, size_t size);