In the Linux kernel, the following vulnerability has been resolved:
btrfs: zoned: traverse devices under chunkmutex in btrfscanactivatezone
btrfscanactivatezone() can be called with the devicelist_mutex already held, which will lead to a deadlock:
insertdevextents() // Takes devicelistmutex
-> insert_dev_extent()
-> btrfsinsertemptyitem()
-> btrfs_insert_empty_items()
-> btrfssearch_slot()
-> btrfs_cow_block()
-> _btrfscowblock()
-> btrfs_alloc_tree_block()
-> btrfsreserveextent()
-> find_free_extent()
-> findfreeextentupdateloop()
-> can_allocate_chunk()
-> btrfscanactivatezone() // Takes devicelistmutex again
Instead of using the RCU on fsdevices->devicelist we can use fsdevices->alloclist, protected by the chunk_mutex to traverse the list of active devices.
We are in the chunk allocation thread. The newer chunk allocation happens from the devices in the fsdevice->alloclist protected by the chunk_mutex.
btrfscreatechunk() lockdepassertheld(&info->chunkmutex); gatherdeviceinfo listforeachentry(device, &fsdevices->alloclist, devalloclist)
Also, a device that reappears after the mount won't join the alloclist yet and, it will be in the devlist, which we don't want to consider in the context of the chunk alloc.
[15.166572] WARNING: possible recursive locking detected [15.167117] 5.17.0-rc6-dennis #79 Not tainted [15.167487] -------------------------------------------- [15.167733] kworker/u8:3/146 is trying to acquire lock: [15.167733] ffff888102962ee0 (&fsdevs->devicelistmutex){+.+.}-{3:3}, at: findfreeextent+0x15a/0x14f0 [btrfs] [15.167733] [15.167733] but task is already holding lock: [15.167733] ffff888102962ee0 (&fsdevs->devicelistmutex){+.+.}-{3:3}, at: btrfscreatependingblockgroups+0x20a/0x560 [btrfs] [15.167733] [15.167733] other info that might help us debug this: [15.167733] Possible unsafe locking scenario: [15.167733] [15.171834] CPU0 [15.171834] ---- [15.171834] lock(&fsdevs->devicelistmutex); [15.171834] lock(&fsdevs->devicelistmutex); [15.171834] [15.171834] *** DEADLOCK *** [15.171834] [15.171834] May be due to missing lock nesting notation [15.171834] [15.171834] 5 locks held by kworker/u8:3/146: [15.171834] #0: ffff888100050938 ((wqcompletion)eventsunbound){+.+.}-{0:0}, at: processonework+0x1c3/0x5a0 [15.171834] #1: ffffc9000067be80 ((workcompletion)(&fsinfo->asyncdatareclaimwork)){+.+.}-{0:0}, at: processonework+0x1c3/0x5a0 [15.176244] #2: ffff88810521e620 (sbinternal){.+.+}-{0:0}, at: flushspace+0x335/0x600 [btrfs] [15.176244] #3: ffff888102962ee0 (&fsdevs->devicelistmutex){+.+.}-{3:3}, at: btrfscreatependingblockgroups+0x20a/0x560 [btrfs] [15.176244] #4: ffff8881152e4b78 (btrfs-dev-00){++++}-{3:3}, at: __btrfstreelock+0x27/0x130 [btrfs] [15.179641] [15.179641] stack backtrace: [15.179641] CPU: 1 PID: 146 Comm: kworker/u8:3 Not tainted 5.17.0-rc6-dennis #79 [15.179641] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1.fc35 04/01/2014 [15.179641] Workqueue: events_unbound btrfsasyncreclaimdataspace [btrfs] [15.179641] Call Trace: [15.179641] <TASK> [15.179641] dumpstacklvl+0x45/0x59 [15.179641] __lockacquire.cold+0x217/0x2b2 [15.179641] lockacquire+0xbf/0x2b0 [15.183838] ? findfreeextent+0x15a/0x14f0 [btrfs] [15.183838] __mutexlock+0x8e/0x970 [15.183838] ? findfreeextent+0x15a/0x14f0 [btrfs] [15.183838] ? findfreeextent+0x15a/0x14f0 [btrfs] [15.183838] ? lockisheldtype+0xd7/0x130 [15.183838] ? findfreeextent+0x15a/0x14f0 [btrfs] [15.183838] findfreeextent+0x15a/0x14f0 [btrfs] [15.183838] ? rawspinunlock+0x24/0x40 [15.183838] ? btrfsgetallocprofile+0x106/0x230 [btrfs] [15.187601] btrfsreserveextent+0x131/0x260 [btrfs] [15. ---truncated---
{
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2022/49xxx/CVE-2022-49079.json"
}