In the Linux kernel, the following vulnerability has been resolved:
btrfs: fix transaction atomicity bug when enabling simple quotas
Set squota incompat bit before committing the transaction that enables the feature.
With the config CONFIGBTRFSASSERT enabled, an assertion failure occurs regarding the simple quota feature.
[5.596534] assertion failed: btrfsfsincompat(fsinfo, SIMPLEQUOTA), in fs/btrfs/qgroup.c:365 [5.597098] ------------[ cut here ]------------ [5.597371] kernel BUG at fs/btrfs/qgroup.c:365! [5.597946] CPU: 1 UID: 0 PID: 268 Comm: mount Not tainted 6.13.0-rc2-00031-gf92f4749861b #146 [5.598450] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 [5.599008] RIP: 0010:btrfsreadqgroupconfig+0x74d/0x7a0 [5.604303] <TASK> [5.605230] ? btrfsreadqgroupconfig+0x74d/0x7a0 [5.605538] ? excinvalidop+0x56/0x70 [5.605775] ? btrfsreadqgroupconfig+0x74d/0x7a0 [5.606066] ? asmexcinvalidop+0x1f/0x30 [5.606441] ? btrfsreadqgroupconfig+0x74d/0x7a0 [5.606741] ? btrfsreadqgroupconfig+0x74d/0x7a0 [5.607038] ? trytowakeup+0x317/0x760 [5.607286] openctree+0xd9c/0x1710 [5.607509] btrfsgettree+0x58a/0x7e0 [5.608002] vfsgettree+0x2e/0x100 [5.608224] fcmount+0x16/0x60 [5.608420] btrfsgettree+0x2f8/0x7e0 [5.608897] vfsgettree+0x2e/0x100 [5.609121] pathmount+0x4c8/0xbc0 [5.609538] _x64sys_mount+0x10d/0x150
The issue can be easily reproduced using the following reproducer:
root@q:linux# cat repro.sh set -e
mkfs.btrfs -q -f /dev/sdb mount /dev/sdb /mnt/btrfs btrfs quota enable -s /mnt/btrfs umount /mnt/btrfs mount /dev/sdb /mnt/btrfs
The issue is that when enabling quotas, at btrfsquotaenable(), we set BTRFSQGROUPSTATUSFLAGSIMPLEMODE at fsinfo->qgroupflags and persist it in the quota root in the item with the key BTRFSQGROUPSTATUSKEY, but we only set the incompat bit BTRFSFEATUREINCOMPATSIMPLEQUOTA after we commit the transaction used to enable simple quotas.
This means that if after that transaction commit we unmount the filesystem without starting and committing any other transaction, or we have a power failure, the next time we mount the filesystem we will find the flag BTRFSQGROUPSTATUSFLAGSIMPLEMODE set in the item with the key BTRFSQGROUPSTATUSKEY but we will not find the incompat bit BTRFSFEATUREINCOMPATSIMPLEQUOTA set in the superblock, triggering an assertion failure at:
btrfsreadqgroupconfig() -> qgroupreadenablegen()
To fix this issue, set the BTRFSFEATUREINCOMPATSIMPLEQUOTA flag immediately after setting the BTRFSQGROUPSTATUSFLAGSIMPLE_MODE. This ensures that both flags are flushed to disk within the same transaction.