summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLi Zhijian <lizhijian@cn.fujitsu.com>2021-12-28 09:44:06 +0800
committerJason Gunthorpe <jgg@nvidia.com>2022-01-04 10:29:34 -0400
commit8ff5f5d9d8cfce6a1e368a6daa7123be133a6c35 (patch)
tree7393e9589e14b2601094969804e503574860ab7b /drivers
parentc9e6606c7fe92b50a02ce51dda82586ebdf99b48 (diff)
downloadlinux-8ff5f5d9d8cfce6a1e368a6daa7123be133a6c35.tar.gz
RDMA/rxe: Prevent double freeing rxe_map_set()
The same rxe_map_set could be freed twice:

rxe_reg_user_mr()
  -> rxe_mr_init_user()
    -> rxe_mr_free_map_set() # 1st

  -> rxe_drop_ref()
   ...
    -> rxe_mr_cleanup()
      -> rxe_mr_free_map_set() # 2nd

Follow normal convection and put resource cleanup either in the error
unwind of the allocator, or the overall free function. Leave the object
unchanged with a NULL cur_map_set on failure and remove the unncessary
free in rxe_mr_init_user().

Link: https://lore.kernel.org/r/20211228014406.1033444-1-lizhijian@cn.fujitsu.com
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Acked-by: Zhu Yanjun <zyjzyj2000@gmail.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mr.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
index 53271df10e47..bcf717bcf0b3 100644
--- a/drivers/infiniband/sw/rxe/rxe_mr.c
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -135,19 +135,19 @@ static int rxe_mr_alloc(struct rxe_mr *mr, int num_buf, int both)
 
 	ret = rxe_mr_alloc_map_set(num_map, &mr->cur_map_set);
 	if (ret)
-		goto err_out;
+		return -ENOMEM;
 
 	if (both) {
 		ret = rxe_mr_alloc_map_set(num_map, &mr->next_map_set);
-		if (ret) {
-			rxe_mr_free_map_set(mr->num_map, mr->cur_map_set);
-			goto err_out;
-		}
+		if (ret)
+			goto err_free;
 	}
 
 	return 0;
 
-err_out:
+err_free:
+	rxe_mr_free_map_set(mr->num_map, mr->cur_map_set);
+	mr->cur_map_set = NULL;
 	return -ENOMEM;
 }
 
@@ -214,7 +214,7 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova,
 				pr_warn("%s: Unable to get virtual address\n",
 						__func__);
 				err = -ENOMEM;
-				goto err_cleanup_map;
+				goto err_release_umem;
 			}
 
 			buf->addr = (uintptr_t)vaddr;
@@ -237,8 +237,6 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova,
 
 	return 0;
 
-err_cleanup_map:
-	rxe_mr_free_map_set(mr->num_map, mr->cur_map_set);
 err_release_umem:
 	ib_umem_release(umem);
 err_out: