In the Linux kernel, the following vulnerability has been resolved:
btrfs: fix racy bitfield write in btrfs_clear_space_info_full()
From the memory-barriers.txt document regarding memory barrier ordering guarantees:
(*) These guarantees do not apply to bitfields, because compilers often generate code to modify these using non-atomic read-modify-write sequences. Do not attempt to use bitfields to synchronize parallel algorithms.
(*) Even in cases where bitfields are protected by locks, all fields in a given bitfield must be protected by one lock. If two fields in a given bitfield are protected by different locks, the compiler's non-atomic read-modify-write sequences can cause an update to one field to corrupt the value of an adjacent field.
btrfs_space_info has a bitfield sharing an underlying word consisting of the fields full, chunk_alloc, and flush:
struct btrfs_space_info { struct btrfs_fs_info * fs_info; /* 0 8 / struct btrfs_space_info * parent; / 8 8 / ... int clamp; / 172 4 / unsigned int full:1; / 176: 0 4 / unsigned int chunk_alloc:1; / 176: 1 4 / unsigned int flush:1; / 176: 2 4 */ ...
Therefore, to be safe from parallel read-modify-writes losing a write to one of the bitfield members protected by a lock, all writes to all the bitfields must use the lock. They almost universally do, except for btrfs_clear_space_info_full() which iterates over the space_infos and writes out found->full = 0 without a lock.
Imagine that we have one thread completing a transaction in which we finished deleting a block_group and are thus calling btrfs_clear_space_info_full() while simultaneously the data reclaim ticket infrastructure is running do_async_reclaim_data_space():...
Exploitability
AV:LAC:LPR:LUI:NScope
S:UImpact
C:NI:NA:H5.5/CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H