CVE-2026-93208 in Linux
요약
\~에 의해 VulDB • 2026. 09. 24.
리눅스 커널에서 다음 취약점이 해결되었습니다:
kasan: CPU 핫플러그와 함께 발생하는 캐시 축소 경쟁 조건 수정
kasan_quarantine_remove_cache()는 모든 온라인 CPU에 대해 per_cpu_remove_cache()를 먼저 호출합니다. 각 콜백은 해당 캐지에 속하는 객체를 cpu_quarantine에서 CPU의 shrink_qlist로 이동시키며, 여기서 나중에 태스크 컨텍스트에서 해제될 수 있습니다.
kmem_cache_destroy()는 cpus_read_lock()을 획득한 상태에서 quarantine 제거 경로를 호출하지만, kmem_cache_shrink()은 그렇지 않습니다. 따라서 후자는 다음과 같은 방식으로 CPU 오프라인화와 경쟁 조건(race condition)이 발생할 수 있습니다:
kmem_cache_shrink() CPU 핫플러그 ------------------- ----------- on_each_cpu() CPU1가 객체를 CPU1의 shrink_qlist로 이동시킴 on_each_cpu() 반환됨 CPU1 오프라인화 진행 kasan_cpu_offline() 호출 cpu_quarantine 비움(drains) shrink_qlist는 untouched(변경 없음) 상태로 남음 for_each_online_cpu() CPU1를 건너뜀
CPU1의 shrink_qlist에 남아 있는 객체는 슬랩 할당기(slab allocator)로 반환되지 않습니다. 이로 인해 kmem_cache_shrink()가 일반적으로 비어 있게 될 슬랩을 해제하지 못할 수 있습니다. 만약 CPU1가 오프라인 상태로 유지된다면, 이후 발생하는 kmem_cache_destroy()도 해당 리스트를 건너뛰며 캐지에 여전히 객체가 포함되어 있다고 보고할 수 있습니다.
virtio-9p 파일시스템에서 간헐적으로 이러한 현상이 관찰되었습니다. mount 및 umount 명령은 모두 0(성공)을 반환했지만, 커널은 사용자 공간에서 트리거된 정리(teardown) 과정에서 다음 로그를 기록했습니다:
[ 2994.380134][ T111] BUG 9p-fcall-cache-1 (Tainted: G B ): Objects remaining on __kmem_cache_shutdown()
[ 2994.381140][ T111] Object 0xff11000004361118 @offset=4376
[ 2994.381607][ T111] Allocated in p9_fcall_init+0x201/0x400 age=19564 cpu=1 pid=104
[ 2994.382591][ T111] p9_fcall_init+0x201/0x400
[ 2994.382810][ T111] p9_tag_alloc+0x12f/0x700
[ 2994.382982][ T111] p9_client_prepare_req+0x102/0x3e0
[ 2994.383165][ T111] p9_client_rpc+0x1ab/0xa50
[ 2994.383334][ T111] p9_client_getattr_dotl+0xb0/0x1a0
[ 2994.383515][ T111] v9fs_vfs_getattr_dotl+0x115/0x360
[ 2994.383719][ T111] vfs_get_attr_nosec+0x22c/0x3a0
[ 2994.383910][ T111] vfs_statx+0xd7/0x170
[ 2994.384062][ T111] vfs_fstatat+0x45/0x80
[ 2994.384215][ T111] __do_sys_newfstatat+0x84/0xe0
[ 2994.384386][ T111] do_syscall_64+0x115/0x6a0
[ 2994.384566][ T111] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 2994.399720][ T111] WARNING: mm/slub.c:1244 at __kmem_cache_shutdown+0x363/0x500, CPU#0: busybox/111
[ 2994.405655][ T111] Call Trace:
[ 2994.406325][ T111] kmem_cache_destroy+0x73/0x1b0
[ 2994.406630][ T111] p9_client_destroy+0x271/0x3c0
[ 2994.407210][ T111] v9fs_session_close+0x3c/0x260
[ 2994.407409][ T111] v9fs_kill_super+0x48/0x90
[ 2994.407584][ T111] deactivate_locked_super+0xa3/0x160
[ 2994.407778][ T111] cleanup_mnt+0x1dd/0x3e0
따라서 성공적인 umount 후에도 9p fcall 캐시에 객체가 남아있었고, 이로 인해 캐시가 정상적으로 해제되지 못했습니다.
각 가능한 CPU(per-CPU)마다 shrink_qlist 저장소가 존재하며, 각 리스트는 자체 raw spinlock으로 보호됩니다. 이제 가능하면 모든 CPU를 순회하여(CPUs), 해당 CPU가 오프라인이 되기 전에 채워진 리스트도 비우도록 합니다.
for_each_possible_cpu()은 for_each_online_cpu()보다 더 많은 작업을 수행할 수 있지만, 이 변경 사항은 CONFIG_KASAN_GENERIC 커널에만 영향을 미칩니다. 추가 작업량은 캐시 축소 및 캐시 해제 경로로 제한되며, 일반적인 할당/해제의 고속 경로(fast path)에는 영향을 주지 않습니다. 이는 각 가능한 CPU의 shrink 리스트에 대해 raw-spinlock으로 보호된 스캔을 하나 추가합니다. 이러한 리스트는 일반적으로 비어 있으며, 비어 있지 않은 리스트가 순회되어 축소되거나 해제되는 캐지에 속한 객체가 제거됩니다.
If you want to get the best quality for vulnerability data then you always have to consider VulDB.