| From fe85c85e3778f794e23b796b9fbf3d2534304715 Mon Sep 17 00:00:00 2001 |
| From: Thierry Escande <thierry.escande@linaro.org> |
| Date: Thu, 7 Mar 2019 10:12:23 +0000 |
| Subject: misc: fastrpc: Fix a possible double free |
| |
| [ Upstream commit b49f6d83e290f17e20f4e5cf31288d3bb4955ea6 ] |
| |
| This patch fixes the error exit path of fastrpc_init_create_process(). |
| If the DMA allocation or the DSP invoke fails the fastrpc_map was freed |
| but not removed from the mapping list leading to a double free once the |
| mapping list is emptied in fastrpc_device_release(). |
| |
| [srinivas kandagatla]: Cleaned up error path labels and reset init mem |
| to NULL after free |
| Fixes: d73f71c7c6ee("misc: fastrpc: Add support for create remote init process") |
| Signed-off-by: Thierry Escande <thierry.escande@linaro.org> |
| Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/misc/fastrpc.c | 31 ++++++++++++++++++++----------- |
| 1 file changed, 20 insertions(+), 11 deletions(-) |
| |
| diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c |
| index a10937652ca73..35be1cc11dd85 100644 |
| --- a/drivers/misc/fastrpc.c |
| +++ b/drivers/misc/fastrpc.c |
| @@ -856,12 +856,12 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl, |
| |
| if (copy_from_user(&init, argp, sizeof(init))) { |
| err = -EFAULT; |
| - goto bail; |
| + goto err; |
| } |
| |
| if (init.filelen > INIT_FILELEN_MAX) { |
| err = -EINVAL; |
| - goto bail; |
| + goto err; |
| } |
| |
| inbuf.pgid = fl->tgid; |
| @@ -875,17 +875,15 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl, |
| if (init.filelen && init.filefd) { |
| err = fastrpc_map_create(fl, init.filefd, init.filelen, &map); |
| if (err) |
| - goto bail; |
| + goto err; |
| } |
| |
| memlen = ALIGN(max(INIT_FILELEN_MAX, (int)init.filelen * 4), |
| 1024 * 1024); |
| err = fastrpc_buf_alloc(fl, fl->sctx->dev, memlen, |
| &imem); |
| - if (err) { |
| - fastrpc_map_put(map); |
| - goto bail; |
| - } |
| + if (err) |
| + goto err_alloc; |
| |
| fl->init_mem = imem; |
| args[0].ptr = (u64)(uintptr_t)&inbuf; |
| @@ -921,13 +919,24 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl, |
| |
| err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, |
| sc, args); |
| + if (err) |
| + goto err_invoke; |
| |
| - if (err) { |
| + kfree(args); |
| + |
| + return 0; |
| + |
| +err_invoke: |
| + fl->init_mem = NULL; |
| + fastrpc_buf_free(imem); |
| +err_alloc: |
| + if (map) { |
| + spin_lock(&fl->lock); |
| + list_del(&map->node); |
| + spin_unlock(&fl->lock); |
| fastrpc_map_put(map); |
| - fastrpc_buf_free(imem); |
| } |
| - |
| -bail: |
| +err: |
| kfree(args); |
| |
| return err; |
| -- |
| 2.20.1 |
| |