Skip to content

Commit d4cd090

Browse files
author
Bartosz Golaszewski
committed
gpio: cdev: make sure the cdev fd is still active before emitting events
With the final call to fput() on a file descriptor, the release action may be deferred and scheduled on a work queue. The reference count of that descriptor is still zero and it must not be used. It's possible that a GPIO change, we want to notify the user-space about, happens AFTER the reference count on the file descriptor associated with the character device went down to zero but BEFORE the .release() callback was called from the workqueue and so BEFORE we unregistered from the notifier. Using the regular get_file() routine in this situation triggers the following warning: struct file::f_count incremented from zero; use-after-free condition present! So use the get_file_active() variant that will return NULL on file descriptors that have been or are being released. Fixes: 40b7c49 ("gpio: cdev: put emitting the line state events on a workqueue") Reported-by: Alexander Sverdlin <alexander.sverdlin@siemens.com> Closes: https://lore.kernel.org/all/5d605f7fc99456804911403102a4fe999a14cc85.camel@siemens.com/ Tested-by: Alexander Sverdlin <alexander.sverdlin@siemens.com> Link: https://lore.kernel.org/r/20251117-gpio-cdev-get-file-v1-1-28a16b5985b8@linaro.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
1 parent 6a23ae0 commit d4cd090

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

drivers/gpio/gpiolib-cdev.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,10 +2548,17 @@ static int lineinfo_changed_notify(struct notifier_block *nb,
25482548
container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb);
25492549
struct lineinfo_changed_ctx *ctx;
25502550
struct gpio_desc *desc = data;
2551+
struct file *fp;
25512552

25522553
if (!test_bit(gpio_chip_hwgpio(desc), cdev->watched_lines))
25532554
return NOTIFY_DONE;
25542555

2556+
/* Keep the file descriptor alive for the duration of the notification. */
2557+
fp = get_file_active(&cdev->fp);
2558+
if (!fp)
2559+
/* Chardev file descriptor was or is being released. */
2560+
return NOTIFY_DONE;
2561+
25552562
/*
25562563
* If this is called from atomic context (for instance: with a spinlock
25572564
* taken by the atomic notifier chain), any sleeping calls must be done
@@ -2575,8 +2582,6 @@ static int lineinfo_changed_notify(struct notifier_block *nb,
25752582
/* Keep the GPIO device alive until we emit the event. */
25762583
ctx->gdev = gpio_device_get(desc->gdev);
25772584
ctx->cdev = cdev;
2578-
/* Keep the file descriptor alive too. */
2579-
get_file(ctx->cdev->fp);
25802585

25812586
INIT_WORK(&ctx->work, lineinfo_changed_func);
25822587
queue_work(ctx->gdev->line_state_wq, &ctx->work);

0 commit comments

Comments
 (0)