Fix multiple bugs, refactor InitializeMsrBitmaps
This commit is contained in:
@@ -123,12 +123,12 @@ AsmHypervisorEntryPoint proc frame
|
|||||||
;
|
;
|
||||||
; Restore XMM registers.
|
; Restore XMM registers.
|
||||||
;
|
;
|
||||||
movaps xmm0, xmmword ptr [rsp + 0h]
|
|
||||||
movaps xmm1, xmmword ptr [rsp + 10h]
|
|
||||||
movaps xmm2, xmmword ptr [rsp + 20h]
|
|
||||||
movaps xmm3, xmmword ptr [rsp + 30h]
|
|
||||||
movaps xmm4, xmmword ptr [rsp + 40h]
|
|
||||||
movaps xmm5, xmmword ptr [rsp + 50h]
|
movaps xmm5, xmmword ptr [rsp + 50h]
|
||||||
|
movaps xmm4, xmmword ptr [rsp + 40h]
|
||||||
|
movaps xmm3, xmmword ptr [rsp + 30h]
|
||||||
|
movaps xmm2, xmmword ptr [rsp + 20h]
|
||||||
|
movaps xmm1, xmmword ptr [rsp + 10h]
|
||||||
|
movaps xmm0, xmmword ptr [rsp + 0h]
|
||||||
add rsp, 68h
|
add rsp, 68h
|
||||||
|
|
||||||
;
|
;
|
||||||
@@ -182,7 +182,7 @@ VmxError:
|
|||||||
; VMRESUME or VMXOFF instruction failed. Unrecoverble. The most useful
|
; VMRESUME or VMXOFF instruction failed. Unrecoverble. The most useful
|
||||||
; thing to do here is to call a C-function to diagnose the issue.
|
; thing to do here is to call a C-function to diagnose the issue.
|
||||||
;
|
;
|
||||||
pushf
|
pushfq
|
||||||
PUSHAQ
|
PUSHAQ
|
||||||
mov rcx, rsp
|
mov rcx, rsp
|
||||||
sub rsp, 20h
|
sub rsp, 20h
|
||||||
|
|||||||
@@ -421,13 +421,16 @@ FindImageBase (
|
|||||||
UINT64 GuestVirtualAddress
|
UINT64 GuestVirtualAddress
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
UINT64 imageBase;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Starting with the 1MB aligned address, and search up IMAGE_DOS_SIGNATURE
|
// Starting with the page aligned address, and search up IMAGE_DOS_SIGNATURE
|
||||||
// every 1MB.
|
// every page up to 16MB (0x1000000). Ntoskrnl.exe can be mapped at the page
|
||||||
|
// boundary and not the 64KB boundary unlike other images.
|
||||||
//
|
//
|
||||||
for (UINT64 imageBase = (GuestVirtualAddress & ~(0x10000 - 1));
|
imageBase = (GuestVirtualAddress & ~(PAGE_SIZE - 1));
|
||||||
/**/;
|
|
||||||
imageBase -= 0x10000)
|
for (int i = 0; i < 0x1000; i++, imageBase -= PAGE_SIZE)
|
||||||
{
|
{
|
||||||
BOOLEAN ok;
|
BOOLEAN ok;
|
||||||
UINT16 contents;
|
UINT16 contents;
|
||||||
@@ -441,12 +444,90 @@ FindImageBase (
|
|||||||
&errorInfo);
|
&errorInfo);
|
||||||
if (ok == FALSE)
|
if (ok == FALSE)
|
||||||
{
|
{
|
||||||
return 0;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contents == 0x5A4D)
|
if (contents == 0x5A4D)
|
||||||
{
|
{
|
||||||
return imageBase;
|
goto Exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imageBase = 0;
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
return imageBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
VOID
|
||||||
|
UpdateMsrBitmaps (
|
||||||
|
MSR_BITMAPS* Bitmaps,
|
||||||
|
IA32_MSR_ADDRESS Msr,
|
||||||
|
OPERATION_TYPE InterOperation,
|
||||||
|
BOOLEAN Intercept
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IA32_MSR_ADDRESS msrTemp;
|
||||||
|
BOOLEAN highValue;
|
||||||
|
UINT64 byteOffset;
|
||||||
|
UINT64 bitMask;
|
||||||
|
UINT8* msrBitmap;
|
||||||
|
|
||||||
|
//
|
||||||
|
// MSR must be within either 0x0 - 0x1fff or 0xc0000000 - 0xc0001fff
|
||||||
|
// inclusive, and at least read or write intercept must be specified.
|
||||||
|
//
|
||||||
|
MV_ASSERT((Msr <= 0x1fff) ||
|
||||||
|
((Msr >= 0xc0000000) && (Msr <= 0xc0001fff)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if the MSR belongs to high bitmaps.
|
||||||
|
//
|
||||||
|
highValue = BooleanFlagOn(Msr, 0xc0000000);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Computes offsets and bitmaps to update the bitmaps.
|
||||||
|
//
|
||||||
|
msrTemp = (Msr & ~0xc0000000);
|
||||||
|
byteOffset = (msrTemp / CHAR_BIT);
|
||||||
|
bitMask = (1ull << (msrTemp % CHAR_BIT));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Select the bitmap to work on.
|
||||||
|
//
|
||||||
|
if (InterOperation == OperationRead)
|
||||||
|
{
|
||||||
|
if (highValue == FALSE)
|
||||||
|
{
|
||||||
|
msrBitmap = Bitmaps->ReadBitmapLow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msrBitmap = Bitmaps->ReadBitmapHigh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (highValue == FALSE)
|
||||||
|
{
|
||||||
|
msrBitmap = Bitmaps->WriteBitmapLow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msrBitmap = Bitmaps->WriteBitmapHigh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set of clear the bit.
|
||||||
|
//
|
||||||
|
if (Intercept != FALSE)
|
||||||
|
{
|
||||||
|
SetFlag(msrBitmap[byteOffset], bitMask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClearFlag(msrBitmap[byteOffset], bitMask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,3 +231,24 @@ FindImageBase (
|
|||||||
_In_ GUEST_CONTEXT* GuestContext,
|
_In_ GUEST_CONTEXT* GuestContext,
|
||||||
_In_ UINT64 GuestVirtualAddress
|
_In_ UINT64 GuestVirtualAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief Updates the MSR bitmap as specified.
|
||||||
|
|
||||||
|
@param[in] Bitmaps - The pointer to the MSR bitmaps.
|
||||||
|
|
||||||
|
@param[in,out] Msr - The MSR to change configurations. Must be in the range of
|
||||||
|
0x0 - 0x1fff or 0xc0000000 - 0xc0001fff.
|
||||||
|
|
||||||
|
@param[in] InterOperation - The type of operation to change configurations.
|
||||||
|
|
||||||
|
@param[in] Intercept - TRUE if the hypervisor should intercept the specified
|
||||||
|
type of access.
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
UpdateMsrBitmaps (
|
||||||
|
_Inout_ MSR_BITMAPS* Bitmaps,
|
||||||
|
_In_ IA32_MSR_ADDRESS Msr,
|
||||||
|
_In_ OPERATION_TYPE InterOperation,
|
||||||
|
_In_ BOOLEAN Intercept
|
||||||
|
);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ HandleVmcallUninstall (
|
|||||||
//
|
//
|
||||||
gdtr.BaseAddress = VmxRead(VMCS_GUEST_GDTR_BASE);
|
gdtr.BaseAddress = VmxRead(VMCS_GUEST_GDTR_BASE);
|
||||||
gdtr.Limit = (UINT16)VmxRead(VMCS_GUEST_GDTR_LIMIT);
|
gdtr.Limit = (UINT16)VmxRead(VMCS_GUEST_GDTR_LIMIT);
|
||||||
_sgdt(&gdtr);
|
_lgdt(&gdtr);
|
||||||
|
|
||||||
idtr.BaseAddress = VmxRead(VMCS_GUEST_IDTR_BASE);
|
idtr.BaseAddress = VmxRead(VMCS_GUEST_IDTR_BASE);
|
||||||
idtr.Limit = (UINT16)VmxRead(VMCS_GUEST_IDTR_LIMIT);
|
idtr.Limit = (UINT16)VmxRead(VMCS_GUEST_IDTR_LIMIT);
|
||||||
|
|||||||
@@ -996,6 +996,7 @@ SetupVmcs (
|
|||||||
// Finally, place necessary data for hypervisor into the hypervisor stack.
|
// Finally, place necessary data for hypervisor into the hypervisor stack.
|
||||||
//
|
//
|
||||||
ProcessorContext->HypervisorStack.u.Layout.Context.ProcessorNumber = GetCurrentProcessorNumber();
|
ProcessorContext->HypervisorStack.u.Layout.Context.ProcessorNumber = GetCurrentProcessorNumber();
|
||||||
|
ProcessorContext->HypervisorStack.u.Layout.Context.SharedMsrBitmaps = &SharedProcessorContext->MsrBitmaps;
|
||||||
ProcessorContext->HypervisorStack.u.Layout.Context.SharedProcessorContext = SharedProcessorContext;
|
ProcessorContext->HypervisorStack.u.Layout.Context.SharedProcessorContext = SharedProcessorContext;
|
||||||
ProcessorContext->HypervisorStack.u.Layout.Context.EptContext = &ProcessorContext->EptContext;
|
ProcessorContext->HypervisorStack.u.Layout.Context.EptContext = &ProcessorContext->EptContext;
|
||||||
ProcessorContext->HypervisorStack.u.Layout.Context.MemoryAccessContext = &ProcessorContext->MemoryAccessContext;
|
ProcessorContext->HypervisorStack.u.Layout.Context.MemoryAccessContext = &ProcessorContext->MemoryAccessContext;
|
||||||
@@ -1178,14 +1179,28 @@ InitializeMsrBitmaps (
|
|||||||
_Out_ MSR_BITMAPS* Bitmaps
|
_Out_ MSR_BITMAPS* Bitmaps
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
static CONST UINT64 biosSignatureByteOffset = (IA32_BIOS_SIGN_ID / CHAR_BIT);
|
typedef struct _INTERCEPT_MSR_REGISTRATION
|
||||||
static CONST UINT64 biosSignatureBitMask = (1ull << (IA32_BIOS_SIGN_ID % CHAR_BIT));
|
{
|
||||||
|
IA32_MSR_ADDRESS Msr;
|
||||||
|
OPERATION_TYPE InterceptType;
|
||||||
|
} INTERCEPT_MSR_REGISTRATION;
|
||||||
|
|
||||||
|
static CONST INTERCEPT_MSR_REGISTRATION registrations[] =
|
||||||
|
{
|
||||||
|
{ IA32_BIOS_SIGN_ID, OperationRead, },
|
||||||
|
};
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
RtlZeroMemory(Bitmaps, sizeof(*Bitmaps));
|
RtlZeroMemory(Bitmaps, sizeof(*Bitmaps));
|
||||||
|
|
||||||
Bitmaps->ReadBitmapLow[biosSignatureByteOffset] |= biosSignatureBitMask;
|
for (int i = 0; i < RTL_NUMBER_OF(registrations); ++i)
|
||||||
|
{
|
||||||
|
UpdateMsrBitmaps(Bitmaps,
|
||||||
|
registrations[i].Msr,
|
||||||
|
registrations[i].InterceptType,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -41,7 +41,11 @@ typedef struct _HYPERVISOR_CONTEXT
|
|||||||
//
|
//
|
||||||
UINT32 ProcessorNumber;
|
UINT32 ProcessorNumber;
|
||||||
UINT32 Padding1;
|
UINT32 Padding1;
|
||||||
UINT64 Padding2;
|
|
||||||
|
//
|
||||||
|
// The pointer to the MSR bitmaps that are shared across processor.
|
||||||
|
//
|
||||||
|
struct _MSR_BITMAPS* SharedMsrBitmaps;
|
||||||
|
|
||||||
//
|
//
|
||||||
// A pointer to the shared processor context. This value is not used by the
|
// A pointer to the shared processor context. This value is not used by the
|
||||||
|
|||||||
Reference in New Issue
Block a user