FASTRPC_IOCTL_MEM_UNMAP found a map under fl->lock, then dropped the lock.
It used that map until the DSP completed the unmap. A second unmap can find the same map and race to fastrpc_map_put(). That can cause a use-after-free or double list deletion. Remove the map from the lookup list before the remote unmap. Reinsert it if the remote side reports an error. Signed-off-by: Yousef Alhouseen <[email protected]> --- drivers/misc/fastrpc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 6a5239b1c..6ced210ca 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -365,7 +365,8 @@ static void fastrpc_free_map(struct kref *ref) if (map->fl) { spin_lock(&map->fl->lock); - list_del(&map->node); + if (!list_empty(&map->node)) + list_del_init(&map->node); spin_unlock(&map->fl->lock); map->fl = NULL; } @@ -2064,6 +2065,7 @@ static int fastrpc_req_mem_unmap_impl(struct fastrpc_user *fl, struct fastrpc_me list_for_each_entry_safe(iter, m, &fl->maps, node) { if ((req->fd < 0 || iter->fd == req->fd) && (iter->raddr == req->vaddr)) { map = iter; + list_del_init(&map->node); break; } } @@ -2088,6 +2090,9 @@ static int fastrpc_req_mem_unmap_impl(struct fastrpc_user *fl, struct fastrpc_me &args[0]); if (err) { dev_err(dev, "unmmap\tpt fd = %d, 0x%09llx error\n", map->fd, map->raddr); + spin_lock(&fl->lock); + list_add_tail(&map->node, &fl->maps); + spin_unlock(&fl->lock); return err; } fastrpc_map_put(map); -- 2.54.0
