Skip to content

Commit db42944

Browse files
Alex Williamsongregkh
authored andcommitted
vfio: Fix group release deadlock
commit 811642d8d8a82c0cce8dc2debfdaf23c5a144839 upstream. If vfio_iommu_group_notifier() acquires a group reference and that reference becomes the last reference to the group, then vfio_group_put introduces a deadlock code path where we're trying to unregister from the iommu notifier chain from within a callout of that chain. Use a work_struct to release this reference asynchronously. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Tested-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent fca8859 commit db42944

1 file changed

Lines changed: 36 additions & 1 deletion

File tree

drivers/vfio/vfio.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,34 @@ static void vfio_group_put(struct vfio_group *group)
296296
kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock);
297297
}
298298

299+
struct vfio_group_put_work {
300+
struct work_struct work;
301+
struct vfio_group *group;
302+
};
303+
304+
static void vfio_group_put_bg(struct work_struct *work)
305+
{
306+
struct vfio_group_put_work *do_work;
307+
308+
do_work = container_of(work, struct vfio_group_put_work, work);
309+
310+
vfio_group_put(do_work->group);
311+
kfree(do_work);
312+
}
313+
314+
static void vfio_group_schedule_put(struct vfio_group *group)
315+
{
316+
struct vfio_group_put_work *do_work;
317+
318+
do_work = kmalloc(sizeof(*do_work), GFP_KERNEL);
319+
if (WARN_ON(!do_work))
320+
return;
321+
322+
INIT_WORK(&do_work->work, vfio_group_put_bg);
323+
do_work->group = group;
324+
schedule_work(&do_work->work);
325+
}
326+
299327
/* Assume group_lock or group reference is held */
300328
static void vfio_group_get(struct vfio_group *group)
301329
{
@@ -620,7 +648,14 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb,
620648
break;
621649
}
622650

623-
vfio_group_put(group);
651+
/*
652+
* If we're the last reference to the group, the group will be
653+
* released, which includes unregistering the iommu group notifier.
654+
* We hold a read-lock on that notifier list, unregistering needs
655+
* a write-lock... deadlock. Release our reference asynchronously
656+
* to avoid that situation.
657+
*/
658+
vfio_group_schedule_put(group);
624659
return NOTIFY_OK;
625660
}
626661

0 commit comments

Comments
 (0)