Bitdefender Hypervisor Memory Introspection
winpower.c File Reference

This file handles Windows guest power state changes. More...

#include "winpower.h"
#include "guests.h"
#include "ptfilter.h"
#include "vecore.h"
#include "winagent.h"

Go to the source code of this file.

Functions

static INTRO_POWER_STATE IntWinPowFromGuestToIntroPowState (DWORD GuestPowerAction, DWORD GuestPowerState)
 Converts in-guest parameters given to NtSetSystemPowerState to an internal introspection used power state. More...
 
static INTSTATUS IntWinPowGetRequestedPowerState (DWORD *RequestedPowerAction, DWORD *RequestedPowerState)
 Gets the parameters of NtSetSystemPowerState depending on OS architecture. More...
 
INTSTATUS IntWinPowEnableSpinWait (void)
 This function is called in order to re-enable spin waiting in the handler after it was previously disabled. More...
 
INTSTATUS IntWinPowDisableSpinWait (void)
 This function is called in order to disable spin waiting after everything we needed to be unloaded was done. More...
 
static INTSTATUS IntWinPowHandleEventCommon (INTRO_POWER_STATE PowerState)
 This function will be called on any power state change event. Everything that we want to uninit on every power state event will be put here. Note that this function will enable the NtSetSystemPowerState spinwait only if there is something to be done - if there isn't anything it will just return. More...
 
static void IntWinPowHandleHibernateEvent (void)
 Callback called when the change of guest power state to hibernate occurs. More...
 
INTSTATUS IntWinPowHandlePowerStateChange (void *Detour)
 Detour callback which is called whenever NtSetSystemPowerState is called, resulting in a hypercall to the introspection engine. More...
 

Detailed Description

This file handles Windows guest power state changes.

Due to various actions the guest takes when a power state change occurs, introspection engine must be aware of these changes and act accordingly depending on the situation. For example, due to empiric observations, it seems like the Windows operating system remaps NonPagedPool pages when going through a hybrid sleep. This affects the in-guest agents like the VE agent or the PT filter agent, as going through remappings will issue a page fault if there would be executions inside the agent. Other cases like these have been observed both during reboots and shutdowns. For this case we should always remove our agents at the moment of the thus the need of intercepting them through detouring the NtSetSystemPowerState Windows API is required. Other cases involve possible race conditions when hibernating. For example, if we only stop the VAD monitoring then there is the possibility that in the meantime, a new module loads and hooks some user-mode APIs in a protected process. Thus when hibernating, although there is a time frame of at most a couple of seconds where the protection is lost, we disable all protection, thus removing the probability of a race condition to occur. It is worth noting that the NtSetSystemPowerState detour handler will have a small space inside the guest where the introspection engine might decide to insert a spinlock, in order to keep the guest spinning while some operations involving guest execution are done. This is needed to wait for the VE agent unloader/PT filter unloader to finish executing in guest before actually giving the control back to the NtSetSystemPowerState function and let the guest continue the power state change flow. The agent unloader should be given the option AG_OPT_INJECT_ON_RIP_POWSTATE_CHANGE, as a performance tweak, guaranteeing that the agent will start executing directly from the NtSetSystemPowerState detour (e.g. the needed instruction won't be chosen anymore from the syscall handler return, but rather it will be the next instruction from the in-guest RIP, since the NtSetSystemPowerState runs at PASSIVE_LEVEL, it will have the same effect but instead of waiting for a syscall to be executed, it will give the control to the bootstrap immediately).

Definition in file winpower.c.

Function Documentation

◆ IntWinPowDisableSpinWait()

INTSTATUS IntWinPowDisableSpinWait ( void  )

This function is called in order to disable spin waiting after everything we needed to be unloaded was done.

Returns
INT_STATUS_SUCCESS on success, or other error INTSTATUS values which may be returned by IntDetModifyPublicData.

Definition at line 170 of file winpower.c.

Referenced by IntPtCompleteUnloader(), and IntVeCompleteUnloader().

◆ IntWinPowEnableSpinWait()

INTSTATUS IntWinPowEnableSpinWait ( void  )

This function is called in order to re-enable spin waiting in the handler after it was previously disabled.

Returns
INT_STATUS_SUCCESS on success, or other error INTSTATUS values which may be returned by IntDetModifyPublicData.

Definition at line 137 of file winpower.c.

Referenced by IntWinPowHandleEventCommon().

◆ IntWinPowFromGuestToIntroPowState()

static INTRO_POWER_STATE IntWinPowFromGuestToIntroPowState ( DWORD  GuestPowerAction,
DWORD  GuestPowerState 
)
static

Converts in-guest parameters given to NtSetSystemPowerState to an internal introspection used power state.

Parameters
[in]GuestPowerActionThe first parameter of NtSetSystemPowerState, which is the requested action.
[in]GuestPowerStateThe second parameter of NtSetSystemPowerState, being the requested state in which the system should enter.
Returns
An introspection-defined state, see INTRO_POWER_STATE for more details.

Definition at line 42 of file winpower.c.

Referenced by IntWinPowHandlePowerStateChange().

◆ IntWinPowGetRequestedPowerState()

static INTSTATUS IntWinPowGetRequestedPowerState ( DWORD RequestedPowerAction,
DWORD RequestedPowerState 
)
static

Gets the parameters of NtSetSystemPowerState depending on OS architecture.

Parameters
[out]RequestedPowerActionContains, on success, the first parameter, the power action requested to the system.
[out]RequestedPowerStateContains, on success the requested power state in which the system must be after the NtSetSystemPowerState execution.
Returns
INT_STATUS_SUCCESS on success; other error INTSTATUS values which IntKernVirtMemRead may return.

Definition at line 96 of file winpower.c.

Referenced by IntWinPowHandlePowerStateChange().

◆ IntWinPowHandleEventCommon()

static INTSTATUS IntWinPowHandleEventCommon ( INTRO_POWER_STATE  PowerState)
static

This function will be called on any power state change event. Everything that we want to uninit on every power state event will be put here. Note that this function will enable the NtSetSystemPowerState spinwait only if there is something to be done - if there isn't anything it will just return.

Parameters
[in]PowerStateThe power state in which the guest desires to enter
Returns
INT_STATUS_NOT_NEEDED_HINT if the state is unknown or there is nothing to be done; other error INTSTATUS values depending on what IntPtiRemovePtFilter, IntVeRemoveAgent or IntWinPowEnableSpinWait might return

Definition at line 201 of file winpower.c.

Referenced by IntWinPowHandlePowerStateChange().

◆ IntWinPowHandleHibernateEvent()

static void IntWinPowHandleHibernateEvent ( void  )
static

Callback called when the change of guest power state to hibernate occurs.

Definition at line 258 of file winpower.c.

Referenced by IntWinPowHandlePowerStateChange().