From: Patrisious Haddad <phaddad@xxxxxxxxxx> resolve_prepare_src() changes the destination address of the id, regardless of success, and on failure zeroes it out. Instead on function failure keep the original destination address of the id. Since the id could have been already added to the cm id tree and zeroing its destination address, could result in a key mismatch or multiple ids having the same key(zero) in the tree which could lead to: BUG: KASAN: slab-out-of-bounds in compare_netdev_and_ip.isra.0+0x25/0x120 drivers/infiniband/core/cma.c:473 Read of size 4 at addr ffff88800920d9e4 by task syz-executor.4/14865 CPU: 2 PID: 14865 Comm: syz-executor.4 Not tainted 5.19.0-rc2 #21 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x6e/0x91 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:313 [inline] print_report.cold+0xff/0x68e mm/kasan/report.c:429 kasan_report+0xa8/0x130 mm/kasan/report.c:491 compare_netdev_and_ip.isra.0+0x25/0x120 drivers/infiniband/core/cma.c:473 cma_add_id_to_tree drivers/infiniband/core/cma.c:506 [inline] rdma_resolve_route+0xbc4/0x1560 drivers/infiniband/core/cma.c:3303 ucma_resolve_route+0xe4/0x150 drivers/infiniband/core/ucma.c:746 ucma_write+0x19f/0x280 drivers/infiniband/core/ucma.c:1744 vfs_write fs/read_write.c:589 [inline] vfs_write+0x181/0x580 fs/read_write.c:571 ksys_write+0x1a1/0x1e0 fs/read_write.c:644 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3d/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 RIP: 0033:0x7f2afbe8c89d Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f2afcf1ec28 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 00007f2afbfabf60 RCX: 00007f2afbe8c89d RDX: 0000000000000010 RSI: 0000000020000100 RDI: 0000000000000003 RBP: 00007f2afbef910d R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007ffcdc77c66f R14: 00007f2afbfabf60 R15: 00007f2afcf1edc0 </TASK> Fixes: 19b752a19dce ("IB/cma: Allow port reuse for rdma_id") Signed-off-by: Patrisious Haddad <phaddad@xxxxxxxxxx> Reviewed-by: Maor Gottlieb <maorg@xxxxxxxxxx> Reported-by: Wei Chen <harperchen1110@xxxxxxxxx> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxx> --- drivers/infiniband/core/cma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 1fca0a24f30f..2d4c391e36a9 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3584,8 +3584,11 @@ static int resolve_prepare_src(struct rdma_id_private *id_priv, struct sockaddr *src_addr, const struct sockaddr *dst_addr) { + struct sockaddr org_addr = {}; int ret; + memcpy(&org_addr, cma_dst_addr(id_priv), + rdma_addr_size(cma_dst_addr(id_priv))); memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) { /* For a well behaved ULP state will be RDMA_CM_IDLE */ @@ -3608,7 +3611,7 @@ static int resolve_prepare_src(struct rdma_id_private *id_priv, err_state: cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, RDMA_CM_ADDR_BOUND); err_dst: - memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr)); + memcpy(cma_dst_addr(id_priv), &org_addr, rdma_addr_size(&org_addr)); return ret; } -- 2.38.1