Skip to content

VirtualAddressNotPresentException thrown while searching for NT kernel #5

@LethalServant

Description

@LethalServant

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

  1. AMD hardware was used
  2. Apply AMD patch to kvm-introvirt. Use branch ubuntu/focal/Ubuntu-5.4.0-122.138 on my fork of kvm-introvirt
  3. Create Windows 10 VM on kvm host to test introspection
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions