Summary
When IntroVirt attempts to detect the OS for the specific domain (kvm guest), the VirtualAddressNotPresent Exception is thrown while searching in memory for the start of the Windows NT Kernel. This causes the search to end early and the OS detection to fail for the domain.
This bug was found while adding support for AMD in the kvm-introvirt repo. Further testing needs to be done on Intel hardware to rule out that this bug is specific to CPU architecture.
Component(s)
NtKernelImpl
NtKernelmpl search_ptr
What is the current bug behavior?
The thrown exception cause the search for the kernel to stop early and thus the OS detection to fail.
What is the expected behavior?
The exception should be handle so that the memory region were the kernel is load can be fully search, leading to OS dectection.
System specs
CPU: AMD
KVM Host: Linux introvirt 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
KVM Guest: Windows 10 Version 21H2 (OS Build 19044.1288)
Steps to reproduce
- AMD hardware was used
- Apply AMD patch to kvm-introvirt. Use branch ubuntu/focal/Ubuntu-5.4.0-122.138 on my fork of kvm-introvirt
- Create Windows 10 VM on kvm host to test introspection
- Run ivguestinfo -D guest name
Relevant logs and/or screenshots
root@introvirt:/home/dev/IntroVirt# ivguestinfo -D win10-1
TRACE : libintrovirt v0.57.3-1-g6706bab: DEBUG=1 Optimized=0
WARN : You are running an unoptimized build of libintrovirt!
TRACE : Domain win10-1 attached vcpu 0
TRACE : Domain 91212 Vcpu 0 paused
TRACE : Domain 91212 Vcpu 0 resumed
TRACE : Domain 91212 Vcpu 0 paused
TRACE : Domain 91212 Vcpu 0 resumed
DEBUG : Domain win10-1 Vcpu0 intercept_exception(INT3, 1)
TRACE : Domain win10-1 attached vcpu 1
TRACE : Domain 91212 Vcpu 1 paused
TRACE : Domain 91212 Vcpu 1 resumed
TRACE : Domain 91212 Vcpu 1 paused
TRACE : Domain 91212 Vcpu 1 resumed
DEBUG : Domain win10-1 Vcpu1 intercept_exception(INT3, 1)
DEBUG : Domain win10-1 attached 2 vcpus
TRACE : Domain 91212 Vcpu 0 paused
DEBUG : Domain win10-1 Vcpu 0: Loading registers for paused VCPU
TRACE : Domain 91212 Vcpu 0 resumed
DEBUG : Attempting OS detection...
TRACE : Domain 91212 Vcpu 0 paused
TRACE : Domain 91212 Vcpu 1 paused
DEBUG : Domain win10-1 Vcpu 0 intercept_cr_writes(3, 1)
TRACE : Domain 91212 Vcpu 0 resumed
TRACE : Domain 91212 Vcpu 1 resumed
TRACE : Received event for VCPU 0:1 Type: EVENT_CR_WRITE
TRACE : Domain 91212 Vcpu 0 paused
TRACE : Domain 91212 Vcpu 1 paused
DEBUG : Using event VCPU 0
DEBUG : Starting NT kernel search at address 0xFFFFF80136408000
DEBUG : Virtual address 0xFFFFF801361FF000 not present
0# introvirt::TraceableException::IMPL::IMPL() in /lib/libintrovirt.so
1# std::_MakeUniq<introvirt::TraceableException::IMPL>::__single_object std::make_unique<introvirt::TraceableException::IMPL>() in /lib/libintrovirt.so
2# introvirt::TraceableException::TraceableException(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) at /home/dev/IntroVirt/src/core/exception/TraceableException.cc:45
3# introvirt::MemoryException::MemoryException(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) at /home/dev/IntroVirt/src/core/exception/MemoryException.cc:21
4# introvirt::VirtualAddressNotPresentException::VirtualAddressNotPresentException(unsigned long, unsigned long) at /home/dev/IntroVirt/src/core/exception/VirtualAddressNotPresentException.cc:28
5# introvirt::x86::PageDirectory::translate(unsigned long, unsigned long) const at /home/dev/IntroVirt/src/core/arch/x86/PageDirectory.cc:203
6# void introvirt::basic_guest_ptr<unsigned short, void, false, void>::_remap<false, (void*)0>() at /home/dev/IntroVirt/include/introvirt/core/memory/guest_ptr.hh:795
7# introvirt::basic_guest_ptr<unsigned short, void, false, void>::_reset(unsigned long, unsigned long) at /home/dev/IntroVirt/include/introvirt/core/memory/guest_ptr.hh:865
8# introvirt::basic_guest_ptr<unsigned short, void, false, void>& introvirt::basic_guest_ptr<unsigned short, void, false, void>::operator-=<unsigned long>(unsigned long) at /home/dev/IntroVirt/include/introvirt/core/memory/guest_ptr.hh:637
9# introvirt::windows::nt::NtKernelImpl<unsigned long>::NtKernelImpl(introvirt::windows::WindowsGuest&) at /home/dev/IntroVirt/src/windows/kernel/nt/NtKernelImpl.cc:392
10# void std::_Optional_base_impl<introvirt::windows::nt::NtKernelImpl<unsigned long>, std::_Optional_base<introvirt::windows::nt::NtKernelImpl<unsigned long>, false, false> >::_M_construct<introvirt::windows::WindowsGuestImpl<unsigned long>&>(introvirt::windows::WindowsGuestImpl<unsigned long>&) at /usr/include/c++/9/optional:419
11# std::enable_if<is_constructible_v<introvirt::windows::nt::NtKernelImpl<unsigned long>, introvirt::windows::WindowsGuestImpl<unsigned long>&>, introvirt::windows::nt::NtKernelImpl<unsigned long>&>::type std::optional<introvirt::windows::nt::NtKernelImpl<unsigned long> >::emplace<introvirt::windows::WindowsGuestImpl<unsigned long>&>(introvirt::windows::WindowsGuestImpl<unsigned long>&) at /usr/include/c++/9/optional:849
12# introvirt::windows::WindowsGuestImpl<unsigned long>::WindowsGuestImpl(introvirt::Domain&) at /home/dev/IntroVirt/src/windows/WindowsGuestImpl.cc:515
13# std::_MakeUniq<introvirt::windows::WindowsGuestImpl<unsigned long> >::__single_object std::make_unique<introvirt::windows::WindowsGuestImpl<unsigned long>, introvirt::DomainImpl&>(introvirt::DomainImpl&) at /usr/include/c++/9/bits/unique_ptr.h:857
14# introvirt::DomainImpl::detect_guest() at /home/dev/IntroVirt/src/core/domain/DomainImpl.cc:352
15# main at /home/dev/IntroVirt/tools/ivguestinfo.cc:98
16# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
17# _start in ivguestinfo
TRACE : Domain 91212 Vcpu 0 resumed
TRACE : Domain 91212 Vcpu 1 resumed
DEBUG : Failed to detect WindowsGuest: Domain win10-1 failed guest detection: Virtual address 0xFFFFF801361FF000 not present
0# introvirt::TraceableException::IMPL::IMPL() in /lib/libintrovirt.so
1# std::_MakeUniq<introvirt::TraceableException::IMPL>::__single_object std::make_unique<introvirt::TraceableException::IMPL>() in /lib/libintrovirt.so
2# introvirt::TraceableException::TraceableException(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) at /home/dev/IntroVirt/src/core/exception/TraceableException.cc:45
3# introvirt::GuestDetectionException::GuestDetectionException(introvirt::Domain const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) at /home/dev/IntroVirt/src/core/exception/GuestDetectionException.cc:29
4# introvirt::windows::WindowsGuestImpl<unsigned long>::WindowsGuestImpl(introvirt::Domain&) at /home/dev/IntroVirt/src/windows/WindowsGuestImpl.cc:528
5# std::_MakeUniq<introvirt::windows::WindowsGuestImpl<unsigned long> >::__single_object std::make_unique<introvirt::windows::WindowsGuestImpl<unsigned long>, introvirt::DomainImpl&>(introvirt::DomainImpl&) at /usr/include/c++/9/bits/unique_ptr.h:857
6# introvirt::DomainImpl::detect_guest() at /home/dev/IntroVirt/src/core/domain/DomainImpl.cc:352
7# main at /home/dev/IntroVirt/tools/ivguestinfo.cc:98
8# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
9# _start in ivguestinfo
TRACE : Completing event 1
TRACE : KvmVcpu::complete_event() completed
...
Additional context or possible fixes
potential fix for this bug
Summary
When IntroVirt attempts to detect the OS for the specific domain (kvm guest), the VirtualAddressNotPresent Exception is thrown while searching in memory for the start of the Windows NT Kernel. This causes the search to end early and the OS detection to fail for the domain.
This bug was found while adding support for AMD in the kvm-introvirt repo. Further testing needs to be done on Intel hardware to rule out that this bug is specific to CPU architecture.
Component(s)
NtKernelImpl
NtKernelmpl search_ptr
What is the current bug behavior?
The thrown exception cause the search for the kernel to stop early and thus the OS detection to fail.
What is the expected behavior?
The exception should be handle so that the memory region were the kernel is load can be fully search, leading to OS dectection.
System specs
CPU: AMD
KVM Host: Linux introvirt 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
KVM Guest: Windows 10 Version 21H2 (OS Build 19044.1288)
Steps to reproduce
Relevant logs and/or screenshots
Additional context or possible fixes
potential fix for this bug