]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
misc: fastrpc: Fix NULL pointer dereference in rpmsg callback
authorMukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Sat, 30 May 2026 20:45:27 +0000 (21:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 5 Jun 2026 15:20:51 +0000 (17:20 +0200)
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: f6f9279f2bf0 ("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>
drivers/misc/fastrpc.c

index cca7489605c56e43c14225b8ca73185d8e60f3d2..47cf3d21b51db86a314a21f0f2f0a7e2bf8aa7d6 100644 (file)
@@ -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);