fastrpc_put_args() copies output buffers from the DSP-shared metadata area using the pointer and length stored in rpra[]. The DSP can update that coherent buffer before the CPU reads it back.
Keep the kernel-owned inline buffer address and original userspace length in the invoke context, and use that state for output copies. This prevents remote updates to the metadata from steering kernel reads or expanding the copyout length. Signed-off-by: Yousef Alhouseen <[email protected]> --- drivers/misc/fastrpc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 8dd8315d5..c91d5da42 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -247,6 +247,7 @@ struct fastrpc_invoke_ctx { struct fastrpc_map **maps; struct fastrpc_buf *buf; struct fastrpc_invoke_args *args; + uintptr_t *buf_pv; struct fastrpc_buf_overlap *olaps; struct fastrpc_channel_ctx *cctx; }; @@ -570,6 +571,7 @@ static void fastrpc_context_free(struct kref *ref) spin_unlock_irqrestore(&cctx->lock, flags); kfree(ctx->maps); + kfree(ctx->buf_pv); kfree(ctx->olaps); kfree(ctx); @@ -681,9 +683,17 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( kfree(ctx); return ERR_PTR(-ENOMEM); } + ctx->buf_pv = kzalloc_objs(*ctx->buf_pv, ctx->nscalars); + if (!ctx->buf_pv) { + kfree(ctx->olaps); + kfree(ctx->maps); + kfree(ctx); + return ERR_PTR(-ENOMEM); + } ctx->args = args; ret = fastrpc_get_buff_overlaps(ctx); if (ret) { + kfree(ctx->buf_pv); kfree(ctx->olaps); kfree(ctx->maps); kfree(ctx); @@ -727,6 +737,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( fastrpc_user_put(user); fastrpc_channel_ctx_put(cctx); kfree(ctx->maps); + kfree(ctx->buf_pv); kfree(ctx->olaps); kfree(ctx); @@ -1136,6 +1147,7 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) args = args + mlen; rlen -= mlen; } + ctx->buf_pv[i] = (uintptr_t)rpra[i].buf.pv; if (i < inbufs && !ctx->maps[i]) { void *dst = (void *)(uintptr_t)rpra[i].buf.pv; @@ -1193,9 +1205,9 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx, for (i = inbufs; i < ctx->nbufs; ++i) { if (!ctx->maps[i]) { - void *src = (void *)(uintptr_t)rpra[i].buf.pv; + void *src = (void *)ctx->buf_pv[i]; void *dst = (void *)(uintptr_t)ctx->args[i].ptr; - u64 len = rpra[i].buf.len; + u64 len = ctx->args[i].length; if (!kernel) { if (copy_to_user((void __user *)dst, src, len)) { -- 2.54.0
