* [PATCH v2] nfsd: avoid dereferencing callback connection after unlocking
@ 2026-09-28 8:34 Jinpyo Lee
2026-10-05 15:01 ` Chuck Lever
0 siblings, 1 reply; 2+ messages in thread
From: Jinpyo Lee @ 2026-09-28 8:34 UTC (permalink / raw)
To: linux-nfs
Cc: Chuck Lever, Jeff Layton, NeilBrown, Olga Kornievskaia, Dai Ngo,
Tom Talpey, bobtobabz, Jinpyo Lee
nfsd4_process_cb_update() takes a reference on c->cn_xprt while
holding clp->cl_lock, but retains the raw nfsd4_conn pointer after
dropping the lock. The svc_xprt reference keeps the transport alive;
it does not retain the enclosing nfsd4_conn.
Concurrent transport-loss handling can unlink and free the connection
through nfsd4_conn_lost(). If setup_callback_client() subsequently
fails, the original error path evaluates c->cn_xprt through the freed
connection in order to release the transport reference, resulting in
a use-after-free read.
Store c->cn_xprt in a separate local variable and take its reference
while clp->cl_lock still protects the connection. After dropping the
lock, use only the independently referenced transport for callback
setup and error cleanup. This avoids dereferencing nfsd4_conn outside
its protected lifetime.
The KASAN reproducer established two NFSv4.1 connections, selected a
backchannel connection, caused normal transport-loss handling to
release that connection, and injected one task-scoped allocation
failure during callback setup. setup_callback_client() returned
-ENOMEM after the connection had been released. With this patch
applied, the affected error path completed without the original KASAN
report.
The fault injection makes the callback-setup failure deterministic; it
does not demonstrate a reliable remote-only trigger. A source
reproducer and the complete KASAN log are available privately on
request.
Basic NFSv4.2 and NFSv3 read/write/unmount smoke tests also passed.
fs/nfsd/nfs4callback.o was additionally compile-tested with GCC 13.3
without new warnings.
The vulnerability research and validation were conducted by members of
the Tobabz team as part of the Best of the Best 15th program.
Fixes: a4abc6b12eb1 ("nfsd: Fix svc_xprt refcnt leak when setup callback client failed")
Assisted-by: LLM
Signed-off-by: Jinpyo Lee <bint4b13@gmail.com>
---
Changes in v2:
- Expand the description of the lifetime bug and runtime validation.
- No code changes.
fs/nfsd/nfs4callback.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index a6b31d3f2..70ab4fd32 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1800,6 +1800,7 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
struct nfs4_client *clp = cb->cb_clp;
struct nfsd4_session *ses = NULL;
struct nfsd4_conn *c;
+ struct svc_xprt *cb_xprt = NULL;
int err;
trace_nfsd_cb_bc_update(clp, cb);
@@ -1833,8 +1834,9 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
c = __nfsd4_find_backchannel(clp);
if (c) {
- svc_xprt_get(c->cn_xprt);
- conn.cb_xprt = c->cn_xprt;
+ cb_xprt = c->cn_xprt;
+ svc_xprt_get(cb_xprt);
+ conn.cb_xprt = cb_xprt;
ses = c->cn_session;
}
spin_unlock(&clp->cl_lock);
@@ -1842,8 +1844,8 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
err = setup_callback_client(clp, &conn, ses);
if (err) {
nfsd4_mark_cb_down(clp);
- if (c)
- svc_xprt_put(c->cn_xprt);
+ if (cb_xprt)
+ svc_xprt_put(cb_xprt);
rcu_assign_pointer(clp->cl_cb_session, ses);
return;
}
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] nfsd: avoid dereferencing callback connection after unlocking
2026-09-28 8:34 [PATCH v2] nfsd: avoid dereferencing callback connection after unlocking Jinpyo Lee
@ 2026-10-05 15:01 ` Chuck Lever
0 siblings, 0 replies; 2+ messages in thread
From: Chuck Lever @ 2026-10-05 15:01 UTC (permalink / raw)
To: linux-nfs, Jinpyo Lee
Cc: Jeff Layton, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
bobtobabz
On Mon, 28 Sep 2026 17:34:24 +0900, Jinpyo Lee wrote:
> nfsd4_process_cb_update() takes a reference on c->cn_xprt while
> holding clp->cl_lock, but retains the raw nfsd4_conn pointer after
> dropping the lock. The svc_xprt reference keeps the transport alive;
> it does not retain the enclosing nfsd4_conn.
>
> Concurrent transport-loss handling can unlink and free the connection
> through nfsd4_conn_lost(). If setup_callback_client() subsequently
> fails, the original error path evaluates c->cn_xprt through the freed
> connection in order to release the transport reference, resulting in
> a use-after-free read.
>
> [...]
Applied, thanks!
[1/1] nfsd: avoid dereferencing callback connection after unlocking
commit: c186c6483c45f5c0867faad9c63f95a53dad46e7
Best regards,
--
Chuck Lever <cel@kernel.org>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-05 15:01 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-28 8:34 [PATCH v2] nfsd: avoid dereferencing callback connection after unlocking Jinpyo Lee
2026-10-05 15:01 ` Chuck Lever
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox