CVE-2026-89708
In the Linux kernel, the following vulnerability has been resolved:
nfsd: RCU-protect clcbsession 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->clcbsession. nfsd4probecallback_sync() flushes
clcallbackwq, but once nfsd4runcb_work() has called
rpccallasync() the rpc_task lives on rpciod; flushing the workqueue
does not wait for it. rpcshutdownclient() does drain rpciod tasks,
but uses a 1-second waiteventtimeout — tasks stuck in rpc_delay()
(e.g. 2-second NFS4ERR_DELAY retries) can outlive the drain.
destroy path rpciod
------------ ------
unhash_session(ses)
nfsd4probecallback_sync(clp)
flushworkqueue(clcallback_wq)
/ returns; rpc_task still live /
nfsd4putsession_locked(ses)
free_session(ses) -> kfree(ses)
nfsd4cbsequence_done()
reads cbclp->clcb_session
/ freed slab /
A second window exists in nfsd4processcb_update(). When
_nfsd4findbackchannel() returns NULL because unhashsession() has
already removed the destroyed session from cl_sessions,
setupcallbackclient() takes the v4.1 early return so
clp->clcbsession = ses never fires and the field retains a pointer
to the about-to-be-freed session.
Fix both by converting clcbsession to an RCU-protected pointer:
- Move the clcbsession = ses assignment in setupcallbackclient()
to after rpc_create() succeeds, so it is only published when a
working backchannel exists. Clear clcbsession on the error
return in nfsd4processcb_update(). Both stores use
rcuassignpointer().
- Annotate clcbsession with __rcu. All rpciod-side readers use
rcureadlock()/rcu_dereference() and check for NULL, bailing to
the appropriate error or requeue path:
encodecbsequence4args(), decodecbsequence4resok(),
nfsd41cbgetslot(), nfsd41cbreleaseslot(),
nfsd4cbprepare(), and nfsd4cbsequence_done().
- Switch _freesession() from kfree() to kfree_rcu() so the
session slab is not reclaimed until after an RCU grace period,
guaranteeing that rpciod readers inside rcureadlock() never
dereference freed memory.
- Pass the session pointer to the nfsdcbseq_status and
nfsdcbfree_slot tracepoints instead of having them re-read
clcbsession.
- nfsd4cbprepare() calls rpc_exit() when the session is NULL,
routing through the done/release path to requeue the callback.
Package Versions Affected
Automatically patch vulnerabilities without upgrading
CVSS Version



Related Resources
References
https://git.kernel.org/stable/c/01c5d5f58a5db9b0ee5afba2e49d3157788687b2, https://git.kernel.org/stable/c/13bdd486c3aad4fc19e6d8b9c3556a4b4c190b25, https://git.kernel.org/stable/c/2775ec1d617e665eab71ce0f13ab1f7959713a2b, https://git.kernel.org/stable/c/f164eb52b6f3cbf40f07fe379f9f421f88e02f76, https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/89xxx/CVE-2026-89708.json, https://nvd.nist.gov/vuln/detail/CVE-2026-89708, https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git