Skip to content

Commit 2b48f52

Browse files
rosatomjAlex Williamson
authored andcommitted
vfio: fix deadlock between group lock and kvm lock
After 51cdc8b, 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: 51cdc8b ("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>
1 parent e592296 commit 2b48f52

4 files changed

Lines changed: 109 additions & 15 deletions

File tree

drivers/vfio/group.c

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,18 @@ static int vfio_group_ioctl_set_container(struct vfio_group *group,
154154
return ret;
155155
}
156156

157+
static void vfio_device_group_get_kvm_safe(struct vfio_device *device)
158+
{
159+
spin_lock(&device->group->kvm_ref_lock);
160+
if (!device->group->kvm)
161+
goto unlock;
162+
163+
_vfio_device_get_kvm_safe(device, device->group->kvm);
164+
165+
unlock:
166+
spin_unlock(&device->group->kvm_ref_lock);
167+
}
168+
157169
static int vfio_device_group_open(struct vfio_device *device)
158170
{
159171
int ret;
@@ -164,13 +176,23 @@ static int vfio_device_group_open(struct vfio_device *device)
164176
goto out_unlock;
165177
}
166178

179+
mutex_lock(&device->dev_set->lock);
180+
167181
/*
168-
* Here we pass the KVM pointer with the group under the lock. If the
169-
* device driver will use it, it must obtain a reference and release it
170-
* during close_device.
182+
* Before the first device open, get the KVM pointer currently
183+
* associated with the group (if there is one) and obtain a reference
184+
* now that will be held until the open_count reaches 0 again. Save
185+
* the pointer in the device for use by drivers.
171186
*/
172-
ret = vfio_device_open(device, device->group->iommufd,
173-
device->group->kvm);
187+
if (device->open_count == 0)
188+
vfio_device_group_get_kvm_safe(device);
189+
190+
ret = vfio_device_open(device, device->group->iommufd, device->kvm);
191+
192+
if (device->open_count == 0)
193+
vfio_device_put_kvm(device);
194+
195+
mutex_unlock(&device->dev_set->lock);
174196

175197
out_unlock:
176198
mutex_unlock(&device->group->group_lock);
@@ -180,7 +202,14 @@ static int vfio_device_group_open(struct vfio_device *device)
180202
void vfio_device_group_close(struct vfio_device *device)
181203
{
182204
mutex_lock(&device->group->group_lock);
205+
mutex_lock(&device->dev_set->lock);
206+
183207
vfio_device_close(device, device->group->iommufd);
208+
209+
if (device->open_count == 0)
210+
vfio_device_put_kvm(device);
211+
212+
mutex_unlock(&device->dev_set->lock);
184213
mutex_unlock(&device->group->group_lock);
185214
}
186215

@@ -450,6 +479,7 @@ static struct vfio_group *vfio_group_alloc(struct iommu_group *iommu_group,
450479

451480
refcount_set(&group->drivers, 1);
452481
mutex_init(&group->group_lock);
482+
spin_lock_init(&group->kvm_ref_lock);
453483
INIT_LIST_HEAD(&group->device_list);
454484
mutex_init(&group->device_lock);
455485
group->iommu_group = iommu_group;
@@ -803,9 +833,9 @@ void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
803833
if (!vfio_file_is_group(file))
804834
return;
805835

806-
mutex_lock(&group->group_lock);
836+
spin_lock(&group->kvm_ref_lock);
807837
group->kvm = kvm;
808-
mutex_unlock(&group->group_lock);
838+
spin_unlock(&group->kvm_ref_lock);
809839
}
810840
EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
811841

drivers/vfio/vfio.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct vfio_group {
7474
struct file *opened_file;
7575
struct blocking_notifier_head notifier;
7676
struct iommufd_ctx *iommufd;
77+
spinlock_t kvm_ref_lock;
7778
};
7879

7980
int vfio_device_set_group(struct vfio_device *device,
@@ -244,4 +245,18 @@ extern bool vfio_noiommu __read_mostly;
244245
enum { vfio_noiommu = false };
245246
#endif
246247

248+
#ifdef CONFIG_HAVE_KVM
249+
void _vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm);
250+
void vfio_device_put_kvm(struct vfio_device *device);
251+
#else
252+
static inline void _vfio_device_get_kvm_safe(struct vfio_device *device,
253+
struct kvm *kvm)
254+
{
255+
}
256+
257+
static inline void vfio_device_put_kvm(struct vfio_device *device)
258+
{
259+
}
260+
#endif
261+
247262
#endif

drivers/vfio/vfio_main.c

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include <linux/fs.h>
1717
#include <linux/idr.h>
1818
#include <linux/iommu.h>
19+
#ifdef CONFIG_HAVE_KVM
20+
#include <linux/kvm_host.h>
21+
#endif
1922
#include <linux/list.h>
2023
#include <linux/miscdevice.h>
2124
#include <linux/module.h>
@@ -338,6 +341,55 @@ void vfio_unregister_group_dev(struct vfio_device *device)
338341
}
339342
EXPORT_SYMBOL_GPL(vfio_unregister_group_dev);
340343

