In the Linux kernel, the following vulnerability has been resolved:
writeback: fix race between cgroupwritebackumount() and inodeswitchwbs()
When a container exits, the following BUG_ON() 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
The root cause is a race between cgroupwritebackumount() and inodeswitchwbs()/cleanupofflinecgwb(). There is a window between inodepreparewbsswitch() returning true and the subsequent wbqueue_isw() 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.
{
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/64xxx/CVE-2026-64378.json",
"cna_assigner": "Linux"
}