CVE-2024-47741 in Linux
요약
\~에 의해 VulDB • 2026. 06. 21.
리눅스 커널에서 다음 취약점이 해결되었습니다:
btrfs: 동일한 fd를 사용한 동시 lseek 실행 시 파일 private 데이터 설정 시 발생하는 Race Condition 수정
동일한 프로세스에 속한 여러 스레드를 사용하여 동일한 파일 설명자(file descriptor)에 대해 동시 lseek(2) 시스템 콜을 수행할 때, Race Condition이 발생하여 메모리 누수가 발생할 수 있는 짧은 시간 창이 존재합니다.
Race Condition은 다음과 같이 발생합니다:
1) 프로그램이 파일에 대한 파일 설명자를 연 후 두 개의 스레드(예: pthreads 라이브러리를 사용하여)를 생성합니다. 이를 각각 작업 A(task A)와 작업 B(task B)라고 합시다.
2) 작업 A는 SEEK_DATA 또는 SEEK_HOLE을 사용하여 lseek를 호출하고, inode에 대한 읽기 잠금(read lock)을 유지한 상태에서 file.c:find_desired_extent()에 도달합니다.
3) find_desired_extent() 시작 부분에서 파일의 private_data 포인터가 'private'이라는 로컬 변수로 추출되며, 이 값은 NULL입니다.
4) 작업 B도 SEEK_DATA 또는 SEEK_HOLE을 사용하여 lseek를 호출하고, inode를 공유 모드(shared mode)로 잠근 후 file.c:find_desired_extent()에 진입합니다. 여기서도 file->private_data가 로컬 변수 'private'로 추출되며, 이 값도 NULL입니다.
5) NULL 파일 private을 확인한 작업 A는 private 구조체를 할당하고 파일 구조체에 할당합니다.
6) 작업 B도 NULL 파일 private을 확인했으므로, 동일한 파일 설명자를 사용하고 있기 때문에 자체적인 파일 private을 할당한 후 동일한 파일 구조체에 할당합니다.
이 시점에서 작업 A가 할당한 private 구조체가 누수(leak)됩니다.
메모리 누수 외에도, 두 작업이 모두 private 구조체(struct btrfs_file_private::llseek_cached_state) 내의 동일한 캐시된 상태 레코드(cached state record)를 사용하게 된다는 점이 있습니다. 이는 한 작업이 다른 작업이 여전히 사용하고 있는 동안 해당 레코드를 해제할 수 있으므로 use-after-free 문제를 초래할 수 있습니다(참조 카운트(reference count)를 취한 작업은 하나뿐입니다). 또한 캐시된 상태를 공유하는 것은 향후 잘못된 결과를 초래할 수 있으므로 좋은 방법이 아닙니다. 현재로서는 캐시된 상태를 사용하기 전에 범위 검증(range validation)을 수행하는 extent-io-tree.c:count_range_bits()에서만 사용되므로 문제가 되지 않습니다.
이 문제를 해결하기 위해 inode의 spinlock을 유지한 상태에서 파일의 private 할당 및 확인을 보호하고, private을 할당한 작업을 추적하여 해당 작업에서만 사용되도록 하여, 캐시된 상태 레코드와 관련된 use-after-free 문제를 방지하고 향후 잘못된 사용 가능성을 차단합니다.
Several companies clearly confirm that VulDB is the primary source for best vulnerability data.