* [PATCH] gpiolib: keep the line state workqueue alive until device release
@ 2026-11-09 14:24 Bartosz Golaszewski
2026-11-09 14:34 ` sashiko-bot
0 siblings, 1 reply; 2+ messages in thread
From: Bartosz Golaszewski @ 2026-11-09 14:24 UTC (permalink / raw)
To: Bartosz Golaszewski, Kent Gibson, Linus Walleij
Cc: linux-gpio, linux-kernel, stable, Bartosz Golaszewski
gpiod_line_state_notify() races with a concurrent gpiochip_remove() which
unconditionally destroys the line state workqueue causing
a use-after-free situation where queue_work() can schedule a work on a
freed workqueue.
Keep the line state workqueue alive until GPIO device release.
Cc: stable@vger.kernel.org
Fixes: 07c61d4da43f ("gpiolib: notify user-space about in-kernel line state changes")
Closes: https://sashiko.dev/#/bug/linux-d0e9e518-2348-4fe3-857d-f3d61a42f159
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/gpio/gpiolib-cdev.c | 1 -
drivers/gpio/gpiolib.c | 4 ++++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index f68e33cbd7d4cd5153e82ad77768cf52a90601d6..1dc170364c46a51092d21391c5a602bf9dee820c 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -2768,7 +2768,6 @@ int gpiolib_cdev_register(struct gpio_chip *gc, dev_t devt)
void gpiolib_cdev_unregister(struct gpio_device *gdev)
{
- destroy_workqueue(gdev->line_state_wq);
cdev_device_del(&gdev->chrdev, &gdev->dev);
blocking_notifier_call_chain(&gdev->device_notifier, 0, NULL);
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index fbdeda2f278713a47c2e3d2a6640f387f6d92227..c954c7eec2bee3a8dd55b949ec9b92f31461b25d 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -28,6 +28,7 @@
#include <linux/srcu.h>
#include <linux/string.h>
#include <linux/string_choices.h>
+#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
@@ -898,6 +899,9 @@ static void gpiodev_release(struct device *dev)
synchronize_srcu(&gdev->desc_srcu);
cleanup_srcu_struct(&gdev->desc_srcu);
+ if (gdev->line_state_wq)
+ destroy_workqueue(gdev->line_state_wq);
+
ida_free(&gpio_ida, gdev->id);
kfree_const(gdev->label);
kfree(gdev->descs);
---
base-commit: ddfe51b0a0f5dc9e415cc2c8ad8db17532dd426b
change-id: 20261109-gpio-line-state-wq-uaf-e7343655998a
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] gpiolib: keep the line state workqueue alive until device release
2026-11-09 14:24 [PATCH] gpiolib: keep the line state workqueue alive until device release Bartosz Golaszewski
@ 2026-11-09 14:34 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-11-09 14:34 UTC (permalink / raw)
To: Bartosz Golaszewski; +Cc: linux-gpio
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] gpiolib: double destroy_workqueue() in gpiodev_release() on
cdev add error
--
commit f0714550a8f7080c7dd00f07240622c9dd77f912
Author: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
gpiolib: keep the line state workqueue alive until device release
This commit moves the destruction of gdev->line_state_wq from
gpiolib_cdev_unregister() to gpiodev_release() to avoid a use-after-free
race with concurrent gpiod_line_state_notify() calls during chip removal.
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index fbdeda2f27871..c954c7eec2bee 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
[ ... ]
> @@ -898,6 +899,9 @@ static void gpiodev_release(struct device *dev)
> synchronize_srcu(&gdev->desc_srcu);
> cleanup_srcu_struct(&gdev->desc_srcu);
>
> + if (gdev->line_state_wq)
> + destroy_workqueue(gdev->line_state_wq);
[Severity: Medium]
Can this call destroy_workqueue() a second time on gdev->line_state_wq if
cdev_device_add() fails in gpiolib_cdev_register()?
drivers/gpio/gpiolib-cdev.c:gpiolib_cdev_register() {
...
ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
if (ret) {
destroy_workqueue(gdev->line_state_wq);
return ret;
}
...
}
When gpiolib_cdev_register() fails here, it destroys gdev->line_state_wq
without clearing the pointer. The caller then unwinds via
gpio_device_put(gdev) -> gpiodev_release(), which sees the non-NULL
dangling pointer and calls destroy_workqueue() again, causing a
use-after-free.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261109-gpio-line-state-wq-uaf-v1-1-2e126ca3427d@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-09 14:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-09 14:24 [PATCH] gpiolib: keep the line state workqueue alive until device release Bartosz Golaszewski
2026-11-09 14:34 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox