mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
KVM: arm64: Disassociate vcpus from redistributor region on teardown
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: e5a3563546 ("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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
92c77807d9
commit
68df4fc449
@@ -355,7 +355,7 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
|
|||||||
|
|
||||||
if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
|
if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
|
||||||
list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list)
|
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);
|
INIT_LIST_HEAD(&dist->rd_regions);
|
||||||
} else {
|
} else {
|
||||||
dist->vgic_cpu_base = VGIC_ADDR_UNDEF;
|
dist->vgic_cpu_base = VGIC_ADDR_UNDEF;
|
||||||
|
|||||||
@@ -942,8 +942,19 @@ free:
|
|||||||
return ret;
|
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);
|
list_del(&rdreg->list);
|
||||||
kfree(rdreg);
|
kfree(rdreg);
|
||||||
}
|
}
|
||||||
@@ -968,7 +979,7 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count)
|
|||||||
|
|
||||||
mutex_lock(&kvm->arch.config_lock);
|
mutex_lock(&kvm->arch.config_lock);
|
||||||
rdreg = vgic_v3_rdist_region_from_index(kvm, index);
|
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);
|
mutex_unlock(&kvm->arch.config_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,7 +301,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,
|
struct vgic_redist_region *vgic_v3_rdist_region_from_index(struct kvm *kvm,
|
||||||
u32 index);
|
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);
|
bool vgic_v3_rdist_overlap(struct kvm *kvm, gpa_t base, size_t size);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user