summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuho Choi <dbgh9129@gmail.com>2026-06-30 15:27:14 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-17 14:54:39 +0200
commit67b6fc084b034a91c3ec7907a3fed89a2450f30b (patch)
treeba43879693e52b28ab7ac03ae0ca7c06e2056160
parent7bf924f96d6ef4dc7700e7adf984e3b90492c435 (diff)
downloadlinux-next-67b6fc084b034a91c3ec7907a3fed89a2450f30b.tar.gz
linux-next-67b6fc084b034a91c3ec7907a3fed89a2450f30b.zip
uio: Fix stale info pointer in failed registration path
After device_add(), the UIO device is visible to userspace and /dev/uioX can be opened. If a later setup step fails, __uio_register_device() unwinds the device but leaves idev->info pointing at the caller-owned struct uio_info. That is unsafe when an opener races with the failed registration path. The open file keeps a reference to the uio_device, while the caller sees registration failure and may free its struct uio_info. Later file operations can then follow idev->info and dereference freed memory. Handle post-device_add() failures like unregister: remove UIO attributes while the info pointer is still valid, then clear idev->info under info_lock and wake existing waiters/async users before removing the device and minor. This makes already-open file descriptors observe the same "device gone" state as normal uio_unregister_device(). Fixes: a93e7b331568 ("uio: Prevent device destruction while fds are open") Signed-off-by: Yuho Choi <dbgh9129@gmail.com> Link: https://patch.msgid.link/20260630192714.1867170-1-dbgh9129@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/uio/uio.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 1e4ade78ed84..e77d5e7d5f64 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -1057,6 +1057,11 @@ int __uio_register_device(struct module *owner,
err_request_irq:
uio_dev_del_attributes(idev);
err_uio_dev_add_attributes:
+ mutex_lock(&idev->info_lock);
+ idev->info = NULL;
+ mutex_unlock(&idev->info_lock);
+ wake_up_interruptible(&idev->wait);
+ kill_fasync(&idev->async_queue, SIGIO, POLL_HUP);
device_del(&idev->dev);
err_device_create:
uio_free_minor(idev->minor);