Skip to content

Commit d7a3b33

Browse files
Jianping-Liquic-vkatoch
authored andcommitted
FROMLIST: misc: fastrpc: Allocate entire reserved memory for Audio PD in probe
Allocating and freeing Audio PD memory from userspace is unsafe because the kernel cannot reliably determine when the DSP has finished using the memory. Userspace may free buffers while they are still in use by the DSP, and remote free requests cannot be safely trusted. Additionally, the current implementation allows userspace to repeatedly grow the Audio PD heap, but does not support shrinking it. This can lead to unbounded memory usage over time, effectively causing a memory leak. Fix this by allocating the entire Audio PD reserved-memory region during rpmsg probe and tying its lifetime to the rpmsg channel. This removes userspace-controlled alloc/free and ensures that memory is reclaimed only when the DSP process is torn down. Link: https://lore.kernel.org/all/20260526111124.515-5-jianping.li@oss.qualcomm.com/ Fixes: 0871561 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Jianping Li <jianping.li@oss.qualcomm.com> Signed-off-by: Vinayak Katoch <vkatoch@qti.qualcomm.com>
1 parent 3845976 commit d7a3b33

1 file changed

Lines changed: 43 additions & 53 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 43 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ struct fastrpc_channel_ctx {
294294
struct kref refcount;
295295
/* Flag if dsp attributes are cached */
296296
bool valid_attributes;
297+
/* Flag if audio PD init mem was allocated */
298+
bool audio_init_mem;
297299
u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
298300
struct fastrpc_device *secure_fdevice;
299301
struct fastrpc_device *fdevice;
@@ -1459,15 +1461,16 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14591461
struct fastrpc_init_create_static init;
14601462
struct fastrpc_invoke_args *args;
14611463
struct fastrpc_phy_page pages[1];
1464+
struct fastrpc_channel_ctx *cctx = fl->cctx;
14621465
char *name;
14631466
int err;
1464-
bool scm_done = false;
14651467
struct {
14661468
int client_id;
14671469
u32 namelen;
14681470
u32 pageslen;
14691471
} inbuf;
14701472
u32 sc;
1473+
unsigned long flags;
14711474

14721475
if (!fl->cctx->remote_heap ||
14731476
!fl->cctx->remote_heap->dma_addr ||
@@ -1498,31 +1501,6 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14981501
inbuf.client_id = fl->client_id;
14991502
inbuf.namelen = init.namelen;
15001503
inbuf.pageslen = 0;
1501-
if (!fl->cctx->remote_heap) {
1502-
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
1503-
&fl->cctx->remote_heap);
1504-
if (err)
1505-
goto err_name;
1506-
1507-
/* Map if we have any heap VMIDs associated with this ADSP Static Process. */
1508-
if (fl->cctx->vmcount) {
1509-
u64 src_perms = BIT(QCOM_SCM_VMID_HLOS);
1510-
1511-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr,
1512-
(u64)fl->cctx->remote_heap->size,
1513-
&src_perms,
1514-
fl->cctx->vmperms, fl->cctx->vmcount);
1515-
if (err) {
1516-
dev_err(fl->sctx->dev,
1517-
"Failed to assign memory with dma_addr %pad size 0x%llx err %d\n",
1518-
&fl->cctx->remote_heap->dma_addr,
1519-
fl->cctx->remote_heap->size, err);
1520-
goto err_map;
1521-
}
1522-
scm_done = true;
1523-
inbuf.pageslen = 1;
1524-
}
1525-
}
15261504

15271505
fl->pd = USER_PD;
15281506

@@ -1534,8 +1512,17 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
15341512
args[1].length = inbuf.namelen;
15351513
args[1].fd = -1;
15361514

1537-
pages[0].addr = fl->cctx->remote_heap->dma_addr;
1538-
pages[0].size = fl->cctx->remote_heap->size;
1515+
spin_lock_irqsave(&cctx->lock, flags);
1516+
if (!fl->cctx->audio_init_mem) {
1517+
pages[0].addr = fl->cctx->remote_heap->dma_addr;
1518+
pages[0].size = fl->cctx->remote_heap->size;
1519+
fl->cctx->audio_init_mem = true;
1520+
inbuf.pageslen = 1;
1521+
} else {
1522+
pages[0].addr = 0;
1523+
pages[0].size = 0;
1524+
}
1525+
spin_unlock_irqrestore(&cctx->lock, flags);
15391526

