Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ionescu007/SimpleVisor.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'shvos.c')
-rw-r--r--shvos.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/shvos.c b/shvos.c
index a1a68cb..0dac126 100644
--- a/shvos.c
+++ b/shvos.c
@@ -65,6 +65,15 @@ typedef struct _SHV_DPC_CONTEXT
PSHV_CALLBACK_CONTEXT Context;
} SHV_DPC_CONTEXT, *PSHV_DPC_CONTEXT;
+#define KGDT64_R3_DATA 0x28
+#define KGDT64_R3_CMTEB 0x50
+
+VOID
+ShvVmxCleanup (
+ _In_ UINT16 Data,
+ _In_ UINT16 Teb
+ );
+
NTSTATUS
FORCEINLINE
ShvOsErrorToError (
@@ -110,6 +119,24 @@ ShvOsDpcRoutine (
dpcContext->Routine(dpcContext->Context);
//
+ // During unload SimpleVisor uses the RtlRestoreContext function which will
+ // unfortunately use the "iretq" opcode in order to restore execution back.
+ // This causes the processor to remove the RPL bits off the segments. As
+ // the x64 kernel does not expect kernel-mode code to change the value of
+ // any segments, this results in the DS and ES segments being stuck 0x20,
+ // and the FS segment being stuck at 0x50, until the next context switch.
+ //
+ // If the DPC happened to have interrupted either the idle thread or system
+ // thread, that's perfectly fine (albeit unusual). If the DPC interrupted a
+ // 64-bit long-mode thread, that's also fine. However if the DPC interrupts
+ // a thread in compatibility-mode, running as part of WoW64, it will hit a
+ // GPF instantenously and crash.
+ //
+ // Thus, set the segments to their correct value, one more time, as a fix.
+ //
+ ShvVmxCleanup(KGDT64_R3_DATA | RPL_MASK, KGDT64_R3_CMTEB | RPL_MASK);
+
+ //
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);