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

Zhu Yanjun
2026-04-25T21:26:25Z

在 2026/4/24 23:04, Kuniyuki Iwashima 写道:
> 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>

Thanks a lot. Please David Ahern, Leon and Jason comment.

Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>

Zhu Yanjun

> ---
> 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 */
>