From ef22e806ae3b6728df20b5a6c07aa5a01db38e7b Mon Sep 17 00:00:00 2001 From: Zhongqiu Han Date: Wed, 17 Dec 2025 14:51:08 +0800 Subject: [PATCH 1/6] rpmsg: Replace sprintf() with sysfs_emit() in sysfs show Use sysfs_emit() instead of sprintf() in sysfs attribute show functions. sysfs_emit() is the recommended API for sysfs output as it provides buffer overflow protection and proper formatting. No functional changes. Signed-off-by: Zhongqiu Han Reviewed-by: Chris Lew Link: https://lore.kernel.org/r/20251217065112.18392-2-zhongqiu.han@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_smd.c | 2 +- drivers/rpmsg/rpmsg_char.c | 6 +++--- drivers/rpmsg/rpmsg_core.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index 3ac863f400ec..7dbe1c6efe41 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c @@ -1460,7 +1460,7 @@ static ssize_t rpmsg_name_show(struct device *dev, { struct qcom_smd_edge *edge = to_smd_edge(dev); - return sprintf(buf, "%s\n", edge->name); + return sysfs_emit(buf, "%s\n", edge->name); } static DEVICE_ATTR_RO(rpmsg_name); diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index bff5aefee212..68a0e5e93744 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -371,7 +371,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, { struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", eptdev->chinfo.name); + return sysfs_emit(buf, "%s\n", eptdev->chinfo.name); } static DEVICE_ATTR_RO(name); @@ -380,7 +380,7 @@ static ssize_t src_show(struct device *dev, struct device_attribute *attr, { struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", eptdev->chinfo.src); + return sysfs_emit(buf, "%d\n", eptdev->chinfo.src); } static DEVICE_ATTR_RO(src); @@ -389,7 +389,7 @@ static ssize_t dst_show(struct device *dev, struct device_attribute *attr, { struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", eptdev->chinfo.dst); + return sysfs_emit(buf, "%d\n", eptdev->chinfo.dst); } static DEVICE_ATTR_RO(dst); diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index c56f69c22e42..cfe7d04381ee 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -348,7 +348,7 @@ field##_show(struct device *dev, \ { \ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ \ - return sprintf(buf, format_string, rpdev->path); \ + return sysfs_emit(buf, format_string, rpdev->path); \ } \ static DEVICE_ATTR_RO(field); @@ -368,7 +368,7 @@ static ssize_t modalias_show(struct device *dev, if (len != -ENODEV) return len; - return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); + return sysfs_emit(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); } static DEVICE_ATTR_RO(modalias); From 31a42429e043cde8a94da8872e002781a7068827 Mon Sep 17 00:00:00 2001 From: Zhongqiu Han Date: Wed, 17 Dec 2025 14:51:09 +0800 Subject: [PATCH 2/6] rpmsg: core: Fix incorrect return value documentation The unregister_rpmsg_driver() function has a void return type but the documentation incorrectly described a return value. Remove the incorrect return value documentation to match the actual function signature. Fixes: bcabbccabffe ("rpmsg: add virtio-based remote processor messaging bus") Signed-off-by: Zhongqiu Han Reviewed-by: Chris Lew Link: https://lore.kernel.org/r/20251217065112.18392-3-zhongqiu.han@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/staging/rpmsg.rst | 1 - drivers/rpmsg/rpmsg_core.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/Documentation/staging/rpmsg.rst b/Documentation/staging/rpmsg.rst index 42bac1149d9d..63612b7ee120 100644 --- a/Documentation/staging/rpmsg.rst +++ b/Documentation/staging/rpmsg.rst @@ -212,7 +212,6 @@ be probed with. unregisters an rpmsg driver from the rpmsg bus. user should provide a pointer to a previously-registered rpmsg_driver struct. -Returns 0 on success, and an appropriate error value on failure. Typical usage diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index cfe7d04381ee..04bfcc75f05b 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -598,8 +598,6 @@ EXPORT_SYMBOL(__register_rpmsg_driver); /** * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus * @rpdrv: pointer to a struct rpmsg_driver - * - * Return: 0 on success, and an appropriate error value on failure. */ void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv) { From ad6d7795388dbfc8a4c8980b49ad43648b1d6efe Mon Sep 17 00:00:00 2001 From: Sudeepgoud Patil Date: Thu, 11 Dec 2025 14:18:34 +0530 Subject: [PATCH 3/6] rpmsg: glink: Replace strcpy() with strscpy() Replace strcpy() with the safer strscpy() to address unsafe API usage warnings[1] from static analysis tools, as strcpy() performs no bounds checking on the destination buffer. [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strcpy Signed-off-by: Sudeepgoud Patil Signed-off-by: Vishnu Santhosh Reviewed-by: Chris Lew Link: https://lore.kernel.org/r/20251211-rpmsg-glink-strcpy-replace-v1-1-be06308e5724@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index d9d4468e4cbd..022b4bcb40d6 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -501,7 +501,7 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink, req->cmd = cpu_to_le16(GLINK_CMD_OPEN); req->param1 = cpu_to_le16(channel->lcid); req->param2 = cpu_to_le32(name_len); - strcpy(req->data, channel->name); + strscpy(req->data, channel->name, GLINK_NAME_SIZE); trace_qcom_glink_cmd_open_tx(glink->label, channel->name, channel->lcid, channel->rcid); From 1f9c2897afb0fe86c1fdf4f5e23c5fb8f7442f6d Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 6 Apr 2026 09:59:50 +0530 Subject: [PATCH 4/6] rpmsg: char: Check for ongoing chrdev destroy A null pointer panic is observed when stopping a remoteproc and closing a character device using the RPMSG_DESTROY_EPT_IOCTL. There is a race where each context calls rpmsg_chrdev_eptdev_destroy(). The thread that runs second will call cdev_device_del() for a second time, which fails because the first call already removed the device from sysfs. Add a check at the beginning of destroy and exit early if the destroy call has already been done. [ 26.654130] Call trace [ 26.656658] kernfs_find_and_get_ns+0x28/0x8 [ 26.661140] sysfs_unmerge_group+0x2c/0x7 [ 26.665357] dpm_sysfs_remove+0x38/0x8 [ 26.669305] device_del+0xa4/0x3e [ 26.672811] cdev_device_del+0x28/0x7 [ 26.676675] rpmsg_chrdev_eptdev_destroy+0x68/0x98 [ 26.682765] rpmsg_eptdev_ioctl+0x130/0x11c8 [ 26.688318] __arm64_sys_ioctl+0xb4/0x10 [ 26.692448] invoke_syscall+0x50/0x12 [ 26.696312] el0_svc_common.constprop.0+0xc8/0xf [ 26.701151] do_el0_svc+0x24/0x3 [ 26.704570] el0_svc+0x40/0x17 [ 26.707810] el0t_64_sync_handler+0x120/0x13 [ 26.712288] el0t_64_sync+0x1a0/0x1a Signed-off-by: Chris Lew Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260406-rpmsg-char-fix-chrdev-destroy-race-v1-1-7317434fa246@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/rpmsg_char.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index 68a0e5e93744..550fda217da4 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -79,6 +79,11 @@ int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data) struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev); mutex_lock(&eptdev->ept_lock); + if (!eptdev->rpdev) { + mutex_unlock(&eptdev->ept_lock); + return 0; + } + eptdev->rpdev = NULL; if (eptdev->ept) { /* The default endpoint is released by the rpmsg core */ From 5a5a48e788e02fd8a8eb7188ce440572d6c12418 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Thu, 4 Jun 2026 14:12:53 +0530 Subject: [PATCH 5/6] rpmsg: glink: fix deadlock in endpoint destroy during driver detach MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During driver detach, the device core holds the device mutex throughout the driver's remove callback chain. When the rpmsg endpoint is destroyed as part of that teardown, the GLINK endpoint destroy implementation attempts to unregister the underlying rpmsg device. That unregistration calls device_del(), which tries to re-acquire the same device mutex already held higher up the stack, causing rmmod to hang indefinitely. The deadlock manifests with the following call chain: [<0>] device_del+0x44/0x414  <- tries to acquire same mutex [<0>] device_unregister+0x18/0x34 [<0>] rpmsg_unregister_device+0x28/0x4c [<0>] qcom_glink_remove_rpmsg_device+0x70/0xc0 [<0>] qcom_glink_destroy_ept+0x58/0xbc [<0>] rpmsg_dev_remove+0x50/0x60 [<0>] device_remove+0x4c/0x80 [<0>] device_release_driver_internal+0x1cc/0x228 <- acquires device mutex [<0>] driver_detach+0x4c/0x98 [<0>] bus_remove_driver+0x6c/0xbc [<0>] driver_unregister+0x30/0x60 [<0>] unregister_rpmsg_driver+0x10/0x1c [<0>] fastrpc_exit+0x28/0x38 [fastrpc] [<0>] __arm64_sys_delete_module+0x1b8/0x294 [<0>] invoke_syscall+0x48/0x10c [<0>] el0_svc_common.constprop.0+0xc0/0xe0 [<0>] do_el0_svc+0x1c/0x28 [<0>] el0_svc+0x34/0x108 [<0>] el0t_64_sync_handler+0xa0/0xe4 [<0>] el0t_64_sync+0x198/0x19c The rpmsg device unregistration inside endpoint destroy is redundant. In both contexts where endpoint destruction is triggered: - Driver detach path: the driver core already tears down the rpmsg device. - Channel close path: the rpmsg device is already unregistered before endpoint destruction is reached. Remove the redundant unregistration to fix the deadlock. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Tested-by: Bjorn Andersson Fixes: a53e356df548 ("rpmsg: glink: fix rpmsg device leak") Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260604-rpmsg-glink-fix-deadlock-destroy-ept-v1-1-b8a54ad1e4fd@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 022b4bcb40d6..55793fc18293 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1418,9 +1418,6 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) channel->ept.cb = NULL; spin_unlock_irqrestore(&channel->recv_lock, flags); - /* Decouple the potential rpdev from the channel */ - qcom_glink_remove_rpmsg_device(glink, channel); - qcom_glink_send_close_req(glink, channel); } From 786439ad58763e04b91bc2ec5f590e463939f197 Mon Sep 17 00:00:00 2001 From: Chunkai Deng Date: Thu, 18 Jun 2026 00:16:39 -0700 Subject: [PATCH 6/6] rpmsg: glink: smem: order FIFO read after availability check glink_smem_rx_peek() reads the RX FIFO payload after the caller has determined data is available via glink_smem_rx_avail(), which reads the remote-updated head index. A control dependency between the head read and the subsequent payload read does not order the two loads, so the CPU may speculatively read the FIFO before observing the head update and consume stale data the remote has not yet published. Add rmb() in glink_smem_rx_peek() before the memcpy_fromio() so the availability (head) read is ordered ahead of the FIFO payload read, matching the consumer pattern in Documentation/core-api/circular-buffers.rst. Fixes: caf989c350e8 ("rpmsg: glink: Introduce glink smem based transport") Cc: stable@vger.kernel.org Signed-off-by: Chunkai Deng Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260618-rpmsg-glink-smem-mb-v1-1-68a026453a69@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_smem.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 62adc4db2317..35bb03e67ae8 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -103,6 +103,13 @@ static void glink_smem_rx_peek(struct qcom_glink_pipe *np, if (tail >= pipe->native.length) tail -= pipe->native.length; + /* + * Order the availability (head) read in glink_smem_rx_avail() + * against the FIFO payload read below, so APPS never consumes + * stale data the remote has not yet published. + */ + rmb(); + len = min_t(size_t, count, pipe->native.length - tail); if (len) memcpy_fromio(data, pipe->fifo + tail, len);