* [PATCH v4 0/3] misc: fastrpc: fix ADSP duplicate session creation
@ 2026-08-26 13:25 Vinayak Katoch
2026-08-26 13:25 ` [PATCH v4 1/3] misc: fastrpc: iterate CB nodes manually instead of of_platform_populate Vinayak Katoch
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Vinayak Katoch @ 2026-08-26 13:25 UTC (permalink / raw)
To: Srinivas Kandagatla, Amol Maheshwari, Arnd Bergmann,
Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, dri-devel, linux-kernel, Bharath Kumar,
Chenna Kesava Raju, Ekansh Gupta, devicetree, Vinayak Katoch,
Krzysztof Kozlowski
For ADSP, only a limited number of FastRPC context banks (CBs) are
available. Each CB supports a single session, which means only a few
processes can run on ADSP simultaneously. If all sessions are consumed
by fastrpc daemons, no session remains available when a user application
starts, causing the application to fail.
To work around this, some DT set:
qcom,nsessions = <5>;
which duplicated sessions inline during context bank initialisation.
Upstream feedback indicated that this policy does not belong in DT and
should be handled at the driver level instead.
This series iterates over CB child nodes directly and synchronously,
replacing of_platform_populate(), and moves the ADSP session duplication
to the driver. The qcom,nsessions binding is deprecated in the same
series.
Signed-off-by: Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
---
Changes in v4:
- Rebased on latest linux-next (a8406e6c0b79, 2026-08-25)
- Link to v3: https://lore.kernel.org/r/20260824-dup-sessions-v3-0-4b019def4e0b@oss.qualcomm.com
Changes in v3:
- Add patch to fix async probe race with of_platform_populate().
- Rename fastrpc_cb_probe() to fastrpc_cb_init().
- Reorder series: sync fix, nsessions, binding.
- Collect Reviewed-by tags.
- Link to v2: https://lore.kernel.org/r/20260708-dup-sessions-v2-0-da40f9c98a2b@oss.qualcomm.com
Changes in v2:
- Added patch to deprecate the qcom,nsessions dt-binding.
- Kept the logic unchanged; only split into two patches.
- Link to v1: https://lore.kernel.org/r/20260609-dup-sessions-v1-1-26934abb9fa3@oss.qualcomm.com
---
Vinayak Katoch (3):
misc: fastrpc: iterate CB nodes manually instead of of_platform_populate
misc: fastrpc: move ADSP duplicate session creation to the driver
dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions
.../devicetree/bindings/misc/qcom,fastrpc.yaml | 2 +
drivers/misc/fastrpc.c | 112 +++++++++------------
2 files changed, 48 insertions(+), 66 deletions(-)
---
base-commit: a8406e6c0b793ce0788019683837c40855b55995
change-id: 20260609-dup-sessions-ea2acaac1994
Best regards,
--
Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 1/3] misc: fastrpc: iterate CB nodes manually instead of of_platform_populate
2026-08-26 13:25 [PATCH v4 0/3] misc: fastrpc: fix ADSP duplicate session creation Vinayak Katoch
@ 2026-08-26 13:25 ` Vinayak Katoch
2026-08-26 13:45 ` sashiko-bot
2026-08-26 13:25 ` [PATCH v4 2/3] misc: fastrpc: move ADSP duplicate session creation to the driver Vinayak Katoch
2026-08-26 13:25 ` [PATCH v4 3/3] dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions Vinayak Katoch
2 siblings, 1 reply; 7+ messages in thread
From: Vinayak Katoch @ 2026-08-26 13:25 UTC (permalink / raw)
To: Srinivas Kandagatla, Amol Maheshwari, Arnd Bergmann,
Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, dri-devel, linux-kernel, Bharath Kumar,
Chenna Kesava Raju, Ekansh Gupta, devicetree, Vinayak Katoch
of_platform_populate() only guarantees that child devices are registered,
not that their probes have completed before it returns. This creates a
window where fastrpc_cb_init() may not have run for all context bank
nodes, leaving the channel context partially initialised.
Iterate over the child device tree nodes directly, initialising each
qcom,fastrpc-compute-cb device synchronously. This ensures all context
banks are fully initialised before fastrpc_rpmsg_probe() returns. Since
fastrpc_cb_driver is no longer needed as an independent platform driver,
remove it along with its match table and remove callback. Set
OF_POPULATED_BUS on the rpmsg node so that of_platform_depopulate()
correctly removes the manually created CB devices on teardown.
Signed-off-by: Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
---
drivers/misc/fastrpc.c | 83 ++++++++++++++++++--------------------------------
1 file changed, 29 insertions(+), 54 deletions(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index d4fac2caca86..a153107d0085 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -2363,7 +2363,7 @@ static const struct file_operations fastrpc_fops = {
.compat_ioctl = fastrpc_device_ioctl,
};
-static int fastrpc_cb_probe(struct platform_device *pdev)
+static int fastrpc_cb_init(struct platform_device *pdev)
{
struct fastrpc_channel_ctx *cctx;
struct fastrpc_session_ctx *sess;
@@ -2385,7 +2385,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
spin_lock_irqsave(&cctx->lock, flags);
if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
spin_unlock_irqrestore(&cctx->lock, flags);
- dev_err(&pdev->dev, "too many sessions\n");
+ dev_err(dev, "too many sessions\n");
return -ENOSPC;
}
dma_bits = cctx->soc_data->dma_addr_bits_default;
@@ -2419,38 +2419,6 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
return 0;
}
-static void fastrpc_cb_remove(struct platform_device *pdev)
-{
- struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent);
- struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev);
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&cctx->lock, flags);
- for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
- if (cctx->session[i].sid == sess->sid) {
- cctx->session[i].valid = false;
- cctx->sesscount--;
- }
- }
- spin_unlock_irqrestore(&cctx->lock, flags);
-}
-
-static const struct of_device_id fastrpc_match_table[] = {
- { .compatible = "qcom,fastrpc-compute-cb" },
- { }
-};
-
-static struct platform_driver fastrpc_cb_driver = {
- .probe = fastrpc_cb_probe,
- .remove = fastrpc_cb_remove,
- .driver = {
- .name = "qcom,fastrpc-cb",
- .of_match_table = fastrpc_match_table,
- .suppress_bind_attrs = true,
- },
-};
-
static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ctx *cctx,
bool is_secured, const char *domain)
{
@@ -2642,12 +2610,29 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
data->rpdev = rpdev;
dev_set_drvdata(&rpdev->dev, data);
- err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
- if (err)
- goto err_deregister_fdev;
+ of_node_set_flag(rdev->of_node, OF_POPULATED_BUS);
+
+ for_each_available_child_of_node_scoped(rdev->of_node, np) {
+ struct platform_device *pdev;
+
+ if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb"))
+ continue;
+
+ pdev = of_platform_device_create(np, NULL, rdev);
+ if (!pdev) {
+ err = -EINVAL;
+ goto err_depopulate;
+ }
+
+ err = fastrpc_cb_init(pdev);
+ if (err)
+ goto err_depopulate;
+ }
return 0;
+err_depopulate:
+ of_platform_depopulate(rdev);
err_deregister_fdev:
if (data->fdevice)
misc_deregister(&data->fdevice->miscdev);
@@ -2677,6 +2662,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
struct fastrpc_buf *buf, *b;
struct fastrpc_user *user;
unsigned long flags;
+ int i;
/* No invocations past this point */
spin_lock_irqsave(&cctx->lock, flags);
@@ -2697,6 +2683,11 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
if (cctx->remote_heap)
fastrpc_buf_free(cctx->remote_heap);
+ spin_lock_irqsave(&cctx->lock, flags);
+ for (i = 0; i < FASTRPC_MAX_SESSIONS; i++)
+ cctx->session[i].valid = false;
+ spin_unlock_irqrestore(&cctx->lock, flags);
+
of_platform_depopulate(&rpdev->dev);
fastrpc_channel_ctx_put(cctx);
@@ -2786,28 +2777,12 @@ static struct rpmsg_driver fastrpc_driver = {
static int fastrpc_init(void)
{
- int ret;
-
- ret = platform_driver_register(&fastrpc_cb_driver);
- if (ret < 0) {
- pr_err("fastrpc: failed to register cb driver\n");
- return ret;
- }
-
- ret = register_rpmsg_driver(&fastrpc_driver);
- if (ret < 0) {
- pr_err("fastrpc: failed to register rpmsg driver\n");
- platform_driver_unregister(&fastrpc_cb_driver);
- return ret;
- }
-
- return 0;
+ return register_rpmsg_driver(&fastrpc_driver);
}
module_init(fastrpc_init);
static void fastrpc_exit(void)
{
- platform_driver_unregister(&fastrpc_cb_driver);
unregister_rpmsg_driver(&fastrpc_driver);
}
module_exit(fastrpc_exit);
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 2/3] misc: fastrpc: move ADSP duplicate session creation to the driver
2026-08-26 13:25 [PATCH v4 0/3] misc: fastrpc: fix ADSP duplicate session creation Vinayak Katoch
2026-08-26 13:25 ` [PATCH v4 1/3] misc: fastrpc: iterate CB nodes manually instead of of_platform_populate Vinayak Katoch
@ 2026-08-26 13:25 ` Vinayak Katoch
2026-08-26 13:40 ` sashiko-bot
2026-08-26 13:25 ` [PATCH v4 3/3] dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions Vinayak Katoch
2 siblings, 1 reply; 7+ messages in thread
From: Vinayak Katoch @ 2026-08-26 13:25 UTC (permalink / raw)
To: Srinivas Kandagatla, Amol Maheshwari, Arnd Bergmann,
Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, dri-devel, linux-kernel, Bharath Kumar,
Chenna Kesava Raju, Ekansh Gupta, devicetree, Vinayak Katoch
For ADSP, only a limited number of FastRPC context banks (CBs) are
available. Each CB supports a single session, which means only a few
processes can run on ADSP simultaneously. If all sessions are consumed
by fastrpc daemons, no session remains available when a user application
starts, causing the application to fail.
To work around this, qcom,nsessions = <5> was set in DT to duplicate
sessions inline during fastrpc_cb_init(). This policy does not belong
in DT and should be handled at the driver level instead.
Remove the qcom,nsessions DT property read and the per-CB duplication
logic from fastrpc_cb_init(). After all context banks have been
initialised in fastrpc_rpmsg_probe(), append FASTRPC_DUP_SESSIONS (4)
copies of the last session for the ADSP domain.
Signed-off-by: Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
---
drivers/misc/fastrpc.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index a153107d0085..98a61b8b9013 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -34,6 +34,7 @@
#define CDSP_DOMAIN_ID (3)
#define GDSP_DOMAIN_ID (4)
#define FASTRPC_MAX_SESSIONS 14
+#define FASTRPC_DUP_SESSIONS 4
#define FASTRPC_MAX_VMIDS 16
#define FASTRPC_ALIGN 128
#define FASTRPC_MAX_FDLIST 16
@@ -2368,7 +2369,6 @@ static int fastrpc_cb_init(struct platform_device *pdev)
struct fastrpc_channel_ctx *cctx;
struct fastrpc_session_ctx *sess;
struct device *dev = &pdev->dev;
- int i, sessions = 0;
unsigned long flags;
u32 dma_bits;
u32 sid = 0;
@@ -2378,7 +2378,6 @@ static int fastrpc_cb_init(struct platform_device *pdev)
if (!cctx)
return -EINVAL;
- of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
if (of_property_read_u32(dev->of_node, "reg", &sid))
dev_info(dev, "FastRPC Session ID not specified in DT\n");
@@ -2399,16 +2398,6 @@ static int fastrpc_cb_init(struct platform_device *pdev)
if (cctx->domain_id == CDSP_DOMAIN_ID)
dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
- if (sessions > 0) {
- struct fastrpc_session_ctx *dup_sess;
-
- for (i = 1; i < sessions; i++) {
- if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
- break;
- dup_sess = &cctx->session[cctx->sesscount++];
- memcpy(dup_sess, sess, sizeof(*dup_sess));
- }
- }
spin_unlock_irqrestore(&cctx->lock, flags);
rc = dma_set_mask(dev, DMA_BIT_MASK(dma_bits));
if (rc) {
@@ -2629,6 +2618,22 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
goto err_depopulate;
}
+ if (data->domain_id == ADSP_DOMAIN_ID && data->sesscount > 0) {
+ struct fastrpc_session_ctx *last_sess;
+ struct fastrpc_session_ctx *dup_sess;
+ unsigned long flags;
+
+ spin_lock_irqsave(&data->lock, flags);
+ last_sess = &data->session[data->sesscount - 1];
+ for (i = 0; i < FASTRPC_DUP_SESSIONS; i++) {
+ if (data->sesscount >= FASTRPC_MAX_SESSIONS)
+ break;
+ dup_sess = &data->session[data->sesscount++];
+ memcpy(dup_sess, last_sess, sizeof(*dup_sess));
+ }
+ spin_unlock_irqrestore(&data->lock, flags);
+ }
+
return 0;
err_depopulate:
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 3/3] dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions
2026-08-26 13:25 [PATCH v4 0/3] misc: fastrpc: fix ADSP duplicate session creation Vinayak Katoch
2026-08-26 13:25 ` [PATCH v4 1/3] misc: fastrpc: iterate CB nodes manually instead of of_platform_populate Vinayak Katoch
2026-08-26 13:25 ` [PATCH v4 2/3] misc: fastrpc: move ADSP duplicate session creation to the driver Vinayak Katoch
@ 2026-08-26 13:25 ` Vinayak Katoch
2026-08-26 13:40 ` sashiko-bot
2 siblings, 1 reply; 7+ messages in thread
From: Vinayak Katoch @ 2026-08-26 13:25 UTC (permalink / raw)
To: Srinivas Kandagatla, Amol Maheshwari, Arnd Bergmann,
Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, dri-devel, linux-kernel, Bharath Kumar,
Chenna Kesava Raju, Ekansh Gupta, devicetree, Vinayak Katoch,
Krzysztof Kozlowski
The qcom,nsessions property was used to duplicate FastRPC sessions
inline during context bank initialisation. Session duplication is now
handled at the driver level, making this DT property redundant. Mark
it deprecated.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
---
Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml
index 49d2a5e8ba39..e945c8ba75e3 100644
--- a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml
+++ b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml
@@ -101,8 +101,10 @@ patternProperties:
qcom,nsessions:
$ref: /schemas/types.yaml#/definitions/uint32
default: 1
+ deprecated: true
description: >
A value indicating how many sessions can share this context bank.
+ Session duplication is now handled by the driver.
required:
- compatible
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v4 2/3] misc: fastrpc: move ADSP duplicate session creation to the driver
2026-08-26 13:25 ` [PATCH v4 2/3] misc: fastrpc: move ADSP duplicate session creation to the driver Vinayak Katoch
@ 2026-08-26 13:40 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-26 13:40 UTC (permalink / raw)
To: Vinayak Katoch; +Cc: dri-devel, robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Session duplication non-atomicity introduces a race window allowing a permanent leak of duplicated sessions.
Pre-existing issues:
- [Critical] Premature character device registration allows unprivileged userspace to free the channel context during probe, leading to a Use-After-Free.
- [High] Dangling pointer in rdev->dma_mask after probe failure leads to use-after-free.
- [High] Dangling pointer to child platform devices after fastrpc_rpmsg_remove leads to UAF during DMA allocations.
--
commit a8d47b7ddf0527e896eee27dcc31b42059209d4c
Author: Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
misc: fastrpc: move ADSP duplicate session creation to the driver
For ADSP, only a limited number of FastRPC context banks (CBs) are
available. Each CB supports a single session, which means only a few
processes can run on ADSP simultaneously. If all sessions are consumed
by fastrpc daemons, no session remains available when a user application
starts, causing the application to fail.
To work around this, qcom,nsessions = <5> was set in DT to duplicate
sessions inline during fastrpc_cb_init(). This policy does not belong
in DT and should be handled at the driver level instead.
Remove the qcom,nsessions DT property read and the per-CB duplication
logic from fastrpc_cb_init(). After all context banks have been
initialised in fastrpc_rpmsg_probe(), append FASTRPC_DUP_SESSIONS (4)
copies of the last session for the ADSP domain.
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index a153107d00853..98a61b8b90131 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
[ ... ]
> @@ -2399,16 +2398,6 @@ static int fastrpc_cb_init(struct platform_device *pdev)
> if (cctx->domain_id == CDSP_DOMAIN_ID)
> dma_bits = cctx->soc_data->dma_addr_bits_cdsp;
>
> - if (sessions > 0) {
> - struct fastrpc_session_ctx *dup_sess;
> -
> - for (i = 1; i < sessions; i++) {
> - if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
> - break;
> - dup_sess = &cctx->session[cctx->sesscount++];
> - memcpy(dup_sess, sess, sizeof(*dup_sess));
> - }
> - }
> spin_unlock_irqrestore(&cctx->lock, flags);
[Severity: High]
Does moving this duplication logic out of fastrpc_cb_init() introduce a
race window?
The lock is released here, but duplication now happens later in
fastrpc_rpmsg_probe(). In the meantime, userspace can open the device
and allocate this session, setting its used flag to true.
[Severity: High]
This isn't a bug introduced by this patch, but earlier in
fastrpc_cb_init(), a weak pointer to the child platform device is stored
in the session context without incrementing its reference count:
sess->dev = dev;
During module unbind, fastrpc_rpmsg_remove() destroys these child
devices via of_platform_depopulate(). However, active userspace file
descriptors are not closed.
Could subsequent ioctls on an open fastrpc file descriptor pass this
dangling sess->dev pointer to dma_alloc_coherent(), causing a
use-after-free in the DMA API?
> rc = dma_set_mask(dev, DMA_BIT_MASK(dma_bits));
> if (rc) {
[ ... ]
> @@ -2629,6 +2618,22 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
> goto err_depopulate;
> }
>
> + if (data->domain_id == ADSP_DOMAIN_ID && data->sesscount > 0) {
> + struct fastrpc_session_ctx *last_sess;
> + struct fastrpc_session_ctx *dup_sess;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&data->lock, flags);
> + last_sess = &data->session[data->sesscount - 1];
> + for (i = 0; i < FASTRPC_DUP_SESSIONS; i++) {
> + if (data->sesscount >= FASTRPC_MAX_SESSIONS)
> + break;
> + dup_sess = &data->session[data->sesscount++];
> + memcpy(dup_sess, last_sess, sizeof(*dup_sess));
[Severity: High]
If a racing userspace process has already allocated last_sess and set
its used flag to true, does this memcpy() blindly copy the used = true
state to the newly duplicated sessions?
Since these duplicated sessions are not attached to any open file
descriptor, it seems they will never be freed on close(), permanently
leaking ADSP sessions.
> + }
> + spin_unlock_irqrestore(&data->lock, flags);
> + }
> +
> return 0;
>
> err_depopulate:
[Severity: Critical]
This isn't a bug introduced by this patch, but earlier in
fastrpc_rpmsg_probe(), the character device is registered and exposed
to userspace before critical data structures are initialized:
err = fastrpc_device_register(rdev, data, secure_dsp, domain);
...
kref_init(&data->refcount);
If unprivileged userspace immediately opens the device before sessions
are added, fastrpc_device_open() fails to find a session and calls
fastrpc_channel_ctx_put().
Does this underflow the 0-initialized refcount and free the data struct
while fastrpc_rpmsg_probe() is still executing, leading to a
use-after-free?
[Severity: High]
This isn't a bug introduced by this patch, but earlier in
fastrpc_rpmsg_probe(), the device's DMA mask pointer is assigned to a
field inside the dynamically allocated data structure:
rdev->dma_mask = &data->dma_mask;
If the probe subsequently fails, the err_free_data path frees data but
fails to clear rdev->dma_mask. Since the rpmsg_device outlives the
probe failure, could subsequent DMA operations or teardown checks by
the driver core dereference this dangling pointer and cause a
use-after-free?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260826-dup-sessions-v4-0-35555d2bfed4@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 3/3] dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions
2026-08-26 13:25 ` [PATCH v4 3/3] dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions Vinayak Katoch
@ 2026-08-26 13:40 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-26 13:40 UTC (permalink / raw)
To: Vinayak Katoch; +Cc: conor+dt, devicetree, robh, dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Child context bank devices are never attached to their IOMMU domains, breaking DMA mapping and causing SMMU faults.
Pre-existing issues:
- [High] Unconditional `kfree(data)` on the probe error path causes a Use-After-Free if userspace opened the device.
--
commit e928c95aa5ca7ef57a0d4943351ae2891fcf2b1c
Author: Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
misc: fastrpc: iterate CB nodes manually instead of of_platform_populate
This commit replaces of_platform_populate() with manual iteration over child
device tree nodes to initialize qcom,fastrpc-compute-cb devices synchronously.
It aims to ensure all context banks are fully initialized before
fastrpc_rpmsg_probe() returns by directly calling fastrpc_cb_init().
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index d4fac2caca867..a153107d00853 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -2363,7 +2363,7 @@ static const struct file_operations fastrpc_fops = {
> .compat_ioctl = fastrpc_device_ioctl,
> };
>
> -static int fastrpc_cb_probe(struct platform_device *pdev)
> +static int fastrpc_cb_init(struct platform_device *pdev)
> {
> struct fastrpc_channel_ctx *cctx;
> struct fastrpc_session_ctx *sess;
[ ... ]
> @@ -2642,12 +2610,29 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
> data->rpdev = rpdev;
> dev_set_drvdata(&rpdev->dev, data);
>
> - err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
> - if (err)
> - goto err_deregister_fdev;
> + of_node_set_flag(rdev->of_node, OF_POPULATED_BUS);
> +
> + for_each_available_child_of_node_scoped(rdev->of_node, np) {
> + struct platform_device *pdev;
> +
> + if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb"))
> + continue;
> +
> + pdev = of_platform_device_create(np, NULL, rdev);
> + if (!pdev) {
> + err = -EINVAL;
> + goto err_depopulate;
> + }
> +
> + err = fastrpc_cb_init(pdev);
[Severity: High]
By replacing driver core matching with manual of_platform_device_create()
followed by fastrpc_cb_init() in fastrpc_rpmsg_probe(), does this child
device skip the driver core's platform probe path?
It appears this manual initialization skips IOMMU and DMA configuration
logic, such as of_dma_configure(), which normally runs during probe.
Since these context bank devices are no longer bound to a platform driver,
they are never attached to their SMMU domains. Could this result in SMMU
translation faults and a failure of DSP context bank DMA operations when a
DSP invocation attempts DMA?
> + if (err)
> + goto err_depopulate;
> + }
>
> return 0;
>
> +err_depopulate:
> + of_platform_depopulate(rdev);
> err_deregister_fdev:
> if (data->fdevice)
> misc_deregister(&data->fdevice->miscdev);
[Severity: High]
This is a pre-existing issue, but if fastrpc_cb_init() fails, this error path
jumps to err_depopulate and eventually reaches err_free_data in
fastrpc_rpmsg_probe():
err_free_data:
kfree(data);
return err;
Since fastrpc_device_register() makes the misc device available to userspace
earlier in the probe, what happens if userspace has already called open()
and incremented the data reference count via fastrpc_channel_ctx_get()?
Does this unconditional kfree(data) ignore active references held by open
file descriptors, leading to a use-after-free condition if userspace later
performs an ioctl() on the still-open file descriptor?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260826-dup-sessions-v4-0-35555d2bfed4@oss.qualcomm.com?part=3
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 1/3] misc: fastrpc: iterate CB nodes manually instead of of_platform_populate
2026-08-26 13:25 ` [PATCH v4 1/3] misc: fastrpc: iterate CB nodes manually instead of of_platform_populate Vinayak Katoch
@ 2026-08-26 13:45 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-26 13:45 UTC (permalink / raw)
To: Vinayak Katoch; +Cc: robh, conor+dt, dri-devel, devicetree
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Critical Use-After-Free and uninitialized state exposure when `fastrpc_rpmsg_probe` fails after prematurely registering the misc device.
- [High] Preexisting Use-After-Free in `fastrpc_rpmsg_probe()` where `rdev->dma_mask` is left pointing to freed memory on error paths.
- [High] Use-After-Free of context bank devices (`sess->dev`) upon fastrpc channel removal due to missing device references.
--
commit e928c95aa5ca7ef57a0d4943351ae2891fcf2b1c
Author: Vinayak Katoch <vinayak.katoch@oss.qualcomm.com>
misc: fastrpc: iterate CB nodes manually instead of of_platform_populate
of_platform_populate() only guarantees that child devices are registered,
not that their probes have completed before it returns. This creates a
window where fastrpc_cb_init() may not have run for all context bank
nodes, leaving the channel context partially initialised.
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index d4fac2caca867..a153107d00853 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -2363,7 +2363,7 @@ static const struct file_operations fastrpc_fops = {
> .compat_ioctl = fastrpc_device_ioctl,
> };
>
> -static int fastrpc_cb_probe(struct platform_device *pdev)
> +static int fastrpc_cb_init(struct platform_device *pdev)
> {
> struct fastrpc_channel_ctx *cctx;
> struct fastrpc_session_ctx *sess;
> @@ -2385,7 +2385,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
> spin_lock_irqsave(&cctx->lock, flags);
> if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
> spin_unlock_irqrestore(&cctx->lock, flags);
> - dev_err(&pdev->dev, "too many sessions\n");
> + dev_err(dev, "too many sessions\n");
> return -ENOSPC;
> }
> dma_bits = cctx->soc_data->dma_addr_bits_default;
[Severity: High]
This is a pre-existing issue, but does fastrpc_cb_init() save the child
device pointer without holding a reference to it?
If sess->dev is assigned without get_device(dev), and fastrpc_rpmsg_remove()
calls of_platform_depopulate(), the child platform devices are destroyed.
Since active file descriptors aren't revoked, could an active ioctl later
call fastrpc_dmabuf_alloc() and invoke dma_alloc_coherent() on fl->sctx->dev,
using the dangling pointer and leading to a use-after-free?
[ ... ]
> @@ -2642,12 +2610,29 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
> data->rpdev = rpdev;
> dev_set_drvdata(&rpdev->dev, data);
>
> - err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
> - if (err)
> - goto err_deregister_fdev;
> + of_node_set_flag(rdev->of_node, OF_POPULATED_BUS);
> +
> + for_each_available_child_of_node_scoped(rdev->of_node, np) {
> + struct platform_device *pdev;
> +
> + if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb"))
> + continue;
> +
> + pdev = of_platform_device_create(np, NULL, rdev);
> + if (!pdev) {
> + err = -EINVAL;
> + goto err_depopulate;
> + }
> +
> + err = fastrpc_cb_init(pdev);
> + if (err)
> + goto err_depopulate;
[Severity: Critical]
This is a pre-existing issue, but is it possible that this error path leads
to a use-after-free and uninitialized state exposure?
Earlier in fastrpc_rpmsg_probe(), fastrpc_device_register() is called, which
makes the misc device available to userspace. A userspace program can then
open the device, acquiring a reference to the data structure.
If fastrpc_cb_init() fails here, the code jumps to err_depopulate, and
eventually calls kfree(data).
Since userspace could already have an open file descriptor pointing to data,
would this kfree() result in a use-after-free when subsequent ioctls or
close() are called?
[Severity: High]
This isn't a bug introduced by this patch, but does the same error path leave
rdev->dma_mask pointing to freed memory?
Earlier in fastrpc_rpmsg_probe(), rdev->dma_mask is redirected to point
to the dynamically allocated &data->dma_mask.
If this probe function fails and frees data via kfree(data), the rpmsg
device remains in the system unbound.
Will a userspace read of /sys/devices/.../dma_mask_bits trigger a read from
freed memory through dma_mask_bits_show() since rdev->dma_mask wasn't
restored to its original value?
> + }
>
> return 0;
>
> +err_depopulate:
> + of_platform_depopulate(rdev);
> err_deregister_fdev:
> if (data->fdevice)
> misc_deregister(&data->fdevice->miscdev);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260826-dup-sessions-v4-0-35555d2bfed4@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-26 13:45 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26 13:25 [PATCH v4 0/3] misc: fastrpc: fix ADSP duplicate session creation Vinayak Katoch
2026-08-26 13:25 ` [PATCH v4 1/3] misc: fastrpc: iterate CB nodes manually instead of of_platform_populate Vinayak Katoch
2026-08-26 13:45 ` sashiko-bot
2026-08-26 13:25 ` [PATCH v4 2/3] misc: fastrpc: move ADSP duplicate session creation to the driver Vinayak Katoch
2026-08-26 13:40 ` sashiko-bot
2026-08-26 13:25 ` [PATCH v4 3/3] dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions Vinayak Katoch
2026-08-26 13:40 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox