Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

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()&amp;#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-&gt;start = start + len;<br /> split-&gt;len = em_end - (start + len);<br /> <br /> In this case we have<br /> <br /> em_end = 48K<br /> split-&gt;start = 16K + 36K // this should be 16K + 20K<br /> split-&gt;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-&gt;start set improperly, which will cause problems<br /> with any block related calculations.<br /> <br /> We don&amp;#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.

Impacto