[PATCH v1 1/3] misc: fastrpc: initialise channel refcount before exposing the misc device

From: Jianping Li

Date: Wed Oct 07 2026 - 04:45:46 EST


fastrpc_device_register() calls misc_register(), which immediately makes
/dev/fastrpc-<domain> visible to userspace. However, kref_init() on the
channel context refcount only runs after the whole domain switch()
completes, several statements later.

Any process that opens the device in that window reaches
fastrpc_device_open() -> fastrpc_channel_ctx_get() -> kref_get() on a
refcount that has never been initialised and is still zero, which
refcount_t correctly reports as a use-after-free:

refcount_t: addition on 0; use-after-free.
WARNING: CPU: 0 PID: 760 at lib/refcount.c:25 refcount_warn_saturate+0x120/0x144
CPU: 0 UID: 0 PID: 760 Comm: adsprpcd
Call trace:
refcount_warn_saturate
fastrpc_device_open [fastrpc]
misc_open
chrdev_open
do_dentry_open
vfs_open
path_openat
do_filp_open
do_sys_openat2
__arm64_sys_openat

This is easy to hit after a subsystem restart, when the DSP daemon
reopens the device as soon as it observes the PD coming back up, racing
with fastrpc_rpmsg_probe() on the rebind path.

Move kref_init() ahead of the device registration so the refcount is
always valid by the time the node is reachable from userspace.

Fixes: f6f9279f2bf0 ("misc: fastrpc: Add Qualcomm fastrpc basic driver model")
Signed-off-by: Jianping Li <jianping.li@xxxxxxxxxxxxxxxx>
---
drivers/misc/fastrpc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index af18ff1992ee..05b2e7e4ad3b 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -2599,6 +2599,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
data->poll_mode_supported = soc_data->poll_mode_supported ||
of_machine_get_match(fastrpc_poll_supported_machines);

+ kref_init(&data->refcount);
switch (domain_id) {
case ADSP_DOMAIN_ID:
case MDSP_DOMAIN_ID:
@@ -2626,7 +2627,6 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
goto err_free_data;
}

- kref_init(&data->refcount);
atomic_set(&data->ctx_seq, 0);

rdev->dma_mask = &data->dma_mask;
--
2.43.0