15401527
args[2].ptr = (u64)(uintptr_t) pages;
15411528
args[2].length = sizeof(*pages);
@@ -1553,27 +1540,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
15531540

15541541
return 0;
15551542
err_invoke:
1556-
if (fl->cctx->vmcount && scm_done) {
1557-
u64 src_perms = 0;
1558-
struct qcom_scm_vmperm dst_perms;
1559-
u32 i;
1560-
1561-
for (i = 0; i < fl->cctx->vmcount; i++)
1562-
src_perms |= BIT(fl->cctx->vmperms[i].vmid);
1563-
1564-
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
1565-
dst_perms.perm = QCOM_SCM_PERM_RWX;
1566-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->dma_addr,
1567-
(u64)fl->cctx->remote_heap->size,
1568-
&src_perms, &dst_perms, 1);
1569-
if (err)
1570-
dev_err(fl->sctx->dev, "Failed to assign memory dma_addr %pad size 0x%llx err %d\n",
1571-
&fl->cctx->remote_heap->dma_addr, fl->cctx->remote_heap->size, err);
1572-
}
1573-
err_map:
1574-
fastrpc_buf_free(fl->cctx->remote_heap);
1575-
fl->cctx->remote_heap = NULL;
1576-
err_name:
1543+
fl->cctx->audio_init_mem = false;
15771544
kfree(name);
15781545
err:
15791546
kfree(args);
@@ -2594,20 +2561,28 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
25942561
}
25952562
}
25962563

2597-
if (domain_id == SDSP_DOMAIN_ID) {
2564+
if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) {
25982565
struct resource res;
25992566
u64 src_perms;
26002567

26012568
err = of_reserved_mem_region_to_resource(rdev->of_node, 0, &res);
26022569
if (!err) {
2570+
if (domain_id == ADSP_DOMAIN_ID) {
2571+
data->remote_heap =
2572+
kzalloc_obj(*data->remote_heap, GFP_KERNEL);
2573+
if (!data->remote_heap)
2574+
return -ENOMEM;
2575+
2576+
data->remote_heap->dma_addr = res.start;
2577+
data->remote_heap->size = resource_size(&res);
2578+
}
26032579
src_perms = BIT(QCOM_SCM_VMID_HLOS);
26042580

26052581
err = qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms,
26062582
data->vmperms, data->vmcount);
26072583
if (err)
26082584
goto err_free_data;
26092585
}
2610-
26112586
}
26122587

26132588
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
@@ -2688,6 +2663,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
26882663
struct fastrpc_buf *buf, *b;
26892664
struct fastrpc_user *user;
26902665
unsigned long flags;
2666+
int err;
26912667

26922668
/* No invocations past this point */
26932669
spin_lock_irqsave(&cctx->lock, flags);
@@ -2705,8 +2681,22 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
27052681
list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node)
27062682
list_del(&buf->node);
27072683

2708-
if (cctx->remote_heap)
2709-
fastrpc_buf_free(cctx->remote_heap);
2684+
if (cctx->remote_heap && cctx->vmcount) {
2685+
u64 src_perms = 0;
2686+
struct qcom_scm_vmperm dst_perms;
2687+
2688+
for (u32 i = 0; i < cctx->vmcount; i++)
2689+
src_perms |= BIT(cctx->vmperms[i].vmid);
2690+
2691+
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
2692+
dst_perms.perm = QCOM_SCM_PERM_RWX;
2693+
2694+
err = qcom_scm_assign_mem(cctx->remote_heap->dma_addr,
2695+
cctx->remote_heap->size, &src_perms,
2696+
&dst_perms, 1);
2697+
if (!err)
2698+
kfree(cctx->remote_heap);
2699+
}
27102700

27112701
of_platform_depopulate(&rpdev->dev);
27122702

0 commit comments

Comments
 (0)