[PATCH v2 1/4] gpio: shared: fix use-after-free bug when adding shared proxies

From: Bartosz Golaszewski

Date: Thu Oct 01 2026 - 10:55:56 EST


The GPIO lookup table can stay alive for longer than the kobject whose
name string's address we're assigning to lookup->dev_id. Fix a potential
UAF by duplicating the string.

Assisted-by: LLM
Cc: stable@xxxxxxxxxxxxxxx
Fixes: a060b8c511ab ("gpiolib: implement low-level, shared GPIO support")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
---
drivers/gpio/gpiolib-shared.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index 5f9623e40b0fbebcf318fcfb2e75768cf6e3f313..6acfec73b73477245c7e4c593f2925efbc8980c6 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -450,7 +450,6 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, struct fwnode_handle *
const char *con_id, unsigned long lflags)
{
const char *dev_id = dev_name(consumer);
- struct gpiod_lookup_table *lookup;
struct gpio_shared_entry *entry;
struct gpio_shared_ref *ref;

@@ -480,18 +479,22 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, struct fwnode_handle *
if (!key)
return -ENOMEM;

- lookup = kzalloc_flex(*lookup, table, 2);
+ struct gpiod_lookup_table *lookup __free(kfree) =
+ kzalloc_flex(*lookup, table, 2);
if (!lookup)
return -ENOMEM;

pr_debug("Adding machine lookup entry for a shared GPIO for consumer %s, with key '%s' and con_id '%s'\n",
dev_id, key, ref->con_id ?: "none");

- lookup->dev_id = dev_id;
+ lookup->dev_id = kstrdup(dev_id, GFP_KERNEL);
+ if (!lookup->dev_id)
+ return -ENOMEM;
+
lookup->table[0] = GPIO_LOOKUP(no_free_ptr(key), 0,
ref->con_id, lflags);

- ref->lookup = lookup;
+ ref->lookup = no_free_ptr(lookup);
gpiod_add_lookup_table(ref->lookup);

return 0;
@@ -611,6 +614,7 @@ void gpio_device_teardown_shared(struct gpio_device *gdev)
if (ref->lookup) {
gpiod_remove_lookup_table(ref->lookup);
kfree(ref->lookup->table[0].key);
+ kfree(ref->lookup->dev_id);
kfree(ref->lookup);
ref->lookup = NULL;
}

--
2.47.3