vhost: switch to __get/__put_user exclusively
authorMichael S. Tsirkin <mst@redhat.com>
Mon, 1 Dec 2014 15:39:39 +0000 (17:39 +0200)
committerMichael S. Tsirkin <mst@redhat.com>
Tue, 9 Dec 2014 10:05:29 +0000 (12:05 +0200)
Most places in vhost can use __get/__put_user rather than
get/put_user since addresses are pre-validated.
This should be good for performance, but this also
will help make code sparse-clean: get/put_user macros
don't play well with __virtioXX bitwise tags.
Switch to get/put_user to __ variants everywhere in vhost.
There's one exception - for consistency switch that
as well, and add an explicit access_ok check.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/vhost/vhost.c

index c90f4374442a571610da46b56dc94d51a3e26feb..6a408377598aff0f8a1bd4c8613c9f856c0ba255 100644 (file)
@@ -1038,6 +1038,7 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
 
 int vhost_init_used(struct vhost_virtqueue *vq)
 {
+       u16 last_used_idx;
        int r;
        if (!vq->private_data)
                return 0;
@@ -1046,7 +1047,13 @@ int vhost_init_used(struct vhost_virtqueue *vq)
        if (r)
                return r;
        vq->signalled_used_valid = false;
-       return get_user(vq->last_used_idx, &vq->used->idx);
+       if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx))
+               return -EFAULT;
+       r = __get_user(last_used_idx, &vq->used->idx);
+       if (r)
+               return r;
+       vq->last_used_idx = last_used_idx;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(vhost_init_used);
 
@@ -1404,7 +1411,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
 
        /* Make sure buffer is written before we update index. */
        smp_wmb();
-       if (put_user(vq->last_used_idx, &vq->used->idx)) {
+       if (__put_user(vq->last_used_idx, &vq->used->idx)) {
                vq_err(vq, "Failed to increment used idx");
                return -EFAULT;
        }
@@ -1449,7 +1456,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
        if (unlikely(!v))
                return true;
 
-       if (get_user(event, vhost_used_event(vq))) {
+       if (__get_user(event, vhost_used_event(vq))) {
                vq_err(vq, "Failed to get used event idx");
                return true;
        }