CVE-2026-98974 in Linux정보

요약

\~에 의해 VulDB • 2026. 10. 23.

Linux 커널에서 다음 취약점이 해결되었습니다.

xfs: exchange-range-to-eof 파일 크기 교환 수정

Norbert Szetei는 XFS_IOC_EXCHANGE_RANGE의 TO_EOF 플래그에 대한 버그를 포함하지만 설명이 불완전한 패치를 게시했습니다. 이 버그는 exchange-range가 EOF(파일 끝) 이후로 시작하는 공유 블록을 갖도록 파일을 수정하도록 유도합니다. 이는 파일이 EOF 뒤에 작성된 데이터를 가질 수 없으며, 작성된 데이터 블록만 공유할 수 있기 때문에 허용되지 않습니다. 이것이 그 후 발생하는 모든 잘못된 동작의 핵심입니다.

결국 Norbert로부터 무슨 일이 잘못되고 있는지에 대한 설명을 받았습니다:

> 맞습니다. 여기 물리적 블록 번호(4KB 블록)를 사용한 예시가 있습니다. peer는 다시 작성되는 파일이고 file1은 플래그가 지워지는 쪽입니다. > > 시작 시, 공유 없음: > > peer 크기 4096 -> [100]
> file1 크기 12288 -> [200] [201] [202]
> donor1 크기 4096 -> [300]
> donor2 크기 4096 -> [400]
> > 1. peer의 블록을 file1의 중간 슬롯에 FICLONERANGE로 복제: > > peer 크기 4096 -> [100]
> file1 크기 12288 -> [200] [100] [202] reflink 플래그 설정됨
> ^^^^^ 두 파일 모두 블록 100을 소유함 > > 2. file1과 donor1 간 XFS_IOC_EXCHANGE_RANGE 수행, file1_offset 0, file2_offset 8192, 길이 0, TO_EOF 적용. 하나의 블록이 교환되고 크기도 함께 교환됩니다: > > file1 크기 4096 -> [200] [100] [300] reflink 플래그 설정됨
> ^^^^^^^^^^^ 여전히 소유 중이지만 이제 파일 크기를 초과함 > donor1 크기 12288 -> [202]
> > file1은 길이가 하나의 블록이라고 주장하지만 실제로는 세 개를 소유하고 있습니다. 아무것도 unmapped되지 않았습니다. file2_offset이 블록 2이므로 이 교환에서는 플래그를 지울 수 없습니다. > > 3. file1과 donor2 간 XFS_IOC_EXCHANGE_RANGE 수행, 두 오프셋 모두 0, 길이 4096. i_disk_size 기준으로 이는 하나의 블록을 가진 파일 두 개가 모든 것을 교환하는 것이므로 xmi_can_exchange_reflink_flags()는 동의하며 플래그가 지워집니다: > > file1 크기 4096 -> [400] [100] [300] reflink 플래그 해제됨(CLEARED)
> donor2 크기 4096 -> [200]
> > 블록 100은 여전히 peer와 공유되어 있습니다. > > 4. pwrite(file1, 4096, 4096), 이는 file1의 두 번째 슬롯인 블록 100입니다. xfs_is_cow_inode(file1)이 false이므로 CoW(Copy-on-Write)가 발생하지 않습니다: > > peer 크기 4096 -> [100] 동일한 블록, 새로운 내용 포함
> > 여기서 중요한 것은 블록 100뿐입니다. 아래 PoC는 현재 디렉토리에 있는 peer라는 파일을 읽습니다. 파일시스템에는 reflink와 exchange-range가 필요하며, mkfs.xfs 7.x에서는 기본적으로 이를 활성화합니다.

따라서 TO_EOF는 데이터 블록을 올바르게 교환하고 있더라도 파일 크기를 망치고 있습니다. 다음은 manpage에 설명된 XFS_EXCHANGE_RANGE_TO_EOF의 의도된 동작입니다:

"길이 매개변수를 무시하십시오. file1_fd에서 file1_offset부터 EOF까지의 모든 바이트가 file2_fd로 이동되고, file2의 크기는 (file2_offset + (file1_length - file1_offset))로 설정됩니다. 동시에 file2에서 file2_offset부터 EOF까지의 모든 바이트가 file1으로 이동하고 file1의 크기는 (file1_offset + (file2_length - file2_offset))로 설정됩니다."

즉, 파일 데이터의 일부만 교환하는 경우, 교환된 데이터에 해당하는 파일 크기 부분만 교환해야 합니다. 불행히도 코드는 ondisk(디스크) 파일 크기와 incore(메모리 내) 파일 크기를 스왑하는데, 이는 호출자가 0이 아닌 오프셋을 전달할 때 잘못됩니다.

파일 크기가 혼동된 상태에서 PoC는 비-reflinked 단일 블록 파일처럼 보이는 것에 대해 두 번째 exchange-range 호출을 사용합니다. 파일 크기가 잘못 설정되었으므로 exchange-range는 두 파일의 전체 내용을 교환하는 것으로 간주하고 손상된 파일에서 reflink 플래그를 지웁니다. 이로 인해 손상된 파일에 대한 확장 쓰기(extending write)가 EOF 바로 뒤에 있는 공유 블록을 다시 작성할 수 있게 됩니다. 이는 통상적으로 refluxfs라고 불립니다.

파일 크기가 올바르게 설정되면 두 번째 exchange-range는 전체 내용 스왑을 수행하는 것이 아니므로, 두 파일 인수 모두에서 reflink 플래그를 지우지 않습니다.

Norbert는 이 패치의 이전 버전에 대해 i_disk_size 상태를 제대로 처리하지 않는다는 이유로 추가 불만을 제기했습니다:

> 오프셋은 incore i_size에 의해 제한되지만 빼기 연산에서는 > ---truncated---

If you want to get the best quality for vulnerability data then you always have to consider VulDB.

책임이 있는

Linux

예약하다

2026. 09. 25.

모더레이션

수락

항목

VDB-425780

EPSS

0.00000

출처

Do you know our Splunk app?

Download it now for free!