[PATCH] media: rc: fix use-after-free of rc_map.name on register error path

From: YuanZhe Liu

Date: Wed Oct 14 2026 - 05:36:25 EST


If rc_register_device() fails after device_add() - for example when
ir_raw_event_register() cannot create its kthread - the unwind path
frees the keymap via rc_free_rx_device() while the device is still
visible in sysfs, and never clears dev->registered.

A userspace reader of the uevent attribute then enters
rc_dev_uevent(), passes the registered check under dev->lock and
dereferences the already freed dev->rc_map.name:

BUG: KASAN: slab-use-after-free in string+0x483/0x4c0
lib/vsprintf.c:737
Read of size 1 at addr ffff888007ca9d80
rc_dev_uevent+0xd7/0x1d0 drivers/media/rc/rc-main.c:1628
dev_uevent+0x28d/0x570 drivers/base/core.c:2709
uevent_show+0x1af/0x380 drivers/base/core.c:2756

Fix it the same way rc_unregister_device() does: take dev->lock,
close the input device if it is still open and clear
dev->registered before releasing any resources. rc_dev_uevent()
then observes the cleared flag and returns -ENODEV instead of
reading rc_map.name.

Fixes: f56928abaa6d ("[media] rc-core: cleanup rc_register_device")
Cc: stable@xxxxxxxxxxxxxxx
Co-developed-by: Bin Yu <byu@xxxxxxxxxxxxx>
Signed-off-by: Bin Yu <byu@xxxxxxxxxxxxx>
Co-developed-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
Signed-off-by: Cheng Wen <wencheng@xxxxxxxxxxxxx>
Signed-off-by: YuanZhe Liu <25031212351@xxxxxxxxxxxxxxxxx>
---
drivers/media/rc/rc-main.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index dda3479ea3ad..903ae3d3441d 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1970,6 +1970,18 @@ int rc_register_device(struct rc_dev *dev)
return 0;

out_rx:
+ /*
+ * device_add() has succeeded, so userspace may read the uevent
+ * file and access rc_map.name. Take dev->lock and clear
+ * registered, as rc_unregister_device() does, before any
+ * resources are released below.
+ */
+ mutex_lock(&dev->lock);
+ if (dev->users && dev->close)
+ dev->close(dev);
+ dev->registered = false;
+ mutex_unlock(&dev->lock);
+
rc_free_rx_device(dev);
out_lirc:
if (dev->allowed_protocols != RC_PROTO_BIT_CEC)
--
2.34.1