Using the RPMSG_RELEASE_DEV_IOCTL is possible to remove any rpmsg device (such as the rpmsg ns or the rpmsg ctrldev). Add a new field to store the removability of the device. By default the rpmsg device can not be removed by user space. It is set to 1 by the rpmsg ctrl on RPMSG_CREATE_DEV_IOCTL request, but could also be set by an rpmsg driver during probe. Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@xxxxxxxxxxx> --- drivers/rpmsg/rpmsg_ctrl.c | 17 ++++++++++++++++- include/linux/rpmsg.h | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/rpmsg/rpmsg_ctrl.c b/drivers/rpmsg/rpmsg_ctrl.c index cb19e32d05e1..e93c6ec49038 100644 --- a/drivers/rpmsg/rpmsg_ctrl.c +++ b/drivers/rpmsg/rpmsg_ctrl.c @@ -74,6 +74,7 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd, struct rpmsg_endpoint_info eptinfo; struct rpmsg_channel_info chinfo; struct rpmsg_device *rpdev; + struct device *dev; int ret = 0; if (copy_from_user(&eptinfo, argp, sizeof(eptinfo))) @@ -95,11 +96,25 @@ static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd, if (!rpdev) { dev_err(&ctrldev->dev, "failed to create %s channel\n", chinfo.name); ret = -ENXIO; + } else { + /* Allow user space to release the device. */ + rpdev->us_removable = 1; } break; case RPMSG_RELEASE_DEV_IOCTL: - ret = rpmsg_release_channel(ctrldev->rpdev, &chinfo); + dev = rpmsg_find_device(ctrldev->rpdev->dev.parent, &chinfo); + if (!dev) + ret = -ENXIO; + + /* Verify that rpmsg device removal is allowed. */ + if (!ret) { + rpdev = to_rpmsg_device(dev); + if (!rpdev->us_removable) + ret = -EACCES; + } + if (!ret) + ret = rpmsg_release_channel(ctrldev->rpdev, &chinfo); if (ret) dev_err(&ctrldev->dev, "failed to release %s channel (%d)\n", chinfo.name, ret); diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index d97dcd049f18..3642aad1a789 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -47,6 +47,7 @@ struct rpmsg_channel_info { * @ept: the rpmsg endpoint of this channel * @announce: if set, rpmsg will announce the creation/removal of this channel * @little_endian: True if transport is using little endian byte representation + * @us_removable: True if userspace application has permission to remove the rpmsg device */ struct rpmsg_device { struct device dev; @@ -57,6 +58,7 @@ struct rpmsg_device { struct rpmsg_endpoint *ept; bool announce; bool little_endian; + bool us_removable; const struct rpmsg_device_ops *ops; }; -- 2.17.1