344+
#ifdef CONFIG_HAVE_KVM
345+
void _vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm)
346+
{
347+
void (*pfn)(struct kvm *kvm);
348+
bool (*fn)(struct kvm *kvm);
349+
bool ret;
350+
351+
lockdep_assert_held(&device->dev_set->lock);
352+
353+
pfn = symbol_get(kvm_put_kvm);
354+
if (WARN_ON(!pfn))
355+
return;
356+
357+
fn = symbol_get(kvm_get_kvm_safe);
358+
if (WARN_ON(!fn)) {
359+
symbol_put(kvm_put_kvm);
360+
return;
361+
}
362+
363+
ret = fn(kvm);
364+
symbol_put(kvm_get_kvm_safe);
365+
if (!ret) {
366+
symbol_put(kvm_put_kvm);
367+
return;
368+
}
369+
370+
device->put_kvm = pfn;
371+
device->kvm = kvm;
372+
}
373+
374+
void vfio_device_put_kvm(struct vfio_device *device)
375+
{
376+
lockdep_assert_held(&device->dev_set->lock);
377+
378+
if (!device->kvm)
379+
return;
380+
381+
if (WARN_ON(!device->put_kvm))
382+
goto clear;
383+
384+
device->put_kvm(device->kvm);
385+
device->put_kvm = NULL;
386+
symbol_put(kvm_put_kvm);
387+
388+
clear:
389+
device->kvm = NULL;
390+
}
391+
#endif
392+
341393
/* true if the vfio_device has open_device() called but not close_device() */
342394
static bool vfio_assert_device_open(struct vfio_device *device)
343395
{
@@ -361,7 +413,6 @@ static int vfio_device_first_open(struct vfio_device *device,
361413
if (ret)
362414
goto err_module_put;
363415

364-
device->kvm = kvm;
365416
if (device->ops->open_device) {
366417
ret = device->ops->open_device(device);
367418
if (ret)
@@ -370,7 +421,6 @@ static int vfio_device_first_open(struct vfio_device *device,
370421
return 0;
371422

372423
err_unuse_iommu:
373-
device->kvm = NULL;
374424
if (iommufd)
375425
vfio_iommufd_unbind(device);
376426
else
@@ -387,7 +437,6 @@ static void vfio_device_last_close(struct vfio_device *device,
387437

388438
if (device->ops->close_device)
389439
device->ops->close_device(device);
390-
device->kvm = NULL;
391440
if (iommufd)
392441
vfio_iommufd_unbind(device);
393442
else
@@ -400,27 +449,27 @@ int vfio_device_open(struct vfio_device *device,
400449
{
401450
int ret = 0;
402451

403-
mutex_lock(&device->dev_set->lock);
452+
lockdep_assert_held(&device->dev_set->lock);
453+
404454
device->open_count++;
405455
if (device->open_count == 1) {
406456
ret = vfio_device_first_open(device, iommufd, kvm);
407457
if (ret)
408458
device->open_count--;
409459
}
410-
mutex_unlock(&device->dev_set->lock);
411460

412461
return ret;
413462
}
414463

415464
void vfio_device_close(struct vfio_device *device,
416465
struct iommufd_ctx *iommufd)
417466
{
418-
mutex_lock(&device->dev_set->lock);
467+
lockdep_assert_held(&device->dev_set->lock);
468+
419469
vfio_assert_device_open(device);
420470
if (device->open_count == 1)
421471
vfio_device_last_close(device, iommufd);
422472
device->open_count--;
423-
mutex_unlock(&device->dev_set->lock);
424473
}
425474

426475
/*

include/linux/vfio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ struct vfio_device {
4646
struct vfio_device_set *dev_set;
4747
struct list_head dev_set_list;
4848
unsigned int migration_flags;
49-
/* Driver must reference the kvm during open_device or never touch it */
5049
struct kvm *kvm;
5150

5251
/* Members below here are private, not for driver use */
@@ -58,6 +57,7 @@ struct vfio_device {
5857
struct list_head group_next;
5958
struct list_head iommu_entry;
6059
struct iommufd_access *iommufd_access;
60+
void (*put_kvm)(struct kvm *kvm);
6161
#if IS_ENABLED(CONFIG_IOMMUFD)
6262
struct iommufd_device *iommufd_device;
6363
struct iommufd_ctx *iommufd_ictx;

0 commit comments

Comments
 (0)