diff options
| -rw-r--r-- | drivers/vhost/vhost.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 44f123abb0f4..e36620272715 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
| @@ -320,10 +320,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | |||
| 320 | { | 320 | { |
| 321 | struct vhost_memory mem, *newmem, *oldmem; | 321 | struct vhost_memory mem, *newmem, *oldmem; |
| 322 | unsigned long size = offsetof(struct vhost_memory, regions); | 322 | unsigned long size = offsetof(struct vhost_memory, regions); |
| 323 | long r; | 323 | if (copy_from_user(&mem, m, size)) |
| 324 | r = copy_from_user(&mem, m, size); | 324 | return -EFAULT; |
| 325 | if (r) | ||
| 326 | return r; | ||
| 327 | if (mem.padding) | 325 | if (mem.padding) |
| 328 | return -EOPNOTSUPP; | 326 | return -EOPNOTSUPP; |
| 329 | if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) | 327 | 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 | return -ENOMEM; | 331 | return -ENOMEM; |
| 334 | 332 | ||
| 335 | memcpy(newmem, &mem, size); | 333 | memcpy(newmem, &mem, size); |
| 336 | r = copy_from_user(newmem->regions, m->regions, | 334 | if (copy_from_user(newmem->regions, m->regions, |
| 337 | mem.nregions * sizeof *m->regions); | 335 | mem.nregions * sizeof *m->regions)) { |
| 338 | if (r) { | ||
| 339 | kfree(newmem); | 336 | kfree(newmem); |
| 340 | return r; | 337 | return -EFAULT; |
| 341 | } | 338 | } |
| 342 | 339 | ||
| 343 | if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) | 340 | 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 | r = -EBUSY; | 386 | r = -EBUSY; |
| 390 | break; | 387 | break; |
| 391 | } | 388 | } |
| 392 | r = copy_from_user(&s, argp, sizeof s); | 389 | if (copy_from_user(&s, argp, sizeof s)) { |
| 393 | if (r < 0) | 390 | r = -EFAULT; |
| 394 | break; | 391 | break; |
| 392 | } | ||
| 395 | if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) { | 393 | if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) { |
| 396 | r = -EINVAL; | 394 | r = -EINVAL; |
| 397 | break; | 395 | break; |
| @@ -405,9 +403,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 405 | r = -EBUSY; | 403 | r = -EBUSY; |
| 406 | break; | 404 | break; |
| 407 | } | 405 | } |
| 408 | r = copy_from_user(&s, argp, sizeof s); | 406 | if (copy_from_user(&s, argp, sizeof s)) { |
| 409 | if (r < 0) | 407 | r = -EFAULT; |
| 410 | break; | 408 | break; |
| 409 | } | ||
| 411 | if (s.num > 0xffff) { | 410 | if (s.num > 0xffff) { |
| 412 | r = -EINVAL; | 411 | r = -EINVAL; |
| 413 | break; | 412 | break; |
| @@ -419,12 +418,14 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 419 | case VHOST_GET_VRING_BASE: | 418 | case VHOST_GET_VRING_BASE: |
| 420 | s.index = idx; | 419 | s.index = idx; |
| 421 | s.num = vq->last_avail_idx; | 420 | s.num = vq->last_avail_idx; |
| 422 | r = copy_to_user(argp, &s, sizeof s); | 421 | if (copy_to_user(argp, &s, sizeof s)) |
| 422 | r = -EFAULT; | ||
| 423 | break; | 423 | break; |
| 424 | case VHOST_SET_VRING_ADDR: | 424 | case VHOST_SET_VRING_ADDR: |
| 425 | r = copy_from_user(&a, argp, sizeof a); | 425 | if (copy_from_user(&a, argp, sizeof a)) { |
| 426 | if (r < 0) | 426 | r = -EFAULT; |
| 427 | break; | 427 | break; |
| 428 | } | ||
| 428 | if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) { | 429 | if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) { |
| 429 | r = -EOPNOTSUPP; | 430 | r = -EOPNOTSUPP; |
| 430 | break; | 431 | break; |
| @@ -477,9 +478,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 477 | vq->used = (void __user *)(unsigned long)a.used_user_addr; | 478 | vq->used = (void __user *)(unsigned long)a.used_user_addr; |
| 478 | break; | 479 | break; |
| 479 | case VHOST_SET_VRING_KICK: | 480 | case VHOST_SET_VRING_KICK: |
| 480 | r = copy_from_user(&f, argp, sizeof f); | 481 | if (copy_from_user(&f, argp, sizeof f)) { |
| 481 | if (r < 0) | 482 | r = -EFAULT; |
| 482 | break; | 483 | break; |
| 484 | } | ||
| 483 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 485 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
| 484 | if (IS_ERR(eventfp)) { | 486 | if (IS_ERR(eventfp)) { |
| 485 | r = PTR_ERR(eventfp); | 487 | r = PTR_ERR(eventfp); |
| @@ -492,9 +494,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 492 | filep = eventfp; | 494 | filep = eventfp; |
| 493 | break; | 495 | break; |
| 494 | case VHOST_SET_VRING_CALL: | 496 | case VHOST_SET_VRING_CALL: |
| 495 | r = copy_from_user(&f, argp, sizeof f); | 497 | if (copy_from_user(&f, argp, sizeof f)) { |
| 496 | if (r < 0) | 498 | r = -EFAULT; |
| 497 | break; | 499 | break; |
| 500 | } | ||
| 498 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 501 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
| 499 | if (IS_ERR(eventfp)) { | 502 | if (IS_ERR(eventfp)) { |
| 500 | r = PTR_ERR(eventfp); | 503 | r = PTR_ERR(eventfp); |
| @@ -510,9 +513,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 510 | filep = eventfp; | 513 | filep = eventfp; |
| 511 | break; | 514 | break; |
| 512 | case VHOST_SET_VRING_ERR: | 515 | case VHOST_SET_VRING_ERR: |
| 513 | r = copy_from_user(&f, argp, sizeof f); | 516 | if (copy_from_user(&f, argp, sizeof f)) { |
| 514 | if (r < 0) | 517 | r = -EFAULT; |
| 515 | break; | 518 | break; |
| 519 | } | ||
| 516 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 520 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
| 517 | if (IS_ERR(eventfp)) { | 521 | if (IS_ERR(eventfp)) { |
| 518 | r = PTR_ERR(eventfp); | 522 | r = PTR_ERR(eventfp); |
| @@ -575,9 +579,10 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg) | |||
| 575 | r = vhost_set_memory(d, argp); | 579 | r = vhost_set_memory(d, argp); |
| 576 | break; | 580 | break; |
| 577 | case VHOST_SET_LOG_BASE: | 581 | case VHOST_SET_LOG_BASE: |
| 578 | r = copy_from_user(&p, argp, sizeof p); | 582 | if (copy_from_user(&p, argp, sizeof p)) { |
| 579 | if (r < 0) | 583 | r = -EFAULT; |
| 580 | break; | 584 | break; |
| 585 | } | ||
| 581 | if ((u64)(unsigned long)p != p) { | 586 | if ((u64)(unsigned long)p != p) { |
| 582 | r = -EFAULT; | 587 | r = -EFAULT; |
| 583 | break; | 588 | break; |
