Skip to content

Commit 51cdc8b

Browse files
yiliu1765awilliam
authored andcommitted
kvm/vfio: Fix potential deadlock on vfio group_lock
Currently it is possible that the final put of a KVM reference comes from vfio during its device close operation. This occurs while the vfio group lock is held; however, if the vfio device is still in the kvm device list, then the following call chain could result in a deadlock: VFIO holds group->group_lock/group_rwsem -> kvm_put_kvm -> kvm_destroy_vm -> kvm_destroy_devices -> kvm_vfio_destroy -> kvm_vfio_file_set_kvm -> vfio_file_set_kvm -> try to hold group->group_lock/group_rwsem The key function is the kvm_destroy_devices() which triggers destroy cb of kvm_device_ops. It calls back to vfio and try to hold group_lock. So if this path doesn't call back to vfio, this dead lock would be fixed. Actually, there is a way for it. KVM provides another point to free the kvm-vfio device which is the point when the device file descriptor is closed. This can be achieved by providing the release cb instead of the destroy cb. Also rename kvm_vfio_destroy() to be kvm_vfio_release(). /* * Destroy is responsible for freeing dev. * * Destroy may be called before or after destructors are called * on emulated I/O regions, depending on whether a reference is * held by a vcpu or other kvm component that gets destroyed * after the emulated I/O. */ void (*destroy)(struct kvm_device *dev); /* * Release is an alternative method to free the device. It is * called when the device file descriptor is closed. Once * release is called, the destroy method will not be called * anymore as the device is removed from the device list of * the VM. kvm->lock is held. */ void (*release)(struct kvm_device *dev); Fixes: 421cfe6 ("vfio: remove VFIO_GROUP_NOTIFY_SET_KVM") Reported-by: Alex Williamson <alex.williamson@redhat.com> Suggested-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Yi Liu <yi.l.liu@intel.com> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Link: https://lore.kernel.org/r/20230114000351.115444-1-mjrosato@linux.ibm.com Link: https://lore.kernel.org/r/20230120150528.471752-1-yi.l.liu@intel.com [aw: update comment as well, s/destroy/release/] Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent 895c074 commit 51cdc8b

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

virt/kvm/vfio.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static int kvm_vfio_has_attr(struct kvm_device *dev,
336336
return -ENXIO;
337337
}
338338

339-
static void kvm_vfio_destroy(struct kvm_device *dev)
339+
static void kvm_vfio_release(struct kvm_device *dev)
340340
{
341341
struct kvm_vfio *kv = dev->private;
342342
struct kvm_vfio_group *kvg, *tmp;
@@ -355,15 +355,15 @@ static void kvm_vfio_destroy(struct kvm_device *dev)
355355
kvm_vfio_update_coherency(dev);
356356

357357
kfree(kv);
358-
kfree(dev); /* alloc by kvm_ioctl_create_device, free by .destroy */
358+
kfree(dev); /* alloc by kvm_ioctl_create_device, free by .release */
359359
}
360360

361361
static int kvm_vfio_create(struct kvm_device *dev, u32 type);
362362

363363
static struct kvm_device_ops kvm_vfio_ops = {
364364
.name = "kvm-vfio",
365365
.create = kvm_vfio_create,
366-
.destroy = kvm_vfio_destroy,
366+
.release = kvm_vfio_release,
367367
.set_attr = kvm_vfio_set_attr,
368368
.has_attr = kvm_vfio_has_attr,
369369
};

0 commit comments

Comments
 (0)