diff options
| author | Michael S. Tsirkin <mst@redhat.com> | 2010-03-17 10:06:11 -0400 |
|---|---|---|
| committer | Michael S. Tsirkin <mst@redhat.com> | 2010-03-17 17:07:35 -0400 |
| commit | 535297a6ae4c3b7a0562e71fac15c213eeec68e7 (patch) | |
| tree | 878526e743260b3666e36fb0655c0800a5d21afc | |
| parent | 0e255572121180c900e24e33b87047abd8153cce (diff) | |
vhost: fix error handling in vring ioctls
Stanse found a locking problem in vhost_set_vring:
several returns from VHOST_SET_VRING_KICK, VHOST_SET_VRING_CALL,
VHOST_SET_VRING_ERR with the vq->mutex held.
Fix these up.
Reported-by: Jiri Slaby <jirislaby@gmail.com>
Acked-by: Laurent Chavey <chavey@google.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
| -rw-r--r-- | drivers/vhost/vhost.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 7cd55e078794..7bd7a1e4409d 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
| @@ -476,8 +476,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 476 | if (r < 0) | 476 | if (r < 0) |
| 477 | break; | 477 | break; |
| 478 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 478 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
| 479 | if (IS_ERR(eventfp)) | 479 | if (IS_ERR(eventfp)) { |
| 480 | return PTR_ERR(eventfp); | 480 | r = PTR_ERR(eventfp); |
| 481 | break; | ||
| 482 | } | ||
| 481 | if (eventfp != vq->kick) { | 483 | if (eventfp != vq->kick) { |
| 482 | pollstop = filep = vq->kick; | 484 | pollstop = filep = vq->kick; |
| 483 | pollstart = vq->kick = eventfp; | 485 | pollstart = vq->kick = eventfp; |
| @@ -489,8 +491,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 489 | if (r < 0) | 491 | if (r < 0) |
| 490 | break; | 492 | break; |
| 491 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 493 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
| 492 | if (IS_ERR(eventfp)) | 494 | if (IS_ERR(eventfp)) { |
| 493 | return PTR_ERR(eventfp); | 495 | r = PTR_ERR(eventfp); |
| 496 | break; | ||
| 497 | } | ||
| 494 | if (eventfp != vq->call) { | 498 | if (eventfp != vq->call) { |
| 495 | filep = vq->call; | 499 | filep = vq->call; |
| 496 | ctx = vq->call_ctx; | 500 | ctx = vq->call_ctx; |
| @@ -505,8 +509,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 505 | if (r < 0) | 509 | if (r < 0) |
| 506 | break; | 510 | break; |
| 507 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 511 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
| 508 | if (IS_ERR(eventfp)) | 512 | if (IS_ERR(eventfp)) { |
| 509 | return PTR_ERR(eventfp); | 513 | r = PTR_ERR(eventfp); |
| 514 | break; | ||
| 515 | } | ||
| 510 | if (eventfp != vq->error) { | 516 | if (eventfp != vq->error) { |
| 511 | filep = vq->error; | 517 | filep = vq->error; |
| 512 | vq->error = eventfp; | 518 | vq->error = eventfp; |
