gpiolib: Fix Oops in gpiod_direction_input_nonotify()
authorDan Carpenter <dan.carpenter@linaro.org>
Fri, 28 Feb 2025 13:03:47 +0000 (16:03 +0300)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Fri, 28 Feb 2025 15:30:48 +0000 (16:30 +0100)
The gpiod_direction_input_nonotify() function is supposed to return zero
if the direction for the pin is input.  But instead it accidentally
returns GPIO_LINE_DIRECTION_IN (1) which will be cast into an ERR_PTR()
in gpiochip_request_own_desc().  The callers dereference it and it leads
to a crash.

I changed gpiod_direction_output_raw_commit() just for consistency but
returning GPIO_LINE_DIRECTION_OUT (0) is fine.

Cc: stable@vger.kernel.org
Fixes: 9d846b1aebbe ("gpiolib: check the return value of gpio_chip::get_direction()")
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Link: https://lore.kernel.org/r/254f3925-3015-4c9d-aac5-bb9b4b2cd2c5@stanley.mountain
[Bartosz: moved the variable declarations to the top of the functions]
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpiolib.c

index fc19df5a64c2be5ce71d8eb115a2a9b522ce70de..8741600af7efb0a258f67fcf4c495a663016a34a 100644 (file)
@@ -2712,7 +2712,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input);
 
 int gpiod_direction_input_nonotify(struct gpio_desc *desc)
 {
-       int ret = 0;
+       int ret = 0, dir;
 
        CLASS(gpio_chip_guard, guard)(desc);
        if (!guard.gc)
@@ -2740,12 +2740,12 @@ int gpiod_direction_input_nonotify(struct gpio_desc *desc)
                ret = guard.gc->direction_input(guard.gc,
                                                gpio_chip_hwgpio(desc));
        } else if (guard.gc->get_direction) {
-               ret = guard.gc->get_direction(guard.gc,
+               dir = guard.gc->get_direction(guard.gc,
                                              gpio_chip_hwgpio(desc));
-               if (ret < 0)
-                       return ret;
+               if (dir < 0)
+                       return dir;
 
-               if (ret != GPIO_LINE_DIRECTION_IN) {
+               if (dir != GPIO_LINE_DIRECTION_IN) {
                        gpiod_warn(desc,
                                   "%s: missing direction_input() operation and line is output\n",
                                    __func__);
@@ -2764,7 +2764,7 @@ int gpiod_direction_input_nonotify(struct gpio_desc *desc)
 
 static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value)
 {
-       int val = !!value, ret = 0;
+       int val = !!value, ret = 0, dir;
 
        CLASS(gpio_chip_guard, guard)(desc);
        if (!guard.gc)
@@ -2788,12 +2788,12 @@ static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value)
        } else {
                /* Check that we are in output mode if we can */
                if (guard.gc->get_direction) {
-                       ret = guard.gc->get_direction(guard.gc,
+                       dir = guard.gc->get_direction(guard.gc,
                                                      gpio_chip_hwgpio(desc));
-                       if (ret < 0)
-                               return ret;
+                       if (dir < 0)
+                               return dir;
 
-                       if (ret != GPIO_LINE_DIRECTION_OUT) {
+                       if (dir != GPIO_LINE_DIRECTION_OUT) {
                                gpiod_warn(desc,
                                           "%s: missing direction_output() operation\n",
                                           __func__);