gpiolib: Never return internal error codes to user space
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Tue, 1 Feb 2022 15:27:55 +0000 (17:27 +0200)
committerBartosz Golaszewski <brgl@bgdev.pl>
Tue, 8 Feb 2022 09:34:15 +0000 (10:34 +0100)
Currently it's possible that character device interface may return
the error codes which are not supposed to be seen by user space.
In this case it's EPROBE_DEFER.

Wrap it to return -ENODEV instead as sysfs does.

Fixes: d7c51b47ac11 ("gpio: userspace ABI for reading/writing GPIO lines")
Fixes: 61f922db7221 ("gpio: userspace ABI for reading GPIO line events")
Fixes: 3c0d9c635ae2 ("gpiolib: cdev: support GPIO_V2_GET_LINE_IOCTL and GPIO_V2_LINE_GET_VALUES_IOCTL")
Reported-by: Suresh Balakrishnan <suresh.balakrishnan@intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
drivers/gpio/gpiolib-cdev.c
drivers/gpio/gpiolib-sysfs.c
drivers/gpio/gpiolib.h

index c7b5446d01fd2363fa65c9d681cfd52bcfe042e7..ffa0256cad5a0b83241f43959cbce11d32a8c23f 100644 (file)
@@ -330,7 +330,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
                        goto out_free_lh;
                }
 
-               ret = gpiod_request(desc, lh->label);
+               ret = gpiod_request_user(desc, lh->label);
                if (ret)
                        goto out_free_lh;
                lh->descs[i] = desc;
@@ -1378,7 +1378,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
                        goto out_free_linereq;
                }
 
-               ret = gpiod_request(desc, lr->label);
+               ret = gpiod_request_user(desc, lr->label);
                if (ret)
                        goto out_free_linereq;
 
@@ -1764,7 +1764,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
                }
        }
 
-       ret = gpiod_request(desc, le->label);
+       ret = gpiod_request_user(desc, le->label);
        if (ret)
                goto out_free_le;
        le->desc = desc;
index 4098bc7f88b7e244db4e2b7f4d9b19e24e4512e7..44c1ad51b3fe9088d7235d50540574e1411a2674 100644 (file)
@@ -475,12 +475,9 @@ static ssize_t export_store(struct class *class,
         * they may be undone on its behalf too.
         */
 
-       status = gpiod_request(desc, "sysfs");
-       if (status) {
-               if (status == -EPROBE_DEFER)
-                       status = -ENODEV;
+       status = gpiod_request_user(desc, "sysfs");
+       if (status)
                goto done;
-       }
 
        status = gpiod_set_transitory(desc, false);
        if (!status) {
index 30bc3f80f83e6c2a71bdb47bb9d054f9011ed175..c31f4626915de3936c1daf89c559738eb475040a 100644 (file)
@@ -135,6 +135,18 @@ struct gpio_desc {
 
 int gpiod_request(struct gpio_desc *desc, const char *label);
 void gpiod_free(struct gpio_desc *desc);
+
+static inline int gpiod_request_user(struct gpio_desc *desc, const char *label)
+{
+       int ret;
+
+       ret = gpiod_request(desc, label);
+       if (ret == -EPROBE_DEFER)
+               ret = -ENODEV;
+
+       return ret;
+}
+
 int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
                unsigned long lflags, enum gpiod_flags dflags);
 int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);