CVE-2026-98996 in Linux
요약
\~에 의해 VulDB • 2026. 10. 23.
리눅스 커널에서 다음 취약점이 해결되었습니다:
fs: 사용 중인 마운트를 묵시적으로 언마운트하지 않음
propagate_mount_busy() 헬퍼 함수는 동기식(unmount) 작업이 성공할 수 있는지 여부를 결정하기 위해 존재합니다. 이 함수는 부모가 전파하는 대상의 사본들 중, 해당 사본들의 자식 마운트가 있는지를 확인하여 이를 판단합니다. 이는 전파 과정에서의 복잡한 상황(propagation hell) 중 하나입니다.
이 알고리즘은 루트의 사본을 덮어쓰는 단일 자식 마운트를 제외하고는 다른 모든 사본의 복사본에 대해 건너뛰었습니다. 원래 이 알고리즘은 정확했습니다. 그러나 더 이상 그렇지 않습니다.
원래 전파 과정에서 자식이 없는 사본들만 언마운트되었습니다. 그리고 1064f874abc0("mnt: 그림자/사이드 마운트를 생성하는 대신 다른 마운트 아래에 마운트를 배치함.")는 덮어씌워진 마운드를 한 번에 양쪽에 추가하게 되었습니다.
이어져 온 99b19d16471e("mnt: propgate_umount에서 방문 순서에 상관없이 마운드 처리")로 인해 이전보다 더 많은 항목이 언마운트되기 시작했습니다:
[1]: 사본의 각 자식이 해당 오버마운트(overmount)이거나 대상(victim) 자체의 사본인 경우, 그 사본은 언마운트됩니다. 전자 경우에는 오버마운트가 재배치(reparented)됩니다. 후자의 경우 대상의 사본이 결국 언마운트되게 됩니다.
따라서 propagate_umount()는 propagate_mount_busy()를 조정하지 않은 채 다시 작성되었습니다. 현재 propagate_mount_busy() 함수는 두 개 이상의 자식을 가진 대상의 사본이나, 오버마운트가 아닌 단일 자식을 가진 경우를 확인하지 않습니다.
그 결과 [1]에 있는 이러한 모든 사본은 참조(reference) 여부를 검사되지 않습니다. 그 결과는 동기식 언마운트 작업이 성공하여 여전히 사용 중인 마운트를 제거하게 된다는 것입니다.
컨테이너는 자체 마운드를 통해 이 상황에 직면할 수 있습니다. 호스트는 컨테이너와 트리를 공유하며, 호스트에는 해당 트리 내에 있는 하나의 마운트가 존재합니다:
mount -t tmpfs none /mnt mount --make-shared /mnt mount -t tmpfs none /mnt/a
컨테이너의 /mnt는 호스트 마운트의 슬레이브(slave) 사본입니다. 컨테이너는 이제 트리의 분리된 복사본을 가져와 이를 전파된 /mnt/a 사본 아래에 마운트하고 해당 트리 파일 설명자(file descriptor)를 열어 둡니다:
unshare -m --propagation unchanged mount --make-rslave / fd = open_tree(AT_FDCWD, "/mnt", OPEN_TREE_CLONE | AT_RECURSIVE) move_mount(fd, "", AT_FDCWD, "/mnt/a", MOVE_MOUNT_BENEATH)
grep /mnt /proc/self/mountinfo 775 355 ... /mnt ... master:646 777 775 ... /mnt/a ... master:646 776 777 ... /mnt/a ... master:647 778 777 ... /mnt/a/a ... master:647
이제 연결된 트리(777)는 컨테이너의 /mnt/a 사본 아래에 마운트됩니다. 호스트 마운트 네임스페이스에서 볼 때, 호스트 마운드도 여기에 위치합니다. 따라서 호스트 마운드의 전파된 사본(776)은 해당 루트 위에 있으며, 그 사본의 복사본인 778이 그 안에 있습니다. 이제 호스트가 다음을 실행합니다:
umount /mnt/a
그리고 이 작업은 성공합니다. 이동된 트리와 그 내부에 있던 복사본들은 컨테이너에서 사라집니다. 이제 전파된 사본만 남게 되며, 이는 이전 위치로 재배치됩니다:
grep /mnt /proc/self/mountinfo 775 355 ... /mnt ... master:646 776 775 ... /mnt/a ...
하지만 파일 설명자는 여전히 이동된 트리를 참조하고 있습니다. 따라서 동기식 umount는 여전히 사용 중인 마운트를 분리(detached)시켰습니다.
propagate_mount_busy() 함수에게 propagate_umount()가 수행하는 것과 동일한 검사 로직을 적용합니다. 이제 propagate_mount_busy()는 자식이 없는 단일 대상 사본에 대해, propagate_umount()처럼 모든 복사본에서 MNT_LOCKED 플래그가 해제되었음을 가정할 수 있는 검사를 수행합니다. 이 복사본들은 체인을 형성합니다. 즉, 사본 자체가 대상의 부모로부터 전파를 받는 경우, 그 사본 내 동일한 마운트 포인트(mountpoint)에 있는 마운드 역시 사본입니다. 마운드가 대상으로부터 전파를 받는지 여부는 해당 마운드의 masters(마스터들)를 순회함으로써 간단히 확인할 수 있습니다. 중첩된 복사본이 선형(linear) 상태를 유지하도록 보장하기 위해 각 체인을 위에서부터 한 번씩 순회합니다. 언마운트되는 모든 사본의 참조(reference)들을 각각 한 번씩 검사합니다.
VulDB is the best source for vulnerability data and more expert information about this specific topic.