Re: [syzbot] [net?] general protection fault in kernel_sock_shutdown (4)

Kuniyuki Iwashima
2026-04-25T01:15:13Z

On Fri, Apr 24, 2026 at 6:11 PM Arjan van de Ven <arjan@linux.intel.com> wrote:
>
>
> Unfortunately the AI had a burp and did not write out the proper URL
> for analysis data; it should have been
>
> http://oops.fenrus.org/reports/lkml/69ea344f.a00a0220.17a17.0040.GAE_google.com/report.html
>
> and in addition, it made a candidate patch (below)
>
>
>
>
>
>
>
>
>
>
>
> From: Arjan van de Ven <arjan@linux.intel.com>
> Subject: [PATCH] RDMA/rxe: fix double-release race on UDP tunnel socket teardown
>
> This patch is based on a BUG as reported at
> https://lore.kernel.org/r/69ea344f.a00a0220.17a17.0040.GAE@google.com.
>
> The Soft RoCE (RXE) driver stores per-network-namespace UDP tunnel
> sockets for IPv4 and IPv6 encapsulation. Two independent code paths
> tear these sockets down: rxe_ns_exit(), called when a network
> namespace is destroyed, and rxe_net_del(), called when an RDMA link
> is deleted via netlink. Both paths read the per-namespace socket
> pointer and call udp_tunnel_sock_release() on it.
>
> A time-of-check/time-of-use (TOCTOU) race exists in rxe_net_del().
> It reads the socket pointer via rxe_ns_pernet_sk4(), then passes it
> to rxe_sock_put() for release. If rxe_ns_exit() runs concurrently
> between the read and the release, it clears the pointer and calls
> udp_tunnel_sock_release() first, causing sock_release() to set
> sock->ops = NULL. When rxe_net_del() then calls
> udp_tunnel_sock_release() on the same socket, kernel_sock_shutdown()
> dereferences the now-NULL sock->ops, triggering a KASAN null-ptr-deref
> at offset 0x68 (the shutdown function pointer in struct proto_ops).
>
> A minimal alternative would guard against NULL sock->ops inside
> udp_tunnel_sock_release() before calling kernel_sock_shutdown(). That
> treats the symptom rather than the root cause and leaves the
> double-release of socket state intact.
>
> Add rxe_ns_pernet_take_sk4() and rxe_ns_pernet_take_sk6() which use
> xchg() to atomically swap the per-namespace socket pointer to NULL
> and return the old value. Replace the non-atomic reads in
> rxe_net_del() with these take variants, and release the socket
> directly via udp_tunnel_sock_release() without going through
> rxe_sock_put().
>
> Whichever teardown path executes take first claims ownership of the
> socket; the second caller gets NULL and skips the release, closing
> the double-release window.
>
> Link: https://lore.kernel.org/r/69ea344f.a00a0220.17a17.0040.GAE@google.com
> Oops-Analysis: http://oops.fenrus.org/reports/lkml/69ea344f.a00a0220.17a17.0040.GAE_google.com/report.html
> Fixes: 13f2a53c2a71 ("RDMA/rxe: Add net namespace support for IPv4/IPv6 sockets")
> Fixes: f1327abd6abe ("RDMA/rxe: Support RDMA link creation and destruction per net namespace")
> Assisted-by: GitHub Copilot patcher:claude linux-kernel-oops-x86.
> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
> Cc: linux-rdma@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: Zhu Yanjun <zyjzyj2000@gmail.com>
> Cc: Jason Gunthorpe <jgg@ziepe.ca>
> Cc: Leon Romanovsky <leon@kernel.org>
>
> ---
> drivers/infiniband/sw/rxe/rxe_net.c | 8 ++++----
> drivers/infiniband/sw/rxe/rxe_ns.c | 14 ++++++++++++++
> drivers/infiniband/sw/rxe/rxe_ns.h | 7 +++++++
> 3 files changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
> index 50a2cb5405e22..4f604636cb7b4 100644
> --- a/drivers/infiniband/sw/rxe/rxe_net.c
> +++ b/drivers/infiniband/sw/rxe/rxe_net.c
> @@ -655,13 +655,13 @@ void rxe_net_del(struct ib_device *dev)
>
> net = dev_net(ndev);
>
> - sk = rxe_ns_pernet_sk4(net);
> + sk = rxe_ns_pernet_take_sk4(net);
> if (sk)
> - rxe_sock_put(sk, rxe_ns_pernet_set_sk4, net);
> + udp_tunnel_sock_release(sk->sk_socket);

This leaks sk->sk_refcnt, no AI slop please.

I'm working on the right fix.

Thanks.