[PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface
Zenghui Yu
yuzenghui at huawei.com
Mon Aug 19 02:39:50 PDT 2024
Hi Marc,
On 2024/8/8 17:15, Marc Zyngier wrote:
> Tearing down a vcpu CPU interface involves freeing the private interrupt
> array. If we don't hold the lock, we may race against another thread
> trying to configure it. Yeah, fuzzers do wonderful things...
>
> Taking the lock early solves this particular problem.
>
> Fixes: 03b3d00a70b5 ("KVM: arm64: vgic: Allocate private interrupts on demand")
> Reported-by: Alexander Potapenko <glider at google.com>
> Tested-by: Alexander Potapenko <glider at google.com>
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
> arch/arm64/kvm/vgic/vgic-init.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
> index 7f68cf58b978..41feb858ff9a 100644
> --- a/arch/arm64/kvm/vgic/vgic-init.c
> +++ b/arch/arm64/kvm/vgic/vgic-init.c
> @@ -438,14 +438,13 @@ void kvm_vgic_destroy(struct kvm *kvm)
> unsigned long i;
>
> mutex_lock(&kvm->slots_lock);
> + mutex_lock(&kvm->arch.config_lock);
>
> vgic_debug_destroy(kvm);
>
> kvm_for_each_vcpu(i, vcpu, kvm)
> __kvm_vgic_vcpu_destroy(vcpu);
>
> - mutex_lock(&kvm->arch.config_lock);
> -
> kvm_vgic_dist_destroy(kvm);
>
> mutex_unlock(&kvm->arch.config_lock);
The following splat was triggered when running the vgic_init selftest on
a lockdep kernel (I use rc4, with defconfig + PROVE_LOCKING).
I'm not entirely sure that the splat is related to this change. Just
haven't got time to dig further so post it out early for record.
======================================================
WARNING: possible circular locking dependency detected
6.11.0-rc4-dirty Not tainted
------------------------------------------------------
vgic_init/358856 is trying to acquire lock:
ffff2028021b53c8 (&kvm->srcu){.+.+}-{0:0}, at: __synchronize_srcu+0x0/0x170
but task is already holding lock:
ffff2028021b4f80 (&kvm->arch.config_lock){+.+.}-{3:3}, at:
kvm_vgic_destroy+0x50/0x1e0
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (&kvm->arch.config_lock){+.+.}-{3:3}:
__mutex_lock+0x84/0x400
mutex_lock_nested+0x24/0x30
vgic_mmio_write_v3_misc+0x48/0x120
dispatch_mmio_write+0x90/0x128
__kvm_io_bus_write+0xb4/0xec
kvm_io_bus_write+0x68/0x100
io_mem_abort+0xf0/0x3f0
kvm_handle_guest_abort+0x5d0/0x108c
handle_exit+0x6c/0x1c4
kvm_arch_vcpu_ioctl_run+0x41c/0xac4
kvm_vcpu_ioctl+0x310/0xaf4
__arm64_sys_ioctl+0xa8/0xec
invoke_syscall+0x48/0x110
el0_svc_common.constprop.0+0x40/0xe0
do_el0_svc+0x1c/0x28
el0_svc+0x4c/0x11c
el0t_64_sync_handler+0xc0/0xc4
el0t_64_sync+0x190/0x194
-> #0 (&kvm->srcu){.+.+}-{0:0}:
__lock_acquire+0x1304/0x2044
lock_sync+0xd8/0x128
__synchronize_srcu+0x50/0x170
synchronize_srcu_expedited+0x24/0x34
kvm_io_bus_unregister_dev+0x110/0x26c
vgic_unregister_redist_iodev+0x20/0x2c
kvm_vgic_destroy+0xe8/0x1e0
kvm_vgic_map_resources+0xa8/0x138
kvm_arch_vcpu_run_pid_change+0xc0/0x430
kvm_vcpu_ioctl+0xa24/0xaf4
__arm64_sys_ioctl+0xa8/0xec
invoke_syscall+0x48/0x110
el0_svc_common.constprop.0+0x40/0xe0
do_el0_svc+0x1c/0x28
el0_svc+0x4c/0x11c
el0t_64_sync_handler+0xc0/0xc4
el0t_64_sync+0x190/0x194
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&kvm->arch.config_lock);
lock(&kvm->srcu);
lock(&kvm->arch.config_lock);
sync(&kvm->srcu);
*** DEADLOCK ***
3 locks held by vgic_init/358856:
#0: ffff20280aa19b40 (&vcpu->mutex){+.+.}-{3:3}, at:
kvm_vcpu_ioctl+0x84/0xaf4
#1: ffff2028021b40a8 (&kvm->slots_lock){+.+.}-{3:3}, at:
kvm_vgic_destroy+0x44/0x1e0
#2: ffff2028021b4f80 (&kvm->arch.config_lock){+.+.}-{3:3}, at:
kvm_vgic_destroy+0x50/0x1e0
stack backtrace:
CPU: 74 UID: 0 PID: 358856 Comm: vgic_init Kdump: loaded Not tainted
6.11.0-rc4-dirty
Call trace:
dump_backtrace+0x98/0xf0
show_stack+0x18/0x24
dump_stack_lvl+0x90/0xd0
dump_stack+0x18/0x24
print_circular_bug+0x290/0x370
check_noncircular+0x15c/0x170
__lock_acquire+0x1304/0x2044
lock_sync+0xd8/0x128
__synchronize_srcu+0x50/0x170
synchronize_srcu_expedited+0x24/0x34
kvm_io_bus_unregister_dev+0x110/0x26c
vgic_unregister_redist_iodev+0x20/0x2c
kvm_vgic_destroy+0xe8/0x1e0
kvm_vgic_map_resources+0xa8/0x138
kvm_arch_vcpu_run_pid_change+0xc0/0x430
kvm_vcpu_ioctl+0xa24/0xaf4
__arm64_sys_ioctl+0xa8/0xec
invoke_syscall+0x48/0x110
el0_svc_common.constprop.0+0x40/0xe0
do_el0_svc+0x1c/0x28
el0_svc+0x4c/0x11c
el0t_64_sync_handler+0xc0/0xc4
el0t_64_sync+0x190/0x194
Thanks,
Zenghui
More information about the linux-arm-kernel
mailing list