Re: [PATCH v2 2/4] rpmsg: core: use generic driver_override infrastructure
From: Mathieu Poirier
Date: Mon Jun 08 2026 - 14:17:49 EST
On Wed, 3 Jun 2026 at 21:52, Runyu Xiao <runyu.xiao@xxxxxxxxxx> 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/DGRGTIRHA62X.3RY09D9SOK77P@xxxxxxxxxx/
> Fixes: 39e47767ec9b ("rpmsg: Add driver_override device attribute for rpmsg_device")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Runyu Xiao <runyu.xiao@xxxxxxxxxx>
> ---
> 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 <mathieu.poirier@xxxxxxxxxx>
> 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