| From f4e81c529767b9a33d1b27695c54dc84a14af30d Mon Sep 17 00:00:00 2001 |
| From: Lars-Peter Clausen <lars@metafoo.de> |
| Date: Wed, 30 Nov 2016 13:05:21 +0100 |
| Subject: gpio: chardev: Return error for seek operations |
| |
| From: Lars-Peter Clausen <lars@metafoo.de> |
| |
| commit f4e81c529767b9a33d1b27695c54dc84a14af30d upstream. |
| |
| The GPIO chardev is used for management tasks (allocating line and event |
| handles) and does neither support read() nor write() operations. Hence it |
| does not make much sense to allow seek operations. |
| |
| Currently the chardev uses noop_llseek() for its seek implementation. This |
| function does not move the pointer and simply returns the current position |
| (always 0 for the GPIO chardev). noop_llseek() is primarily meant for |
| devices that can not support seek, but where there might be a user that |
| depends on the seek() operation succeeding. For newly added devices that |
| can not support seek operations it is recommended to use no_llseek(), which |
| will return an error. For more information see commit 6038f373a3dc |
| ("llseek: automatically add .llseek fop"). |
| |
| Unfortunately this was overlooked when the GPIO chardev ABI was introduced. |
| But it is highly unlikely that since then userspace applications have |
| appeared that rely on being able to perform non-failing seek operations on |
| a GPIO chardev file descriptor. So it should be safe to change from |
| noop_llseel() to no_seek(). Also use nonseekable_open() in the chardev |
| open() callback to clear the FMODE_SEEK, FMODE_PREAD and FMODE_PWRITE flags |
| from the file. Neither of these should be set on a file that does not |
| support seek operations. |
| |
| Fixes: 3c702e9987e2 ("gpio: add a userspace chardev ABI for GPIOs") |
| Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> |
| Signed-off-by: Linus Walleij <linus.walleij@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpio/gpiolib.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/gpio/gpiolib.c |
| +++ b/drivers/gpio/gpiolib.c |
| @@ -984,7 +984,8 @@ static int gpio_chrdev_open(struct inode |
| return -ENODEV; |
| get_device(&gdev->dev); |
| filp->private_data = gdev; |
| - return 0; |
| + |
| + return nonseekable_open(inode, filp); |
| } |
| |
| /** |
| @@ -1009,7 +1010,7 @@ static const struct file_operations gpio |
| .release = gpio_chrdev_release, |
| .open = gpio_chrdev_open, |
| .owner = THIS_MODULE, |
| - .llseek = noop_llseek, |
| + .llseek = no_llseek, |
| .unlocked_ioctl = gpio_ioctl, |
| #ifdef CONFIG_COMPAT |
| .compat_ioctl = gpio_ioctl_compat, |