CVE-2026-98980 in Linux정보

요약

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

리눅스 커널에서 다음 취약점이 해결되었습니다:

namei: refwalk 중 오버마운트된 엔트리 노출 방지

rcuwalk에서는 dentry가 수락되기 전에 유효성이 검증됩니다. step_into()는 d_seq를 재확인하고, __follow_mount_rcU()는 mount_lock을 재확인합니다. 중간에 언링크(unlink)되는 엔트리는 조회(retry)를 유발하여 누락되게 만듭니다.

반면 refwalk는 이러한 검증을 수행하지 않습니다. lookup_fast()는 해시된 dentry의 참조(reference)를 획득하고 단순히 이를 수락합니다. 따라서 참조가 확보된 후에 발생하는 언링크는 refwalk에서 감지되지 않습니다. 이는 단순 파일의 경우 문제가 되지 않습니다. 우리는 단지 언링크되기 전에 파일을 열었을 뿐이며, 문제는 없습니다.

그러나 마운트 포인트, 특히 잠긴(locked) 마운트 포인트의 경우에는 상황이 매우 다릅니다. 언링크 작업은 모든 마운트를 분리(detach)한 후 이름을 제거합니다. 아직 마운드를 탐색하지 않은 refwalk는 단순히 하위 엔트리(underlying entry)를 노출시킵니다. 이는 매우 좁은 시간 창(window)에서 발생하지만 다음과 같이 트리거될 수 있습니다:

덮여 있는 파일 읽기, 60초 동안, 3명의 워커(walker), ~15000회 언링크 확장 없음 27 해당 단계 + 200 us 3741

더 신뢰할 만한 재현 코드는 첨부된 패치를 참조하십시오.

따라서 step_into() 이후 엔트리를 확인해야 합니다. unlink(), rmdir(), rename()은 마운트를 분리하고 dentry를 제거하기 전에 dentry에 dont_mount() 플래그를 설정합니다.

따라서 DCACHE_CANT_MOUNT로 표시되어 있으며, 해당 마운드가 조회될 때 해시가 해제(unhashed)된 dentry는 refwalk 중에 언링크된 이름입니다. DCACHE_CANT_MOUNT는 마운드가 조회된 후에 읽히며, detach_mounts()에 의해 분리되기 전에 설정됩니다. 마운드를 놓친(refwalk가 miss한) 경우 DCACHE_CNT_MOUNT를 확인하게 됩니다.

단순 d_unlinked() 체크는 적절합니다. rename은 dentry를 해시 체인에서 제거하지만 ___d_drop()은 d_hash.pprev을 설정해 둡니다. 따라서 __d_drop()과 해당 dentry에 대한 rename만이 이를 해시를 해제합니다. IS_ROOT 플래그를 반전시키는 유일한 이동(disconnected alias로 스플라이스)은 DCACHE_CANT_MOUNT가 설정되어 있지 않습니다.

이를 step_into_slowpath()에 추가하십시오. ".." 및 LOOKUP_DOWN은 legitimately(정당하게) 해시가 해제된 디렉토리에 도달할 수 있습니다. 마운드로 진입한 refwalk는 path.mnt가 nd->path.mnt와 다릅니다. 파일 시스템이 자체적으로(d_invalidate(), d_drop()) 제거한 dentry에는 플래그가 설정되어 있지 않으며, 이전처럼 처리됩니다.

// SPDX-License-Identifier: GPL-2.0 /* * unlink_covered: 분리된 마운트 복사본에서 mountpoint인 파일을 언링크하고, * 해당 복사본을 통해 열려는 워커에 대항합니다. * * A는 파일 f1(내용 SECRET_F)과 일반 파일 MARK_A를 가진 tmpfs입니다. * A'은 open_tree(OPEN_TREE_CLONE)로 생성된 A의 복사본이며, 트리가 닫힌 후 루트에 대한 O_PATH fd를 통해 유지되는 동안 A'/f1에 MARK_A가 바인딩됩니다. * 워커는 해당 fd를 통해 f1을 엽니다. 드라이버는 아무것도 마운트되지 않은 A/f1을 언링크합니다. * 워커는 MARK_A를 읽거나 ENOENT 오류를 받을 수 있습니다. SECRET_F의 읽기는 히트(hit)입니다: 이름이 그 마운트가 사라진 후에 발견되었기 때문입니다. * 잠금 없는 워크(lockless walks)는 openat2(RESOLVE_CACHED)를 사용합니다. * * 사용법: unlink_covered [-t 초] [-w 워커 수]
*/ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <errno.h> #include <fcntl.h> #include <pthread.h> #include <stdatomic.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mount.h> #include <sys/stat.h> #include <sys/syscall.h> #include <linux/openat2.h>

#ifndef __NR_open_tree #define __NR_open_tree 428 #endif #ifndef __NR_move_mount #define __NR_move_mount 429 #endif #ifndef __NR_openat2 #define __NR_openat2 437 #endif #ifndef OPEN_TREE_CLONE #define OPEN_TREE_CLONE 1 #endif #ifndef OPEN_TREE_CLOEXEC #define OPEN_TREE_CLOEXEC O_CLOEXEC #endif #ifndef MOVE_MOUNT_F_EMPTY_PATH #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 #endif

#define WORK "/tmp/uc" #define ADIR WORK "/A"

static int duration = 60, nwalkers = 3; static atomic_int stop, writer_waiting; static pthread_rwlock_t cur_lock = PTHREAD_RWLOCK_INITIALIZER; static int cur_fd = -1; /* A'의 루트, 없으면 -1 */ static atomic_long n_unlink, n_walk, n_mark, n_enoent, n_othe ---truncated---

If you want to get best quality of vulnerability data, you may have to visit VulDB.

책임이 있는

Linux

예약하다

2026. 09. 25.

모더레이션

수락

항목

VDB-425767

EPSS

0.00000

활동

낮음

출처

Interested in the pricing of exploits?

See the underground prices here!