🇰🇷 한글 설명
Linux 커널의 btrfs 파일시스템에서, 유효한 extent 트리가 없는 상태(손상된 이미지를 rescue=all,ro 옵션으로 마운트한 경우)에서 scrub을 실행하면 scrub_find_fill_first_stripe() 함수가 NULL 포인터 역참조로 커널 크래시를 일으킬 수 있습니다. 수정 사항은 함수 시작 시 extent root 유효성 검사를 추가하는 것입니다.
💡 쉬운 설명
손상된 btrfs 디스크를 읽기 전용으로 복구 마운트한 뒤 데이터 검사(scrub)를 실행하면 리눅스 시스템이 갑자기 멈출 수 있는 문제입니다. 패치를 적용하면 이 상황을 미리 감지해 안전하게 오류를 반환합니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
btrfs: avoid NULL pointer dereference if no valid extent tree
[BUG]
Syzbot reported a crash with the following call trace:
BTRFS info (device loop0): scrub: started on devid 1
BUG: kernel NULL pointer dereference, address: 0000000000000208
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 106e70067 P4D 106e70067 PUD 107143067 PMD 0
Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI
CPU: 1 UID: 0 PID: 689 Comm: repro Kdump: loaded Tainted: G O 6.13.0-rc4-custom+ #206
Tainted: [O]=OOT_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022
RIP: 0010:find_first_extent_item+0x26/0x1f0 [btrfs]
Call Trace:
<TASK>
scrub_find_fill_first_stripe+0x13d/0x3b0 [btrfs]
scrub_simple_mirror+0x175/0x260 [btrfs]
scrub_stripe+0x5d4/0x6c0 [btrfs]
scrub_chunk+0xbb/0x170 [btrfs]
scrub_enumerate_chunks+0x2f4/0x5f0 [btrfs]
btrfs_scrub_dev+0x240/0x600 [btrfs]
btrfs_ioctl+0x1dc8/0x2fa0 [btrfs]
? do_sys_openat2+0xa5/0xf0
__x64_sys_ioctl+0x97/0xc0
do_syscall_64+0x4f/0x120
entry_SYSCALL_64_after_hwframe+0x76/0x7e
</TASK>
[CAUSE]
The reproducer is using a corrupted image where extent tree root is
corrupted, thus forcing to use "rescue=all,ro" mount option to mount the
image.
Then it triggered a scrub, but since scrub relies on extent tree to find
where the data/metadata extents are, scrub_find_fill_first_stripe()
relies on an non-empty extent root.
But unfortunately scrub_find_fill_first_stripe() doesn't really expect
an NULL pointer for extent root, it use extent_root to grab fs_info and
triggered a NULL pointer dereference.
[FIX]
Add an extra check for a valid extent root at the beginning of
scrub_find_fill_first_stripe().
The new error path is introduced by 42437a6386ff ("btrfs: introduce
mount option rescue=ignorebadroots"), but that's pretty old, and later
commit b979547513ff ("btrfs: scrub: introduce helper to find and fill
sector info for a scrub_stripe") changed how we do scrub.
So for kernels older than 6.6, the fix will need manual backport.
📍 영향받는 시스템
btrfs를 사용하는 Linux 커널 (6.6 이전 버전은 수동 백포트 필요, 패치 적용 전 커널 버전 확인 필요)
⚔️ 공격 벡터
손상되었거나 조작된 btrfs 이미지를 rescue=all,ro 옵션으로 마운트한 뒤 scrub 작업을 트리거하여 커널 패닉(서비스 거부)을 유발
🛡️ 대응 방법
커널을 해당 CVE 수정이 포함된 최신 안정 버전으로 업데이트하거나, 6.6 이전 커널은 커널 패치를 수동 백포트 적용
🔧 검증 코드
출력된 커널 버전이 배포판 보안 공지에서 해당 CVE 수정이 포함된 버전 이상인지 확인하고, 6.6 미만이면 벤더 패치 적용 여부를 점검합니다.