diff options
author | ionescu007 <aionescu+git@gmail.com> | 2016-08-29 08:43:50 +0300 |
---|---|---|
committer | ionescu007 <aionescu+git@gmail.com> | 2016-08-29 08:43:50 +0300 |
commit | 34472d9045d16280c9a4502ac83b383d75b7f740 (patch) | |
tree | dcedd9c86adbb914b90f230a659d9fb0911f4420 | |
parent | 20e2c570c3c5ca080143fb49c2d340a66d494e04 (diff) |
Death to global data!
Each routine knew exactly how to get its VP Data except the
post-launch-guest-resumer. We now run it on the hypervisor stack (which
shouldn't matter -- because it uses no stack variables other than the
home space), which means it can essentially "containing record" its VP
data based on it.
-rw-r--r-- | shv.c | 25 | ||||
-rw-r--r-- | shv.h | 2 | ||||
-rw-r--r-- | shvvmx.c | 2 | ||||
-rw-r--r-- | shvvp.c | 29 |
4 files changed, 22 insertions, 36 deletions
@@ -22,8 +22,6 @@ Environment: #include "shv.h" -PSHV_VP_DATA* ShvGlobalData; - VOID ShvUnload ( _In_ PDRIVER_OBJECT DriverObject @@ -45,12 +43,6 @@ ShvUnload ( KeGenericCallDpc(ShvVpCallbackDpc, &dpcContext); // - // Global data is always allocated and should be freed - // - NT_ASSERT(ShvGlobalData); - ExFreePoolWithTag(ShvGlobalData, 'ShvA'); - - // // Indicate unload // DbgPrintEx(77, 0, "The SHV has been uninstalled.\n"); @@ -62,24 +54,10 @@ ShvInitialize ( _In_ PUNICODE_STRING RegistryPath ) { - LONG cpuCount; SHV_DPC_CONTEXT dpcContext; UNREFERENCED_PARAMETER(RegistryPath); // - // Allocate the global shared data which all virtual processors will share. - // - cpuCount = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS); - ShvGlobalData = ExAllocatePoolWithTag(NonPagedPoolNx, - cpuCount * sizeof(PVOID), - 'ShvA'); - if (!ShvGlobalData) - { - return STATUS_HV_INSUFFICIENT_BUFFER; - } - __stosq((PULONG64)ShvGlobalData, 0, cpuCount); - - // // Attempt to enter VMX root mode on all logical processors. This will // broadcast a DPC interrupt which will execute the callback routine in // parallel on the LPs. Send the callback routine the physical address of @@ -99,12 +77,11 @@ ShvInitialize ( // // Note that each VP is responsible for freeing its VP data on failure. // - if (dpcContext.InitCount != cpuCount) + if (dpcContext.InitCount != KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS)) { DbgPrintEx(77, 0, "The SHV failed to initialize (0x%lX) Failed CPU: %d\n", dpcContext.FailureStatus, dpcContext.FailedCpu); NT_ASSERT(dpcContext.FailureStatus != STATUS_SUCCESS); - ExFreePoolWithTag(ShvGlobalData, 'ShvA'); return dpcContext.FailureStatus; } @@ -151,7 +151,7 @@ ShvVpRestoreAfterLaunch ( typedef struct _SHV_DPC_CONTEXT { ULONG64 Cr3; - volatile LONG InitCount; + volatile ULONG InitCount; LONG FailedCpu; NTSTATUS FailureStatus; } SHV_DPC_CONTEXT, *PSHV_DPC_CONTEXT; @@ -374,7 +374,7 @@ ShvVmxSetupVmcsForVp ( // corresponds exactly to the location where RtlCaptureContext will return // to inside of ShvVpInitialize. // - __vmx_vmwrite(GUEST_RSP, context->Rsp); + __vmx_vmwrite(GUEST_RSP, (ULONG_PTR)VpData->ShvStackLimit + KERNEL_STACK_SIZE - sizeof(CONTEXT)); __vmx_vmwrite(GUEST_RIP, (ULONG_PTR)ShvVpRestoreAfterLaunch); __vmx_vmwrite(GUEST_RFLAGS, context->EFlags); @@ -85,10 +85,20 @@ ShvVpRestoreAfterLaunch ( VOID ) { - PSHV_VP_DATA vpData = ShvGlobalData[KeGetCurrentProcessorNumberEx(NULL)]; + PSHV_VP_DATA vpData; // - // Record that VMX is now enabled + // Get the per-processor data. This routine temporarily executes on the + // same stack as the hypervisor (using no real stack space except the home + // registers), so we can retrieve the VP the same way the hypervisor does. + // + vpData = (PSHV_VP_DATA)((ULONG_PTR)_AddressOfReturnAddress() + + sizeof(CONTEXT) - + KERNEL_STACK_SIZE); + + // + // Record that VMX is now enabled by returning back to ShvVpInitialize with + // the Alignment Check (AC) bit set. // vpData->ContextFrame.EFlags |= EFLAGS_ALIGN_CHECK; @@ -213,6 +223,7 @@ ShvVpCallbackDpc ( { PSHV_DPC_CONTEXT dpcContext = Context; ULONG cpuIndex; + PSHV_VP_DATA vpData; UNREFERENCED_PARAMETER(Dpc); // @@ -234,8 +245,8 @@ ShvVpCallbackDpc ( // // Allocate the per-VP data for this logical processor // - ShvGlobalData[cpuIndex] = ShvVpAllocateData(); - if (ShvGlobalData[cpuIndex] == NULL) + vpData = ShvVpAllocateData(); + if (vpData == NULL) { dpcContext->FailureStatus = STATUS_HV_NO_RESOURCES; goto Quickie; @@ -246,12 +257,12 @@ ShvVpCallbackDpc ( // all virtual processors, regardless of which process the current LP // has interrupted, can share the correct kernel address space. // - ShvGlobalData[cpuIndex]->SystemDirectoryTableBase = dpcContext->Cr3; + vpData->SystemDirectoryTableBase = dpcContext->Cr3; // // Initialize the virtual processor // - ShvVpInitialize(ShvGlobalData[cpuIndex]); + ShvVpInitialize(vpData); // // Our hypervisor should now be seen as present on this LP, @@ -262,8 +273,7 @@ ShvVpCallbackDpc ( // // Free the per-processor data // - MmFreeContiguousMemory(ShvGlobalData[cpuIndex]); - ShvGlobalData[cpuIndex] = NULL; + MmFreeContiguousMemory(vpData); dpcContext->FailureStatus = STATUS_HV_NOT_PRESENT; dpcContext->FailedCpu = cpuIndex; goto Quickie; @@ -272,7 +282,7 @@ ShvVpCallbackDpc ( // // This CPU is hyperjacked! // - InterlockedIncrement(&dpcContext->InitCount); + InterlockedIncrement((PLONG)&dpcContext->InitCount); } else { @@ -286,7 +296,6 @@ ShvVpCallbackDpc ( // Free the VP data // //MmFreeContiguousMemory(ShvGlobalData[cpuIndex]); - ShvGlobalData[cpuIndex] = NULL; } Quickie: |