]> www.infradead.org Git - linux.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)
committerMarc Zyngier <maz@kernel.org>
Thu, 6 Jun 2024 07:54:15 +0000 (08:54 +0100)
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
arch/arm64/kvm/vgic/vgic-init.c
arch/arm64/kvm/vgic/vgic-mmio-v3.c
arch/arm64/kvm/vgic/vgic.h

index 8f5b7a3e7009e3be4770c34149eb26ec4f0c4588..7f68cf58b978fb11c78b4b0bb6d9c15a0625c45b 100644 (file)
@@ -391,7 +391,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 a3983a631b5ad1cafce9bb5ec91bcc19a20c250f..9e50928f5d7dfd22880f8fb874a6bebb16f36989 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 6106ebd5ba429907632cb7eee9281162f1f9153d..03d356a123771fda53c9aff25e475cbb68079bc6 100644 (file)
@@ -316,7 +316,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);