Bitdefender Hypervisor Memory Introspection
lixvdso.c File Reference
#include "lixvdso.h"
#include "alerts.h"
#include "decoder.h"
#include "hook.h"
#include "lixstack.h"
#include "lixksym.h"

Go to the source code of this file.

Macros

#define LIX_VDSO_GPA_HOOK_PAGE_COUNT   3
 

Functions

static void IntLixVdsoHandleKernelModeWrite (QWORD Address, INTRO_OBJECT_TYPE Type, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
 Handles vDSO modification (from kernel-mode) detected by the EPT mechanism. More...
 
static void IntLixVdsoHandleUserModeWrite (QWORD Address, INTRO_OBJECT_TYPE Type, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
 Handles vDSO modification (from user-mode) detected by the EPT mechanism. More...
 
static INTSTATUS IntLixVdsoHandleWriteCommon (void *Context, HOOK_GPA *Hook, QWORD Address, INTRO_ACTION *Action)
 Handles vDSO modification detected by the EPT mechanism. More...
 
static BOOLEAN IntLixVdsoIsInitWrite (QWORD Rip)
 Checks if the write is over the vDSO on the initialization phase. More...
 
static INTSTATUS IntLixVdsoHandleWrite (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 Handles vDSO modification detected by the EPT mechanism. More...
 
static INTSTATUS IntLixVdsoResolveImageAddress (char *FunctionName, QWORD *Address)
 Parse the provided function and search the 'vdso_image...' address. More...
 
static INTSTATUS IntLixVdsoResolveDynamicOffset (void)
 Fetch the address of the 'vdso_image_64', 'vdso_image_x32' ksyms or the address of the 'vdso_start', 'vdso_end', 'vdsox32_start', 'vdsox32_end' ksyms. More...
 
static INTSTATUS IntLixVdsoDynamicProtectRelocate (void)
 Protect the vDSO using GPA hooks. More...
 
static INTSTATUS IntLixVdsoDynamicProtectNonRelocate (void)
 Protect the vDSO using GVA hooks. More...
 
INTSTATUS IntLixVdsoDynamicProtect (void)
 This function activates the protection for the vDSO image. More...
 
static INTSTATUS IntLixVdsoFixedProtect (void)
 This function activates the protection for the VSYSCALL. More...
 
INTSTATUS IntLixVdsoFetchAddress (LIX_TASK_OBJECT *Task, QWORD *Address)
 Fetch the guest virtual address of the vDSO mapped on the provided task. More...
 
INTSTATUS IntLixVdsoProtect (void)
 Activates protection for the vDSO image and VSYSCALL. More...
 
void IntLixVdsoUnprotect (void)
 Remove protection for the vDSO image and VSYSCALL. More...
 

Variables

static void * gVdsoHook = NULL
 
static void * gVdsoGpaHook [LIX_VDSO_GPA_HOOK_PAGE_COUNT]
 
static LIX_SYMBOL gInitVdsoSym = { 0 }
 
static LIX_SYMBOL gAddNopsSym = { 0 }
 
static LIX_SYMBOL gTextPokeEarlySym = { 0 }
 

Macro Definition Documentation

◆ LIX_VDSO_GPA_HOOK_PAGE_COUNT

#define LIX_VDSO_GPA_HOOK_PAGE_COUNT   3

Definition at line 13 of file lixvdso.c.

Function Documentation

◆ IntLixVdsoDynamicProtect()

INTSTATUS IntLixVdsoDynamicProtect ( void  )

This function activates the protection for the vDSO image.

The function checks if the vDSO image is relocated and calls the proper function to activate the protection. The 'init_vdso', 'text_poke_early', 'add_nops' ksyms are fetched in order to except the init writes (see IntLixVdsoIsInitWrite).

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 726 of file lixvdso.c.

Referenced by IntLixTaskHandleExec(), and IntLixVdsoProtect().

◆ IntLixVdsoDynamicProtectNonRelocate()

static INTSTATUS IntLixVdsoDynamicProtectNonRelocate ( void  )
static

Protect the vDSO using GVA hooks.

This function is used if the vDSO image that is not relocated (see IntLixVdsoDynamicProtectRelocate). This function hooks the [vdso_start, vdso_end] range and the [vdso32_start, vdso32_end] range, if any.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 646 of file lixvdso.c.

Referenced by IntLixVdsoDynamicProtect().

◆ IntLixVdsoDynamicProtectRelocate()

static INTSTATUS IntLixVdsoDynamicProtectRelocate ( void  )
static

Protect the vDSO using GPA hooks.

This function is used if the vDSO image is relocated; the kernel 2.6 discards the initial vDSO image and move it to another guest virtual address. In order to find the guest physical address of the vDSO image, the function fetch the task_struct->mm->context->vdso of the 'init' task that is a guest virtual address of the mapped vDSO image in that task. The address of the vDSO image is translated to the guest physical address and then the function set a GPA hook.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZED_HINTIf the vDSO is not initialized yet.

Definition at line 564 of file lixvdso.c.

Referenced by IntLixVdsoDynamicProtect().

◆ IntLixVdsoFetchAddress()

INTSTATUS IntLixVdsoFetchAddress ( LIX_TASK_OBJECT Task,
QWORD Address 
)

Fetch the guest virtual address of the vDSO mapped on the provided task.

Parameters
[in]TaskThe task from which the vDSO address is fetched.
[out]AddressThe address of the vDSO image.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If the provided task is invalid.

Definition at line 850 of file lixvdso.c.

Referenced by IntLixVdsoDynamicProtectRelocate().

◆ IntLixVdsoFixedProtect()

static INTSTATUS IntLixVdsoFixedProtect ( void  )
static

This function activates the protection for the VSYSCALL.

A GVA hook is set for the VSYSCALL page.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the kernel is build without VSYSCALL support.

Definition at line 787 of file lixvdso.c.

Referenced by IntLixVdsoProtect().

◆ IntLixVdsoHandleKernelModeWrite()

static void IntLixVdsoHandleKernelModeWrite ( QWORD  Address,
INTRO_OBJECT_TYPE  Type,
INTRO_ACTION Action,
INTRO_ACTION_REASON Reason 
)
static

Handles vDSO modification (from kernel-mode) detected by the EPT mechanism.

If a write from kernel-mode occurs the exceptions mechanism is used to decide if the write should be allowed.

Parameters
[in]AddressThe modified guest physical address.
[in]TypeThe type of the modified zone.
[out]ActionThe action that will be taken.
[out]ReasonThe reason for which Action is taken.

Definition at line 26 of file lixvdso.c.

Referenced by IntLixVdsoHandleWriteCommon().

◆ IntLixVdsoHandleUserModeWrite()

static void IntLixVdsoHandleUserModeWrite ( QWORD  Address,
INTRO_OBJECT_TYPE  Type,
INTRO_ACTION Action,
INTRO_ACTION_REASON Reason 
)
static

Handles vDSO modification (from user-mode) detected by the EPT mechanism.

If a write from user-mode occurs the exceptions mechanism is used to decide if the write should be allowed.

Parameters
[in]AddressThe modified guest physical address.
[in]TypeThe type of the modified zone.
[out]ActionThe action that will be taken.
[out]ReasonThe reason for which Action is taken.

Definition at line 88 of file lixvdso.c.

Referenced by IntLixVdsoHandleWriteCommon().

◆ IntLixVdsoHandleWrite()

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

Handles vDSO modification detected by the EPT mechanism.

This function checks if the modification is an initialization write; if the 'init' write is detected, the write is allowed, otherwise IntLixVdsoHandleWriteCommon is called. The IntLixVdsoIsInitWrite is called for the stack-trace too.

Parameters
[in]ContextThe type of the modified zone.
[in]HookThe HOOK_GPA for which this callback was invoked.
[in]AddressThe modified guest physical address.
[out]ActionThe action that will be taken.
Return values
INT_STATUS_SUCCESSAlways.

Definition at line 279 of file lixvdso.c.

Referenced by IntLixVdsoDynamicProtectNonRelocate(), and IntLixVdsoDynamicProtectRelocate().

◆ IntLixVdsoHandleWriteCommon()

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

Handles vDSO modification detected by the EPT mechanism.

This function calls the IntLixVdsoHandleKernelModeWrite or IntLixVdsoHandleUserModeWrite according to the RIP to handle the vDSO write. If the write is not allowed or feedback-only reason is set, the event is reported to the integrator.

Parameters
[in]ContextThe type of the modified zone.
[in]HookThe HOOK_GPA for which this callback was invoked.
[in]AddressThe modified guest physical address.
[out]ActionThe action that will be taken.
Return values
INT_STATUS_SUCCESSAlways.

Definition at line 164 of file lixvdso.c.

Referenced by IntLixVdsoFixedProtect(), and IntLixVdsoHandleWrite().

◆ IntLixVdsoIsInitWrite()

static BOOLEAN IntLixVdsoIsInitWrite ( QWORD  Rip)
static

Checks if the write is over the vDSO on the initialization phase.

This function verify if the provided RIP:

  • is in range [text_poke_early_start, text_poke_early_end];
  • is in range [add_nops_start, add_nops_end];
  • is in range [init_vdso_start, init_vdso_end];
Parameters
[in]RipThe originator RIP of the write.
Return values
Trueif at least one condition is met, otherwise false.

Definition at line 257 of file lixvdso.c.

Referenced by IntLixVdsoHandleWrite().

◆ IntLixVdsoProtect()

INTSTATUS IntLixVdsoProtect ( void  )

Activates protection for the vDSO image and VSYSCALL.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 883 of file lixvdso.c.

Referenced by IntGuestUpdateCoreOptions(), and IntLixGuestActivateProtection().

◆ IntLixVdsoResolveDynamicOffset()

static INTSTATUS IntLixVdsoResolveDynamicOffset ( void  )
static

Fetch the address of the 'vdso_image_64', 'vdso_image_x32' ksyms or the address of the 'vdso_start', 'vdso_end', 'vdsox32_start', 'vdsox32_end' ksyms.

If the guest has vDSO image struct this function fetch the addresses of the 'vdso_image_64', 'vdso_image_x32' ksyms. If these symbols are exported, this function call the IntKsymFindByName , otherwise IntLixVdsoResolveImageAddress is called. If the guest hasn't vDSO image struct the function fetch the addresses of the 'vdso_start', 'vdso_end', 'vdsox32_start', 'vdsox32_end' ksyms by calling the IntKsymFindByName.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the addresses are not found.

Definition at line 433 of file lixvdso.c.

Referenced by IntLixVdsoProtect().

◆ IntLixVdsoResolveImageAddress()

static INTSTATUS IntLixVdsoResolveImageAddress ( char *  FunctionName,
QWORD Address 
)
static

Parse the provided function and search the 'vdso_image...' address.

The function decode the instructions of the provided function until the 'mov rdi, immediate; call/jmp map_vdso' pattern is found. This function is used for the Linux guests that don't export the 'vdso_image...' address.

Parameters
[in]FunctionNameThe provided function name.
[out]AddressThe address of the 'vdso_image...'.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the address of the 'vdso_image...' is not found.

Definition at line 331 of file lixvdso.c.

Referenced by IntLixVdsoResolveDynamicOffset().

◆ IntLixVdsoUnprotect()

void IntLixVdsoUnprotect ( void  )

Remove protection for the vDSO image and VSYSCALL.

Definition at line 928 of file lixvdso.c.

Referenced by IntGuestUpdateCoreOptions(), and IntLixGuestUninit().

Variable Documentation

◆ gAddNopsSym

LIX_SYMBOL gAddNopsSym = { 0 }
static

Definition at line 20 of file lixvdso.c.

◆ gInitVdsoSym

LIX_SYMBOL gInitVdsoSym = { 0 }
static

Definition at line 19 of file lixvdso.c.

◆ gTextPokeEarlySym

LIX_SYMBOL gTextPokeEarlySym = { 0 }
static

Definition at line 21 of file lixvdso.c.

◆ gVdsoGpaHook

void* gVdsoGpaHook[LIX_VDSO_GPA_HOOK_PAGE_COUNT]
static

Definition at line 16 of file lixvdso.c.

Referenced by IntLixVdsoDynamicProtectRelocate(), and IntLixVdsoUnprotect().

◆ gVdsoHook

void* gVdsoHook = NULL
static