Look up another CVE · open CVE-2026-89708 in the interactive tracker
CVE-2026-89708
nfsd: RCU-protect cl_cb_session to fix use-after-free on session teardown
Published 2026-09-11 (37 days ago) by the Linux kernel CNA. Subsystem fs/nfsd. Debian urgency: not yet assigned.
What to do, per Debian release
Debian's own status for CVE-2026-89708 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source
| Release | Status | Version | What this means |
|---|---|---|---|
| Debian 12bookworm | vulnerable | 6.1.190-1 | No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication. |
| Debian 13trixie | fixedDSA-6528-1 · 2026-09-29 · text | 6.12.111-1 | Update the kernel and reboot. DSA-6528-1 shipped the fix on 2026-09-29, in 6.12.111-1. A running kernel keeps the old code until the machine restarts. |
| Debian 14forky | fixed | 7.2.6-1 | Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts. |
| Debian unstablesid | fixed | 7.2.6-1 | Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts. |
| Debian 12bookworm · linux-6.12 | fixedDLA-4817-1 · 2026-10-04 · text | 6.12.111-1~deb12u1 | Update the kernel and reboot. DLA-4817-1 shipped the fix on 2026-10-04, in 6.12.111-1~deb12u1. A running kernel keeps the old code until the machine restarts. |
The vulnerability
What the bug is
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.
Where it lives
The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4state.c
fs/nfsd/state.h
fs/nfsd/trace.h
- What this is
- KERNEL NFSD, SUNRPC, AND LOCKD SERVERSMAINTAINERS section matched on fs/nfsd/ · linux-nfs@vger.kernel.org · Supported
- Kernel module
- nfsd
Check it on the machine
grep -wE 'CONFIG_NFSD|CONFIG_NFSD_V4' /boot/config-$(uname -r)Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.
lsmod | grep -w nfsdPrints a line if that module is loaded right now, and nothing if it is not. One that is not loaded can still be loaded later by anything that needs it.
Show whether Debian builds this, per release
Debian builds this as a loadable module. Every release below compiles it as a module on every flavour, so whether the code is in the running kernel depends on whether that module is loaded.
- bookworm, trixie, forky, sid, bookworm · linux-6.12m
- m
- a loadable module on every flavour - check lsmod, can be blacklisted
- Build switches
- CONFIG_NFSD, CONFIG_NFSD_V4
- Reads as
- all on means the file is compiled; any one off means it is not.
From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages
Signals
- Published
- 2026-09-11 (37 days ago)source
- CVSS
- 9.8 critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:Hsource recompute it - Attack vector
- network (AV:N)source
- EPSS
- 0.44%, higher than 37.2% of all CVEssource
- CISA KEV
- not listedthe KEV catalogue
- Debian urgency
- not yet assignedsource
- Subsystem
- fs/nfsd
Upstream fixes
The versions the CNA records as introducing and fixing this, and the commit for each. source
| Introduced | Fixed in | Commit |
|---|---|---|
| 2.6.38 | 6.12.111 | 2775ec1d617e |
| 2.6.38 | 6.18.50 | f164eb52b6f3 |
| 2.6.38 | 7.2.4 | 13bdd486c3aa |
| 2.6.38 | 7.3 | 01c5d5f58a5d |
Debian advisories
| Advisory | Date | Shipped to | Debian |
|---|---|---|---|
| DLA-4817-1 | 2026-10-04 | bookworm 6.12.111-1~deb12u1 | tracker |
| DSA-6528-1 | 2026-09-29 | trixie 6.12.111-1 | tracker |
Why the CNA scored it this way
Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source
- AV:NAttack vector, network
- The UAF is in nfsd NFSv4.1 session teardown (nfsd4_destroy_session) and the rpciod callback path (nfsd4_cb_sequence_done). DESTROY_SESSION and the inflight CB_COMPOUND run over TCP/2049, so a remote NFS client reaches the bug with no local access.
- AC:LAttack complexity, low
- The attacker controls both sides: they keep a callback rpc_task on rpciod (e.g. NFS4ERR_DELAY so rpc_delay is 2s) and send DESTROY_SESSION. flush_workqueue does not wait for rpciod, and rpc_shutdown_client's 1s drain can expire first, so the window is attacker-driven and retryable.
- PR:NPrivileges required, none
- Typical nfsd exports use AUTH_SYS/AUTH_NULL, so RPC identities are self-asserted. EXCHANGE_ID, CREATE_SESSION with a backchannel, OPEN, and DESTROY_SESSION succeed for any host allowed by the export; nfsd4_mach_creds_match is a no-op under default SP4_NONE. No local account is required.
- UI:NUser interaction, none
- The attacking NFS client issues CREATE_SESSION, OPEN/CB_RECALL traffic, NFS4ERR_DELAY replies, and DESTROY_SESSION itself. No victim on the server must mount a filesystem, open a file, or take any other action.
- S:UScope, unchanged
- The use-after-free corrupts a kmalloc'd nfsd4_session in the host nfsd kernel. Impact stays in that kernel security authority and does not cross a VM, IOMMU, or sandbox boundary.
- C:HConfidentiality impact, high
- After free_session kfree's the session, rpciod still reads se_sessionid and se_cb_seq_nr in encode_cb_sequence4args and decode_cb_sequence4resok. Reclaim of that slab lets the attacker disclose kernel memory via the callback they receive. Per kernel guidance a UAF is C:H.
- I:HIntegrity impact, high
- The same dangling cl_cb_session is written by update_cb_slot_table (attacker-controlled target_highest_slotid), grab_slot/nfsd41_cb_release_slot (se_cb_slot_avail and se_lock), and nfsd4_cb_sequence_done (se_cb_seq_nr++). That is a UAF write primitive for heap corruption and control-flow hijack.
- A:HAvailability impact, high
- Use-after-free of struct nfsd4_session from an rpciod callback oopses or panics the NFS server even without full exploitation, and the attacker can repeat DESTROY_SESSION against inflight callbacks to deny service.