mirror of
https://github.com/lkl/linux.git
synced 2025-12-19 08:03:01 +09:00
vfio: fix deadlock between group lock and kvm lock
After51cdc8bc12, we have another deadlock scenario between the kvm->lock and the vfio group_lock with two different codepaths acquiring the locks in different order. Specifically in vfio_open_device, vfio holds the vfio group_lock when issuing device->ops->open_device but some drivers (like vfio-ap) need to acquire kvm->lock during their open_device routine; Meanwhile, kvm_vfio_release will acquire the kvm->lock first before calling vfio_file_set_kvm which will acquire the vfio group_lock. To resolve this, let's remove the need for the vfio group_lock from the kvm_vfio_release codepath. This is done by introducing a new spinlock to protect modifications to the vfio group kvm pointer, and acquiring a kvm ref from within vfio while holding this spinlock, with the reference held until the last close for the device in question. Fixes:51cdc8bc12("kvm/vfio: Fix potential deadlock on vfio group_lock") Reported-by: Anthony Krowiak <akrowiak@linux.ibm.com> Suggested-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> Tested-by: Tony Krowiak <akrowiak@linux.ibm.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Yi Liu <yi.l.liu@intel.com> Link: https://lore.kernel.org/r/20230203215027.151988-2-mjrosato@linux.ibm.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
committed by
Alex Williamson
parent
e592296cd6
commit
2b48f52f2b
@@ -46,7 +46,6 @@ struct vfio_device {
|
||||
struct vfio_device_set *dev_set;
|
||||
struct list_head dev_set_list;
|
||||
unsigned int migration_flags;
|
||||
/* Driver must reference the kvm during open_device or never touch it */
|
||||
struct kvm *kvm;
|
||||
|
||||
/* Members below here are private, not for driver use */
|
||||
@@ -58,6 +57,7 @@ struct vfio_device {
|
||||
struct list_head group_next;
|
||||
struct list_head iommu_entry;
|
||||
struct iommufd_access *iommufd_access;
|
||||
void (*put_kvm)(struct kvm *kvm);
|
||||
#if IS_ENABLED(CONFIG_IOMMUFD)
|
||||
struct iommufd_device *iommufd_device;
|
||||
struct iommufd_ctx *iommufd_ictx;
|
||||
|
||||
Reference in New Issue
Block a user