From: sashiko-bot@kernel.org
To: "Li Xiasong" <lixiasong1@huawei.com>
Cc: linux-rdma@vger.kernel.org, "Chuck Lever" <cel@kernel.org>,
"Jeff Layton" <jlayton@kernel.org>,
"Anna Schumaker" <anna@kernel.org>
Subject: Re: [PATCH 2/3] rpcrdma: Pin notifications during removal callbacks
Date: Fri, 23 Oct 2026 12:49:05 +0000 [thread overview]
Message-ID: <sashiko-outbox-182794@kernel.org> (raw)
In-Reply-To: <20261023125033.528835-3-lixiasong1@huawei.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] xprtrdma: use-after-free of ep->re_xprt in rpcrdma_ep_removal_done()
--
commit a86275f4d3e636fe6cee2fb36e6c7d9cb58af726
Author: Li Xiasong <lixiasong1@huawei.com>
rpcrdma: Pin notifications during removal callbacks
This commit adds reference-counting get and put callbacks to
rpcrdma_notification and serializes rpcrdma_rn_unregister() with
rpcrdma_device_mutex so device removal callbacks can safely run outside the
mutex.
[ ... ]
> diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
> index be335eed329d1..9b00e71c80a7a 100644
> --- a/net/sunrpc/xprtrdma/verbs.c
> +++ b/net/sunrpc/xprtrdma/verbs.c
> @@ -297,6 +297,22 @@ static void rpcrdma_ep_removal_done(struct rpcrdma_notification *rn)
> xprt_force_disconnect(ep->re_xprt);
> }
>
> +static bool rpcrdma_ep_removal_get(struct rpcrdma_notification *rn)
> +{
> + struct rpcrdma_ep *ep = container_of(rn, struct rpcrdma_ep, re_rn);
> +
> + return kref_get_unless_zero(&ep->re_kref);
> +}
> +
> +static void rpcrdma_ep_removal_put(struct rpcrdma_notification *rn)
> +{
> + struct rpcrdma_ep *ep = container_of(rn, struct rpcrdma_ep, re_rn);
> + struct rdma_cm_id *id = ep->re_id;
> +
> + if (rpcrdma_ep_put(ep))
> + rdma_destroy_id(id);
> +}
[Severity: High]
Can pinning only ep->re_kref in rpcrdma_ep_removal_get() lead to a
use-after-free of ep->re_xprt in rpcrdma_ep_removal_done()?
ep->re_xprt is an unreferenced pointer to &r_xprt->rx_xprt. When
rpcrdma_remove_one() acquires a reference on ep->re_kref via
rpcrdma_ep_removal_get() and drops rpcrdma_device_mutex before calling
rpcrdma_ep_removal_done(), a concurrent transport teardown in
xprt_destroy() -> xprt_destroy_cb() -> xprt_rdma_destroy() can run:
net/sunrpc/xprtrdma/verbs.c:rpcrdma_xprt_disconnect() {
...
if (rpcrdma_ep_put(ep))
rdma_destroy_id(id);
r_xprt->rx_ep = NULL;
}
Because rpcrdma_remove_one() is holding the extra reference on ep->re_kref,
rpcrdma_ep_put(ep) does not reach zero and returns 0 without calling
rpcrdma_ep_destroy() or rpcrdma_rn_unregister(). rpcrdma_xprt_disconnect()
then returns immediately to xprt_rdma_destroy():
net/sunrpc/xprtrdma/transport.c:xprt_rdma_destroy() {
...
rpcrdma_xprt_disconnect(r_xprt);
...
xprt_rdma_free_addresses(xprt);
xprt_free(xprt);
}
xprt_rdma_destroy() frees xprt->address_strings[] and schedules xprt for
destruction via kfree_rcu() while rpcrdma_remove_one() is executing in
sleepable process context outside any RCU read-side section. When
rpcrdma_ep_removal_done() then calls xprt_force_disconnect(ep->re_xprt), it
accesses the freed address_strings[] in trace_xprt_disconnect_force(), locks
xprt->transport_lock, and schedules xprt->task_cleanup on the freed
rpc_xprt.
The follow-up change ("xprtrdma: Wake connect worker on device removal")
still leaves this window open when rpcrdma_ep_removal_done() observes
xchg(&ep->re_connect_status, -ENODEV) == 1 and transitions
ep->re_force_disconnect from 0 to 1 via rpcrdma_force_disconnect(ep) before
rpcrdma_xprt_drain() flushes the receive queue (or when no receive WRs are
posted), as rpcrdma_xprt_disconnect() will still return with ep->re_kref > 0
while rpcrdma_force_disconnect() proceeds to call
xprt_force_disconnect(ep->re_xprt).
Should rpcrdma_ep_removal_get() also acquire a reference on ep->re_xprt (for
example via xprt_get_unless_zero(), or by ensuring transport teardown waits
for in-flight removal callbacks) before rpcrdma_ep_removal_done()
dereferences ep->re_xprt?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261023125033.528835-1-lixiasong1@huawei.com?part=2
next prev parent reply other threads:[~2026-10-23 12:49 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-23 12:50 [PATCH 0/3] rpcrdma: Fix device removal races and endpoint cleanup Li Xiasong
2026-10-23 12:50 ` [PATCH 1/3] rpcrdma: Serialize notification registration with device removal Li Xiasong
2026-10-23 12:38 ` sashiko-bot
2026-10-23 19:28 ` Chuck Lever
2026-10-23 12:50 ` [PATCH 2/3] rpcrdma: Pin notifications during removal callbacks Li Xiasong
2026-10-23 12:49 ` sashiko-bot [this message]
2026-10-23 19:31 ` Chuck Lever
2026-10-23 12:50 ` [PATCH 3/3] xprtrdma: Wake connect worker on device removal Li Xiasong
2026-10-23 12:49 ` sashiko-bot
2026-10-23 19:35 ` Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-182794@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=anna@kernel.org \
--cc=cel@kernel.org \
--cc=jlayton@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=lixiasong1@huawei.com \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox