Skip to content

Commit e0e29bd

Browse files
jgunthorpeawilliam
authored andcommitted
vfio: Fully lock struct vfio_group::container
This is necessary to avoid various user triggerable races, for instance racing SET_CONTAINER/UNSET_CONTAINER: ioctl(VFIO_GROUP_SET_CONTAINER) ioctl(VFIO_GROUP_UNSET_CONTAINER) vfio_group_unset_container int users = atomic_cmpxchg(&group->container_users, 1, 0); // users == 1 container_users == 0 __vfio_group_unset_container(group); container = group->container; vfio_group_set_container() if (!atomic_read(&group->container_users)) down_write(&container->group_lock); group->container = container; up_write(&container->group_lock); down_write(&container->group_lock); group->container = NULL; up_write(&container->group_lock); vfio_container_put(container); /* woops we lost/leaked the new container */ This can then go on to NULL pointer deref since container == 0 and container_users == 1. Wrap all touches of container, except those on a performance path with a known open device, with the group_rwsem. The only user of vfio_group_add_container_user() holds the user count for a simple operation, change it to just hold the group_lock over the operation and delete vfio_group_add_container_user(). Containers now only gain a user when a device FD is opened. Reviewed-by: Kevin Tian <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Tested-by: Nicolin Chen <[email protected]> Tested-by: Matthew Rosato <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alex Williamson <[email protected]>
1 parent 805bb6c commit e0e29bd

File tree

1 file changed

+40
-26
lines changed

1 file changed

+40
-26
lines changed

drivers/vfio/vfio.c

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,8 @@ static void __vfio_group_unset_container(struct vfio_group *group)
918918
struct vfio_container *container = group->container;
919919
struct vfio_iommu_driver *driver;
920920

921+
lockdep_assert_held_write(&group->group_rwsem);
922+
921923
down_write(&container->group_lock);
922924

923925
driver = container->iommu_driver;
@@ -953,6 +955,8 @@ static int vfio_group_unset_container(struct vfio_group *group)
953955
{
954956
int users = atomic_cmpxchg(&group->container_users, 1, 0);
955957

958+
lockdep_assert_held_write(&group->group_rwsem);
959+
956960
if (!users)
957961
return -EINVAL;
958962
if (users != 1)
@@ -971,8 +975,10 @@ static int vfio_group_unset_container(struct vfio_group *group)
971975
*/
972976
static void vfio_group_try_dissolve_container(struct vfio_group *group)
973977
{
978+
down_write(&group->group_rwsem);
974979
if (0 == atomic_dec_if_positive(&group->container_users))
975980
__vfio_group_unset_container(group);
981+
up_write(&group->group_rwsem);
976982
}
977983

978984
static int vfio_group_set_container(struct vfio_group *group, int container_fd)
@@ -982,6 +988,8 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
982988
struct vfio_iommu_driver *driver;
983989
int ret = 0;
984990

991+
lockdep_assert_held_write(&group->group_rwsem);
992+
985993
if (atomic_read(&group->container_users))
986994
return -EINVAL;
987995

@@ -1039,23 +1047,6 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
10391047
return ret;
10401048
}
10411049

1042-
static int vfio_group_add_container_user(struct vfio_group *group)
1043-
{
1044-
if (!atomic_inc_not_zero(&group->container_users))
1045-
return -EINVAL;
1046-
1047-
if (group->type == VFIO_NO_IOMMU) {
1048-
atomic_dec(&group->container_users);
1049-
return -EPERM;
1050-
}
1051-
if (!group->container->iommu_driver) {
1052-
atomic_dec(&group->container_users);
1053-
return -EINVAL;
1054-
}
1055-
1056-
return 0;
1057-
}
1058-
10591050
static const struct file_operations vfio_device_fops;
10601051

