]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xprtrdma: Initialize re_id before removal registration
authorChris Mason <clm@meta.com>
Thu, 4 Jun 2026 17:06:34 +0000 (13:06 -0400)
committerAnna Schumaker <anna.schumaker@hammerspace.com>
Wed, 10 Jun 2026 19:47:06 +0000 (15:47 -0400)
rpcrdma_create_id() registers ep->re_rn with the rpcrdma ib_client
before returning the new rdma_cm_id to rpcrdma_ep_create(). However
rpcrdma_ep_create() currently stores that pointer in ep->re_id only
after rpcrdma_create_id() returns.

A local administrator can race an NFS/RDMA mount against RDMA device
removal. If rpcrdma_remove_one() observes the just-registered
notification before rpcrdma_ep_create() assigns ep->re_id,
rpcrdma_ep_removal_done() calls trace_xprtrdma_device_removal(NULL).
The tracepoint dereferences id->device->name and copies
id->route.addr.dst_addr, so the callback can crash the kernel with a
NULL pointer dereference.

Store the rdma_cm_id in ep->re_id immediately before publishing
ep->re_rn. The existing error path still destroys the id directly if
registration fails; ep is then freed by the caller without using
ep->re_id. Remove the later duplicate assignment in rpcrdma_ep_create().

Fixes: 3f4eb9ff9234 ("xprtrdma: Handle device removal outside of the CM event handler")
Assisted-by: kres:openai-gpt-5
Signed-off-by: Chris Mason <clm@meta.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
net/sunrpc/xprtrdma/verbs.c

index 7ddab4ed5d0366c01aa36cf0411ca8e70748e47b..a192b77ce739dcc2b20e099765fc853a417eecaa 100644 (file)
@@ -334,6 +334,7 @@ static struct rdma_cm_id *rpcrdma_create_id(struct rpcrdma_xprt *r_xprt,
        if (rc)
                goto out;
 
+       ep->re_id = id;
        rc = rpcrdma_rn_register(id->device, &ep->re_rn, rpcrdma_ep_removal_done);
        if (rc)
                goto out;
@@ -406,7 +407,6 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
        }
        __module_get(THIS_MODULE);
        device = id->device;
-       ep->re_id = id;
        reinit_completion(&ep->re_done);
 
        ep->re_max_requests = r_xprt->rx_xprt.max_reqs;