drivers/misc/fastrpc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
A NULL pointer dereference was observed on Hawi at boot when the DSP
sends a glink message before fastrpc_rpmsg_probe() has completed
initialization:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000178
pc : _raw_spin_lock_irqsave+0x34/0x8c
lr : fastrpc_rpmsg_callback+0x3c/0xcc [fastrpc]
...
Call trace:
_raw_spin_lock_irqsave+0x34/0x8c (P)
fastrpc_rpmsg_callback+0x3c/0xcc [fastrpc]
qcom_glink_native_rx+0x538/0x6a4
qcom_glink_smem_intr+0x14/0x24 [qcom_glink_smem]
The faulting address 0x178 corresponds to the lock variable inside
struct fastrpc_channel_ctx, confirming that cctx is NULL when
fastrpc_rpmsg_callback() attempts to take the spinlock.
There are two issues here. First, dev_set_drvdata() is called before
spin_lock_init() and idr_init(), leaving a window where the callback
can retrieve a valid cctx pointer but operate on an uninitialized
spinlock. Second, the rpmsg channel becomes live as soon as the driver
is bound, so fastrpc_rpmsg_callback() can fire before dev_set_drvdata()
is called at all, resulting in dev_get_drvdata() returning NULL.
Fix both issues by moving all cctx initialization ahead of
dev_set_drvdata() so the structure is fully initialized before it
becomes visible to the callback, and add a NULL check in
fastrpc_rpmsg_callback() as a guard against any remaining window.
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
drivers/misc/fastrpc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 1080f9acf70a..a1a54453bb7e 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -2431,7 +2431,6 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
kref_init(&data->refcount);
- dev_set_drvdata(&rpdev->dev, data);
rdev->dma_mask = &data->dma_mask;
dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32));
INIT_LIST_HEAD(&data->users);
@@ -2440,6 +2439,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
idr_init(&data->ctx_idr);
data->domain_id = domain_id;
data->rpdev = rpdev;
+ dev_set_drvdata(&rpdev->dev, data);
err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
if (err)
@@ -2513,6 +2513,9 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
if (len < sizeof(*rsp))
return -EINVAL;
+ if (!cctx)
+ return -ENODEV;
+
ctxid = ((rsp->ctx & FASTRPC_CTXID_MASK) >> 4);
spin_lock_irqsave(&cctx->lock, flags);
--
2.53.0
On Sat, Apr 18, 2026 at 01:31:46AM +0530, Mukesh Ojha wrote: > A NULL pointer dereference was observed on Hawi at boot when the DSP > sends a glink message before fastrpc_rpmsg_probe() has completed > initialization: > > Unable to handle kernel NULL pointer dereference at virtual address 0000000000000178 > pc : _raw_spin_lock_irqsave+0x34/0x8c > lr : fastrpc_rpmsg_callback+0x3c/0xcc [fastrpc] > ... > Call trace: > _raw_spin_lock_irqsave+0x34/0x8c (P) > fastrpc_rpmsg_callback+0x3c/0xcc [fastrpc] > qcom_glink_native_rx+0x538/0x6a4 > qcom_glink_smem_intr+0x14/0x24 [qcom_glink_smem] > > The faulting address 0x178 corresponds to the lock variable inside > struct fastrpc_channel_ctx, confirming that cctx is NULL when > fastrpc_rpmsg_callback() attempts to take the spinlock. > > There are two issues here. First, dev_set_drvdata() is called before > spin_lock_init() and idr_init(), leaving a window where the callback > can retrieve a valid cctx pointer but operate on an uninitialized > spinlock. Second, the rpmsg channel becomes live as soon as the driver > is bound, so fastrpc_rpmsg_callback() can fire before dev_set_drvdata() > is called at all, resulting in dev_get_drvdata() returning NULL. > > Fix both issues by moving all cctx initialization ahead of > dev_set_drvdata() so the structure is fully initialized before it > becomes visible to the callback, and add a NULL check in > fastrpc_rpmsg_callback() as a guard against any remaining window. > > Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com> Missing Fixes / cc:stable. Otherwise LGTM. As a side note, we really should rewrite that part into loop over subnodes instead of the of_populate and depending on subdevices to probe. -- With best wishes Dmitry
On Sat, Apr 18, 2026 at 01:35:00AM +0300, Dmitry Baryshkov wrote: > On Sat, Apr 18, 2026 at 01:31:46AM +0530, Mukesh Ojha wrote: > > A NULL pointer dereference was observed on Hawi at boot when the DSP > > sends a glink message before fastrpc_rpmsg_probe() has completed > > initialization: > > > > Unable to handle kernel NULL pointer dereference at virtual address 0000000000000178 > > pc : _raw_spin_lock_irqsave+0x34/0x8c > > lr : fastrpc_rpmsg_callback+0x3c/0xcc [fastrpc] > > ... > > Call trace: > > _raw_spin_lock_irqsave+0x34/0x8c (P) > > fastrpc_rpmsg_callback+0x3c/0xcc [fastrpc] > > qcom_glink_native_rx+0x538/0x6a4 > > qcom_glink_smem_intr+0x14/0x24 [qcom_glink_smem] > > > > The faulting address 0x178 corresponds to the lock variable inside > > struct fastrpc_channel_ctx, confirming that cctx is NULL when > > fastrpc_rpmsg_callback() attempts to take the spinlock. > > > > There are two issues here. First, dev_set_drvdata() is called before > > spin_lock_init() and idr_init(), leaving a window where the callback > > can retrieve a valid cctx pointer but operate on an uninitialized > > spinlock. Second, the rpmsg channel becomes live as soon as the driver > > is bound, so fastrpc_rpmsg_callback() can fire before dev_set_drvdata() > > is called at all, resulting in dev_get_drvdata() returning NULL. > > > > Fix both issues by moving all cctx initialization ahead of > > dev_set_drvdata() so the structure is fully initialized before it > > becomes visible to the callback, and add a NULL check in > > fastrpc_rpmsg_callback() as a guard against any remaining window. > > > > Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com> > > Missing Fixes / cc:stable. Otherwise LGTM. Will add in v2. > > As a side note, we really should rewrite that part into loop over > subnodes instead of the of_populate and depending on subdevices to > probe. > I get your point and worked on removing of_populate and removeing probe/remove while it can be simple init call from the parent probe. Let me refactor it. > -- > With best wishes > Dmitry -- -Mukesh Ojha
© 2016 - 2026 Red Hat, Inc.