From 34472d9045d16280c9a4502ac83b383d75b7f740 Mon Sep 17 00:00:00 2001 From: ionescu007 Date: Sun, 28 Aug 2016 22:43:50 -0700 Subject: 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. --- shv.c | 25 +------------------------ shv.h | 2 +- shvvmx.c | 2 +- shvvp.c | 29 +++++++++++++++++++---------- 4 files changed, 22 insertions(+), 36 deletions(-) diff --git a/shv.c b/shv.c index 12a7038..e10973c 100644 --- a/shv.c +++ b/shv.c @@ -22,8 +22,6 @@ Environment: #include "shv.h" -PSHV_VP_DATA* ShvGlobalData; - VOID ShvUnload ( _In_ PDRIVER_OBJECT DriverObject @@ -44,12 +42,6 @@ ShvUnload ( dpcContext.Cr3 = 0; KeGenericCallDpc(ShvVpCallbackDpc, &dpcContext); - // - // Global data is always allocated and should be freed - // - NT_ASSERT(ShvGlobalData); - ExFreePoolWithTag(ShvGlobalData, 'ShvA'); - // // Indicate unload // @@ -62,23 +54,9 @@ 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 @@ -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; } diff --git a/shv.h b/shv.h index 67218d1..7331a0c 100644 --- a/shv.h +++ b/shv.h @@ -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; diff --git a/shvvmx.c b/shvvmx.c index df24586..0fb4338 100644 --- a/shvvmx.c +++ b/shvvmx.c @@ -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); diff --git a/shvvp.c b/shvvp.c index 46fcf17..1f1f744 100644 --- a/shvvp.c +++ b/shvvp.c @@ -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: -- cgit v1.2.3