From 20d4dc00608c4aa809b37fa8dbde06746f65a12b Mon Sep 17 00:00:00 2001 From: nishant chaubey Date: Thu, 18 May 2023 14:31:58 +0530 Subject: [PATCH] Potential use of freed ctx in async invoke After message is sent to DSP, async response thread could immediately get the response and free context, which will result in a use-after-free in invoke send. To fix this, add local copy of ctx to trace and gmsg logging. To fix async response and SSR race, we rely on is_job_sent_to_remote_ss of ctx, now check valid ctx from ctxtable to set is_job_sent_to_remote_ss. Change-Id: I1ebbed61443beda7b5ffcbe858481a54cca96acb Signed-off-by: nishant chaubey --- dsp/adsprpc.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/dsp/adsprpc.c b/dsp/adsprpc.c index 4e506bdcff..7e4daf98bd 100644 --- a/dsp/adsprpc.c +++ b/dsp/adsprpc.c @@ -2825,6 +2825,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, { struct smq_msg *msg = &ctx->msg; struct smq_msg msg_temp; + struct smq_invoke_ctx ctx_temp; struct fastrpc_file *fl = ctx->fl; struct fastrpc_channel_ctx *channel_ctx = NULL; int err = 0, cid = -1; @@ -2832,6 +2833,8 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, int64_t ns = 0; uint64_t xo_time_in_us = 0; int isasync = (ctx->asyncjob.isasyncjob ? true : false); + unsigned long irq_flags = 0; + uint32_t index = 0; if (!fl) { err = -EBADF; @@ -2870,16 +2873,27 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, /* * After message is sent to DSP, async response thread could immediately * get the response and free context, which will result in a use-after-free - * in this function. So use a local variable for message. + * in this function. So use a local variable for message and context. */ memcpy(&msg_temp, msg, sizeof(struct smq_msg)); msg = &msg_temp; + memcpy(&ctx_temp, ctx, sizeof(struct smq_invoke_ctx)); + index = (uint32_t)GET_TABLE_IDX_FROM_CTXID(ctx->ctxid); } + err = fastrpc_transport_send(cid, (void *)msg, sizeof(*msg), fl->tvm_remote_domain); - if (isasync && !err) { - spin_lock(&fl->hlock); - ctx->is_job_sent_to_remote_ss = true; - spin_unlock(&fl->hlock); + if (isasync) { + if (!err) { + /* + * Validate the ctx as this could have been already + * freed by async response. + */ + spin_lock_irqsave(&channel_ctx->ctxlock, irq_flags); + if (index < FASTRPC_CTX_MAX && channel_ctx->ctxtable[index] == ctx) + ctx->is_job_sent_to_remote_ss = true; + spin_unlock_irqrestore(&channel_ctx->ctxlock, irq_flags); + } + ctx = &ctx_temp; } trace_fastrpc_transport_send(cid, (uint64_t)ctx, msg->invoke.header.ctx, handle, sc, msg->invoke.page.addr, msg->invoke.page.size);