Revert "net: vhost: lock the vqs one by one"
authorJason Wang <jasowang@redhat.com>
Thu, 13 Dec 2018 02:53:39 +0000 (10:53 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 13 Dec 2018 05:56:20 +0000 (21:56 -0800)
This reverts commit 78139c94dc8c96a478e67dab3bee84dc6eccb5fd. We don't
protect device IOTLB with vq mutex, which will lead e.g use after free
for device IOTLB entries. And since we've switched to use
mutex_trylock() in previous patch, it's safe to revert it without
having deadlock.

Fixes: commit 78139c94dc8c ("net: vhost: lock the vqs one by one")
Cc: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/vhost/vhost.c

index 5915f240275a9f122aa84cc6777f33410b1aa6be..55e5aa662ad59d4b72c44db743198876654f2d2d 100644 (file)
@@ -295,11 +295,8 @@ static void vhost_vq_meta_reset(struct vhost_dev *d)
 {
        int i;
 
-       for (i = 0; i < d->nvqs; ++i) {
-               mutex_lock(&d->vqs[i]->mutex);
+       for (i = 0; i < d->nvqs; ++i)
                __vhost_vq_meta_reset(d->vqs[i]);
-               mutex_unlock(&d->vqs[i]->mutex);
-       }
 }
 
 static void vhost_vq_reset(struct vhost_dev *dev,
@@ -895,6 +892,20 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,
 #define vhost_get_used(vq, x, ptr) \
        vhost_get_user(vq, x, ptr, VHOST_ADDR_USED)
 
+static void vhost_dev_lock_vqs(struct vhost_dev *d)
+{
+       int i = 0;
+       for (i = 0; i < d->nvqs; ++i)
+               mutex_lock_nested(&d->vqs[i]->mutex, i);
+}
+
+static void vhost_dev_unlock_vqs(struct vhost_dev *d)
+{
+       int i = 0;
+       for (i = 0; i < d->nvqs; ++i)
+               mutex_unlock(&d->vqs[i]->mutex);
+}
+
 static int vhost_new_umem_range(struct vhost_umem *umem,
                                u64 start, u64 size, u64 end,
                                u64 userspace_addr, int perm)
@@ -976,6 +987,7 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev,
        int ret = 0;
 
        mutex_lock(&dev->mutex);
+       vhost_dev_lock_vqs(dev);
        switch (msg->type) {
        case VHOST_IOTLB_UPDATE:
                if (!dev->iotlb) {
@@ -1009,6 +1021,7 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev,
                break;
        }
 
+       vhost_dev_unlock_vqs(dev);
        mutex_unlock(&dev->mutex);
 
        return ret;