CVE-2026-89670 Overview
CVE-2026-89670 is a use-after-free vulnerability in the Linux kernel's NFS server (nfsd) subsystem. The flaw resides in nfsd_open_local_fh(), where a cmpxchg retry loop loads a pointer to an nfsd_file object and then calls nfsd_file_get() without holding rcu_read_lock. Because nfsd_file objects are freed via call_rcu() and the nfsd_file_slab cache is created without SLAB_TYPESAFE_BY_RCU, the backing slab page can be reclaimed between the load and the reference bump. A local attacker with the ability to trigger localio NFS operations can race the retry path against a concurrent nfsd_file_put_local() and dereference recycled memory.
Critical Impact
Successful exploitation enables local privilege escalation or kernel memory corruption through a use-after-free on a freed nfsd_file object.
Affected Products
- Linux kernel builds containing the nfsd localio open path prior to commits 559570f, 5888469, and 763c0ba
- Distributions shipping the affected nfsd_open_local_fh() retry logic
- Systems using NFS localio with the kernel NFS server enabled
Discovery Timeline
- 2026-09-11 - CVE-2026-89670 published to the National Vulnerability Database (NVD)
- 2026-09-13 - Last updated in NVD database
Technical Details for CVE-2026-89670
Vulnerability Analysis
The defect is a classic read-side race against RCU-deferred free. nfsd_file objects are freed through call_rcu() in filecache.c:296, and the slab cache is allocated with KMEM_CACHE(nfsd_file, 0) at filecache.c:789, which does not set SLAB_TYPESAFE_BY_RCU. Once an RCU grace period elapses, the slab page can be reclaimed and reused for unrelated allocations.
Inside the again: retry block of nfsd_open_local_fh(), the code performs cmpxchg(pnf, NULL, ...) to install a new file reference. If another CPU wins the race, the function loads the competing pointer and calls nfsd_file_get(new), which is a refcount_inc_not_zero() on new->nf_ref. The sole caller nfs_open_local_fh() drops rcu_read_lock before invoking this helper, leaving the pointer unguarded.
Root Cause
The root cause is a missing RCU reader-side critical section around a speculative pointer dereference. Because the object may be freed and its slab page recycled between the cmpxchg load and the refcount bump, a non-zero word at the nf_ref offset of the recycled allocation makes refcount_inc_not_zero() appear to succeed. The caller then dereferences new->nf_net and new->nf_file from freed memory.
Attack Vector
Exploitation requires local access with the ability to invoke NFS localio operations that reach nfsd_open_local_fh(). An attacker races two CPUs: one traversing the retry path while another calls nfsd_file_put_local() to drop the last reference. After the grace period, the attacker sprays the slab to place a controlled value at the nf_ref offset, causing the refcount check to pass and subsequent pointer dereferences to operate on attacker-influenced memory.
No public proof-of-concept code is available. See the upstream fix commits for technical details: Kernel Git Commit 559570f, Kernel Git Commit 5888469, and Kernel Git Commit 763c0ba.
Detection Methods for CVE-2026-89670
Indicators of Compromise
- Unexpected kernel oops or general protection faults referencing nfsd_file_get, nfsd_open_local_fh, or nfs_open_local_fh in dmesg
- KASAN use-after-free reports naming the nfsd_file slab cache
- Unexplained NFS server crashes on hosts using localio with concurrent client activity
Detection Strategies
- Enable CONFIG_KASAN on test kernels to surface the use-after-free during stress testing of NFS localio workloads
- Monitor kernel ring buffer telemetry for repeated refcount_t warnings tied to the nfsd subsystem
- Correlate kernel crash signatures with running kernel versions to identify unpatched hosts
Monitoring Recommendations
- Ship kernel logs and crash dumps to a central analytics pipeline for signature-based review
- Track kernel package versions across the fleet and flag hosts running builds without the three upstream fix commits
- Alert on NFS server daemon restarts that follow kernel faults in nfsd code paths
How to Mitigate CVE-2026-89670
Immediate Actions Required
- Apply the upstream kernel patches referenced in commits 559570f, 5888469, and 763c0ba to affected stable branches
- Restrict local access on multi-tenant systems that run nfsd with localio enabled
- Prioritize patching on NFS servers that also host untrusted local users or containers
Patch Information
The fix wraps the cmpxchg and subsequent nfsd_file_get(new) call inside rcu_read_lock() and releases it on all three exits of the if (new) block: the goto again retry, the lost-race cleanup path, and the install-succeeded path. nfsd_file_put() and nfsd_net_put() remain outside the RCU section so they can still block. Rebuild and reboot into a kernel that includes the referenced commits.
Workarounds
- Disable NFS localio functionality where operationally feasible until the patched kernel is deployed
- Unload the nfsd kernel module on systems that do not require NFS server capabilities
- Limit local shell access and container workloads on hosts that must continue running an unpatched nfsd
# Verify kernel version and unload nfsd where NFS server is not required
uname -r
sudo systemctl stop nfs-server
sudo modprobe -r nfsd
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.