In the Linux kernel, the following vulnerability has been resolved:
ubifs: Fix deadlock in concurrent rename whiteout and inode writeback
Following hung tasks: [ 77.028764] task:kworker/u8:4 state:D stack: 0 pid: 132 [ 77.028820] Call Trace: [ 77.029027] schedule+0x8c/0x1b0 [ 77.029067] mutexlock+0x50/0x60 [ 77.029074] ubifswriteinode+0x68/0x1f0 [ubifs] [ 77.029117] _writebacksingleinode+0x43c/0x570 [ 77.029128] writebacksbinodes+0x259/0x740 [ 77.029148] wbwriteback+0x107/0x4d0 [ 77.029163] wbworkfn+0x162/0x7b0
[ 92.390442] task:aa state:D stack: 0 pid: 1506 [ 92.390448] Call Trace: [ 92.390458] schedule+0x8c/0x1b0 [ 92.390461] wbwaitforcompletion+0x82/0xd0 [ 92.390469] _writebackinodessbnr+0xb2/0x110 [ 92.390472] writebackinodessbnr+0x14/0x20 [ 92.390476] ubifsbudgetspace+0x705/0xdd0 [ubifs] [ 92.390503] dorename.cold+0x7f/0x187 [ubifs] [ 92.390549] ubifsrename+0x8b/0x180 [ubifs] [ 92.390571] vfsrename+0xdb2/0x1170 [ 92.390580] dorenameat2+0x554/0x770
, are caused by concurrent rename whiteout and inode writeback processes: renamewhiteout(Thread 1) wbworkfn(Thread2) ubifsrename dorename lock4inodes (Hold uimutex) ubifsbudgetspace makefreespace shrinkliability _writebackinodessbnr bdisplitworktowbs (Queue new wb work) wbdowriteback(wb work) _writebacksingleinode ubifswriteinode LOCK(uimutex) ↑ wbwaitfor_completion (Wait wb work) <-- deadlock!
Reproducer (Detail program in [Link]): 1. SYSrenameat2("/mp/dir/file", "/mp/dir/whiteout", RENAMEWHITEOUT) 2. Consume out of space before kernel(mdelay) doing budget for whiteout
Fix it by doing whiteout space budget before locking ubifs inodes. BTW, it also fixes wrong goto tag 'outrelease' in whiteout budget error handling path(It should at least recover dir isize and unlock 4 ubifs inodes).