Commit 7ad9c9d2 authored by Takuya Yoshikawa's avatar Takuya Yoshikawa Committed by Michael S. Tsirkin

vhost: fix to check the return value of copy_to/from_user() correctly

copy_to/from_user() returns the number of bytes that could not be copied.

So we need to check if it is not zero, and in that case, we should return
the error number -EFAULT rather than directly return the return value from
copy_to/from_user().
Signed-off-by: default avatarTakuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 0f3d9a17
...@@ -320,10 +320,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) ...@@ -320,10 +320,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
{ {
struct vhost_memory mem, *newmem, *oldmem; struct vhost_memory mem, *newmem, *oldmem;
unsigned long size = offsetof(struct vhost_memory, regions); unsigned long size = offsetof(struct vhost_memory, regions);
long r; if (copy_from_user(&mem, m, size))
r = copy_from_user(&mem, m, size); return -EFAULT;
if (r)
return r;
if (mem.padding) if (mem.padding)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS)
...@@ -333,11 +331,10 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) ...@@ -333,11 +331,10 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
return -ENOMEM; return -ENOMEM;
memcpy(newmem, &mem, size); memcpy(newmem, &mem, size);
r = copy_from_user(newmem->regions, m->regions, if (copy_from_user(newmem->regions, m->regions,
mem.nregions * sizeof *m->regions); mem.nregions * sizeof *m->regions)) {
if (r) {
kfree(newmem); kfree(newmem);
return r; return -EFAULT;
} }
if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL)))
...@@ -389,9 +386,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) ...@@ -389,9 +386,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
r = -EBUSY; r = -EBUSY;
break; break;
} }
r = copy_from_user(&s, argp, sizeof s); if (copy_from_user(&s, argp, sizeof s)) {
if (r < 0) r = -EFAULT;
break; break;
}
if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) { if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) {
r = -EINVAL; r = -EINVAL;
break; break;
...@@ -405,9 +403,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) ...@@ -405,9 +403,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
r = -EBUSY; r = -EBUSY;
break; break;
} }
r = copy_from_user(&s, argp, sizeof s); if (copy_from_user(&s, argp, sizeof s)) {
if (r < 0) r = -EFAULT;
break; break;
}
if (s.num > 0xffff) { if (s.num > 0xffff) {
r = -EINVAL; r = -EINVAL;
break; break;
...@@ -419,12 +418,14 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) ...@@ -419,12 +418,14 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
case VHOST_GET_VRING_BASE: case VHOST_GET_VRING_BASE:
s.index = idx; s.index = idx;
s.num = vq->last_avail_idx; s.num = vq->last_avail_idx;
r = copy_to_user(argp, &s, sizeof s); if (copy_to_user(argp, &s, sizeof s))
r = -EFAULT;
break; break;
case VHOST_SET_VRING_ADDR: case VHOST_SET_VRING_ADDR:
r = copy_from_user(&a, argp, sizeof a); if (copy_from_user(&a, argp, sizeof a)) {
if (r < 0) r = -EFAULT;
break; break;
}
if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) { if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) {
r = -EOPNOTSUPP; r = -EOPNOTSUPP;
break; break;
...@@ -477,9 +478,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) ...@@ -477,9 +478,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
vq->used = (void __user *)(unsigned long)a.used_user_addr; vq->used = (void __user *)(unsigned long)a.used_user_addr;
break; break;
case VHOST_SET_VRING_KICK: case VHOST_SET_VRING_KICK:
r = copy_from_user(&f, argp, sizeof f); if (copy_from_user(&f, argp, sizeof f)) {
if (r < 0) r = -EFAULT;
break; break;
}
eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
if (IS_ERR(eventfp)) { if (IS_ERR(eventfp)) {
r = PTR_ERR(eventfp); r = PTR_ERR(eventfp);
...@@ -492,9 +494,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) ...@@ -492,9 +494,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
filep = eventfp; filep = eventfp;
break; break;
case VHOST_SET_VRING_CALL: case VHOST_SET_VRING_CALL:
r = copy_from_user(&f, argp, sizeof f); if (copy_from_user(&f, argp, sizeof f)) {
if (r < 0) r = -EFAULT;
break; break;
}
eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
if (IS_ERR(eventfp)) { if (IS_ERR(eventfp)) {
r = PTR_ERR(eventfp); r = PTR_ERR(eventfp);
...@@ -510,9 +513,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) ...@@ -510,9 +513,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
filep = eventfp; filep = eventfp;
break; break;
case VHOST_SET_VRING_ERR: case VHOST_SET_VRING_ERR:
r = copy_from_user(&f, argp, sizeof f); if (copy_from_user(&f, argp, sizeof f)) {
if (r < 0) r = -EFAULT;
break; break;
}
eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
if (IS_ERR(eventfp)) { if (IS_ERR(eventfp)) {
r = PTR_ERR(eventfp); r = PTR_ERR(eventfp);
...@@ -575,9 +579,10 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg) ...@@ -575,9 +579,10 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
r = vhost_set_memory(d, argp); r = vhost_set_memory(d, argp);
break; break;
case VHOST_SET_LOG_BASE: case VHOST_SET_LOG_BASE:
r = copy_from_user(&p, argp, sizeof p); if (copy_from_user(&p, argp, sizeof p)) {
if (r < 0) r = -EFAULT;
break; break;
}
if ((u64)(unsigned long)p != p) { if ((u64)(unsigned long)p != p) {
r = -EFAULT; r = -EFAULT;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment