mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
misc: fastrpc: Fix NULL pointer dereference in rpmsg callback
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.
Fixes: f6f9279f2b ("misc: fastrpc: Add Qualcomm fastrpc basic driver model")
Cc: stable@vger.kernel.org
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Reviewed-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
Link: https://patch.msgid.link/20260530204528.116920-4-srini@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
464c6ad2aa
commit
5401fb4fe1
@@ -2460,7 +2460,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);
|
||||
@@ -2469,6 +2468,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)
|
||||
@@ -2542,6 +2542,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);
|
||||
|
||||
Reference in New Issue
Block a user