🇰🇷 한글 설명
Linux 커널 KVM의 nSVM 모듈에서, 중첩 SVM VMRUN 시 중첩 TSC 스케일링 지원 여부를 확인하는 대신 assert(WARN)를 사용하던 문제입니다. 사용자 공간이 L1의 MSR_AMD64_TSC_RATIO를 변경한 뒤 게스트 CPUID에서 해당 기능을 숨기면 커널 경고가 반복적으로 발생할 수 있습니다.
💡 쉬운 설명
가상 머신 관리 프로그램이 특정 설정을 잘못된 순서로 바꾸면 커널이 경고 로그를 계속 남기는 문제입니다. 이 경고로 시스템이 완전히 멈추거나 권한이 탈취되지는 않는 것으로 알려져 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
KVM: nSVM: Check instead of asserting on nested TSC scaling support
Check for nested TSC scaling support on nested SVM VMRUN instead of
asserting that TSC scaling is exposed to L1 if L1's MSR_AMD64_TSC_RATIO
has diverged from KVM's default. Userspace can trigger the WARN at will
by writing the MSR and then updating guest CPUID to hide the feature
(modifying guest CPUID is allowed anytime before KVM_RUN). E.g. hacking
KVM's state_test selftest to do
vcpu_set_msr(vcpu, MSR_AMD64_TSC_RATIO, 0);
vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_TSCRATEMSR);
after restoring state in a new VM+vCPU yields an endless supply of:
------------[ cut here ]------------
WARNING: CPU: 164 PID: 62565 at arch/x86/kvm/svm/nested.c:699
nested_vmcb02_prepare_control+0x3d6/0x3f0 [kvm_amd]
Call Trace:
<TASK>
enter_svm_guest_mode+0x114/0x560 [kvm_amd]
nested_svm_vmrun+0x260/0x330 [kvm_amd]
vmrun_interception+0x29/0x30 [kvm_amd]
svm_invoke_exit_handler+0x35/0x100 [kvm_amd]
svm_handle_exit+0xe7/0x180 [kvm_amd]
kvm_arch_vcpu_ioctl_run+0x1eab/0x2570 [kvm]
kvm_vcpu_ioctl+0x4c9/0x5b0 [kvm]
__se_sys_ioctl+0x7a/0xc0
__x64_sys_ioctl+0x21/0x30
do_syscall_64+0x41/0x90
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x45ca1b
Note, the nested #VMEXIT path has the same flaw, but needs a different
fix and will be handled separately.
📍 영향받는 시스템
AMD SVM 기반 KVM을 사용하는 수정 이전의 Linux 커널 (KVM 모듈 kvm_amd)
⚔️ 공격 벡터
권한이 있는 사용자 공간 프로세스가 MSR_AMD64_TSC_RATIO를 변경한 뒤 게스트 CPUID의 TSCRATEMSR 기능을 제거하고 VMRUN을 반복 호출하여 커널 경고를 유발
🛡️ 대응 방법
배포판이 제공하는 Linux 커널 보안 업데이트(해당 CVE 수정 패치 포함 버전)로 업그레이드 후 재부팅
🔧 검증 코드
출력된 커널 버전이 배포판 보안 공지에서 해당 CVE가 수정된 버전 이상인지 비교하고, 낮으면 업데이트가 필요합니다.
uname -r && (dpkg -l linux-image-$(uname -r) 2>/dev/null || rpm -q kernel 2>/dev/null) | head -n 5