CVE-2026-64378: writeback: fix race between cgroup_writeback_umount() and inode_switch_wbs()
In the Linux kernel, the following vulnerability has been resolved:
writeback: fix race between cgroupwritebackumount() and inodeswitchwbs()
When a container exits, the following BUGON() is occasionally triggered:
================================================================== VFS: Busy inodes after unmount of sdb (ext4) ------------[ cut here ]------------ kernel BUG at fs/super.c:695! CPU: 3 PID: 6 Comm: containerd-shim Tainted: G OE K 6.6 #1 pstate: 63400009 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--) pc : genericshutdownsuper+0xf0/0x100 lr : genericshutdownsuper+0xf0/0x100 Call trace: genericshutdownsuper+0xf0/0x100 killblocksuper+0x20/0x48 ext4killsb+0x28/0x60 deactivatelockedsuper+0x54/0x130 deactivatesuper+0x84/0xa0 cleanupmnt+0xa4/0x140 cleanupmnt+0x18/0x28 taskworkrun+0x78/0xe0 donotifyresume+0x204/0x240 ==================================================================
The root cause is a race between cgroupwritebackumount() and inodeswitchwbs()/cleanupofflinecgwb(). There is a window between inodepreparewbsswitch() returning true and the subsequent wbqueueisw() call. Following is the process that triggers the issue:
CPU A (umount) | CPU B (writeback) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ inodeswitchwbs/cleanupofflinecgwb atomicinc(&iswnrinflight) inodepreparewbsswitch -> passes SBACTIVE check iget(inode) genericshutdownsuper sb->sflags &= ~SBACTIVE cgroupwritebackumount(sb) smpmb() atomicread(&iswnrinflight) rcubarrier() -> no pending RCU callbacks flushworkqueue(iswwq) -> nothing queued, returns evictinodes(sb) -> Inode skipped as isw still holds a ref. sop->putsuper(sb) / destroys percpu counters / -> VFS: Busy inodes after unmount! wbqueueisw() queuework(iswwq, ...) / later in work function / inodeswitchwbsworkfn processinodeswitchwbs iput() -> evict percpucounterdec() // UAF!
Fix this by extending the RCU read-side critical section in inodeswitchwbs() and cleanupofflinecgwb() to cover from inodepreparewbsswitch() through wbqueueisw(). Since there is no sleep in this window, rcureadlock() can be used. Then add a synchronizercu() in cgroupwritebackumount() before the existing rcubarrier(), so that all in-flight switchers that have passed the SBACTIVE check have completed queuework() before flushworkqueue() is called.
The existing rcubarrier() is intentionally retained so this fix can be backported unchanged to stable kernels (5.10.y, 6.6.y, ...) that still queue switches via queuercuwork(). It is a no-op on current mainline (since commit e1b849cfa6b6 ("writeback: Avoid contention on wb->listlock when switching inodes")) and is removed in a follow-up patch.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 6.6.145.2-1 - Upgrade
Upgrade
writeback: Avoid contention on wb_queue_isw() callto a version that resolves this vulnerability.Patch e1b849cfa6b6