From: Tzung-Bi Shih <tzungbi@kernel.org>
To: Arnd Bergmann <arnd@arndb.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Bartosz Golaszewski <brgl@kernel.org>,
Linus Walleij <linusw@kernel.org>
Cc: Benson Leung <bleung@chromium.org>,
tzungbi@kernel.org, linux-kernel@vger.kernel.org,
chrome-platform@lists.linux.dev, driver-core@lists.linux.dev,
linux-doc@vger.kernel.org, linux-gpio@vger.kernel.org,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Jonathan Corbet <corbet@lwn.net>, Shuah Khan <shuah@kernel.org>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Wolfram Sang <wsa+renesas@sang-engineering.com>,
Jason Gunthorpe <jgg@nvidia.com>, Johan Hovold <johan@kernel.org>,
"Paul E . McKenney" <paulmck@kernel.org>
Subject: [PATCH v10 4/9] gpio: cdev: Leverage revocable for accessing struct gpio_chip
Date: Fri, 8 May 2026 18:54:43 +0800 [thread overview]
Message-ID: <20260508105448.31799-5-tzungbi@kernel.org> (raw)
In-Reply-To: <20260508105448.31799-1-tzungbi@kernel.org>
Struct gpio_device now provides a revocable provider to the underlying
struct gpio_chip. Leverage revocable for accessing the struct
gpio_chip.
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
---
v10:
- No changes.
v9: https://lore.kernel.org/all/20260427135841.96266-5-tzungbi@kernel.org
- New to the series.
- Rename "chip_rp" -> "chip_rev".
v4 - v8:
- Doesn't exist.
v3: https://lore.kernel.org/all/20260213092958.864411-9-tzungbi@kernel.org
- Change revocable API usages accordingly.
v2: https://lore.kernel.org/all/20260203061059.975605-9-tzungbi@kernel.org
- Change usages accordingly after applying
https://lore.kernel.org/all/20260129143733.45618-4-tzungbi@kernel.org.
- Preserve a local storage for `struct revocable`.
- Combine multiple patches (see "v1:").
- Fix a race condition reported in
https://lore.kernel.org/all/CAMRc=McDaipt85OHm0MksLkuf6E79dY1uNSqqbcJnoQTUs81Pw@mail.gmail.com/
and analyzed in
https://lore.kernel.org/all/aXEEUWwkxHZzCnaI@tzungbi-laptop/.
In v1, the blocking_notifier_chain_unregister() will be skipped if the
chip has been removed, leading an UAF in gpiolib_cdev_unregister().
In v2, it won't skip blocking_notifier_chain_unregister().
v1:
- https://lore.kernel.org/all/20260116081036.352286-14-tzungbi@kernel.org
- https://lore.kernel.org/all/20260116081036.352286-15-tzungbi@kernel.org
- https://lore.kernel.org/all/20260116081036.352286-16-tzungbi@kernel.org
- https://lore.kernel.org/all/20260116081036.352286-17-tzungbi@kernel.org
- https://lore.kernel.org/all/20260116081036.352286-18-tzungbi@kernel.org
---
drivers/gpio/gpiolib-cdev.c | 68 ++++++++++++++-----------------------
1 file changed, 26 insertions(+), 42 deletions(-)
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index f36b7c06996d..d8a7ccb406a5 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -22,6 +22,7 @@
#include <linux/overflow.h>
#include <linux/pinctrl/consumer.h>
#include <linux/poll.h>
+#include <linux/revocable.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/string.h>
@@ -210,11 +211,9 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd,
DECLARE_BITMAP(vals, GPIOHANDLES_MAX);
unsigned int i;
int ret;
+ struct gpio_chip *gc;
- guard(srcu)(&lh->gdev->srcu);
-
- if (!rcu_access_pointer(lh->gdev->chip))
- return -ENODEV;
+ revocable_try_access_or_return(&lh->gdev->chip_rev, gc);
switch (cmd) {
case GPIOHANDLE_GET_LINE_VALUES_IOCTL:
@@ -1432,11 +1431,9 @@ static long linereq_ioctl(struct file *file, unsigned int cmd,
{
struct linereq *lr = file->private_data;
void __user *ip = (void __user *)arg;
+ struct gpio_chip *gc;
- guard(srcu)(&lr->gdev->srcu);
-
- if (!rcu_access_pointer(lr->gdev->chip))
- return -ENODEV;
+ revocable_try_access_or_return(&lr->gdev->chip_rev, gc);
switch (cmd) {
case GPIO_V2_LINE_GET_VALUES_IOCTL:
@@ -1463,10 +1460,10 @@ static __poll_t linereq_poll(struct file *file,
{
struct linereq *lr = file->private_data;
__poll_t events = 0;
+ struct gpio_chip *gc;
- guard(srcu)(&lr->gdev->srcu);
-
- if (!rcu_access_pointer(lr->gdev->chip))
+ revocable_try_access_with(&lr->gdev->chip_rev, gc);
+ if (!gc)
return EPOLLHUP | EPOLLERR;
poll_wait(file, &lr->wait, wait);
@@ -1485,11 +1482,9 @@ static ssize_t linereq_read(struct file *file, char __user *buf,
struct gpio_v2_line_event le;
ssize_t bytes_read = 0;
int ret;
+ struct gpio_chip *gc;
- guard(srcu)(&lr->gdev->srcu);
-
- if (!rcu_access_pointer(lr->gdev->chip))
- return -ENODEV;
+ revocable_try_access_or_return(&lr->gdev->chip_rev, gc);
if (count < sizeof(le))
return -EINVAL;
@@ -1759,10 +1754,10 @@ static __poll_t lineevent_poll(struct file *file,
{
struct lineevent_state *le = file->private_data;
__poll_t events = 0;
+ struct gpio_chip *gc;
- guard(srcu)(&le->gdev->srcu);
-
- if (!rcu_access_pointer(le->gdev->chip))
+ revocable_try_access_with(&le->gdev->chip_rev, gc);
+ if (!gc)
return EPOLLHUP | EPOLLERR;
poll_wait(file, &le->wait, wait);
@@ -1797,11 +1792,9 @@ static ssize_t lineevent_read(struct file *file, char __user *buf,
ssize_t bytes_read = 0;
ssize_t ge_size;
int ret;
+ struct gpio_chip *gc;
- guard(srcu)(&le->gdev->srcu);
-
- if (!rcu_access_pointer(le->gdev->chip))
- return -ENODEV;
+ revocable_try_access_or_return(&le->gdev->chip_rev, gc);
/*
* When compatible system call is being used the struct gpioevent_data,
@@ -1879,11 +1872,9 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd,
struct lineevent_state *le = file->private_data;
void __user *ip = (void __user *)arg;
struct gpiohandle_data ghd;
+ struct gpio_chip *gc;
- guard(srcu)(&le->gdev->srcu);
-
- if (!rcu_access_pointer(le->gdev->chip))
- return -ENODEV;
+ revocable_try_access_or_return(&le->gdev->chip_rev, gc);
/*
* We can get the value for an event line but not set it,
@@ -2385,12 +2376,10 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct gpio_chardev_data *cdev = file->private_data;
struct gpio_device *gdev = cdev->gdev;
void __user *ip = (void __user *)arg;
-
- guard(srcu)(&gdev->srcu);
+ struct gpio_chip *gc;
/* We fail any subsequent ioctl():s when the chip is gone */
- if (!rcu_access_pointer(gdev->chip))
- return -ENODEV;
+ revocable_try_access_or_return(&gdev->chip_rev, gc);
/* Fill in the struct and pass to userspace */
switch (cmd) {
@@ -2448,12 +2437,9 @@ static void lineinfo_changed_func(struct work_struct *work)
* Pin functions are in general much more static and while it's
* not 100% bullet-proof, it's good enough for most cases.
*/
- scoped_guard(srcu, &ctx->gdev->srcu) {
- gc = srcu_dereference(ctx->gdev->chip, &ctx->gdev->srcu);
- if (gc &&
- !pinctrl_gpio_can_use_line(gc, ctx->chg.info.offset))
+ revocable_try_access_or_skip_scoped(&ctx->gdev->chip_rev, gc)
+ if (!pinctrl_gpio_can_use_line(gc, ctx->chg.info.offset))
ctx->chg.info.flags |= GPIO_V2_LINE_FLAG_USED;
- }
}
ret = kfifo_in_spinlocked(&ctx->cdev->events, &ctx->chg, 1,
@@ -2534,10 +2520,10 @@ static __poll_t lineinfo_watch_poll(struct file *file,
{
struct gpio_chardev_data *cdev = file->private_data;
__poll_t events = 0;
+ struct gpio_chip *gc;
- guard(srcu)(&cdev->gdev->srcu);
-
- if (!rcu_access_pointer(cdev->gdev->chip))
+ revocable_try_access_with(&cdev->gdev->chip_rev, gc);
+ if (!gc)
return EPOLLHUP | EPOLLERR;
poll_wait(file, &cdev->wait, pollt);
@@ -2557,11 +2543,9 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
ssize_t bytes_read = 0;
int ret;
size_t event_size;
+ struct gpio_chip *gc;
- guard(srcu)(&cdev->gdev->srcu);
-
- if (!rcu_access_pointer(cdev->gdev->chip))
- return -ENODEV;
+ revocable_try_access_or_return(&cdev->gdev->chip_rev, gc);
#ifndef CONFIG_GPIO_CDEV_V1
event_size = sizeof(struct gpio_v2_line_info_changed);
--
2.51.0
next prev parent reply other threads:[~2026-05-08 10:55 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-08 10:54 [PATCH v10 0/9] drivers/base: Introduce revocable Tzung-Bi Shih
2026-05-08 10:54 ` [PATCH v10 1/9] revocable: Revocable resource management Tzung-Bi Shih
2026-05-11 13:16 ` Bartosz Golaszewski
2026-05-12 8:12 ` Tzung-Bi Shih
2026-05-08 10:54 ` [PATCH v10 2/9] revocable: Add KUnit test cases Tzung-Bi Shih
2026-05-11 13:10 ` Bartosz Golaszewski
2026-05-12 8:12 ` Tzung-Bi Shih
2026-05-08 10:54 ` [PATCH v10 3/9] gpio: Add revocable provider handle for struct gpio_chip Tzung-Bi Shih
2026-05-08 10:54 ` Tzung-Bi Shih [this message]
2026-05-08 10:54 ` [PATCH v10 5/9] gpio: Remove gpio_chip_guard by using revocable Tzung-Bi Shih
2026-05-08 10:54 ` [PATCH v10 6/9] gpio: Leverage revocable for accessing struct gpio_chip Tzung-Bi Shih
2026-05-08 10:54 ` [PATCH v10 7/9] gpio: Remove unused `chip` and `srcu` in struct gpio_device Tzung-Bi Shih
2026-05-11 13:18 ` Bartosz Golaszewski
2026-05-12 8:13 ` Tzung-Bi Shih
2026-05-12 10:41 ` Bartosz Golaszewski
2026-05-08 10:54 ` [PATCH v10 8/9] platform/chrome: Protect cros_ec_device lifecycle with revocable Tzung-Bi Shih
2026-05-08 11:53 ` Jason Gunthorpe
2026-05-11 13:19 ` Bartosz Golaszewski
2026-05-12 8:36 ` Laurent Pinchart
2026-05-14 3:33 ` Tzung-Bi Shih
2026-05-14 16:02 ` Jason Gunthorpe
2026-05-15 8:28 ` Tzung-Bi Shih
2026-05-08 10:54 ` [PATCH v10 9/9] platform/chrome: cros_ec_chardev: Consume cros_ec_device via revocable Tzung-Bi Shih
2026-05-11 13:17 ` [PATCH v10 0/9] drivers/base: Introduce revocable Bartosz Golaszewski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260508105448.31799-5-tzungbi@kernel.org \
--to=tzungbi@kernel.org \
--cc=arnd@arndb.de \
--cc=bleung@chromium.org \
--cc=brgl@kernel.org \
--cc=chrome-platform@lists.linux.dev \
--cc=corbet@lwn.net \
--cc=dakr@kernel.org \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=jgg@nvidia.com \
--cc=johan@kernel.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linusw@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=paulmck@kernel.org \
--cc=rafael@kernel.org \
--cc=shuah@kernel.org \
--cc=wsa+renesas@sang-engineering.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.