CVE-2026-89684: nfsd: fix cpntf publish race in nfs4_init_cp_state
In the Linux kernel, the following vulnerability has been resolved:
nfsd: fix cpntf publish race in nfs4initcpstate
nfs4allocinitcpntfstate() published the new cpntf entry into the s2scpstateids IDR (with cstype set) in one s2scplock section, then took the lock again to listadd() it onto pstid->sccplist. In the gap the entry is reachable by soid but cplist is still {NULL,NULL} from kzalloc. A racing OFFLOADCANCEL (soid is echoed to the client as cnrstateid, so any NFSv4.2 client can drive it) reaches managecpntfstate() -> freecpntfstatelocked() and does listdel() on the zeroed listhead, oopsing the server.
Fold the cstype assignment and the listadd() into the same critical section as idralloccyclic(), so a concurrent lookup either misses the entry or sees a fully linked cplist. INITLISTHEAD() the entry after allocation and switch freecpntfstatelocked() to listdelinit() so a stale unlink is a no-op. nfs4initcopystate() passes NULL pstid and skips the listadd, preserving NFS4COPYSTID semantics.
Affected Software
Event History
Frequently Asked Questions
Which systems are exposed to this race condition?
Linux kernel NFS servers that process NFSv4.2 copy-notification state are exposed. The race occurs when a copy-notification entry can be looked up by its state ID before it has been linked to its parent copy-state list.
What does an attacker need to trigger the issue?
An NFSv4.2 client must be able to race an OFFLOAD_CANCEL request against creation of the copy-notification state. The relevant state ID is echoed to the client as cnr_stateid, allowing the client to drive the cancellation path.
What is the likely impact if the race is triggered?
The NFS server can oops when the cancellation path attempts to delete an uninitialized list entry. This can disrupt the server's NFS service.
How can administrators tell whether the issue may already have been triggered?
A server oops occurring in the OFFLOAD_CANCEL handling path, specifically through manage_cpntf_state() and _free_cpntf_state_locked(), is consistent with this issue.