On Wed, 3 Jun 2026 at 21:52, Runyu Xiao <[email protected]> wrote: > > RPMSG still keeps driver_override in bus-private storage. > > That private pointer can be updated from the sysfs driver_override > attribute, and also from rpmsg_register_device_override(). Both paths > replace the pointer and can free the old value. > > However, driver_match_device() can call rpmsg_dev_match() from > __driver_attach() without holding the device lock, and rpmsg_dev_match() > still dereferences that private pointer directly. > > This leaves the match path racing with concurrent driver_override > updates, with the usual risk of comparing against freed memory. > > Switch rpmsg to the driver-core driver_override infrastructure. This > removes the private storage, uses device_match_driver_override() for the > locked read in rpmsg_dev_match(), and converts > rpmsg_register_device_override() to device_set_driver_override() so the > in-kernel override path uses the same core-managed storage. With that > storage now owned by struct device, drop the remaining rpmsg transport > release-path frees of rpdev->driver_override as well. > > Link: > https://lore.kernel.org/driver-core/[email protected]/ > Fixes: 39e47767ec9b ("rpmsg: Add driver_override device attribute for > rpmsg_device") > Cc: [email protected] > Signed-off-by: Runyu Xiao <[email protected]> > --- > drivers/rpmsg/qcom_glink_native.c | 2 -- > drivers/rpmsg/rpmsg_core.c | 41 ++++++-------------------------------- > drivers/rpmsg/virtio_rpmsg_bus.c | 1 - > include/linux/rpmsg.h | 4 ----
For the bottom 3: Reviewed-by: Mathieu Poirier <[email protected]> > 4 files changed, 6 insertions(+), 42 deletions(-) > > diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c > index e7f7831d37f8..11d3007db5cd 100644 > --- a/drivers/rpmsg/rpmsg_core.c > +++ b/drivers/rpmsg/rpmsg_core.c > @@ -358,33 +358,6 @@ 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"); > > -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) > { > @@ -405,7 +378,6 @@ static struct attribute *rpmsg_dev_attrs[] = { > &dev_attr_dst.attr, > &dev_attr_src.attr, > &dev_attr_announce.attr, > - &dev_attr_driver_override.attr, > NULL, > }; > ATTRIBUTE_GROUPS(rpmsg_dev); > @@ -424,9 +396,11 @@ static int rpmsg_dev_match(struct device *dev, const > struct device_driver *drv) > const struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv); > const struct rpmsg_device_id *ids = rpdrv->id_table; > unsigned int i; > + int ret; > > - if (rpdev->driver_override) > - return !strcmp(rpdev->driver_override, drv->name); > + ret = device_match_driver_override(dev, drv); > + if (ret >= 0) > + return ret; > > if (ids) > for (i = 0; ids[i].name[0]; i++) > @@ -533,6 +507,7 @@ static void rpmsg_dev_remove(struct device *dev) > > static const struct bus_type rpmsg_bus = { > .name = "rpmsg", > + .driver_override = true, > .match = rpmsg_dev_match, > .dev_groups = rpmsg_dev_groups, > .uevent = rpmsg_uevent, > @@ -560,9 +535,7 @@ int rpmsg_register_device_override(struct rpmsg_device > *rpdev, > > device_initialize(dev); > if (driver_override) { > - ret = driver_set_override(dev, &rpdev->driver_override, > - driver_override, > - strlen(driver_override)); > + ret = device_set_driver_override(dev, driver_override); > if (ret) { > dev_err(dev, "device_set_override failed: %d\n", ret); > put_device(dev); > @@ -573,8 +546,6 @@ int rpmsg_register_device_override(struct rpmsg_device > *rpdev, > ret = device_add(dev); > if (ret) { > dev_err(dev, "device_add failed: %d\n", ret); > - kfree(rpdev->driver_override); > - rpdev->driver_override = NULL; > put_device(dev); > } > > diff --git a/drivers/rpmsg/qcom_glink_native.c > b/drivers/rpmsg/qcom_glink_native.c > index 401a4ece0c97..d9d4468e4cbd 100644 > --- a/drivers/rpmsg/qcom_glink_native.c > +++ b/drivers/rpmsg/qcom_glink_native.c > @@ -1626,7 +1626,6 @@ static void qcom_glink_rpdev_release(struct device *dev) > { > struct rpmsg_device *rpdev = to_rpmsg_device(dev); > > - kfree(rpdev->driver_override); > kfree(rpdev); > } > > @@ -1862,7 +1861,6 @@ static void qcom_glink_device_release(struct device > *dev) > > /* Release qcom_glink_alloc_channel() reference */ > kref_put(&channel->refcount, qcom_glink_channel_release); > - kfree(rpdev->driver_override); > kfree(rpdev); > } > > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c > b/drivers/rpmsg/virtio_rpmsg_bus.c > index 5ae15111fb4f..1b8bb05924af 100644 > --- a/drivers/rpmsg/virtio_rpmsg_bus.c > +++ b/drivers/rpmsg/virtio_rpmsg_bus.c > @@ -374,7 +374,6 @@ static void virtio_rpmsg_release_device(struct device > *dev) > struct rpmsg_device *rpdev = to_rpmsg_device(dev); > struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); > > - kfree(rpdev->driver_override); > kfree(vch); > } > > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h > index 83266ce14642..2e40eb54155e 100644 > --- a/include/linux/rpmsg.h > +++ b/include/linux/rpmsg.h > @@ -41,9 +41,6 @@ struct rpmsg_channel_info { > * rpmsg_device - device that belong to the rpmsg bus > * @dev: the device struct > * @id: device id (used to match between rpmsg drivers and devices) > - * @driver_override: driver name to force a match; do not set directly, > - * because core frees it; use driver_set_override() to > - * set or clear it. > * @src: local address > * @dst: destination address > * @ept: the rpmsg endpoint of this channel > @@ -53,7 +50,6 @@ struct rpmsg_channel_info { > struct rpmsg_device { > struct device dev; > struct rpmsg_device_id id; > - const char *driver_override; > u32 src; > u32 dst; > struct rpmsg_endpoint *ept; > -- > 2.34.1

