PT-2026-90424 · Linux · Linux

CVE-2026-89708

·

Published

2026-09-11

·

Updated

2026-09-11

None

No severity ratings or metrics are available. When they are, we'll update the corresponding info on the page.
In the Linux kernel, the following vulnerability has been resolved:
nfsd: RCU-protect cl cb session to fix use-after-free on session teardown
After a DESTROY SESSION the per-session teardown path can free a session while rpciod still holds an inflight callback rpc task that dereferences clp->cl cb session. nfsd4 probe callback sync() flushes cl callback wq, but once nfsd4 run cb work() has called rpc call async() the rpc task lives on rpciod; flushing the workqueue does not wait for it. rpc shutdown client() does drain rpciod tasks, but uses a 1-second wait event timeout — tasks stuck in rpc delay() (e.g. 2-second NFS4ERR DELAY retries) can outlive the drain.
destroy path rpciod

unhash session(ses) nfsd4 probe callback sync(clp) flush workqueue(cl callback wq) /* returns; rpc task still live / nfsd4 put session locked(ses) free session(ses) -> kfree(ses) nfsd4 cb sequence done() reads cb clp->cl cb session / freed slab */
A second window exists in nfsd4 process cb update(). When nfsd4 find backchannel() returns NULL because unhash session() has already removed the destroyed session from cl sessions, setup callback client() takes the v4.1 early return so clp->cl cb session = ses never fires and the field retains a pointer to the about-to-be-freed session.
Fix both by converting cl cb session to an RCU-protected pointer:
  • Move the cl cb session = ses assignment in setup callback client() to after rpc create() succeeds, so it is only published when a working backchannel exists. Clear cl cb session on the error return in nfsd4 process cb update(). Both stores use rcu assign pointer().
  • Annotate cl cb session with rcu. All rpciod-side readers use rcu read lock()/rcu dereference() and check for NULL, bailing to the appropriate error or requeue path: encode cb sequence4args(), decode cb sequence4resok(), nfsd41 cb get slot(), nfsd41 cb release slot(), nfsd4 cb prepare(), and nfsd4 cb sequence done().
  • Switch free session() from kfree() to kfree rcu() so the session slab is not reclaimed until after an RCU grace period, guaranteeing that rpciod readers inside rcu read lock() never dereference freed memory.
  • Pass the session pointer to the nfsd cb seq status and nfsd cb free slot tracepoints instead of having them re-read cl cb session.
  • nfsd4 cb prepare() calls rpc exit() when the session is NULL, routing through the done/release path to requeue the callback.
Found an issue in the description? Have something to add? Feel free to write us 👾

Related Identifiers

CVE-2026-89708

Affected Products

Linux