Bitdefender Hypervisor Memory Introspection
lixguest.c File Reference
#include "lixguest.h"
#include "cr_protection.h"
#include "decoder.h"
#include "drivers.h"
#include "hook.h"
#include "introcpu.h"
#include "lixapi.h"
#include "lixidt.h"
#include "lixkernel.h"
#include "lixmm.h"
#include "lixvdso.h"
#include "msr_protection.h"
#include "dtr_protection.h"
#include "lixfiles.h"
#include "lixksym.h"
#include "memcloak.h"
#include "linux/agents/agents_content.h"
#include "detours_hypercall.h"

Go to the source code of this file.

Macros

#define LIX_KERNEL_MAX_PAGES   16384
 The maximum number of pages of kernel that will be scanned. More...
 
#define LIX_BANNER_START   "Linux version "
 The start of the 'linux_proc_banner' string. More...
 
#define LIX_MODULE_MAPPING_SPACE_START   0xffffffffa0000000
 The start of module mapping region. More...
 
#define LIX_MODULE_MAPPING_SPACE_END   0xfffffffffeffffff
 The end of module mapping region. More...
 
#define LIX_KAISER_ENABLED_PCP_OFFSET_CAP   0xE000UL
 The max value of 'kaiser_enabled_pcp' offset (the maximum observed was 0xD040 on CentOS - kernel 3.10) More...
 

Functions

static void IntLixGuestSetOsVersion (void)
 Computes the OS version number using the version, patch and sublevel. More...
 
static INTSTATUS IntLixGuestParseVersion (const char *Buffer, DWORD BufferLength)
 Parses the 'linux_proc_banner' and searches for 'version.patch.sublevel-backport' pattern. More...
 
INTSTATUS IntLixGuestFindKernelVersionAndRo (QWORD StartGva)
 Scans pages from guest memory, starting from the provided StartGva and tries to find the .rodata section and the Linux kernel version. More...
 
static INTSTATUS IntLixGuestFindKernelBase (QWORD StartGva)
 Scans pages from guest memory, starting from the provided StartGva, until we find a signature that matches a given kernel. More...
 
static INTSTATUS IntLixGuestFindKernel (QWORD SyscallHandler)
 Finds the most things required by Introcore to be able to initialize completely. More...
 
static INTSTATUS IntLixGuestResolveExTableLimits (void)
 Decodes each instruction of the 'search_exception_tables' function and searches for 'MOV REG/RSI, immediate' pattern. More...
 
static void IntLixGuestResolveSymbols (void)
 Searches for the 'memcpy', '__memcpy', 'memset', '__memset' and 'memmove' ksyms. More...
 
static INTSTATUS IntLixResolveCurrentProcessOffset (void)
 Decodes each instruction of the 'do_exit' function and searches for 'MOV REG/MEM, [gs:displacement]' pattern in order to find the 'current' offset. More...
 
static INTSTATUS IntLixResolveCurrentCpuOffset (void)
 Searches for the 'cpu_number' offset. More...
 
static INTSTATUS IntLixResolveThreadStructOffset (void)
 Decodes each instruction of the 'set_tls_desc' function and searches for 'MOV RDI, immediate' pattern in order to find the 'task_struct->thread_struct' offset. More...
 
static INTSTATUS IntLixResolveExeFileOffset (void)
 Decodes each instruction of the 'get_mm_exe_file' function and searches for 'MOV REG, [RDI + Displacement]' pattern in order to find the 'mm_struct->exe_file' offset. More...
 
INTSTATUS IntLixGuestFindProperSyscall (QWORD SyscallAddress, QWORD *ProperSyscallAddress)
 Decodes each instruction from the provided syscall handler address and searches for a pattern if the provided syscall address is not inside the kernel mapping region. More...
 
static INTSTATUS IntLixGuestResolveOffsets (void)
 Finds the offsets required by Introcore. More...
 
static INTSTATUS IntLixGuestActivateProtection (void)
 Activates the protection for a Linux guest. More...
 
INTSTATUS IntLixGuestIsKptiActive (QWORD SyscallGva)
 Checks if the Linux guest has the KPTI active. More...
 
static INTSTATUS IntLixFindDataStart (void)
 Decodes each instruction of the 'mark_rodata_ro' function and searches for end of .rodata section and the start of .data section. More...
 
