diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-11 00:01:00 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-11 00:01:00 +0300 |
commit | cfb4be1a61200fbbd29f2699b11899789855bbe4 (patch) | |
tree | 046c7604ddce9b2e517211a13e6007c062bd98d8 /drivers/gpio/gpiolib-cdev.c | |
parent | f4345f05c0dfc73c617e66f3b809edb8ddd41075 (diff) | |
parent | ee0166b637a5e376118e9659e5b4148080f1d27e (diff) | |
download | linux-cfb4be1a61200fbbd29f2699b11899789855bbe4.tar.xz |
Merge tag 'gpio-fixes-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski:
"Some last-minute fixes for this release from the GPIO subsystem.
The first two address a regression in performance reported to me after
the conversion to using SRCU in GPIOLIB that was merged during the
v6.9 merge window. The second patch is not technically a fix but since
after the first one we no longer need to use a per-descriptor SRCU
struct, I think it's worth to simplify the code before it gets
released on Sunday.
The next two commits fix two memory issues: one use-after-free bug and
one instance of possibly leaking kernel stack memory to user-space.
Summary:
- fix a performance regression in GPIO requesting and releasing after
the conversion to SRCU
- fix a use-after-free bug due to a race-condition
- fix leaking stack memory to user-space in a GPIO uABI corner case"
* tag 'gpio-fixes-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
gpiolib: cdev: fix uninitialised kfifo
gpiolib: cdev: Fix use after free in lineinfo_changed_notify
gpiolib: use a single SRCU struct for all GPIO descriptors
gpiolib: fix the speed of descriptor label setting with SRCU
Diffstat (limited to 'drivers/gpio/gpiolib-cdev.c')
-rw-r--r-- | drivers/gpio/gpiolib-cdev.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index d09c7d728365..9dad67ea2597 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1193,6 +1193,8 @@ static int edge_detector_update(struct line *line, struct gpio_v2_line_config *lc, unsigned int line_idx, u64 edflags) { + u64 eflags; + int ret; u64 active_edflags = READ_ONCE(line->edflags); unsigned int debounce_period_us = gpio_v2_line_config_debounce_period(lc, line_idx); @@ -1204,6 +1206,18 @@ static int edge_detector_update(struct line *line, /* sw debounced and still will be...*/ if (debounce_period_us && READ_ONCE(line->sw_debounced)) { line_set_debounce_period(line, debounce_period_us); + /* + * ensure event fifo is initialised if edge detection + * is now enabled. + */ + eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS; + if (eflags && !kfifo_initialized(&line->req->events)) { + ret = kfifo_alloc(&line->req->events, + line->req->event_buffer_size, + GFP_KERNEL); + if (ret) + return ret; + } return 0; } @@ -2351,7 +2365,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, dflags = READ_ONCE(desc->flags); - scoped_guard(srcu, &desc->srcu) { + scoped_guard(srcu, &desc->gdev->desc_srcu) { label = gpiod_get_label(desc); if (label && test_bit(FLAG_REQUESTED, &dflags)) strscpy(info->consumer, label, @@ -2799,11 +2813,11 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file) struct gpio_chardev_data *cdev = file->private_data; struct gpio_device *gdev = cdev->gdev; - bitmap_free(cdev->watched_lines); blocking_notifier_chain_unregister(&gdev->device_notifier, &cdev->device_unregistered_nb); blocking_notifier_chain_unregister(&gdev->line_state_notifier, &cdev->lineinfo_changed_nb); + bitmap_free(cdev->watched_lines); gpio_device_put(gdev); kfree(cdev); |