Linux: nfsd: convert nfsd_net boolean flags to unsigned long flags word
What fixes it
- 94b450977c60261903c945419d2df4a464de60c4LinuxCVE List
- 40bab0da844c142431a6b1cc21b4cf53491dac44LinuxCVE List
- 11a5fe42e1811f793e04ef885b639ea7668f439dLinuxCVE List
A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.
Description
In the Linux kernel, the following vulnerability has been resolved:
nfsd: convert nfsd_net boolean flags to unsigned long flags word
nfsd_net contains several boolean fields that are accessed from concurrent contexts without serialization. In particular, nfsd4_end_grace() guards its drain path with a plain bool:
if (nn->grace_ended) return; nn->grace_ended = true;
The read and the write are independent, and nothing in struct nfsd_net serializes them. At least two contexts can reach this code with no lock held:
laundromat path laundry_wq kworker nfs4_laundromat() nfsd4_end_grace()
RECLAIM_COMPLETE path nfsd compound kthread nfsd4_reclaim_complete() inc_reclaim_complete() nfsd4_end_grace()
Both callers can observe grace_ended == false on different CPUs, both store true, and both proceed into nfsd4_record_grace_done(), which invokes the active client_tracking_ops->grace_done callback. For tracking ops that drain reclaim_str_hashtbl (legacy_tracking_ops via nfsd4_recdir_purge_old, and the cld v1+ ops via nfsd4_cld_grace_done), grace_done calls nfs4_release_reclaim(), which walks every bucket of reclaim_str_hashtbl with no lock and calls nfs4_remove_reclaim_record() (list_del + kfree) on each entry. Two concurrent walkers corrupt the list and double-free every nfs4_client_reclaim. A concurrent nfsd4_find_reclaim_client() iterating the same bucket reads through freed memory.
A third call site exists in nfs4_state_start_net() on the skip_grace startup path, but it runs under nfsd_mutex before any client has connected and before the laundromat's first delayed work fires, so it cannot race with the two callers above.
Replace the scattered boolean fields in nfsd_net with a single unsigned long flags word and an enum nfsd_net_flag for the bit positions. The grace_ended race is fixed by using test_and_set_bit(), which is atomic on all architectures. The remaining flags (grace_end_forced, in_grace, somebody_reclaimed, track_reclaim_completes, nfsd_net_up, lockd_up) are converted to use test_bit/set_bit/clear_bit for consistency. This avoids sub-word cmpxchg issues on architectures like Hexagon that only support word-sized atomic operations.
Text from CVE List
Affected versions 12
- Linuxaffected: 362063a595be959bc08f4163e6405a0266740091 before 94b450977c60261903c945419d2df4a464de60c4CVE List
- Linuxaffected: 362063a595be959bc08f4163e6405a0266740091 before faac245ca739b66e96fb7bb43e21df537239a4e5CVE List
- Linuxaffected: 362063a595be959bc08f4163e6405a0266740091 before 40bab0da844c142431a6b1cc21b4cf53491dac44CVE List
- Linuxaffected: 362063a595be959bc08f4163e6405a0266740091 before df5922fe09a8131c793ffa86adf204999b0470f8CVE List
- Linuxaffected: 362063a595be959bc08f4163e6405a0266740091 before 11a5fe42e1811f793e04ef885b639ea7668f439dCVE List
- Linuxaffected: 5.2CVE List
- Linuxunaffected: all versions before 5.2CVE List
- Linuxunaffected: 6.6.160 through 6.6.*CVE List
- Linuxunaffected: 6.12.114 through 6.12.*CVE List
- Linuxunaffected: 6.18.57 through 6.18.*CVE List
- Linuxunaffected: 7.2.4 through 7.2.*CVE List
- Linuxunaffected: 7.3CVE List
References 5
- git.kernel.org/stable/c/94b450977c60261903c945419d2df4a464de60c4Referencevia CVE List
- git.kernel.org/stable/c/faac245ca739b66e96fb7bb43e21df537239a4e5Referencevia CVE List
- git.kernel.org/stable/c/40bab0da844c142431a6b1cc21b4cf53491dac44Referencevia CVE List
- git.kernel.org/stable/c/df5922fe09a8131c793ffa86adf204999b0470f8Referencevia CVE List
- git.kernel.org/stable/c/11a5fe42e1811f793e04ef885b639ea7668f439dReferencevia CVE List