diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2016-05-27 08:24:04 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2016-05-30 10:00:31 -0400 |
commit | 8b92e17efe029cc19f435f9fcbdfb1e7b9beb0ef (patch) | |
tree | fa0c46fd884187ffd0a2d852dcb468743941a8c1 | |
parent | 9c10280d85c14a20751ab6c1185ad725172936d6 (diff) |
gpio: handle compatible ioctl() pointers
If we're using the compatible ioctl() we need to handle the
argument pointer in a special way or there will be trouble.
Fixes: 3c702e9987e2 ("gpio: add a userspace chardev ABI for GPIOs")
Reported-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/gpio/gpiolib.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e901d2666b46..68dbff5d8f57 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/cdev.h> | 20 | #include <linux/cdev.h> |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
23 | #include <linux/compat.h> | ||
23 | #include <uapi/linux/gpio.h> | 24 | #include <uapi/linux/gpio.h> |
24 | 25 | ||
25 | #include "gpiolib.h" | 26 | #include "gpiolib.h" |
@@ -316,7 +317,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
316 | { | 317 | { |
317 | struct gpio_device *gdev = filp->private_data; | 318 | struct gpio_device *gdev = filp->private_data; |
318 | struct gpio_chip *chip = gdev->chip; | 319 | struct gpio_chip *chip = gdev->chip; |
319 | int __user *ip = (int __user *)arg; | 320 | void __user *ip = (void __user *)arg; |
320 | 321 | ||
321 | /* We fail any subsequent ioctl():s when the chip is gone */ | 322 | /* We fail any subsequent ioctl():s when the chip is gone */ |
322 | if (!chip) | 323 | if (!chip) |
@@ -388,6 +389,14 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
388 | return -EINVAL; | 389 | return -EINVAL; |
389 | } | 390 | } |
390 | 391 | ||
392 | #ifdef CONFIG_COMPAT | ||
393 | static long gpio_ioctl_compat(struct file *filp, unsigned int cmd, | ||
394 | unsigned long arg) | ||
395 | { | ||
396 | return gpio_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); | ||
397 | } | ||
398 | #endif | ||
399 | |||
391 | /** | 400 | /** |
392 | * gpio_chrdev_open() - open the chardev for ioctl operations | 401 | * gpio_chrdev_open() - open the chardev for ioctl operations |
393 | * @inode: inode for this chardev | 402 | * @inode: inode for this chardev |
@@ -431,7 +440,9 @@ static const struct file_operations gpio_fileops = { | |||
431 | .owner = THIS_MODULE, | 440 | .owner = THIS_MODULE, |
432 | .llseek = noop_llseek, | 441 | .llseek = noop_llseek, |
433 | .unlocked_ioctl = gpio_ioctl, | 442 | .unlocked_ioctl = gpio_ioctl, |
434 | .compat_ioctl = gpio_ioctl, | 443 | #ifdef CONFIG_COMPAT |
444 | .compat_ioctl = gpio_ioctl_compat, | ||
445 | #endif | ||
435 | }; | 446 | }; |
436 | 447 | ||
437 | static void gpiodevice_release(struct device *dev) | 448 | static void gpiodevice_release(struct device *dev) |