[PATCH 4/5] gpiolib: don't overwrite the entire flags field in gpiod_free_commit()

From: Bartosz Golaszewski

Date: Wed Nov 04 2026 - 10:49:55 EST


Use gpiod_update_flags() to clear all request-related flags in one go
instead of risking racing with concurrent users and overwriting any
changes they could have done between READ_ONCE() and WRITE_ONCE().

Cc: stable@xxxxxxxxxxxxxxx
Fixes: 35b545332b80 ("gpio: remove gpio_lock")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
---
drivers/gpio/gpiolib.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 63b65b646fbcfa9ea0f724d1d3e1ac22ba28f638..28d4cf0cef70f437dc4271f82975d09dc55125ea 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2693,23 +2693,23 @@ void gpiod_free_commit(struct gpio_desc *desc)
if (guard.gc->free)
guard.gc->free(guard.gc, gpiod_hwgpio(desc));

- clear_bit(GPIOD_FLAG_ACTIVE_LOW, &flags);
- clear_bit(GPIOD_FLAG_REQUESTED, &flags);
- clear_bit(GPIOD_FLAG_OPEN_DRAIN, &flags);
- clear_bit(GPIOD_FLAG_OPEN_SOURCE, &flags);
- clear_bit(GPIOD_FLAG_PULL_UP, &flags);
- clear_bit(GPIOD_FLAG_PULL_DOWN, &flags);
- clear_bit(GPIOD_FLAG_BIAS_DISABLE, &flags);
- clear_bit(GPIOD_FLAG_EDGE_RISING, &flags);
- clear_bit(GPIOD_FLAG_EDGE_FALLING, &flags);
- clear_bit(GPIOD_FLAG_EVENT_CLOCK_REALTIME, &flags);
- clear_bit(GPIOD_FLAG_EVENT_CLOCK_HTE, &flags);
- clear_bit(GPIOD_FLAG_IS_HOGGED, &flags);
#ifdef CONFIG_OF_DYNAMIC
WRITE_ONCE(desc->hog, NULL);
#endif
desc_set_label(desc, NULL);
- WRITE_ONCE(desc->flags, flags);
+ gpiod_update_flags(desc,
+ BIT(GPIOD_FLAG_ACTIVE_LOW) |
+ BIT(GPIOD_FLAG_REQUESTED) |
+ BIT(GPIOD_FLAG_OPEN_DRAIN) |
+ BIT(GPIOD_FLAG_OPEN_SOURCE) |
+ BIT(GPIOD_FLAG_PULL_UP) |
+ BIT(GPIOD_FLAG_PULL_DOWN) |
+ BIT(GPIOD_FLAG_BIAS_DISABLE) |
+ BIT(GPIOD_FLAG_EDGE_RISING) |
+ BIT(GPIOD_FLAG_EDGE_FALLING) |
+ BIT(GPIOD_FLAG_EVENT_CLOCK_REALTIME) |
+ BIT(GPIOD_FLAG_EVENT_CLOCK_HTE) |
+ BIT(GPIOD_FLAG_IS_HOGGED), 0);
#ifdef CONFIG_GPIO_CDEV
WRITE_ONCE(desc->debounce_period_us, 0);
#endif

--
2.47.3