static INTSTATUS IntLixGuestFindPgd (QWORD *Pgd)
 Searches for the system CR3. More...
 
static INTSTATUS IntLixPatchHandler (void *Detour, LIX_ACTIVE_PATCH *ActivePatch)
 Handles the incoming patches (ftrace/text_poke) from the guest. More...
 
INTSTATUS IntLixTextPokeHandler (void *Detour)
 Handles the incoming 'text_poke' patches from the guest. More...
 
INTSTATUS IntLixFtraceHandler (void *Detour)
 Handles the incoming 'text_poke' patches from the guest. More...
 
INTSTATUS IntLixJumpLabelHandler (void *Detour)
 Handles the incoming read (arch_jmp_label_transform) from the guest. More...
 
static INTSTATUS IntLixGuestInit (void)
 Initializes a new Linux guest. More...
 
void IntLixGuestUninit (void)
 Uninitialize the Linux guest. More...
 
static BOOLEAN IntLixGuestIsSupported (void)
 Load OS information from CAMI if the guest is supported. More...
 
static INTSTATUS IntLixGuestDetourDataHandler (void **Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 Dumps information about the read/write attempt. More...
 
static INTSTATUS IntLixGuestAgentContentHandler (void **Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 Dumps information about the read/write attempt. More...
 
INTSTATUS IntLixGuestAllocateDeploy (void)
 Deploys the content of Linux detours and the content of the Linux agents. More...
 
static INTSTATUS IntLixGuestClearGuestMemory (QWORD Gva, DWORD Length)
 Clear the provided memory zone. More...
 
static INTSTATUS IntLixGuestAllocateFill (void)
 Fill the required information about the allocated memory zone from the guest. More...
 
void IntLixGuestUnhookGuestCode (void)
 Remove the EPT hooks and memcloack from detours and agents. More...
 
INTSTATUS IntLixGuestAllocateHook (void)
 Add EPT hooks for the detours and agents. More...
 
int IntLixGuestGetSystemState (void)
 Get the system state of the Linux guest. More...
 
BOOLEAN IntLixGuestDeployUninitAgent (void)
 Inject the 'uninit' agent to free the previously allocated memory for detours/agents. More...
 
static INTSTATUS IntLixGuestAllocateInit (void)
 Initialize the required information about the allocated memory zone for detours/agents. More...
 
static INTSTATUS IntLixGuestInitAgentHypercall (void *Context)
 This callback is called when the 'init' agent has been allocated the memory zone from guest. More...
 
static INTSTATUS IntLixGuestInitAgentCompletion (void *Context)
 This callback is called when the 'init' agent completed the execution and the protection can be activated. More...
 
static INTSTATUS IntLixGuestAllocate (void)
 Injects the 'init' agent in order to allocate a memory zone inside the guest. More...
 
void IntLixGuestUninitGuestCode (void)
 Removes the EPT hooks from detours/agents memory zone and clears these memory zones. More...
 
INTSTATUS IntLixGuestNew (void)
 Starts the initialization and enable protection for a new Linux guest. More...
 
INTSTATUS IntGetVersionStringLinux (DWORD FullStringSize, DWORD VersionStringSize, CHAR *FullString, CHAR *VersionString)
 Gets the version string for a Linux guest. More...
 

Variables

LINUX_GUESTgLixGuest = NULL
 Global variable holding the state of a Linux guest. More...
 
LIST_HEAD gKernelDrivers
 List of all the drivers currently loaded inside the guest. More...
 
PATTERN_SIGNATUREgLinuxDistSigs
 An array that contains the distro signatures. More...
 
DWORD gLinuxDistSigsCount = 0
 The number of distro signatures from gLinuxDistSigs. More...
 

Macro Definition Documentation

◆ LIX_BANNER_START

#define LIX_BANNER_START   "Linux version "

The start of the 'linux_proc_banner' string.

Definition at line 42 of file lixguest.c.

Referenced by IntLixGuestFindKernelVersionAndRo().

◆ LIX_KAISER_ENABLED_PCP_OFFSET_CAP

#define LIX_KAISER_ENABLED_PCP_OFFSET_CAP   0xE000UL

The max value of 'kaiser_enabled_pcp' offset (the maximum observed was 0xD040 on CentOS - kernel 3.10)

Definition at line 48 of file lixguest.c.

Referenced by IntLixGuestIsKptiActive().

◆ LIX_KERNEL_MAX_PAGES

#define LIX_KERNEL_MAX_PAGES   16384

The maximum number of pages of kernel that will be scanned.

Definition at line 40 of file lixguest.c.

Referenced by IntLixGuestFindKernelBase(), and IntLixGuestFindKernelVersionAndRo().

◆ LIX_MODULE_MAPPING_SPACE_END

#define LIX_MODULE_MAPPING_SPACE_END   0xfffffffffeffffff

The end of module mapping region.

Definition at line 45 of file lixguest.c.

Referenced by IntLixGuestAllocateFill().

◆ LIX_MODULE_MAPPING_SPACE_START

#define LIX_MODULE_MAPPING_SPACE_START   0xffffffffa0000000

The start of module mapping region.

Definition at line 44 of file lixguest.c.

Referenced by IntLixGuestAllocateFill().

Function Documentation

◆ IntGetVersionStringLinux()

INTSTATUS IntGetVersionStringLinux ( DWORD  FullStringSize,
DWORD  VersionStringSize,
CHAR FullString,
CHAR VersionString 
)

Gets the version string for a Linux guest.

Parameters
[in]FullStringSizeThe size of the FullString buffer.
[in]VersionStringSizeThe size of the VersionString buffer.
[out]FullStringA NULL-terminated string containing detailed version information.
[out]VersionStringA NULL-terminated string containing human-readable version information.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_DATA_BUFFER_TOO_SMALLIf the version string length exceed the provided FullStringSize length.
INT_STATUS_INVALID_DATA_VALUEIf the version string is invalid.

Definition at line 2730 of file lixguest.c.

Referenced by IntGetVersionString().

◆ IntLixFindDataStart()

static INTSTATUS IntLixFindDataStart ( void  )
static

Decodes each instruction of the 'mark_rodata_ro' function and searches for end of .rodata section and the start of .data section.

The function searches for the 'MOV REG, immediate' and creates an array that looks like: arr[0] -> _stext arr[1] -> _etext arr[2] -> __start_rodata (it may be unaligned) ... arr[k] -> __end_rodata arr[k + 1] -> __end_rodata_hpage_aligned -> _sdata

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the start/end addresses are not found.

Definition at line 1175 of file lixguest.c.

Referenced by IntLixGuestInit().

◆ IntLixFtraceHandler()

INTSTATUS IntLixFtraceHandler ( void *  Detour)

Handles the incoming 'text_poke' patches from the guest.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1481 of file lixguest.c.

◆ IntLixGuestActivateProtection()

static INTSTATUS IntLixGuestActivateProtection ( void  )
static

Activates the protection for a Linux guest.

Depending on the used core-options, this will activate various protection mechanisms: IDT, MSR, CR4, IDTR, and GDTR.

Return values
INT_STATUS_SUCCESSOn success, or an appropriate INTSTATUS error value.

Definition at line 941 of file lixguest.c.

Referenced by IntLixGuestInitAgentCompletion().

◆ IntLixGuestAgentContentHandler()

static INTSTATUS IntLixGuestAgentContentHandler ( void **  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)
static

Dumps information about the read/write attempt.

Parameters
[in]ContextUnused.
[in]HookThe HOOK_GPA associated to this callback.
[in]AddressThe guest physical address that was accessed.
[in]ActionDesired action (allow, block).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1792 of file lixguest.c.

Referenced by IntLixGuestAllocateHook().

◆ IntLixGuestAllocate()

static INTSTATUS IntLixGuestAllocate ( void  )
static

Injects the 'init' agent in order to allocate a memory zone inside the guest.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the agent-handler is not found.

Definition at line 2488 of file lixguest.c.

Referenced by IntLixGuestNew().

◆ IntLixGuestAllocateDeploy()

INTSTATUS IntLixGuestAllocateDeploy ( void  )

Deploys the content of Linux detours and the content of the Linux agents.

The layout of the detours header (LIX_HYPERCALL_PAGE):

  • Protection options: Used to enable/disable a detour handler; contains the gGuest.Operands.Current.
  • DetoursCount: The number of the detours handler.
  • Detours: An array of LIX_GUEST_DETOUR structures.
  • OsSpecificFields: The offsets used by the detours.

The layout of the LIX_GUEST_DETOUR:

  • Name: The name of the hooked function.
  • HijackName: The name of the hijack-hooked function (see lixapi.c for more information about hijack detours).
  • Address: The guest virtual address of the detour's code.
  • RelocatedCode:The guest virtual address of the detour's relocated code.
  • JumpBack: The guest virtual address of the original function where the detours will jump.
  • EnableOptions:The enable-options for the current detour (e.g. INTRO_OPT_PROT_KM_LX); Used to check if the current detour should generate an exit (if the options is set in LIX_HYPERCALL_PAGE.ProtectionOptions).

The detour's code is located after the LIX_HYPERCALL_PAGE.

The agents code and data is located after the detours (data and code).

NOTE: The deployed detours and agents are protected using EPT hooks. The data is protected only against write (because an EPT hook against read will generate a lot of exits); the code is protected against read and write.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_SUPPORTEDIf the size of detours/agents content exceed the allocated memory.
INT_STATUS_INVALID_INTERNAL_STATEIf the IntKsymFindByName fails.

Definition at line 1829 of file lixguest.c.

Referenced by IntLixGuestAllocateInit().

◆ IntLixGuestAllocateFill()

static INTSTATUS IntLixGuestAllocateFill ( void  )
static

Fill the required information about the allocated memory zone from the guest.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf the allocation fails.

Definition at line 2009 of file lixguest.c.

Referenced by IntLixGuestAllocateInit().

◆ IntLixGuestAllocateHook()

INTSTATUS IntLixGuestAllocateHook ( void  )

Add EPT hooks for the detours and agents.

The data is protected only against write (because an EPT hook against read will generate a lot of exits); the code is protected against read and write.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 2118 of file lixguest.c.

Referenced by IntLixGuestAllocateInit().

◆ IntLixGuestAllocateInit()

static INTSTATUS IntLixGuestAllocateInit ( void  )
static

Initialize the required information about the allocated memory zone for detours/agents.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 2312 of file lixguest.c.

Referenced by IntLixGuestInitAgentHypercall().

◆ IntLixGuestClearGuestMemory()

static INTSTATUS IntLixGuestClearGuestMemory ( QWORD  Gva,
DWORD  Length 
)
static

Clear the provided memory zone.

This function is called after the allocated guest memory zone (used for agents and detours) is freed and we want to remove our data.

Parameters
[in]GvaThe start of the memory zone.
[in]LengthThe length of the memory zone.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1964 of file lixguest.c.

Referenced by IntLixGuestUninitGuestCode().

◆ IntLixGuestDeployUninitAgent()

BOOLEAN IntLixGuestDeployUninitAgent ( void  )

Inject the 'uninit' agent to free the previously allocated memory for detours/agents.

The agents argument structure is completed with the addresses of the previously allocated memory. The page-attrs are also restored.

Return values
Trueif the agent is injected, otherwise false.

Definition at line 2238 of file lixguest.c.

Referenced by IntGuestDisableIntro().

◆ IntLixGuestDetourDataHandler()

static INTSTATUS IntLixGuestDetourDataHandler ( void **  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)
static

Dumps information about the read/write attempt.

Parameters
[in]ContextUnused.
[in]HookThe HOOK_GPA associated to this callback.
[in]AddressThe guest physical address that was accessed.
[in]ActionDesired action (allow, block).
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1752 of file lixguest.c.

Referenced by IntLixGuestAllocateHook().

◆ IntLixGuestFindKernel()

static INTSTATUS IntLixGuestFindKernel ( QWORD  SyscallHandler)
static

Finds the most things required by Introcore to be able to initialize completely.

NOTE: Only the gGuest.KernelVa and gGuest.KernelSize are valid, the layout will be changed after we find and parse the kallsyms.

Parameters
[in]SyscallHandlerThe guest virtual address of the syscall handler.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If the provided SyscallHandler is not a kernel pointer.
INT_STATUS_INVALID_INTERNAL_STATEIf the distro patterns could not be loaded.
INT_STATUS_NOT_FOUNDIf the kernel sections or version are not found.

Definition at line 391 of file lixguest.c.

Referenced by IntLixGuestNew().

◆ IntLixGuestFindKernelBase()

static INTSTATUS IntLixGuestFindKernelBase ( QWORD  StartGva)
static

Scans pages from guest memory, starting from the provided StartGva, until we find a signature that matches a given kernel.

For each mapped guest memory address, the function tries to match a distro pattern from gLinuxDistSigs. We will stop after we parser a maximum number of pages (LIX_KERNEL_MAX_PAGES), or after we find a page that is not present, or when a distro matches. If we find a distro signature that matches, we mark the current guest virtual address as the start of the .text section.

Parameters
[in]StartGvaThe guest virtual address from which we start scanning.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the kernel .text section is not found.

Definition at line 328 of file lixguest.c.

Referenced by IntLixGuestFindKernel().

◆ IntLixGuestFindKernelVersionAndRo()

INTSTATUS IntLixGuestFindKernelVersionAndRo ( QWORD  StartGva)

Scans pages from guest memory, starting from the provided StartGva and tries to find the .rodata section and the Linux kernel version.

This function translates a guest virtual address and maps the corresponding guest physical page. In order to find the Linux kernel version the IntLixGuestParseVersion is called; the 'linux_proc_banner' is the first data from the .rodata section, thus we mark the guest virtual address of the 'linux_proc_banner' as the start of the .rodata section. If the Linux kernel version is found and the current guest physical page is not present, we mark the current guest virtual address as the end of the .rodata section.

Parameters
[in]StartGvaThe guest virtual address from which we start scanning.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the Linux kernel version/.rodata section is not found.

Definition at line 175 of file lixguest.c.

Referenced by IntLixGuestFindKernel().

◆ IntLixGuestFindPgd()

static INTSTATUS IntLixGuestFindPgd ( QWORD Pgd)
static

Searches for the system CR3.

This function tries to get the system CR3 by searching for 'init_top_pgt' or 'init_level4_pgt' ksyms; if the ksym is found the value of it is returned.

If the function ksyms are not available, the 'arch_crash_save_vmcoreinfo' is disassembled and parsed. When the second 'CALL vmcoreinfo_append_str' is found, the function marks the value of the RDX as a system CR3.

arch_crash_save_vmcoreinfo(...) { VMCOREINFO_NUMBER(phys_base); VMCOREINFO_SYMBOL(init_top_pgt); }

NOTE: We are dependent on the guest state for the system cr3. When we are initialized static, the CR3 of the current processor can be anywhere, souse the Linux variable 'init_level4_pgt' ('swapper_pg_dir' points to it).

Parameters
[out]PgdOn success, the value of the system CR3 (PGD).
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the value of the system CR3 is not found.

Definition at line 1285 of file lixguest.c.

Referenced by IntLixGuestNew().

◆ IntLixGuestFindProperSyscall()

INTSTATUS IntLixGuestFindProperSyscall ( QWORD  SyscallAddress,
QWORD ProperSyscallAddress 
)

Decodes each instruction from the provided syscall handler address and searches for a pattern if the provided syscall address is not inside the kernel mapping region.

The function searches for two patterns in the syscall address: 'MOV RDI, immediate' and 'JMP RDI'/'CALL relative_address'. The immediate operand form 'MOV RDI, immediate' instruction represents the 'real' syscall guest virtual address; the function stores this value and search for the next patterns. Next, the function search for 'JMP RDI' or 'CALL realtive_address'; if this pattern is found we mark the previously saved value as the syscall 'real' guest virtual address.

Parameters
[in]SyscallAddressThe guest virtual address of the syscall handler.
[out]ProperSyscallAddressThe 'real' syscall guest virtual address.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the 'real' syscall address is inside the kernel text mapping region or if the 'real' syscall address is not found.

Definition at line 805 of file lixguest.c.

Referenced by IntLixGuestNew().

◆ IntLixGuestGetSystemState()

int IntLixGuestGetSystemState ( void  )

Get the system state of the Linux guest.

This function fetches the value of the 'system_state' ksym.

Return values
Onsuccess, returns the system state value; otherwise returns -1.

Definition at line 2201 of file lixguest.c.

Referenced by IntLixDrvSystemBooting(), and IntLixTaskGuestTerminating().

◆ IntLixGuestInit()

static INTSTATUS IntLixGuestInit ( void  )
static

Initializes a new Linux guest.

Initialize the information required to protect the current guest.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the gGuest.Initialized is false.
INT_STATUS_GUEST_OS_NOT_SUPPORTEDIf the Linux kernel used by the guest is not supported.

Definition at line 1532 of file lixguest.c.

Referenced by IntLixGuestNew().

◆ IntLixGuestInitAgentCompletion()

static INTSTATUS IntLixGuestInitAgentCompletion ( void *  Context)
static

This callback is called when the 'init' agent completed the execution and the protection can be activated.

Depending on the used core-options, this will activate the appropriate protection.

NOTE: Clear the stack to remove any addresses that may have been save by the kernel.

NOTE: The guest protection can be activate ONLY in this point because the memory zone allocated by the 'init' agent doesn't have the required protection attributes (the default attributes is R/NX). The 'init' agent also changes the attributes: the data pages have the NX/WR attributes, the code pages have the WR attributes.

Parameters
[in]ContextUnused.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the guest state is not initialized.

Definition at line 2392 of file lixguest.c.

Referenced by IntLixGuestAllocate().

◆ IntLixGuestInitAgentHypercall()

static INTSTATUS IntLixGuestInitAgentHypercall ( void *  Context)
static

This callback is called when the 'init' agent has been allocated the memory zone from guest.

Parameters
[in]ContextUnused.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the guest state is not initialized.

Definition at line 2349 of file lixguest.c.

Referenced by IntLixGuestAllocate().

◆ IntLixGuestIsKptiActive()

INTSTATUS IntLixGuestIsKptiActive ( QWORD  SyscallGva)

Checks if the Linux guest has the KPTI active.

This function decodes instructions from syscall handler address and searches for the 'MOV CR3, REG' pattern; if this pattern is not found, the KPTI is not active for this guest.

If the 'TEST [gs:displacement], immediate' pattern is not found and the 'MOV CR3, REG', the KPTI is active for this guest, otherwise the value of 'displacement' operand is saved.

NOTE: The 'displacement' operand from instruction 'TEST [gs:displacement], imm' represents the value of 'kaiser_enabled_pcp' kallsym.

If the 'MOV CR3, REG' pattern is found and if the value of [GS:displacement] (previously saved from 'TEST [GS:displacement], imm') has the KAISER_PCP_ENABLED (1 << 0), thus the KPTI is active on this guest; otherwise KPTI is not active.

Parameters
[in]SyscallGvaThe address of the syscall handler.
Return values
INT_STATUS_SUCCESSOn success, or an appropriate INTSTATUS error value.

Definition at line 1032 of file lixguest.c.

Referenced by IntLixGuestNew().

◆ IntLixGuestIsSupported()

static BOOLEAN IntLixGuestIsSupported ( void  )
static

Load OS information from CAMI if the guest is supported.

Loads all OS specific information from CAMI, for the current guest described by GUEST_STATE.OSVersion then sets GUEST_STATE.SafeToApplyOptions

Return values
Trueif the guest is supported, otherwise false.

Definition at line 1727 of file lixguest.c.

Referenced by IntLixGuestNew().

◆ IntLixGuestNew()

INTSTATUS IntLixGuestNew ( void  )

Starts the initialization and enable protection for a new Linux guest.

This function initializes the LINUX_GUEST structure and searches for required objects: syscall, kernel sections, ksyms, version. This function also calls the IntLixGuestAllocate in order to inject the 'init' agent.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_SUPPORTEDIf the guest doesn't have a 64 bit architecture.

Definition at line 2561 of file lixguest.c.

Referenced by IntGuestHandleCr3Write().

◆ IntLixGuestParseVersion()

static INTSTATUS IntLixGuestParseVersion ( const char *  Buffer,
DWORD  BufferLength 
)
static

Parses the 'linux_proc_banner' and searches for 'version.patch.sublevel-backport' pattern.

On success, LINUX_GUEST.Version contains the found version.

Parameters
[in]BufferA buffer that contains the 'linux_proc_banner'.
[in]BufferLengthThe size (bytes) of the banner.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the version is not found.

Definition at line 66 of file lixguest.c.

Referenced by IntLixGuestFindKernelVersionAndRo().

◆ IntLixGuestResolveExTableLimits()

static INTSTATUS IntLixGuestResolveExTableLimits ( void  )
static

Decodes each instruction of the 'search_exception_tables' function and searches for 'MOV REG/RSI, immediate' pattern.

The specified pattern must be found twice. The immediate operand of the MOV instruction represents the start and the end of the exception table.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the 'search_exception_tables' ksym is not found or the start/end of extable is not found.

Definition at line 442 of file lixguest.c.

Referenced by IntLixGuestInit().

◆ IntLixGuestResolveOffsets()

static INTSTATUS IntLixGuestResolveOffsets ( void  )
static

Finds the offsets required by Introcore.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf a required offset is not found.

Definition at line 880 of file lixguest.c.

Referenced by IntLixGuestInit().

◆ IntLixGuestResolveSymbols()

static void IntLixGuestResolveSymbols ( void  )
static

Searches for the 'memcpy', '__memcpy', 'memset', '__memset' and 'memmove' ksyms.

Definition at line 515 of file lixguest.c.

Referenced by IntLixGuestInit().

◆ IntLixGuestSetOsVersion()

static void IntLixGuestSetOsVersion ( void  )
static

Computes the OS version number using the version, patch and sublevel.

Definition at line 52 of file lixguest.c.

Referenced by IntLixGuestParseVersion().

◆ IntLixGuestUnhookGuestCode()

void IntLixGuestUnhookGuestCode ( void  )

Remove the EPT hooks and memcloack from detours and agents.

Definition at line 2073 of file lixguest.c.

Referenced by IntLixGuestAllocateHook(), and IntLixGuestUninitGuestCode().

◆ IntLixGuestUninit()

void IntLixGuestUninit ( void  )

Uninitialize the Linux guest.

This function deactivate the protection and free any resources held by the LINUX_GUEST state.

Definition at line 1674 of file lixguest.c.

Referenced by IntGuestUninit().

◆ IntLixGuestUninitGuestCode()

void IntLixGuestUninitGuestCode ( void  )

Removes the EPT hooks from detours/agents memory zone and clears these memory zones.

Definition at line 2524 of file lixguest.c.

Referenced by IntGuestDisableIntro(), and IntLixGuestUninit().

◆ IntLixJumpLabelHandler()

INTSTATUS IntLixJumpLabelHandler ( void *  Detour)

Handles the incoming read (arch_jmp_label_transform) from the guest.

The function stores the information about the incoming read.

Parameters
[in]DetourThe detour for which this callback is invoked.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1497 of file lixguest.c.

◆ IntLixPatchHandler()

static INTSTATUS IntLixPatchHandler ( void *  Detour,
LIX_ACTIVE_PATCH ActivePatch 
)
static

Handles the incoming patches (ftrace/text_poke) from the guest.

If the originator of the patch is a driver a, the function stores the information about the patch, otherwise patch is ignored. The patch is also ignored if the size of the write is grater the sizeof(ActivePatch->Data).

Parameters
[in]DetourThe detour for which this callback is invoked.
[in]ActivePatchThe active-patch structure that contains information about the patch.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1388 of file lixguest.c.

Referenced by IntLixFtraceHandler(), and IntLixTextPokeHandler().

◆ IntLixResolveCurrentCpuOffset()

static INTSTATUS IntLixResolveCurrentCpuOffset ( void  )
static

Searches for the 'cpu_number' offset.

The function tries to find the 'cpu_number' ksym; if the ksym is found the value of 'cpu_number' is stored.

If the 'cpu_number' can't be found using IntKsymFindByName function, the function decode each instruction of the 'xen_halt' function and search for the first instruction that matches the 'MOV REG/MEM, [gs:displacement]'. The 'displacement' from operand [gs:displacement] represents the offset of 'cpu_number'.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the 'xen_halt' ksym is not found or the offset of the 'cpu_number' is not found.

Definition at line 593 of file lixguest.c.

Referenced by IntLixGuestResolveOffsets().

◆ IntLixResolveCurrentProcessOffset()

static INTSTATUS IntLixResolveCurrentProcessOffset ( void  )
static

Decodes each instruction of the 'do_exit' function and searches for 'MOV REG/MEM, [gs:displacement]' pattern in order to find the 'current' offset.

The 'displacement' from operand [gs:displacement] represents the offset of the 'current' task.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the 'do_exit' ksym is not found or the offset of the 'current' is not found.

Definition at line 541 of file lixguest.c.

Referenced by IntLixGuestResolveOffsets().

◆ IntLixResolveExeFileOffset()

static INTSTATUS IntLixResolveExeFileOffset ( void  )
static

Decodes each instruction of the 'get_mm_exe_file' function and searches for 'MOV REG, [RDI + Displacement]' pattern in order to find the 'mm_struct->exe_file' offset.

The 'Displacement' operand represents the offset of the 'exe_file' in the 'mm_struct' structure (mm_struct->exe_file).

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the 'get_mm_exe_file' ksym is not found or the offset of the 'exe_file' is not found.

Definition at line 731 of file lixguest.c.

Referenced by IntLixGuestResolveOffsets().

◆ IntLixResolveThreadStructOffset()

static INTSTATUS IntLixResolveThreadStructOffset ( void  )
static

Decodes each instruction of the 'set_tls_desc' function and searches for 'MOV RDI, immediate' pattern in order to find the 'task_struct->thread_struct' offset.

The 'Immediate' operand represents the offset of the 'thread_struct' in the 'task_struct' structure.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the 'set_tls_desc' ksym is not found or the offset of the 'thread_struct' is not found.

Definition at line 667 of file lixguest.c.

Referenced by IntLixGuestResolveOffsets().

◆ IntLixTextPokeHandler()

INTSTATUS IntLixTextPokeHandler ( void *  Detour)

Handles the incoming 'text_poke' patches from the guest.

Parameters
[in]DetourThe detour for which this callback is invoked.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1463 of file lixguest.c.

Variable Documentation

◆ gKernelDrivers

LIST_HEAD gKernelDrivers

List of all the drivers currently loaded inside the guest.

Can always be safely used.

Definition at line 11 of file drivers.c.

◆ gLinuxDistSigs

PATTERN_SIGNATURE* gLinuxDistSigs

An array that contains the distro signatures.

Pointer to the linux distribution signatures that will be loaded from the update buffer.

Definition at line 35 of file lixguest.c.

◆ gLinuxDistSigsCount

DWORD gLinuxDistSigsCount = 0

The number of distro signatures from gLinuxDistSigs.

Holds the number of loaded linux distribution signatures.

Definition at line 37 of file lixguest.c.

Referenced by IntCamiLoadLixDistSigs(), and IntLixGuestFindKernelBase().

◆ gLixGuest

LINUX_GUEST* gLixGuest = NULL

Global variable holding the state of a Linux guest.

This is not dynamically allocated. It points to the _LinuxGuest field of the gGuest variable. Its value is set by IntLixGuestNew.

Definition at line 30 of file lixguest.c.

Referenced by IntCamiLoadLinux(), IntCamiLoadOpaqueFields(), IntCamiLoadProtOptionsLinux(), IntDetCallCallback(), IntDetCreateObjectLix(), IntDetHandleWrite(), IntDetIsPtrInHandler(), IntExceptLixKernelIsMemoryFunc(), IntExceptVerifyVersionOsSignature(), IntGuestGetInfo(), IntGuestUninit(), IntKsymInitAbsolute(), IntKsymRelativeFindOffsetTableEnd(), IntKsymRelativeFindOffsetTableStart(), IntLixAgentFillDataFromMemory(), IntLixAgentFindInstruction(), IntLixAgentMatchVersion(), IntLixAgentThreadInject(), IntLixApiHookAll(), IntLixApiUpdateHooks(), IntLixCrashDumpDmesg(), IntLixDepInjectFile(), IntLixDepInjectProcess(), IntLixDrvCreateKernel(), IntLixDrvFindList(), IntLixDrvHandleWrite(), IntLixDrvIsActivePatch(), IntLixDrvIterateList(), IntLixDrvSendViolationEvent(), IntLixDumpStacktrace(), IntLixGetInitTask(), IntLixHookKernelRead(), IntLixHookKernelWrite(), IntLixKernelHandleRead(), IntLixMmGetInitMm(), IntLixPatchSwapgs(), IntLixTaskCreate(), IntLixTaskGetCurrentTaskStruct(), IntLixTaskHandleDoExit(), IntLixTaskHandleExec(), IntLixTaskIterateThreadGroup(), IntLixTaskIterateThreadNode(), IntLixVdsoDynamicProtect(), IntLixVdsoDynamicProtectNonRelocate(), IntLixVdsoDynamicProtectRelocate(), IntLixVdsoFixedProtect(), IntLixVdsoResolveDynamicOffset(), and IntThrSafeLixInspectWaitingThread().