kvm_vm_ioctl_deassign_dev_irq() would potentially recursively get kvm->lock,
because it called kvm_deassigned_irq() which implicit hold kvm->lock by calling
deassign_host_irq().

Fix it by move kvm_deassign_irq() out of critial region. And add the missing
lock for deassign_guest_irq().

Reported-by: Alex Williamson <[email protected]>
Signed-off-by: Sheng Yang <[email protected]>
---
 virt/kvm/kvm_main.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 4d00942..3c69655 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -215,6 +215,8 @@ static void kvm_assigned_dev_ack_irq(struct 
kvm_irq_ack_notifier *kian)
 static void deassign_guest_irq(struct kvm *kvm,
                               struct kvm_assigned_dev_kernel *assigned_dev)
 {
+       mutex_lock(&kvm->lock);
+
        kvm_unregister_irq_ack_notifier(&assigned_dev->ack_notifier);
        assigned_dev->ack_notifier.gsi = -1;
 
@@ -222,6 +224,8 @@ static void deassign_guest_irq(struct kvm *kvm,
                kvm_free_irq_source_id(kvm, assigned_dev->irq_source_id);
        assigned_dev->irq_source_id = -1;
        assigned_dev->irq_requested_type &= ~(KVM_DEV_IRQ_GUEST_MASK);
+
+       mutex_unlock(&kvm->lock);
 }
 
 /* The function implicit hold kvm->lock mutex due to cancel_work_sync() */
@@ -558,20 +562,16 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
                                         struct kvm_assigned_irq
                                         *assigned_irq)
 {
-       int r = -ENODEV;
        struct kvm_assigned_dev_kernel *match;
 
        mutex_lock(&kvm->lock);
-
        match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
                                      assigned_irq->assigned_dev_id);
+       mutex_unlock(&kvm->lock);
        if (!match)
-               goto out;
+               return -ENODEV;
 
-       r = kvm_deassign_irq(kvm, match, assigned_irq->flags);
-out:
-       mutex_unlock(&kvm->lock);
-       return r;
+       return kvm_deassign_irq(kvm, match, assigned_irq->flags);
 }
 
 static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
-- 
1.5.4.5

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to