* Re: [syzbot] [net?] general protection fault in kernel_sock_shutdown (4)
2026-04-23 15:01 [syzbot] [net?] general protection fault in kernel_sock_shutdown (4) syzbot
@ 2026-04-23 17:41 ` Jakub Kicinski
2026-04-24 16:47 ` Arjan van de Ven
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Jakub Kicinski @ 2026-04-23 17:41 UTC (permalink / raw)
To: syzbot
Cc: davem, dsahern, edumazet, horms, linux-kernel, netdev, pabeni,
syzkaller-bugs
On Thu, 23 Apr 2026 08:01:35 -0700 syzbot wrote:
> Subject: [syzbot] [net?] general protection fault in kernel_sock_shutdown (4)
#syz set subsystems: rdma
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [syzbot] [net?] general protection fault in kernel_sock_shutdown (4)
2026-04-23 15:01 [syzbot] [net?] general protection fault in kernel_sock_shutdown (4) syzbot
2026-04-23 17:41 ` Jakub Kicinski
@ 2026-04-24 16:47 ` Arjan van de Ven
2026-04-24 18:08 ` Arjan van de Ven
2026-04-25 1:12 ` Arjan van de Ven
3 siblings, 0 replies; 6+ messages in thread
From: Arjan van de Ven @ 2026-04-24 16:47 UTC (permalink / raw)
To: netdev
Cc: syzbot+d8f76778263ab65c2b21, davem, dsahern, edumazet, horms,
kuba, linux-kernel, pabeni, syzkaller-bugs
This report was analysed with the help of an automated kernel crash
analysis assistant. The analysis below is tentative and should be
reviewed by a human before any action is taken.
Decoded Backtrace
-----------------
1. kernel_sock_shutdown -- crash site (net/socket.c:3785)
3783 int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
3784 {
3785 return READ_ONCE(sock->ops)->shutdown(sock, how);
/* CRASH: sock->ops is NULL (R12 = 0x0); KASAN traps
null-ptr-deref at offset 0x68 = offsetof(proto_ops, shutdown) */
3786 }
Register context at crash:
RBX = 0xffff888058587240 (struct socket *sock)
R12 = 0x0000000000000000 (sock->ops, loaded from RBX+0x20 -- NULL)
RDI = 0x0000000000000068 (= NULL + 0x68, address of shutdown fn ptr)
RBP = 0x0000000000000002 (how = SHUT_RDWR)
2. udp_tunnel_sock_release (net/ipv4/udp_tunnel_core.c:196-202)
196 void udp_tunnel_sock_release(struct socket *sock)
197 {
198 rcu_assign_sk_user_data(sock->sk, NULL);
199 synchronize_rcu();
200 kernel_sock_shutdown(sock, SHUT_RDWR); /* <- calls crash site */
201 sock_release(sock);
202 }
3. rxe_release_udp_tunnel inlined (drivers/infiniband/sw/rxe/rxe_net.c:290-293)
290 static void rxe_release_udp_tunnel(struct socket *sk)
291 {
292 if (sk)
293 udp_tunnel_sock_release(sk);
294 }
4. rxe_sock_put (drivers/infiniband/sw/rxe/rxe_net.c:632-643)
632 static void rxe_sock_put(struct sock *sk,
633 void (*set_sk)(struct net *, struct sock *),
634 struct net *net)
635 {
636 if (refcount_read(&sk->sk_refcnt) > SK_REF_FOR_TUNNEL) {
637 __sock_put(sk);
638 } else {
639 rxe_release_udp_tunnel(sk->sk_socket); /* <- release BEFORE clear */
640 sk = NULL;
641 set_sk(net, sk); /* <- clear AFTER (too late) */
642 }
643 }
Caller: rxe_net_del (rxe_net.c:644-666), triggered via:
nldev_dellink -> rxe_dellink -> rxe_net_del -> rxe_sock_put
Tentative Analysis
------------------
sock->ops is set to NULL by sock_release() (net/socket.c:726) after
calling ops->release(sock). The crash in kernel_sock_shutdown() means
the socket was already passed to sock_release() before this call.
Two independent code paths can release the same UDP tunnel socket stored
in the per-network-namespace rxe_ns_sock structure:
Path 1 -- namespace teardown (rxe_ns.c, rxe_ns_exit()):
rcu_assign_pointer(ns_sk->rxe_sk4, NULL); /* clears pointer FIRST */
udp_tunnel_sock_release(sk->sk_socket); /* then releases */
Path 2 -- RDMA link delete (rxe_net.c, rxe_net_del() -> rxe_sock_put()):
sk = rxe_ns_pernet_sk4(net); /* reads pointer (no ownership) */
rxe_release_udp_tunnel(sk->sk_socket); /* releases FIRST */
set_sk(net, NULL); /* clears AFTER */
The following TOCTOU (time-of-check time-of-use) race is possible when
namespace teardown and RDMA link deletion occur concurrently:
Thread A (rxe_net_del):
rxe_ns_pernet_sk4() -> sk = X (non-NULL)
Thread B (rxe_ns_exit):
rcu_assign_pointer(sk4, NULL)
udp_tunnel_sock_release(X->sk_socket)
sock_release(X->sk_socket)
X->sk_socket->ops = NULL <- clears ops
Thread A (rxe_net_del) continues:
rxe_sock_put(sk=X, ...)
rxe_release_udp_tunnel(X->sk_socket)
kernel_sock_shutdown(X->sk_socket, SHUT_RDWR)
READ_ONCE(sock->ops)->shutdown(...)
<- CRASH: sock->ops == NULL
The bug was introduced by two commits in March 2026 that added
per-network-namespace support to the Soft RoCE (RXE) driver:
13f2a53c2a71e RDMA/rxe: Add net namespace support for IPv4/IPv6 sockets
f1327abd6abed RDMA/rxe: Support RDMA link creation and destruction per
net namespace
Neither commit provides synchronisation between the two teardown paths.
Potential Solution
------------------
Replace rxe_ns_pernet_sk4() calls in rxe_net_del() (and rxe_notify())
with an atomic exchange that simultaneously reads and clears the pernet
pointer, so only one of the two teardown paths can ever obtain a
non-NULL socket pointer:
struct sock *rxe_ns_pernet_take_sk4(struct net *net)
{
struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
return unrcu_pointer(xchg(&ns_sk->rxe_sk4, RCU_INITIALIZER(NULL)));
}
Whichever path (rxe_ns_exit or rxe_net_del) wins the xchg gets the
socket and releases it; the loser gets NULL and skips the release.
More information
----------------
Oops-Analysis: https://lore.kernel.org/r/69ea344f.a00a0220.17a17.0040.GAE@google.com
Assisted-by: linux-kernel-oops-x86 skill (Claude Sonnet 4.6)
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [syzbot] [net?] general protection fault in kernel_sock_shutdown (4)
2026-04-23 15:01 [syzbot] [net?] general protection fault in kernel_sock_shutdown (4) syzbot
2026-04-23 17:41 ` Jakub Kicinski
2026-04-24 16:47 ` Arjan van de Ven
@ 2026-04-24 18:08 ` Arjan van de Ven
2026-04-25 1:12 ` Arjan van de Ven
3 siblings, 0 replies; 6+ messages in thread
From: Arjan van de Ven @ 2026-04-24 18:08 UTC (permalink / raw)
To: netdev
Cc: syzbot+d8f76778263ab65c2b21, dsahern, edumazet, akpm,
linux-kernel, syzkaller-bugs, Arjan van de Ven, linux-rdma,
Zhu Yanjun, Jason Gunthorpe, Leon Romanovsky
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);
- sk = rxe_ns_pernet_sk6(net);
+ sk = rxe_ns_pernet_take_sk6(net);
if (sk)
- rxe_sock_put(sk, rxe_ns_pernet_set_sk6, net);
+ udp_tunnel_sock_release(sk->sk_socket);
dev_put(ndev);
}
diff --git a/drivers/infiniband/sw/rxe/rxe_ns.c b/drivers/infiniband/sw/rxe/rxe_ns.c
index 8b9d734229b24..d9d376e3c670f 100644
--- a/drivers/infiniband/sw/rxe/rxe_ns.c
+++ b/drivers/infiniband/sw/rxe/rxe_ns.c
@@ -91,6 +91,13 @@ void rxe_ns_pernet_set_sk4(struct net *net, struct sock *sk)
synchronize_rcu();
}
+struct sock *rxe_ns_pernet_take_sk4(struct net *net)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+
+ return xchg((__force struct sock **)&ns_sk->rxe_sk4, NULL);
+}
+
#if IS_ENABLED(CONFIG_IPV6)
struct sock *rxe_ns_pernet_sk6(struct net *net)
{
@@ -111,6 +118,13 @@ void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk)
rcu_assign_pointer(ns_sk->rxe_sk6, sk);
synchronize_rcu();
}
+
+struct sock *rxe_ns_pernet_take_sk6(struct net *net)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+
+ return xchg((__force struct sock **)&ns_sk->rxe_sk6, NULL);
+}
#endif /* IPV6 */
int rxe_namespace_init(void)
diff --git a/drivers/infiniband/sw/rxe/rxe_ns.h b/drivers/infiniband/sw/rxe/rxe_ns.h
index 4da2709e6b714..9d9a5106b77c8 100644
--- a/drivers/infiniband/sw/rxe/rxe_ns.h
+++ b/drivers/infiniband/sw/rxe/rxe_ns.h
@@ -5,10 +5,17 @@
struct sock *rxe_ns_pernet_sk4(struct net *net);
void rxe_ns_pernet_set_sk4(struct net *net, struct sock *sk);
+struct sock *rxe_ns_pernet_take_sk4(struct net *net);
#if IS_ENABLED(CONFIG_IPV6)
void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk);
struct sock *rxe_ns_pernet_sk6(struct net *net);
+struct sock *rxe_ns_pernet_take_sk6(struct net *net);
#else /* IPv6 */
static inline struct sock *rxe_ns_pernet_sk6(struct net *net)
{
@@ -18,6 +25,10 @@ static inline void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk)
{
}
+static inline struct sock *rxe_ns_pernet_take_sk6(struct net *net)
+{
+ return NULL;
+}
#endif /* IPv6 */
int rxe_namespace_init(void);
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [syzbot] [net?] general protection fault in kernel_sock_shutdown (4)
2026-04-23 15:01 [syzbot] [net?] general protection fault in kernel_sock_shutdown (4) syzbot
` (2 preceding siblings ...)
2026-04-24 18:08 ` Arjan van de Ven
@ 2026-04-25 1:12 ` Arjan van de Ven
2026-04-25 1:14 ` Kuniyuki Iwashima
3 siblings, 1 reply; 6+ messages in thread
From: Arjan van de Ven @ 2026-04-25 1:12 UTC (permalink / raw)
To: kuniyu
Cc: Arjan van de Ven, linux-rdma, linux-kernel, Zhu Yanjun,
Jason Gunthorpe, Leon Romanovsky
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);
- sk = rxe_ns_pernet_sk6(net);
+ sk = rxe_ns_pernet_take_sk6(net);
if (sk)
- rxe_sock_put(sk, rxe_ns_pernet_set_sk6, net);
+ udp_tunnel_sock_release(sk->sk_socket);
dev_put(ndev);
}
diff --git a/drivers/infiniband/sw/rxe/rxe_ns.c b/drivers/infiniband/sw/rxe/rxe_ns.c
index 8b9d734229b24..d9d376e3c670f 100644
--- a/drivers/infiniband/sw/rxe/rxe_ns.c
+++ b/drivers/infiniband/sw/rxe/rxe_ns.c
@@ -91,6 +91,13 @@ void rxe_ns_pernet_set_sk4(struct net *net, struct sock *sk)
synchronize_rcu();
}
+struct sock *rxe_ns_pernet_take_sk4(struct net *net)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+
+ return xchg((__force struct sock **)&ns_sk->rxe_sk4, NULL);
+}
+
#if IS_ENABLED(CONFIG_IPV6)
struct sock *rxe_ns_pernet_sk6(struct net *net)
{
@@ -111,6 +118,13 @@ void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk)
rcu_assign_pointer(ns_sk->rxe_sk6, sk);
synchronize_rcu();
}
+
+struct sock *rxe_ns_pernet_take_sk6(struct net *net)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+
+ return xchg((__force struct sock **)&ns_sk->rxe_sk6, NULL);
+}
#endif /* IPV6 */
int rxe_namespace_init(void)
diff --git a/drivers/infiniband/sw/rxe/rxe_ns.h b/drivers/infiniband/sw/rxe/rxe_ns.h
index 4da2709e6b714..9d9a5106b77c8 100644
--- a/drivers/infiniband/sw/rxe/rxe_ns.h
+++ b/drivers/infiniband/sw/rxe/rxe_ns.h
@@ -5,10 +5,17 @@
struct sock *rxe_ns_pernet_sk4(struct net *net);
void rxe_ns_pernet_set_sk4(struct net *net, struct sock *sk);
+struct sock *rxe_ns_pernet_take_sk4(struct net *net);
#if IS_ENABLED(CONFIG_IPV6)
void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk);
struct sock *rxe_ns_pernet_sk6(struct net *net);
+struct sock *rxe_ns_pernet_take_sk6(struct net *net);
#else /* IPv6 */
static inline struct sock *rxe_ns_pernet_sk6(struct net *net)
{
@@ -18,6 +25,10 @@ static inline void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk)
{
}
+static inline struct sock *rxe_ns_pernet_take_sk6(struct net *net)
+{
+ return NULL;
+}
#endif /* IPv6 */
int rxe_namespace_init(void);
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [syzbot] [net?] general protection fault in kernel_sock_shutdown (4)
2026-04-25 1:12 ` Arjan van de Ven
@ 2026-04-25 1:14 ` Kuniyuki Iwashima
0 siblings, 0 replies; 6+ messages in thread
From: Kuniyuki Iwashima @ 2026-04-25 1:14 UTC (permalink / raw)
To: Arjan van de Ven
Cc: linux-rdma, linux-kernel, Zhu Yanjun, Jason Gunthorpe,
Leon Romanovsky
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.
^ permalink raw reply [flat|nested] 6+ messages in thread