From 566cf5b6e34504aaccb76167ecccd7e7e69e6456 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 30 Dec 2011 15:16:44 -0800 Subject: Input: evdev - only allow reading events if a full packet is present Without this, it was possible for the reader to get ahead of packet_head. If the input device generated a partial packet *right* after the reader got ahead, then we can get into a situation where the device is marked readable, but read always returns 0 until the next packet is finished (i.e a SYN is generated by the input driver). This situation can also happen if we overflow the buffer while a reader is trying to read an event out. Signed-off-by: Dima Zavin Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input/evdev.c') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 4cf25347b015..03344b3c7c15 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -369,7 +369,7 @@ static int evdev_fetch_next_event(struct evdev_client *client, spin_lock_irq(&client->buffer_lock); - have_event = client->head != client->tail; + have_event = client->packet_head != client->tail; if (have_event) { *event = client->buffer[client->tail++]; client->tail &= client->bufsize - 1; -- cgit v1.2.3 From e90f869cae3b4aedf0f6d2ca8048d60245ee77f7 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 30 Dec 2011 15:16:44 -0800 Subject: Input: evdev - if no events and non-block, return EAGAIN not 0 Signed-off-by: Dima Zavin Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/input/evdev.c') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 03344b3c7c15..a9d871651ce7 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -412,6 +412,9 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, retval += input_event_size(); } + if (retval == 0 && (file->f_flags & O_NONBLOCK)) + return -EAGAIN; + return retval; } -- cgit v1.2.3 From 509f87c5f564627b6b9fc763e74ef3608213d610 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 30 Dec 2011 15:16:44 -0800 Subject: Input: evdev - do not block waiting for an event if fd is nonblock If there is a full packet in the buffer, and we overflow that buffer right after checking for that condition, it would have been possible for us to block indefinitely (rather, until the next full packet) even if the file was marked as O_NONBLOCK. Cc: Jeff Brown Signed-off-by: Dima Zavin Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/input/evdev.c') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index a9d871651ce7..76457d50bc34 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -391,14 +391,13 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, if (count < input_event_size()) return -EINVAL; - if (client->packet_head == client->tail && evdev->exist && - (file->f_flags & O_NONBLOCK)) - return -EAGAIN; - - retval = wait_event_interruptible(evdev->wait, - client->packet_head != client->tail || !evdev->exist); - if (retval) - return retval; + if (!(file->f_flags & O_NONBLOCK)) { + retval = wait_event_interruptible(evdev->wait, + client->packet_head != client->tail || + !evdev->exist); + if (retval) + return retval; + } if (!evdev->exist) return -ENODEV; -- cgit v1.2.3