10611052
/* true if the vfio_device has open_device() called but not close_device() */
@@ -1068,6 +1059,8 @@ static int vfio_device_assign_container(struct vfio_device *device)
10681059
{
10691060
struct vfio_group *group = device->group;
10701061

1062+
lockdep_assert_held_write(&group->group_rwsem);
1063+
10711064
if (0 == atomic_read(&group->container_users) ||
10721065
!group->container->iommu_driver)
10731066
return -EINVAL;
@@ -1084,7 +1077,9 @@ static struct file *vfio_device_open(struct vfio_device *device)
10841077
struct file *filep;
10851078
int ret;
10861079

1080+
down_write(&device->group->group_rwsem);
10871081
ret = vfio_device_assign_container(device);
1082+
up_write(&device->group->group_rwsem);
10881083
if (ret)
10891084
return ERR_PTR(ret);
10901085

@@ -1197,11 +1192,13 @@ static long vfio_group_fops_unl_ioctl(struct file *filep,
11971192

11981193
status.flags = 0;
11991194

1195+
down_read(&group->group_rwsem);
12001196
if (group->container)
12011197
status.flags |= VFIO_GROUP_FLAGS_CONTAINER_SET |
12021198
VFIO_GROUP_FLAGS_VIABLE;
12031199
else if (!iommu_group_dma_owner_claimed(group->iommu_group))
12041200
status.flags |= VFIO_GROUP_FLAGS_VIABLE;
1201+
up_read(&group->group_rwsem);
12051202

12061203
if (copy_to_user((void __user *)arg, &status, minsz))
12071204
return -EFAULT;
@@ -1219,11 +1216,15 @@ static long vfio_group_fops_unl_ioctl(struct file *filep,
12191216
if (fd < 0)
12201217
return -EINVAL;
12211218

1219+
down_write(&group->group_rwsem);
12221220
ret = vfio_group_set_container(group, fd);
1221+
up_write(&group->group_rwsem);
12231222
break;
12241223
}
12251224
case VFIO_GROUP_UNSET_CONTAINER:
1225+
down_write(&group->group_rwsem);
12261226
ret = vfio_group_unset_container(group);
1227+
up_write(&group->group_rwsem);
12271228
break;
12281229
case VFIO_GROUP_GET_DEVICE_FD:
12291230
{
@@ -1709,15 +1710,19 @@ bool vfio_file_enforced_coherent(struct file *file)
17091710
if (file->f_op != &vfio_group_fops)
17101711
return true;
17111712

1712-
/*
1713-
* Since the coherency state is determined only once a container is
1714-
* attached the user must do so before they can prove they have
1715-
* permission.
1716-
*/
1717-
if (vfio_group_add_container_user(group))
1718-
return true;
1719-
ret = vfio_ioctl_check_extension(group->container, VFIO_DMA_CC_IOMMU);
1720-
vfio_group_try_dissolve_container(group);
1713+
down_read(&group->group_rwsem);
1714+
if (group->container) {
1715+
ret = vfio_ioctl_check_extension(group->container,
1716+
VFIO_DMA_CC_IOMMU);
1717+
} else {
1718+
/*
1719+
* Since the coherency state is determined only once a container
1720+
* is attached the user must do so before they can prove they
1721+
* have permission.
1722+
*/
1723+
ret = true;
1724+
}
1725+
up_read(&group->group_rwsem);
17211726
return ret;
17221727
}
17231728
EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
@@ -1910,6 +1915,7 @@ int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
19101915
if (group->dev_counter > 1)
19111916
return -EINVAL;
19121917

1918+
/* group->container cannot change while a vfio device is open */
19131919
container = group->container;
19141920
driver = container->iommu_driver;
19151921
if (likely(driver && driver->ops->pin_pages))
@@ -1945,6 +1951,7 @@ int vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn,
19451951
if (npage > VFIO_PIN_PAGES_MAX_ENTRIES)
19461952
return -E2BIG;
19471953

1954+
/* group->container cannot change while a vfio device is open */
19481955
container = device->group->container;
19491956
driver = container->iommu_driver;
19501957
if (likely(driver && driver->ops->unpin_pages))
@@ -1984,6 +1991,7 @@ int vfio_dma_rw(struct vfio_device *device, dma_addr_t user_iova, void *data,
19841991
if (!data || len <= 0 || !vfio_assert_device_open(device))
19851992
return -EINVAL;
19861993

1994+
/* group->container cannot change while a vfio device is open */
19871995
container = device->group->container;
19881996
driver = container->iommu_driver;
19891997

@@ -2004,13 +2012,16 @@ static int vfio_register_iommu_notifier(struct vfio_group *group,
20042012
struct vfio_iommu_driver *driver;
20052013
int ret;
20062014

2015+
down_read(&group->group_rwsem);
20072016
container = group->container;
20082017
driver = container->iommu_driver;
20092018
if (likely(driver && driver->ops->register_notifier))
20102019
ret = driver->ops->register_notifier(container->iommu_data,
20112020
events, nb);
20122021
else
20132022
ret = -ENOTTY;
2023+
up_read(&group->group_rwsem);
2024+
20142025
return ret;
20152026
}
20162027

@@ -2021,13 +2032,16 @@ static int vfio_unregister_iommu_notifier(struct vfio_group *group,
20212032
struct vfio_iommu_driver *driver;
20222033
int ret;
20232034

2035+
down_read(&group->group_rwsem);
20242036
container = group->container;
20252037
driver = container->iommu_driver;
20262038
if (likely(driver && driver->ops->unregister_notifier))
20272039
ret = driver->ops->unregister_notifier(container->iommu_data,
20282040
nb);
20292041
else
20302042
ret = -ENOTTY;
2043+
up_read(&group->group_rwsem);
2044+
20312045
return ret;
20322046
}
20332047

0 commit comments

Comments
 (0)