CVE-2023-54121
Gravedad:
Pendiente de análisis
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
24/12/2025
Última modificación:
24/12/2025
Descripción
*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: fix incorrect splitting in btrfs_drop_extent_map_range<br />
<br />
In production we were seeing a variety of WARN_ON()&#39;s in the extent_map<br />
code, specifically in btrfs_drop_extent_map_range() when we have to call<br />
add_extent_mapping() for our second split.<br />
<br />
Consider the following extent map layout<br />
<br />
PINNED<br />
[0 16K) [32K, 48K)<br />
<br />
and then we call btrfs_drop_extent_map_range for [0, 36K), with<br />
skip_pinned == true. The initial loop will have<br />
<br />
start = 0<br />
end = 36K<br />
len = 36K<br />
<br />
we will find the [0, 16k) extent, but since we are pinned we will skip<br />
it, which has this code<br />
<br />
start = em_end;<br />
if (end != (u64)-1)<br />
len = start + len - em_end;<br />
<br />
em_end here is 16K, so now the values are<br />
<br />
start = 16K<br />
len = 16K + 36K - 16K = 36K<br />
<br />
len should instead be 20K. This is a problem when we find the next<br />
extent at [32K, 48K), we need to split this extent to leave [36K, 48k),<br />
however the code for the split looks like this<br />
<br />
split->start = start + len;<br />
split->len = em_end - (start + len);<br />
<br />
In this case we have<br />
<br />
em_end = 48K<br />
split->start = 16K + 36K // this should be 16K + 20K<br />
split->len = 48K - (16K + 36K) // this overflows as 16K + 36K is 52K<br />
<br />
and now we have an invalid extent_map in the tree that potentially<br />
overlaps other entries in the extent map. Even in the non-overlapping<br />
case we will have split->start set improperly, which will cause problems<br />
with any block related calculations.<br />
<br />
We don&#39;t actually need len in this loop, we can simply use end as our<br />
end point, and only adjust start up when we find a pinned extent we need<br />
to skip.<br />
<br />
Adjust the logic to do this, which keeps us from inserting an invalid<br />
extent map.<br />
<br />
We only skip_pinned in the relocation case, so this is relatively rare,<br />
except in the case where you are running relocation a lot, which can<br />
happen with auto relocation on.



