tOS Btrfs Driver — Heap Out-of-Bounds Read in Superblock Parsing
In the btrfs mount routine of btrfs.c, the sys_chunk_array_size field of an on-disk btrfs superblock is passed directly as the walk bound to btrfs_parse_sys_chunk_array without being validated against the actual size of the fixed 2048-byte sys_chunk_array member it indexes into. A crafted btrfs filesystem image with an oversized sys_chunk_array_size value causes the parser to read past the end of the superblock's heap allocation, potentially leaking adjacent heap memory into the filesystem's internal chunk-mapping table and causing further out-of-bounds disk reads derived from the corrupted mapping. This is reachable simply by mounting an attacker-supplied btrfs disk image.
After finding filesystem parsing vulnerabilities in the NTFS, EXT2, and XFS drivers in ASI-2026-0006, 0007, and 0008, we decided to review the Btrfs driver with the same lens. While reviewing the mount routine in btrfs.c, we found that the sys_chunk_array_size field in the superblock was used directly as the parser's walk bound with no validation against the actual size of the fixed 2048-byte sys_chunk_array member it indexes into.
The sys_chunk_array_size field of an on-disk btrfs superblock was passed directly as the walk bound to btrfs_parse_sys_chunk_array. However, this field is an independent on-disk value, unrelated to the actual size of the sys_chunk_array[2048] member, and was used with no clamp at all. When sys_chunk_array_size exceeds 2048, the parser reads past the end of the superblock's heap allocation, potentially leaking adjacent heap memory into the filesystem's internal chunk-mapping table and causing further out-of-bounds disk reads derived from the corrupted mapping.
An attacker prepares a malicious btrfs filesystem image with the sys_chunk_array_size field in its superblock set above 2048. When the victim mounts this image, the parser reads past the end of the superblock's heap allocation; adjacent heap memory can leak into the filesystem's internal chunk-mapping table, and this corrupted mapping can lead to further out-of-bounds disk reads. Exploitation requires nothing more than mounting the malicious image.
sys_chunk_array_size is an independent on-disk field, not derived from the actual size of the sys_chunk_array[2048] member, and was passed unclamped as the parser's walk bound.
The value is now clamped to sizeof(sys_chunk_array) before being passed to the parser, so it can never cause a walk past the superblock's heap allocation.
CWE-125, CWE-20
Artfical DT Developer Talha Berk Arslan