Skip to content

Commit c7a198c

Browse files
maorgottliebjgunthorpe
authored andcommitted
RDMA/ucma: Fix use after free in destroy id flow
ucma_free_ctx() should call to __destroy_id() on all the connection requests that have not been delivered to user space. Currently it calls on the context itself and cause to use after free. Fixes the trace: BUG: Unable to handle kernel data access on write at 0x5deadbeef0000108 Faulting instruction address: 0xc0080000002428f4 Oops: Kernel access of bad area, sig: 11 [#1] Call Trace: [c000000207f2b680] [c00800000024280c] .__destroy_id+0x28c/0x610 [rdma_ucm] (unreliable) [c000000207f2b750] [c0080000002429c4] .__destroy_id+0x444/0x610 [rdma_ucm] [c000000207f2b820] [c008000000242c24] .ucma_close+0x94/0xf0 [rdma_ucm] [c000000207f2b8c0] [c00000000046fbdc] .__fput+0xac/0x330 [c000000207f2b960] [c00000000015d48c] .task_work_run+0xbc/0x110 [c000000207f2b9f0] [c00000000012fb00] .do_exit+0x430/0xc50 [c000000207f2bae0] [c0000000001303ec] .do_group_exit+0x5c/0xd0 [c000000207f2bb70] [c000000000144a34] .get_signal+0x194/0xe30 [c000000207f2bc60] [c00000000001f6b4] .do_notify_resume+0x124/0x470 [c000000207f2bd60] [c000000000032484] .interrupt_exit_user_prepare+0x1b4/0x240 [c000000207f2be20] [c000000000010034] interrupt_return+0x14/0x1c0 Rename listen_ctx to conn_req_ctx as the poor name was the cause of this bug. Fixes: a1d33b7 ("RDMA/ucma: Rework how new connections are passed through event delivery") Link: https://lore.kernel.org/r/20201012045600.418271-4-leon@kernel.org Signed-off-by: Maor Gottlieb <maorg@nvidia.com> Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 71abf20 commit c7a198c

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

drivers/infiniband/core/ucma.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ struct ucma_multicast {
112112

113113
struct ucma_event {
114114
struct ucma_context *ctx;
115-
struct ucma_context *listen_ctx;
115+
struct ucma_context *conn_req_ctx;
116116
struct ucma_multicast *mc;
117117
struct list_head list;
118118
struct rdma_ucm_event_resp resp;
@@ -308,7 +308,7 @@ static int ucma_connect_event_handler(struct rdma_cm_id *cm_id,
308308
uevent = ucma_create_uevent(listen_ctx, event);
309309
if (!uevent)
310310
goto err_alloc;
311-
uevent->listen_ctx = listen_ctx;
311+
uevent->conn_req_ctx = ctx;
312312
uevent->resp.id = ctx->id;
313313

314314
ctx->cm_id->context = ctx;
@@ -534,7 +534,7 @@ static int ucma_free_ctx(struct ucma_context *ctx)
534534
/* Cleanup events not yet reported to the user. */
535535
mutex_lock(&ctx->file->mut);
536536
list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) {
537-
if (uevent->ctx == ctx || uevent->listen_ctx == ctx)
537+
if (uevent->ctx == ctx || uevent->conn_req_ctx == ctx)
538538
list_move_tail(&uevent->list, &list);
539539
}
540540
list_del(&ctx->list);
@@ -548,8 +548,9 @@ static int ucma_free_ctx(struct ucma_context *ctx)
548548
*/
549549
list_for_each_entry_safe(uevent, tmp, &list, list) {
550550
list_del(&uevent->list);
551-
if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST)
552-
__destroy_id(uevent->ctx);
551+
if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST &&
552+
uevent->conn_req_ctx != ctx)
553+
__destroy_id(uevent->conn_req_ctx);
553554
kfree(uevent);
554555
}
555556

0 commit comments

Comments
 (0)