[PATCH] gpiolib: fix memory leak in gpiod_set_array_value_complex() EPERM error path
From: Kent Gibson
Date: Fri Oct 16 2026 - 06:56:13 EST
A drive-by review by Sashiko reports that, where the line has not been
configured as an output, gpiod_set_array_value_complex() can return
without freeing potentially alloced bitmaps, thus leaking memory.
Cleanup the bitmaps before returning.
Fixes: 92ac7de3175e ("gpiolib: don't allow setting values on input lines")
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Link: https://lore.kernel.org/linux-gpio/sashiko-outbox-168233@xxxxxxxxxx/
Signed-off-by: Kent Gibson <warthog618@xxxxxxxxx>
---
Based on for-current as it requires the previous patch.
Moved the ret init to the top just to make sure it is always initialised.
Not completely comfortable with the goto jumping out of the loop, so
would be quite happy to rework that if it doesn't work for you.
Cheers,
Kent.
drivers/gpio/gpiolib.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index c0394c7d6279..334a917e3202 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3842,7 +3842,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
unsigned long *value_bitmap)
{
struct gpio_chip *gc;
- int i = 0, ret;
+ int i = 0, ret = 0;
/*
* Validate array_info against desc_array and its size.
@@ -3920,8 +3920,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
int hwgpio = gpiod_hwgpio(desc);
int value = test_bit(i, value_bitmap);
- if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags)))
- return -EPERM;
+ if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags))) {
+ ret = -EPERM;
+ goto cleanup_bitmap;
+ }
/*
* Pins applicable for fast input but not for
@@ -3954,10 +3956,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
} while ((i < array_size) &&
gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc));
/* push collected bits to outputs */
- ret = 0;
if (count != 0)
ret = gpiochip_set_multiple(guard.gc, mask, bits);
+cleanup_bitmap:
if (mask != fastpath_mask)
bitmap_free(mask);
if (bits != fastpath_bits)
base-commit: 205cccd06e545694754e1bf8d626ea96e742cd8a
--
2.56.0