diff options
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/misc/uinput.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index a0a4bbaef02c..772835938a52 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
| @@ -430,20 +430,30 @@ static int uinput_setup_device(struct uinput_device *udev, | |||
| 430 | return retval; | 430 | return retval; |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | static ssize_t uinput_inject_event(struct uinput_device *udev, | 433 | static ssize_t uinput_inject_events(struct uinput_device *udev, |
| 434 | const char __user *buffer, size_t count) | 434 | const char __user *buffer, size_t count) |
| 435 | { | 435 | { |
| 436 | struct input_event ev; | 436 | struct input_event ev; |
| 437 | size_t bytes = 0; | ||
| 437 | 438 | ||
| 438 | if (count < input_event_size()) | 439 | if (count != 0 && count < input_event_size()) |
| 439 | return -EINVAL; | 440 | return -EINVAL; |
| 440 | 441 | ||
| 441 | if (input_event_from_user(buffer, &ev)) | 442 | while (bytes + input_event_size() <= count) { |
| 442 | return -EFAULT; | 443 | /* |
| 444 | * Note that even if some events were fetched successfully | ||
| 445 | * we are still going to return EFAULT instead of partial | ||
| 446 | * count to let userspace know that it got it's buffers | ||
| 447 | * all wrong. | ||
| 448 | */ | ||
| 449 | if (input_event_from_user(buffer + bytes, &ev)) | ||
| 450 | return -EFAULT; | ||
| 443 | 451 | ||
| 444 | input_event(udev->dev, ev.type, ev.code, ev.value); | 452 | input_event(udev->dev, ev.type, ev.code, ev.value); |
| 453 | bytes += input_event_size(); | ||
| 454 | } | ||
| 445 | 455 | ||
| 446 | return input_event_size(); | 456 | return bytes; |
| 447 | } | 457 | } |
| 448 | 458 | ||
| 449 | static ssize_t uinput_write(struct file *file, const char __user *buffer, | 459 | static ssize_t uinput_write(struct file *file, const char __user *buffer, |
| @@ -460,7 +470,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, | |||
| 460 | return retval; | 470 | return retval; |
| 461 | 471 | ||
| 462 | retval = udev->state == UIST_CREATED ? | 472 | retval = udev->state == UIST_CREATED ? |
| 463 | uinput_inject_event(udev, buffer, count) : | 473 | uinput_inject_events(udev, buffer, count) : |
| 464 | uinput_setup_device(udev, buffer, count); | 474 | uinput_setup_device(udev, buffer, count); |
| 465 | 475 | ||
| 466 | mutex_unlock(&udev->mutex); | 476 | mutex_unlock(&udev->mutex); |
