FAILED: Patch "rpmsg: core: fix race in driver_override_show() and use core helper" failed to apply to 6.1-stable tree
Subsystems (2)
Sasha Levin
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 42023d4b6d2661a40ee2dcf7e1a3528a35c638ca Mon Sep 17 00:00:00 2001
From: Gui-Dong Han <[email protected]>
Date: Wed, 3 Dec 2025 01:49:48 +0800
Subject: [PATCH] rpmsg: core: fix race in driver_override_show() and use core
helper
The driver_override_show function reads the driver_override string without holding the device_lock. However, the store function modifies and frees the string while holding the device_lock. This creates a race condition where the string can be freed by the store function while being read by the show function, leading to a use-after-free.
To fix this, replace the rpmsg_string_attr macro with explicit show and store functions. The new driver_override_store uses the standard driver_set_override helper. Since the introduction of driver_set_override, the comments in include/linux/rpmsg.h have stated that this helper must be used to set or clear driver_override, but the implementation was not updated until now.
Because driver_set_override modifies and frees the string while holding the device_lock, the new driver_override_show now correctly holds the device_lock during the read operation to prevent the race.
Additionally, since rpmsg_string_attr has only ever been used for driver_override, removing the macro simplifies the code.
--- drivers/rpmsg/rpmsg_core.c | 66 ++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 39 deletions(-)
drivers/rpmsg/rpmsg_core.c +27 -39
@@ -352,50 +352,38 @@ field##_show(struct device *dev, \ } \static DEVICE_ATTR_RO (field); -#define rpmsg_string_attr (field, member) \ -static ssize_t \ -field##_store(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t sz) \ -{ \ - struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ - const char *old; \ - char *new; \ - \ - new = kstrndup(buf, sz, GFP_KERNEL); \ - if (!new) \ - return -ENOMEM; \ - new[strcspn(new, "\n")] = '\0'; \ - \ - device_lock(dev); \ - old = rpdev->member; \ - if (strlen(new)) { \ - rpdev->member = new; \ - } else { \ - kfree(new); \ - rpdev->member = NULL; \ - } \ - device_unlock(dev); \ - \ - kfree(old); \ - \ - return sz; \ -} \ -static ssize_t \ -field##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ - \ - return sprintf(buf, "%s\n", rpdev->member); \ -} \ -static DEVICE_ATTR_RW(field) -/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ rpmsg_show_attr (name, id.name,"%s\n" );rpmsg_show_attr (src, src,"0x%x\n" );rpmsg_show_attr (dst, dst,"0x%x\n" );rpmsg_show_attr (announce, announce ?"true" :"false" ,"%s\n" ); -rpmsg_string_attr (driver_override, driver_override); + +static ssize_t driver_override_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +struct rpmsg_device *rpdev =to_rpmsg_device (dev); +int ret; + + ret =driver_set_override (dev, &rpdev->driver_override, buf, count); +if (ret) +return ret; + +return count; +} + +static ssize_t driver_override_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct rpmsg_device *rpdev =to_rpmsg_device (dev); +ssize_t len; + +device_lock (dev); + len =sysfs_emit (buf,"%s\n" , rpdev->driver_override); +device_unlock (dev); +return len; +} +static DEVICE_ATTR_RW (driver_override);static ssize_t modalias_show (struct device *dev,struct device_attribute *attr,char *buf)
Signature · 1 line
2.51.0