Skip to content

Commit e062e2d

Browse files
shayshyigregkh
authored andcommitted
RDMA/core: Don't access cm_id after its destruction
[ Upstream commit 889d916 ] restrack should only be attached to a cm_id while the ID has a valid device pointer. It is set up when the device is first loaded, but not cleared when the device is removed. There is also two copies of the device pointer, one private and one in the public API, and these were left out of sync. Make everything go to NULL together and manipulate restrack right around the device assignments. Found by syzcaller: BUG: KASAN: wild-memory-access in __list_del include/linux/list.h:112 [inline] BUG: KASAN: wild-memory-access in __list_del_entry include/linux/list.h:135 [inline] BUG: KASAN: wild-memory-access in list_del include/linux/list.h:146 [inline] BUG: KASAN: wild-memory-access in cma_cancel_listens drivers/infiniband/core/cma.c:1767 [inline] BUG: KASAN: wild-memory-access in cma_cancel_operation drivers/infiniband/core/cma.c:1795 [inline] BUG: KASAN: wild-memory-access in cma_cancel_operation+0x1f4/0x4b0 drivers/infiniband/core/cma.c:1783 Write of size 8 at addr dead000000000108 by task syz-executor716/334 CPU: 0 PID: 334 Comm: syz-executor716 Not tainted 5.11.0+ torvalds#271 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0xbe/0xf9 lib/dump_stack.c:120 __kasan_report mm/kasan/report.c:400 [inline] kasan_report.cold+0x5f/0xd5 mm/kasan/report.c:413 __list_del include/linux/list.h:112 [inline] __list_del_entry include/linux/list.h:135 [inline] list_del include/linux/list.h:146 [inline] cma_cancel_listens drivers/infiniband/core/cma.c:1767 [inline] cma_cancel_operation drivers/infiniband/core/cma.c:1795 [inline] cma_cancel_operation+0x1f4/0x4b0 drivers/infiniband/core/cma.c:1783 _destroy_id+0x29/0x460 drivers/infiniband/core/cma.c:1862 ucma_close_id+0x36/0x50 drivers/infiniband/core/ucma.c:185 ucma_destroy_private_ctx+0x58d/0x5b0 drivers/infiniband/core/ucma.c:576 ucma_close+0x91/0xd0 drivers/infiniband/core/ucma.c:1797 __fput+0x169/0x540 fs/file_table.c:280 task_work_run+0xb7/0x100 kernel/task_work.c:140 exit_task_work include/linux/task_work.h:30 [inline] do_exit+0x7da/0x17f0 kernel/exit.c:825 do_group_exit+0x9e/0x190 kernel/exit.c:922 __do_sys_exit_group kernel/exit.c:933 [inline] __se_sys_exit_group kernel/exit.c:931 [inline] __x64_sys_exit_group+0x2d/0x30 kernel/exit.c:931 do_syscall_64+0x2d/0x40 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: 255d0c1 ("RDMA/cma: rdma_bind_addr() leaks a cma_dev reference count") Link: https://lore.kernel.org/r/3352ee288fe34f2b44220457a29bfc0548686363.1620711734.git.leonro@nvidia.com Signed-off-by: Shay Drory <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent abe31d2 commit e062e2d

File tree

1 file changed

+3
-2
lines changed
  • drivers/infiniband/core

1 file changed

+3
-2
lines changed

drivers/infiniband/core/cma.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ static void cma_release_dev(struct rdma_id_private *id_priv)
482482
list_del(&id_priv->list);
483483
cma_dev_put(id_priv->cma_dev);
484484
id_priv->cma_dev = NULL;
485+
id_priv->id.device = NULL;
485486
if (id_priv->id.route.addr.dev_addr.sgid_attr) {
486487
rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr);
487488
id_priv->id.route.addr.dev_addr.sgid_attr = NULL;
@@ -1864,6 +1865,7 @@ static void _destroy_id(struct rdma_id_private *id_priv,
18641865
iw_destroy_cm_id(id_priv->cm_id.iw);
18651866
}
18661867
cma_leave_mc_groups(id_priv);
1868+
rdma_restrack_del(&id_priv->res);
18671869
cma_release_dev(id_priv);
18681870
}
18691871

@@ -1877,7 +1879,6 @@ static void _destroy_id(struct rdma_id_private *id_priv,
18771879
kfree(id_priv->id.route.path_rec);
18781880

18791881
put_net(id_priv->id.route.addr.dev_addr.net);
1880-
rdma_restrack_del(&id_priv->res);
18811882
kfree(id_priv);
18821883
}
18831884

@@ -3740,7 +3741,7 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
37403741
}
37413742

37423743
id_priv->backlog = backlog;
3743-
if (id->device) {
3744+
if (id_priv->cma_dev) {
37443745
if (rdma_cap_ib_cm(id->device, 1)) {
37453746
ret = cma_ib_listen(id_priv);
37463747
if (ret)

0 commit comments

Comments
 (0)