Input: evdev - fix evdev_write return value on partial writes
authorPeter Korsgaard <jacmet@sunsite.dk>
Fri, 25 Feb 2011 17:30:46 +0000 (09:30 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sun, 27 Feb 2011 09:52:53 +0000 (01:52 -0800)
As was recently brought up on the busybox list
(http://lists.busybox.net/pipermail/busybox/2011-January/074565.html),
evdev_write doesn't properly check the count argument, which will
lead to a return value > count on partial writes if the remaining bytes
are accessible - causing userspace confusion.

Fix it by only handling each full input_event structure and return -EINVAL
if less than 1 struct was written, similar to how it is done in evdev_read.

Reported-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/evdev.c

index c8471a2552e73ea28c7401e58e713b66bbc6cc33..7f42d3a454d2d6aaebdc41e0e5a8c6700d6a00df 100644 (file)
@@ -321,6 +321,9 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
        struct input_event event;
        int retval;
 
+       if (count < input_event_size())
+               return -EINVAL;
+
        retval = mutex_lock_interruptible(&evdev->mutex);
        if (retval)
                return retval;
@@ -330,17 +333,16 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
                goto out;
        }
 
-       while (retval < count) {
-
+       do {
                if (input_event_from_user(buffer + retval, &event)) {
                        retval = -EFAULT;
                        goto out;
                }
+               retval += input_event_size();
 
                input_inject_event(&evdev->handle,
                                   event.type, event.code, event.value);
-               retval += input_event_size();
-       }
+       } while (retval + input_event_size() <= count);
 
  out:
        mutex_unlock(&evdev->mutex);