From ac2db530fb55334be2f5cb3950ad89fb59cc6b75 Mon Sep 17 00:00:00 2001 From: Edgar Flores Date: Thu, 18 Jun 2020 09:44:04 -0700 Subject: [PATCH] msm: adsprpc: double free when creating dynamic process Adding synchronization access to allocated memory of userPD to avoid double-freeing the buffer when multiple calls are made to create dynamic userPD process. Change-Id: I07b2c290cc400007ce00d96b36c5b40b17ea43c9 Signed-off-by: Edgar Flores --- drivers/char/adsprpc.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index a06f2fdc1863..83165dc5b986 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -3166,7 +3166,7 @@ bail: static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init_attrs *uproc) { - int err = 0, memlen = 0, mflags = 0; + int err = 0, memlen = 0, mflags = 0, locked = 0; struct fastrpc_ioctl_invoke_async ioctl; struct fastrpc_ioctl_init *init = &uproc->init; struct smq_phy_page pages[1]; @@ -3176,6 +3176,8 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl, remote_arg_t ra[6]; int fds[6]; unsigned int gid = 0, one_mb = 1024*1024; + struct fastrpc_buf *init_mem; + struct { int pgid; unsigned int namelen; @@ -3248,8 +3250,19 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl, goto bail; } /* Free any previous donated memory */ - if (fl->init_mem) - fastrpc_buf_free(fl->init_mem, 0); + spin_lock(&fl->hlock); + locked = 1; + if (fl->init_mem) { + init_mem = fl->init_mem; + fl->init_mem = NULL; + spin_unlock(&fl->hlock); + locked = 0; + fastrpc_buf_free(init_mem, 0); + } + if (locked) { + spin_unlock(&fl->hlock); + locked = 0; + } /* Allocate DMA buffer in kernel for donating to remote process */ memlen = ALIGN(max(3*one_mb, init->filelen * 4), one_mb); @@ -3324,9 +3337,18 @@ bail: mutex_unlock(&fl->map_mutex); } if (err) { + spin_lock(&fl->hlock); + locked = 1; if (!IS_ERR_OR_NULL(fl->init_mem)) { - fastrpc_buf_free(fl->init_mem, 0); + init_mem = fl->init_mem; fl->init_mem = NULL; + spin_unlock(&fl->hlock); + locked = 0; + fastrpc_buf_free(init_mem, 0); + } + if (locked) { + spin_unlock(&fl->hlock); + locked = 0; } } return err;