In the Linux kernel, the following vulnerability has been resolved:
btrfs: qgroup: fix race between quota disable and quota rescan ioctl
There's a race between a task disabling quotas and another running the rescan ioctl that can result in a use-after-free of qgroup records from the fsinfo->qgrouptree rbtree.
This happens as follows:
1) Task A enters btrfsioctlquotarescan() -> btrfsqgroup_rescan();
2) Task B enters btrfsquotadisable() and calls btrfsqgroupwaitforcompletion(), which does nothing because at that point fsinfo->qgrouprescan_running is false (it wasn't set yet by task A);
3) Task B calls btrfsfreeqgroupconfig() which starts freeing qgroups from fsinfo->qgrouptree without taking the lock fsinfo->qgroup_lock;
4) Task A enters qgrouprescanzerotracking() which starts iterating the fsinfo->qgrouptree tree while holding fsinfo->qgroup_lock, but task B is freeing qgroup records from that tree without holding the lock, resulting in a use-after-free.
Fix this by taking fsinfo->qgrouplock at btrfsfreeqgroupconfig(). Also at btrfsqgroup_rescan() don't start the rescan worker if quotas were already disabled.