CVE-2025-37931
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
20/05/2025
Last modified:
19/12/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: adjust subpage bit start based on sectorsize<br />
<br />
When running machines with 64k page size and a 16k nodesize we started<br />
seeing tree log corruption in production. This turned out to be because<br />
we were not writing out dirty blocks sometimes, so this in fact affects<br />
all metadata writes.<br />
<br />
When writing out a subpage EB we scan the subpage bitmap for a dirty<br />
range. If the range isn&#39;t dirty we do<br />
<br />
bit_start++;<br />
<br />
to move onto the next bit. The problem is the bitmap is based on the<br />
number of sectors that an EB has. So in this case, we have a 64k<br />
pagesize, 16k nodesize, but a 4k sectorsize. This means our bitmap is 4<br />
bits for every node. With a 64k page size we end up with 4 nodes per<br />
page.<br />
<br />
To make this easier this is how everything looks<br />
<br />
[0 16k 32k 48k ] logical address<br />
[0 4 8 12 ] radix tree offset<br />
[ 64k page ] folio<br />
[ 16k eb ][ 16k eb ][ 16k eb ][ 16k eb ] extent buffers<br />
[ | | | | | | | | | | | | | | | | ] bitmap<br />
<br />
Now we use all of our addressing based on fs_info->sectorsize_bits, so<br />
as you can see the above our 16k eb->start turns into radix entry 4.<br />
<br />
When we find a dirty range for our eb, we correctly do bit_start +=<br />
sectors_per_node, because if we start at bit 0, the next bit for the<br />
next eb is 4, to correspond to eb->start 16k.<br />
<br />
However if our range is clean, we will do bit_start++, which will now<br />
put us offset from our radix tree entries.<br />
<br />
In our case, assume that the first time we check the bitmap the block is<br />
not dirty, we increment bit_start so now it == 1, and then we loop<br />
around and check again. This time it is dirty, and we go to find that<br />
start using the following equation<br />
<br />
start = folio_start + bit_start * fs_info->sectorsize;<br />
<br />
so in the case above, eb->start 0 is now dirty, and we calculate start<br />
as<br />
<br />
0 + 1 * fs_info->sectorsize = 4096<br />
4096 >> 12 = 1<br />
<br />
Now we&#39;re looking up the radix tree for 1, and we won&#39;t find an eb.<br />
What&#39;s worse is now we&#39;re using bit_start == 1, so we do bit_start +=<br />
sectors_per_node, which is now 5. If that eb is dirty we will run into<br />
the same thing, we will look at an offset that is not populated in the<br />
radix tree, and now we&#39;re skipping the writeout of dirty extent buffers.<br />
<br />
The best fix for this is to not use sectorsize_bits to address nodes,<br />
but that&#39;s a larger change. Since this is a fs corruption problem fix<br />
it simply by always using sectors_per_node to increment the start bit.
Impact
Base Score 3.x
5.50
Severity 3.x
MEDIUM
Vulnerable products and versions
| CPE | From | Up to |
|---|---|---|
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.13 (including) | 6.1.151 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.2 (including) | 6.6.105 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.7 (including) | 6.12.28 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.13 (including) | 6.14.6 (excluding) |
| cpe:2.3:o:linux:linux_kernel:6.15:rc1:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.15:rc2:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.15:rc3:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.15:rc4:*:*:*:*:*:* | ||
| cpe:2.3:o:debian:debian_linux:11.0:*:*:*:*:*:*:* |
To consult the complete list of CPE names with products and versions, see this page
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/396f4002710030ea1cfd4c789ebaf0a6969ab34f
- https://git.kernel.org/stable/c/5111b148360f50cac9abbae8fca44cc0ac4bf9bf
- https://git.kernel.org/stable/c/977849e8acd2466ac3cb49e04a3ecc73837f6b90
- https://git.kernel.org/stable/c/b80db09b614cb7edec5bada1bc7c7b0eb3b453ea
- https://git.kernel.org/stable/c/e08e49d986f82c30f42ad0ed43ebbede1e1e3739
- https://lists.debian.org/debian-lts-announce/2025/10/msg00008.html



