diff options
Diffstat (limited to 'shvos.c')
-rw-r--r-- | shvos.c | 27 |
1 files changed, 27 insertions, 0 deletions
@@ -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); |