* [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface
@ 2024-08-08 9:15 Marc Zyngier
2024-08-08 17:07 ` Oliver Upton
2024-08-19 9:39 ` Zenghui Yu
0 siblings, 2 replies; 6+ messages in thread
From: Marc Zyngier @ 2024-08-08 9:15 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: James Morse, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Alexander Potapenko
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@google.com>
Tested-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Marc Zyngier <maz@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);
--
2.39.2
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface 2024-08-08 9:15 [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface Marc Zyngier @ 2024-08-08 17:07 ` Oliver Upton 2024-08-19 9:39 ` Zenghui Yu 1 sibling, 0 replies; 6+ messages in thread From: Oliver Upton @ 2024-08-08 17:07 UTC (permalink / raw) To: kvmarm, Marc Zyngier, linux-arm-kernel Cc: Oliver Upton, Suzuki K Poulose, Zenghui Yu, Alexander Potapenko, James Morse On Thu, 8 Aug 2024 10:15:46 +0100, 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. > > > [...] Applied to kvmarm/fixes, thanks! [1/1] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface https://git.kernel.org/kvmarm/kvmarm/c/9eb18136af9f -- Best, Oliver ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface 2024-08-08 9:15 [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface Marc Zyngier 2024-08-08 17:07 ` Oliver Upton @ 2024-08-19 9:39 ` Zenghui Yu 2024-08-19 10:53 ` Marc Zyngier 1 sibling, 1 reply; 6+ messages in thread From: Zenghui Yu @ 2024-08-19 9:39 UTC (permalink / raw) To: Marc Zyngier Cc: kvmarm, linux-arm-kernel, James Morse, Suzuki K Poulose, Oliver Upton, Alexander Potapenko 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@google.com> > Tested-by: Alexander Potapenko <glider@google.com> > Signed-off-by: Marc Zyngier <maz@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 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface 2024-08-19 9:39 ` Zenghui Yu @ 2024-08-19 10:53 ` Marc Zyngier 2024-08-19 12:31 ` Zenghui Yu 0 siblings, 1 reply; 6+ messages in thread From: Marc Zyngier @ 2024-08-19 10:53 UTC (permalink / raw) To: Zenghui Yu Cc: kvmarm, linux-arm-kernel, James Morse, Suzuki K Poulose, Oliver Upton, Alexander Potapenko On Mon, 19 Aug 2024 10:39:50 +0100, Zenghui Yu <yuzenghui@huawei.com> wrote: > > 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@google.com> > > Tested-by: Alexander Potapenko <glider@google.com> > > Signed-off-by: Marc Zyngier <maz@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. Arghh. Thanks for reporting this. Can you try the following patch? It does the trick for me, but I don't trust myself anymore... M. diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 41feb858ff9a..e7c53e8af3d1 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -417,10 +417,8 @@ static void __kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) kfree(vgic_cpu->private_irqs); vgic_cpu->private_irqs = NULL; - if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { - vgic_unregister_redist_iodev(vcpu); + if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; - } } void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) @@ -448,6 +446,11 @@ void kvm_vgic_destroy(struct kvm *kvm) kvm_vgic_dist_destroy(kvm); mutex_unlock(&kvm->arch.config_lock); + + if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) + kvm_for_each_vcpu(i, vcpu, kvm) + vgic_unregister_redist_iodev(vcpu); + mutex_unlock(&kvm->slots_lock); } diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c index 2caa64415ff3..f50274fd5581 100644 --- a/arch/arm64/kvm/vgic/vgic.c +++ b/arch/arm64/kvm/vgic/vgic.c @@ -36,6 +36,11 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = { * we have to disable IRQs before taking this lock and everything lower * than it. * + * The config_lock has additional ordering requirements: + * kvm->slots_lock + * kvm->srcu + * kvm->arch.config_lock + * * If you need to take multiple locks, always take the upper lock first, * then the lower ones, e.g. first take the its_lock, then the irq_lock. * If you are already holding a lock and need to take a higher one, you -- Without deviation from the norm, progress is not possible. ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface 2024-08-19 10:53 ` Marc Zyngier @ 2024-08-19 12:31 ` Zenghui Yu 2024-08-19 12:48 ` Marc Zyngier 0 siblings, 1 reply; 6+ messages in thread From: Zenghui Yu @ 2024-08-19 12:31 UTC (permalink / raw) To: Marc Zyngier Cc: kvmarm, linux-arm-kernel, James Morse, Suzuki K Poulose, Oliver Upton, Alexander Potapenko On 2024/8/19 18:53, Marc Zyngier wrote: > On Mon, 19 Aug 2024 10:39:50 +0100, > Zenghui Yu <yuzenghui@huawei.com> wrote: > > > > 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@google.com> > > > Tested-by: Alexander Potapenko <glider@google.com> > > > Signed-off-by: Marc Zyngier <maz@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. > > Arghh. Thanks for reporting this. Can you try the following patch? It > does the trick for me, but I don't trust myself anymore... I tested it with defconfig+PROVE_LOCKING and my own config, both worked for me (the WARNING disappeared). I think the locking order should be correct now. Thanks, Zenghui ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface 2024-08-19 12:31 ` Zenghui Yu @ 2024-08-19 12:48 ` Marc Zyngier 0 siblings, 0 replies; 6+ messages in thread From: Marc Zyngier @ 2024-08-19 12:48 UTC (permalink / raw) To: Zenghui Yu Cc: kvmarm, linux-arm-kernel, James Morse, Suzuki K Poulose, Oliver Upton, Alexander Potapenko On Mon, 19 Aug 2024 13:31:59 +0100, Zenghui Yu <yuzenghui@huawei.com> wrote: > > On 2024/8/19 18:53, Marc Zyngier wrote: > > On Mon, 19 Aug 2024 10:39:50 +0100, > > Zenghui Yu <yuzenghui@huawei.com> wrote: > > > > > > 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@google.com> > > > > Tested-by: Alexander Potapenko <glider@google.com> > > > > Signed-off-by: Marc Zyngier <maz@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. > > > > Arghh. Thanks for reporting this. Can you try the following patch? It > > does the trick for me, but I don't trust myself anymore... > > I tested it with defconfig+PROVE_LOCKING and my own config, both worked > for me (the WARNING disappeared). I think the locking order should be > correct now. Awesome. Let me post a proper patch right away. Thanks again, M. -- Without deviation from the norm, progress is not possible. ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-08-19 12:49 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-08-08 9:15 [PATCH] KVM: arm64: vgic: Hold config_lock while tearing down a CPU interface Marc Zyngier 2024-08-08 17:07 ` Oliver Upton 2024-08-19 9:39 ` Zenghui Yu 2024-08-19 10:53 ` Marc Zyngier 2024-08-19 12:31 ` Zenghui Yu 2024-08-19 12:48 ` Marc Zyngier
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).