Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/dtor/input

Pull input update from Dmitry Torokhov:
 "The only change is David Hermann's new EVIOCREVOKE evdev ioctl that
  allows safely passing file descriptors to input devices to session
  processes and later being able to stop delivery of events through
  these fds so that inactive sessions will no longer receive user input
  that does not belong to them"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: evdev - add EVIOCREVOKE ioctl
  • Loading branch information
torvalds committed Sep 15, 2013
2 parents 05a8252 + c7dc657 commit 8bf5e36
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
37 changes: 31 additions & 6 deletions drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct evdev_client {
struct evdev *evdev;
struct list_head node;
int clkid;
bool revoked;
unsigned int bufsize;
struct input_event buffer[];
};
Expand Down Expand Up @@ -164,6 +165,9 @@ static void evdev_pass_values(struct evdev_client *client,
struct input_event event;
bool wakeup = false;

if (client->revoked)
return;

event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
mono : real);

Expand Down Expand Up @@ -240,7 +244,7 @@ static int evdev_flush(struct file *file, fl_owner_t id)
if (retval)
return retval;

if (!evdev->exist)
if (!evdev->exist || client->revoked)
retval = -ENODEV;
else
retval = input_flush_device(&evdev->handle, file);
Expand Down Expand Up @@ -429,7 +433,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
if (retval)
return retval;

if (!evdev->exist) {
if (!evdev->exist || client->revoked) {
retval = -ENODEV;
goto out;
}
Expand Down Expand Up @@ -482,7 +486,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
return -EINVAL;

for (;;) {
if (!evdev->exist)
if (!evdev->exist || client->revoked)
return -ENODEV;

if (client->packet_head == client->tail &&
Expand Down Expand Up @@ -511,7 +515,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
if (!(file->f_flags & O_NONBLOCK)) {
error = wait_event_interruptible(evdev->wait,
client->packet_head != client->tail ||
!evdev->exist);
!evdev->exist || client->revoked);
if (error)
return error;
}
Expand All @@ -529,7 +533,11 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)

poll_wait(file, &evdev->wait, wait);

mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR;
if (evdev->exist && !client->revoked)
mask = POLLOUT | POLLWRNORM;
else
mask = POLLHUP | POLLERR;

if (client->packet_head != client->tail)
mask |= POLLIN | POLLRDNORM;

Expand Down Expand Up @@ -795,6 +803,17 @@ static int evdev_handle_mt_request(struct input_dev *dev,
return 0;
}

static int evdev_revoke(struct evdev *evdev, struct evdev_client *client,
struct file *file)
{
client->revoked = true;
evdev_ungrab(evdev, client);
input_flush_device(&evdev->handle, file);
wake_up_interruptible(&evdev->wait);

return 0;
}

static long evdev_do_ioctl(struct file *file, unsigned int cmd,
void __user *p, int compat_mode)
{
Expand Down Expand Up @@ -857,6 +876,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
else
return evdev_ungrab(evdev, client);

case EVIOCREVOKE:
if (p)
return -EINVAL;
else
return evdev_revoke(evdev, client, file);

case EVIOCSCLOCKID:
if (copy_from_user(&i, p, sizeof(unsigned int)))
return -EFAULT;
Expand Down Expand Up @@ -1002,7 +1027,7 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
if (retval)
return retval;

if (!evdev->exist) {
if (!evdev->exist || client->revoked) {
retval = -ENODEV;
goto out;
}
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ struct input_keymap_entry {
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */

#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
#define EVIOCREVOKE _IOW('E', 0x91, int) /* Revoke device access */

#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */

Expand Down

0 comments on commit 8bf5e36

Please sign in to comment.