[PATCH v2 2/2] RDMA/rxe: Fix up RCU usage for rxe_ns_pernet_sk6().

Kuniyuki Iwashima
2026-04-25T06:04:43Z

rxe_ns_pernet_sk6() is fundamentally broken.

rcu_read_lock() only silences rcu_dereference() splat.

The returned socket is no longer protected, and it may be
freed during ip6_dst_lookup_flow().

Let's call rxe_ns_pernet_sk6() and ip6_dst_lookup_flow()
under RCU.

Fixes: f1327abd6abe ("RDMA/rxe: Support RDMA link creation and destruction per net namespace")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
drivers/infiniband/sw/rxe/rxe_net.c | 11 ++++++++---
drivers/infiniband/sw/rxe/rxe_ns.c | 7 +------
2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 9080d4c893a1..8fca5c24c8b1 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -133,16 +133,21 @@ static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
struct in6_addr *saddr,
struct in6_addr *daddr)
{
- struct dst_entry *ndst;
+ struct dst_entry *ndst = NULL;
struct flowi6 fl6 = {};
+ struct sock *sk;

fl6.flowi6_oif = ndev->ifindex;
memcpy(&fl6.saddr, saddr, sizeof(*saddr));
memcpy(&fl6.daddr, daddr, sizeof(*daddr));
fl6.flowi6_proto = IPPROTO_UDP;

- ndst = ip6_dst_lookup_flow(net, rxe_ns_pernet_sk6(net), &fl6, NULL);
- if (IS_ERR(ndst)) {
+ rcu_read_lock();
+ sk = rxe_ns_pernet_sk6(net);
+ if (sk)
+ ndst = ip6_dst_lookup_flow(net, sk, &fl6, NULL);
+ rcu_read_unlock();
+ if (IS_ERR_OR_NULL(ndst)) {
rxe_dbg_qp(qp, "no route to %pI6\n", daddr);
return NULL;
}
diff --git a/drivers/infiniband/sw/rxe/rxe_ns.c b/drivers/infiniband/sw/rxe/rxe_ns.c
index 06eb2e2387a1..ef408ffc0558 100644
--- a/drivers/infiniband/sw/rxe/rxe_ns.c
+++ b/drivers/infiniband/sw/rxe/rxe_ns.c
@@ -91,13 +91,8 @@ static struct pernet_operations rxe_net_ops = {
struct sock *rxe_ns_pernet_sk6(struct net *net)
{
struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
- struct sock *sk;
-
- rcu_read_lock();
- sk = rcu_dereference(ns_sk->rxe_sk6);
- rcu_read_unlock();

- return sk;
+ return rcu_dereference(ns_sk->rxe_sk6);
}
#endif /* IPV6 */

--
2.54.0.rc2.544.gc7ae2d5bb8-goog