| From e3e847c7f15a27c80f526b2a7a8d4dd7ce0960a0 Mon Sep 17 00:00:00 2001 |
| From: Lars-Peter Clausen <lars@metafoo.de> |
| Date: Tue, 18 Oct 2016 16:54:05 +0200 |
| Subject: gpio: GPIO_GET_LINEHANDLE_IOCTL: Reject invalid line flags |
| |
| From: Lars-Peter Clausen <lars@metafoo.de> |
| |
| commit e3e847c7f15a27c80f526b2a7a8d4dd7ce0960a0 upstream. |
| |
| The GPIO_GET_LINEHANDLE_IOCTL currently ignores unknown or undefined |
| linehandle flags. From a backwards and forwards compatibility viewpoint it |
| is highly desirable to reject unknown flags though. |
| |
| On one hand an application that is using newer flags and is running on |
| an older kernel has no way to detect if the new flags were handled |
| correctly if they are silently discarded. |
| |
| On the other hand an application that (accidentally) passes undefined flags |
| will run fine on an older kernel, but may break on a newer kernel when |
| these flags get defined. |
| |
| Ensure that requests that have undefined flags set are rejected with an |
| error, rather than silently discarding the undefined flags. |
| |
| Fixes: d7c51b47ac11 ("gpio: userspace ABI for reading/writing GPIO lines") |
| 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 | 13 +++++++++++++ |
| 1 file changed, 13 insertions(+) |
| |
| --- a/drivers/gpio/gpiolib.c |
| +++ b/drivers/gpio/gpiolib.c |
| @@ -331,6 +331,13 @@ struct linehandle_state { |
| u32 numdescs; |
| }; |
| |
| +#define GPIOHANDLE_REQUEST_VALID_FLAGS \ |
| + (GPIOHANDLE_REQUEST_INPUT | \ |
| + GPIOHANDLE_REQUEST_OUTPUT | \ |
| + GPIOHANDLE_REQUEST_ACTIVE_LOW | \ |
| + GPIOHANDLE_REQUEST_OPEN_DRAIN | \ |
| + GPIOHANDLE_REQUEST_OPEN_SOURCE) |
| + |
| static long linehandle_ioctl(struct file *filep, unsigned int cmd, |
| unsigned long arg) |
| { |
| @@ -448,6 +455,12 @@ static int linehandle_create(struct gpio |
| ret = -EINVAL; |
| goto out_free_descs; |
| } |
| + |
| + /* Return an error if a unknown flag is set */ |
| + if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) { |
| + ret = -EINVAL; |
| + goto out_free_descs; |
| + } |
| |
| desc = &gdev->descs[offset]; |
| ret = gpiod_request(desc, lh->label); |