diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2017-07-07 17:37:38 -0400 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2017-07-07 17:37:38 -0400 |
commit | 7f56c30bd0a232822aca38d288da475613bdff9b (patch) | |
tree | de4ef02762b2c79b6801778defdea587718eeb89 | |
parent | 5d6dee80a1e94cc284d03e06d930e60e8d3ecf7d (diff) |
vfio: Remove unnecessary uses of vfio_container.group_lock
The original intent of vfio_container.group_lock is to protect
vfio_container.group_list, however over time it's become a crutch to
prevent changes in container composition any time we call into the
iommu driver backend. This introduces problems when we start to have
more complex interactions, for example when a user's DMA unmap request
triggers a notification to an mdev vendor driver, who responds by
attempting to unpin mappings within that request, re-entering the
iommu backend. We incorrectly assume that the use of read-locks here
allow for this nested locking behavior, but a poorly timed write-lock
could in fact trigger a deadlock.
The current use of group_lock seems to fall into the trap of locking
code, not data. Correct that by removing uses of group_lock that are
not directly related to group_list. Note that the vfio type1 iommu
backend has its own mutex, vfio_iommu.lock, which it uses to protect
itself for each of these interfaces anyway. The group_lock appears to
be a redundancy for these interfaces and type1 even goes so far as to
release its mutex to allow for exactly the re-entrant code path above.
Reported-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Acked-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Cc: stable@vger.kernel.org # v4.10+
-rw-r--r-- | drivers/vfio/vfio.c | 38 |
1 files changed, 0 insertions, 38 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 7597a377eb4e..330d50582f40 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
@@ -1175,15 +1175,11 @@ static long vfio_fops_unl_ioctl(struct file *filep, | |||
1175 | ret = vfio_ioctl_set_iommu(container, arg); | 1175 | ret = vfio_ioctl_set_iommu(container, arg); |
1176 | break; | 1176 | break; |
1177 | default: | 1177 | default: |
1178 | down_read(&container->group_lock); | ||
1179 | |||
1180 | driver = container->iommu_driver; | 1178 | driver = container->iommu_driver; |
1181 | data = container->iommu_data; | 1179 | data = container->iommu_data; |
1182 | 1180 | ||
1183 | if (driver) /* passthrough all unrecognized ioctls */ | 1181 | if (driver) /* passthrough all unrecognized ioctls */ |
1184 | ret = driver->ops->ioctl(data, cmd, arg); | 1182 | ret = driver->ops->ioctl(data, cmd, arg); |
1185 | |||
1186 | up_read(&container->group_lock); | ||
1187 | } | 1183 | } |
1188 | 1184 | ||
1189 | return ret; | 1185 | return ret; |
@@ -1237,15 +1233,11 @@ static ssize_t vfio_fops_read(struct file *filep, char __user *buf, | |||
1237 | struct vfio_iommu_driver *driver; | 1233 | struct vfio_iommu_driver *driver; |
1238 | ssize_t ret = -EINVAL; | 1234 | ssize_t ret = -EINVAL; |
1239 | 1235 | ||
1240 | down_read(&container->group_lock); | ||
1241 | |||
1242 | driver = container->iommu_driver; | 1236 | driver = container->iommu_driver; |
1243 | if (likely(driver && driver->ops->read)) | 1237 | if (likely(driver && driver->ops->read)) |
1244 | ret = driver->ops->read(container->iommu_data, | 1238 | ret = driver->ops->read(container->iommu_data, |
1245 | buf, count, ppos); | 1239 | buf, count, ppos); |
1246 | 1240 | ||
1247 | up_read(&container->group_lock); | ||
1248 | |||
1249 | return ret; | 1241 | return ret; |
1250 | } | 1242 | } |
1251 | 1243 | ||
@@ -1256,15 +1248,11 @@ static ssize_t vfio_fops_write(struct file *filep, const char __user *buf, | |||
1256 | struct vfio_iommu_driver *driver; | 1248 | struct vfio_iommu_driver *driver; |
1257 | ssize_t ret = -EINVAL; | 1249 | ssize_t ret = -EINVAL; |
1258 | 1250 | ||
1259 | down_read(&container->group_lock); | ||
1260 | |||
1261 | driver = container->iommu_driver; | 1251 | driver = container->iommu_driver; |
1262 | if (likely(driver && driver->ops->write)) | 1252 | if (likely(driver && driver->ops->write)) |
1263 | ret = driver->ops->write(container->iommu_data, | 1253 | ret = driver->ops->write(container->iommu_data, |
1264 | buf, count, ppos); | 1254 | buf, count, ppos); |
1265 | 1255 | ||
1266 | up_read(&container->group_lock); | ||
1267 | |||
1268 | return ret; | 1256 | return ret; |
1269 | } | 1257 | } |
1270 | 1258 | ||
@@ -1274,14 +1262,10 @@ static int vfio_fops_mmap(struct file *filep, struct vm_area_struct *vma) | |||
1274 | struct vfio_iommu_driver *driver; | 1262 | struct vfio_iommu_driver *driver; |
1275 | int ret = -EINVAL; | 1263 | int ret = -EINVAL; |
1276 | 1264 | ||
1277 | down_read(&container->group_lock); | ||
1278 | |||
1279 | driver = container->iommu_driver; | 1265 | driver = container->iommu_driver; |
1280 | if (likely(driver && driver->ops->mmap)) | 1266 | if (likely(driver && driver->ops->mmap)) |
1281 | ret = driver->ops->mmap(container->iommu_data, vma); | 1267 | ret = driver->ops->mmap(container->iommu_data, vma); |
1282 | 1268 | ||
1283 | up_read(&container->group_lock); | ||
1284 | |||
1285 | return ret; | 1269 | return ret; |
1286 | } | 1270 | } |
1287 | 1271 | ||
@@ -1993,8 +1977,6 @@ int vfio_pin_pages(struct device *dev, unsigned long *user_pfn, int npage, | |||
1993 | goto err_pin_pages; | 1977 | goto err_pin_pages; |
1994 | 1978 | ||
1995 | container = group->container; | 1979 | container = group->container; |
1996 | down_read(&container->group_lock); | ||
1997 | |||
1998 | driver = container->iommu_driver; | 1980 | driver = container->iommu_driver; |
1999 | if (likely(driver && driver->ops->pin_pages)) | 1981 | if (likely(driver && driver->ops->pin_pages)) |
2000 | ret = driver->ops->pin_pages(container->iommu_data, user_pfn, | 1982 | ret = driver->ops->pin_pages(container->iommu_data, user_pfn, |
@@ -2002,7 +1984,6 @@ int vfio_pin_pages(struct device *dev, unsigned long *user_pfn, int npage, | |||
2002 | else | 1984 | else |
2003 | ret = -ENOTTY; | 1985 | ret = -ENOTTY; |
2004 | 1986 | ||
2005 | up_read(&container->group_lock); | ||
2006 | vfio_group_try_dissolve_container(group); | 1987 | vfio_group_try_dissolve_container(group); |
2007 | 1988 | ||
2008 | err_pin_pages: | 1989 | err_pin_pages: |
@@ -2042,8 +2023,6 @@ int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn, int npage) | |||
2042 | goto err_unpin_pages; | 2023 | goto err_unpin_pages; |
2043 | 2024 | ||
2044 | container = group->container; | 2025 | container = group->container; |
2045 | down_read(&container->group_lock); | ||
2046 | |||
2047 | driver = container->iommu_driver; | 2026 | driver = container->iommu_driver; |
2048 | if (likely(driver && driver->ops->unpin_pages)) | 2027 | if (likely(driver && driver->ops->unpin_pages)) |
2049 | ret = driver->ops->unpin_pages(container->iommu_data, user_pfn, | 2028 | ret = driver->ops->unpin_pages(container->iommu_data, user_pfn, |
@@ -2051,7 +2030,6 @@ int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn, int npage) | |||
2051 | else | 2030 | else |
2052 | ret = -ENOTTY; | 2031 | ret = -ENOTTY; |
2053 | 2032 | ||
2054 | up_read(&container->group_lock); | ||
2055 | vfio_group_try_dissolve_container(group); | 2033 | vfio_group_try_dissolve_container(group); |
2056 | 2034 | ||
2057 | err_unpin_pages: | 2035 | err_unpin_pages: |
@@ -2073,8 +2051,6 @@ static int vfio_register_iommu_notifier(struct vfio_group *group, | |||
2073 | return -EINVAL; | 2051 | return -EINVAL; |
2074 | 2052 | ||
2075 | container = group->container; | 2053 | container = group->container; |
2076 | down_read(&container->group_lock); | ||
2077 | |||
2078 | driver = container->iommu_driver; | 2054 | driver = container->iommu_driver; |
2079 | if (likely(driver && driver->ops->register_notifier)) | 2055 | if (likely(driver && driver->ops->register_notifier)) |
2080 | ret = driver->ops->register_notifier(container->iommu_data, | 2056 | ret = driver->ops->register_notifier(container->iommu_data, |
@@ -2082,7 +2058,6 @@ static int vfio_register_iommu_notifier(struct vfio_group *group, | |||
2082 | else | 2058 | else |
2083 | ret = -ENOTTY; | 2059 | ret = -ENOTTY; |
2084 | 2060 | ||
2085 | up_read(&container->group_lock); | ||
2086 | vfio_group_try_dissolve_container(group); | 2061 | vfio_group_try_dissolve_container(group); |
2087 | 2062 | ||
2088 | return ret; | 2063 | return ret; |
@@ -2100,8 +2075,6 @@ static int vfio_unregister_iommu_notifier(struct vfio_group *group, | |||
2100 | return -EINVAL; | 2075 | return -EINVAL; |
2101 | 2076 | ||
2102 | container = group->container; | 2077 | container = group->container; |
2103 | down_read(&container->group_lock); | ||
2104 | |||
2105 | driver = container->iommu_driver; | 2078 | driver = container->iommu_driver; |
2106 | if (likely(driver && driver->ops->unregister_notifier)) | 2079 | if (likely(driver && driver->ops->unregister_notifier)) |
2107 | ret = driver->ops->unregister_notifier(container->iommu_data, | 2080 | ret = driver->ops->unregister_notifier(container->iommu_data, |
@@ -2109,7 +2082,6 @@ static int vfio_unregister_iommu_notifier(struct vfio_group *group, | |||
2109 | else | 2082 | else |
2110 | ret = -ENOTTY; | 2083 | ret = -ENOTTY; |
2111 | 2084 | ||
2112 | up_read(&container->group_lock); | ||
2113 | vfio_group_try_dissolve_container(group); | 2085 | vfio_group_try_dissolve_container(group); |
2114 | 2086 | ||
2115 | return ret; | 2087 | return ret; |
@@ -2127,7 +2099,6 @@ static int vfio_register_group_notifier(struct vfio_group *group, | |||
2127 | unsigned long *events, | 2099 | unsigned long *events, |
2128 | struct notifier_block *nb) | 2100 | struct notifier_block *nb) |
2129 | { | 2101 | { |
2130 | struct vfio_container *container; | ||
2131 | int ret; | 2102 | int ret; |
2132 | bool set_kvm = false; | 2103 | bool set_kvm = false; |
2133 | 2104 | ||
@@ -2145,9 +2116,6 @@ static int vfio_register_group_notifier(struct vfio_group *group, | |||
2145 | if (ret) | 2116 | if (ret) |
2146 | return -EINVAL; | 2117 | return -EINVAL; |
2147 | 2118 | ||
2148 | container = group->container; | ||
2149 | down_read(&container->group_lock); | ||
2150 | |||
2151 | ret = blocking_notifier_chain_register(&group->notifier, nb); | 2119 | ret = blocking_notifier_chain_register(&group->notifier, nb); |
2152 | 2120 | ||
2153 | /* | 2121 | /* |
@@ -2158,7 +2126,6 @@ static int vfio_register_group_notifier(struct vfio_group *group, | |||
2158 | blocking_notifier_call_chain(&group->notifier, | 2126 | blocking_notifier_call_chain(&group->notifier, |
2159 | VFIO_GROUP_NOTIFY_SET_KVM, group->kvm); | 2127 | VFIO_GROUP_NOTIFY_SET_KVM, group->kvm); |
2160 | 2128 | ||
2161 | up_read(&container->group_lock); | ||
2162 | vfio_group_try_dissolve_container(group); | 2129 | vfio_group_try_dissolve_container(group); |
2163 | 2130 | ||
2164 | return ret; | 2131 | return ret; |
@@ -2167,19 +2134,14 @@ static int vfio_register_group_notifier(struct vfio_group *group, | |||
2167 | static int vfio_unregister_group_notifier(struct vfio_group *group, | 2134 | static int vfio_unregister_group_notifier(struct vfio_group *group, |
2168 | struct notifier_block *nb) | 2135 | struct notifier_block *nb) |
2169 | { | 2136 | { |
2170 | struct vfio_container *container; | ||
2171 | int ret; | 2137 | int ret; |
2172 | 2138 | ||
2173 | ret = vfio_group_add_container_user(group); | 2139 | ret = vfio_group_add_container_user(group); |
2174 | if (ret) | 2140 | if (ret) |
2175 | return -EINVAL; | 2141 | return -EINVAL; |
2176 | 2142 | ||
2177 | container = group->container; | ||
2178 | down_read(&container->group_lock); | ||
2179 | |||
2180 | ret = blocking_notifier_chain_unregister(&group->notifier, nb); | 2143 | ret = blocking_notifier_chain_unregister(&group->notifier, nb); |
2181 | 2144 | ||
2182 | up_read(&container->group_lock); | ||
2183 | vfio_group_try_dissolve_container(group); | 2145 | vfio_group_try_dissolve_container(group); |
2184 | 2146 | ||
2185 | return ret; | 2147 | return ret; |