aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTakuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>2010-05-27 05:58:03 -0400
committerMichael S. Tsirkin <mst@redhat.com>2010-05-27 06:54:59 -0400
commit7ad9c9d27048547e96e4e3a13b5780ec6f81bb9f (patch)
tree0f70562d0f51c086b02953388578bd87040b5067 /drivers
parent0f3d9a17469d71ba1bab79c07c8eecb9e26e60af (diff)
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: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/vhost/vhost.c51
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;