aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-04-29 10:41:36 -0400
committerAlex Williamson <alex.williamson@redhat.com>2013-04-29 10:41:36 -0400
commit0b43c082338b857c27d2f87c886eb78812ccd236 (patch)
tree4692c09a3ba9b7efb9eff3000f17d8bdbde00630 /drivers/vfio
parent9587f44aa69a4cfb13701b31a633852684bed701 (diff)
vfio: Use down_reads to protect iommu disconnects
If a group or device is released or a container is unset from a group it can race against file ops on the container. Protect these with down_reads to allow concurrent users. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Reported-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/vfio.c62
1 files changed, 46 insertions, 16 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 073788e50e4b..ac7423bfaa7d 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -704,9 +704,13 @@ EXPORT_SYMBOL_GPL(vfio_del_group_dev);
704static long vfio_ioctl_check_extension(struct vfio_container *container, 704static long vfio_ioctl_check_extension(struct vfio_container *container,
705 unsigned long arg) 705 unsigned long arg)
706{ 706{
707 struct vfio_iommu_driver *driver = container->iommu_driver; 707 struct vfio_iommu_driver *driver;
708 long ret = 0; 708 long ret = 0;
709 709
710 down_read(&container->group_lock);
711
712 driver = container->iommu_driver;
713
710 switch (arg) { 714 switch (arg) {
711 /* No base extensions yet */ 715 /* No base extensions yet */
712 default: 716 default:
@@ -736,6 +740,8 @@ static long vfio_ioctl_check_extension(struct vfio_container *container,
736 VFIO_CHECK_EXTENSION, arg); 740 VFIO_CHECK_EXTENSION, arg);
737 } 741 }
738 742
743 up_read(&container->group_lock);
744
739 return ret; 745 return ret;
740} 746}
741 747
@@ -844,9 +850,6 @@ static long vfio_fops_unl_ioctl(struct file *filep,
844 if (!container) 850 if (!container)
845 return ret; 851 return ret;
846 852
847 driver = container->iommu_driver;
848 data = container->iommu_data;
849
850 switch (cmd) { 853 switch (cmd) {
851 case VFIO_GET_API_VERSION: 854 case VFIO_GET_API_VERSION:
852 ret = VFIO_API_VERSION; 855 ret = VFIO_API_VERSION;
@@ -858,8 +861,15 @@ static long vfio_fops_unl_ioctl(struct file *filep,
858 ret = vfio_ioctl_set_iommu(container, arg); 861 ret = vfio_ioctl_set_iommu(container, arg);
859 break; 862 break;
860 default: 863 default:
864 down_read(&container->group_lock);
865
866 driver = container->iommu_driver;
867 data = container->iommu_data;
868
861 if (driver) /* passthrough all unrecognized ioctls */ 869 if (driver) /* passthrough all unrecognized ioctls */
862 ret = driver->ops->ioctl(data, cmd, arg); 870 ret = driver->ops->ioctl(data, cmd, arg);
871
872 up_read(&container->group_lock);
863 } 873 }
864 874
865 return ret; 875 return ret;
@@ -910,35 +920,55 @@ static ssize_t vfio_fops_read(struct file *filep, char __user *buf,
910 size_t count, loff_t *ppos) 920 size_t count, loff_t *ppos)
911{ 921{
912 struct vfio_container *container = filep->private_data; 922 struct vfio_container *container = filep->private_data;
913 struct vfio_iommu_driver *driver = container->iommu_driver; 923 struct vfio_iommu_driver *driver;
924 ssize_t ret = -EINVAL;
914 925
915 if (unlikely(!driver || !driver->ops->read)) 926 down_read(&container->group_lock);
916 return -EINVAL; 927
928 driver = container->iommu_driver;
929 if (likely(driver && driver->ops->read))
930 ret = driver->ops->read(container->iommu_data,
931 buf, count, ppos);
917 932
918 return driver->ops->read(container->iommu_data, buf, count, ppos); 933 up_read(&container->group_lock);
934
935 return ret;
919} 936}
920 937
921static ssize_t vfio_fops_write(struct file *filep, const char __user *buf, 938static ssize_t vfio_fops_write(struct file *filep, const char __user *buf,
922 size_t count, loff_t *ppos) 939 size_t count, loff_t *ppos)
923{ 940{
924 struct vfio_container *container = filep->private_data; 941 struct vfio_container *container = filep->private_data;
925 struct vfio_iommu_driver *driver = container->iommu_driver; 942 struct vfio_iommu_driver *driver;
943 ssize_t ret = -EINVAL;
926 944
927 if (unlikely(!driver || !driver->ops->write)) 945 down_read(&container->group_lock);
928 return -EINVAL; 946
947 driver = container->iommu_driver;
948 if (likely(driver && driver->ops->write))
949 ret = driver->ops->write(container->iommu_data,
950 buf, count, ppos);
951
952 up_read(&container->group_lock);
929 953
930 return driver->ops->write(container->iommu_data, buf, count, ppos); 954 return ret;
931} 955}
932 956
933static int vfio_fops_mmap(struct file *filep, struct vm_area_struct *vma) 957static int vfio_fops_mmap(struct file *filep, struct vm_area_struct *vma)
934{ 958{
935 struct vfio_container *container = filep->private_data; 959 struct vfio_container *container = filep->private_data;
936 struct vfio_iommu_driver *driver = container->iommu_driver; 960 struct vfio_iommu_driver *driver;
961 int ret = -EINVAL;
937 962
938 if (unlikely(!driver || !driver->ops->mmap)) 963 down_read(&container->group_lock);
939 return -EINVAL;
940 964
941 return driver->ops->mmap(container->iommu_data, vma); 965 driver = container->iommu_driver;
966 if (likely(driver && driver->ops->mmap))
967 ret = driver->ops->mmap(container->iommu_data, vma);
968
969 up_read(&container->group_lock);
970
971 return ret;
942} 972}
943 973
944static const struct file_operations vfio_fops = { 974static const struct file_operations vfio_fops = {