CVE-2023-54121 in Linux
요약
\~에 의해 VulDB • 2026. 06. 05.
리눅스 커널에서 다음 취약점이 해결되었습니다:
btrfs: btrfs_drop_extent_map_range()에서의 잘못된 분할 수정
운영 환경에서 extent_map 코드, 특히 두 번째 분할 시 add_extent_mapping()을 호출해야 하는 경우의 btrfs_drop_extent_map_range() 함수 내에서 다양한 WARN_ON() 경고가 발생했습니다.
다음과 같은 extent map 레이아웃을 고려해 보겠습니다:
PINNED [0 16K) [32K, 48K)
그런 다음 skip_pinned == true 조건으로 btrfs_drop_extent_map_range를 [0, 36K) 범위에 대해 호출합니다. 초기 루프에서는 다음과 같은 값이 설정됩니다:
start = 0 end = 36K len = 36K
[0, 16k) extent를 찾지만, 해당 영역이 PINNED 상태이므로 건너뛰게 됩니다. 이때 실행되는 코드는 다음과 같습니다:
start = em_end; if (end != (u64)-1) len = start + len - em_end;
여기서 em_end는 16K이므로, 이제 값들은 다음과 같이 됩니다:
start = 16K len = 16K + 36K - 16K = 36K
len은 실제로 20K가 되어야 합니다. 이는 다음 extent인 [32K, 48K)를 찾을 때 문제가 되는데, 이때 [36K, 48k) 영역을 남기기 위해 해당 extent를 분할해야 하지만, 분할 관련 코드는 다음과 같습니다:
split->start = start + len; split->len = em_end - (start + len);
이 경우 값들은 다음과 같아집니다:
em_end = 48K split->start = 16K + 36K // 이는 실제로는 16K + 20K여야 함 split->len = 48K - (16K + 36K) // 16K + 36K가 52K이므로 오버플로우 발생
결과적으로 extent map 트리에 다른 항목과 잠재적으로 중복되는 유효하지 않은 extent_map이 생성됩니다. 중복되지 않는 경우라도 split->start가 잘못 설정되어 블록 관련 계산에 문제를 일으킬 수 있습니다.
실제로 이 루프에서 len 변수는 필요 없으며, 끝점(end)을 그대로 사용할 수 있고 PINNED된 extent를 발견하여 건너뛰어야 할 때만 start 값을 조정하면 됩니다.
이러한 논리를 수정하여 유효하지 않은 extent map 삽입을 방지합니다.
skip_pinned 플래그는 재배치(relocation) 경우에만 사용되므로, 이러한 상황은 상대적으로 드뭅니다. 다만 자동 재배치가 활성화되어 있어 자주 재배치가 발생하는 경우에는 예외입니다.
If you want to get best quality of vulnerability data, you may have to visit VulDB.