diff --git a/patches.suse/RDMA-cma-Do-not-change-route.addr.src_addr-outside-s.patch b/patches.suse/RDMA-cma-Do-not-change-route.addr.src_addr-outside-s.patch new file mode 100644 index 0000000..efb65ca --- /dev/null +++ b/patches.suse/RDMA-cma-Do-not-change-route.addr.src_addr-outside-s.patch @@ -0,0 +1,119 @@ +From 22e9f71072fa605cbf033158db58e0790101928d Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Wed, 23 Feb 2022 11:23:57 -0400 +Subject: [PATCH 1/1] RDMA/cma: Do not change route.addr.src_addr outside state + checks +Git-commit: 22e9f71072fa605cbf033158db58e0790101928d +Patch-mainline: v5.17 +References: bsc#1210629 CVE-2023-2176 + +If the state is not idle then resolve_prepare_src() should immediately +fail and no change to global state should happen. However, it +unconditionally overwrites the src_addr trying to build a temporary any +address. + +For instance if the state is already RDMA_CM_LISTEN then this will corrupt +the src_addr and would cause the test in cma_cancel_operation(): + + if (cma_any_addr(cma_src_addr(id_priv)) && !id_priv->cma_dev) + +Which would manifest as this trace from syzkaller: + + BUG: KASAN: use-after-free in __list_add_valid+0x93/0xa0 lib/list_debug.c:26 + Read of size 8 at addr ffff8881546491e0 by task syz-executor.1/32204 + + CPU: 1 PID: 32204 Comm: syz-executor.1 Not tainted 5.12.0-rc8-syzkaller #0 + Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 + Call Trace: + __dump_stack lib/dump_stack.c:79 [inline] + dump_stack+0x141/0x1d7 lib/dump_stack.c:120 + print_address_description.constprop.0.cold+0x5b/0x2f8 mm/kasan/report.c:232 + __kasan_report mm/kasan/report.c:399 [inline] + kasan_report.cold+0x7c/0xd8 mm/kasan/report.c:416 + __list_add_valid+0x93/0xa0 lib/list_debug.c:26 + __list_add include/linux/list.h:67 [inline] + list_add_tail include/linux/list.h:100 [inline] + cma_listen_on_all drivers/infiniband/core/cma.c:2557 [inline] + rdma_listen+0x787/0xe00 drivers/infiniband/core/cma.c:3751 + ucma_listen+0x16a/0x210 drivers/infiniband/core/ucma.c:1102 + ucma_write+0x259/0x350 drivers/infiniband/core/ucma.c:1732 + vfs_write+0x28e/0xa30 fs/read_write.c:603 + ksys_write+0x1ee/0x250 fs/read_write.c:658 + do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 + entry_SYSCALL_64_after_hwframe+0x44/0xae + +This is indicating that an rdma_id_private was destroyed without doing +cma_cancel_listens(). + +Instead of trying to re-use the src_addr memory to indirectly create an +any address derived from the dst build one explicitly on the stack and +bind to that as any other normal flow would do. rdma_bind_addr() will copy +it over the src_addr once it knows the state is valid. + +This is similar to commit bc0bdc5afaa7 ("RDMA/cma: Do not change +route.addr.src_addr.ss_family") + +Link: https://lore.kernel.org/r/0-v2-e975c8fd9ef2+11e-syz_cma_srcaddr_jgg@nvidia.com +Cc: stable@vger.kernel.org +Fixes: 732d41c545bb ("RDMA/cma: Make the locking for automatic state transition more clear") +Reported-by: syzbot+c94a3675a626f6333d74@syzkaller.appspotmail.com +Reviewed-by: Leon Romanovsky +Signed-off-by: Jason Gunthorpe +Acked-by: Nicolas Morey +--- + drivers/infiniband/core/cma.c | 40 +++++++++++++++++++++-------------- + 1 file changed, 24 insertions(+), 16 deletions(-) + +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index c447526288f4..50c53409ceb6 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -3370,22 +3370,30 @@ err: + static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + struct sockaddr *dst_addr) + { +- if (!src_addr || !src_addr->sa_family) { +- src_addr = (struct sockaddr *) &id->route.addr.src_addr; +- src_addr->sa_family = dst_addr->sa_family; +- if (IS_ENABLED(CONFIG_IPV6) && +- dst_addr->sa_family == AF_INET6) { +- struct sockaddr_in6 *src_addr6 = (struct sockaddr_in6 *) src_addr; +- struct sockaddr_in6 *dst_addr6 = (struct sockaddr_in6 *) dst_addr; +- src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id; +- if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL) +- id->route.addr.dev_addr.bound_dev_if = dst_addr6->sin6_scope_id; +- } else if (dst_addr->sa_family == AF_IB) { +- ((struct sockaddr_ib *) src_addr)->sib_pkey = +- ((struct sockaddr_ib *) dst_addr)->sib_pkey; +- } ++ struct sockaddr_storage zero_sock = {}; ++ ++ if (src_addr && src_addr->sa_family) ++ return rdma_bind_addr(id, src_addr); ++ ++ /* ++ * When the src_addr is not specified, automatically supply an any addr ++ */ ++ zero_sock.ss_family = dst_addr->sa_family; ++ if (IS_ENABLED(CONFIG_IPV6) && dst_addr->sa_family == AF_INET6) { ++ struct sockaddr_in6 *src_addr6 = ++ (struct sockaddr_in6 *)&zero_sock; ++ struct sockaddr_in6 *dst_addr6 = ++ (struct sockaddr_in6 *)dst_addr; ++ ++ src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id; ++ if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL) ++ id->route.addr.dev_addr.bound_dev_if = ++ dst_addr6->sin6_scope_id; ++ } else if (dst_addr->sa_family == AF_IB) { ++ ((struct sockaddr_ib *)&zero_sock)->sib_pkey = ++ ((struct sockaddr_ib *)dst_addr)->sib_pkey; + } +- return rdma_bind_addr(id, src_addr); ++ return rdma_bind_addr(id, (struct sockaddr *)&zero_sock); + } + + /* +-- +2.39.1.1.gbe015eda0162 + diff --git a/series.conf b/series.conf index fe964d6..dee6cf3 100644 --- a/series.conf +++ b/series.conf @@ -26717,6 +26717,7 @@ patches.suse/net_sched-add-__rcu-annotation-to-netdev-qdisc.patch patches.suse/lib-iov_iter-initialize-flags-in-new-pipe_buffer.patch patches.suse/sr9700-sanity-check-for-packet-length.patch + patches.suse/RDMA-cma-Do-not-change-route.addr.src_addr-outside-s.patch patches.suse/xfrm-fix-mtu-regression.patch patches.suse/fuse-fix-pipe-buffer-lifetime-for-direct_io.patch patches.suse/xen-xenbus-don-t-let-xenbus_grant_ring-remove-grants.patch