From 07de9d1da34daa7035e86a8c0df5e9d11dbdab43 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sun, 1 Dec 2019 20:36:13 +0100 Subject: [PATCH] [NTOS:KE] In KiExitV86Mode, restore KTSS::Esp0 to its standard value. CORE-16531 The trap frame is in a random location on the stack, and setting Esp0 there wastes significant amounts of space and may lead to unexpected stack overflows. Also use a more descriptive expression for the V86 members of the KTRAP_FRAME. --- ntoskrnl/ke/i386/exp.c | 4 ++-- ntoskrnl/ke/i386/thrdini.c | 2 +- ntoskrnl/ke/i386/v86vdm.c | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ntoskrnl/ke/i386/exp.c b/ntoskrnl/ke/i386/exp.c index de97192c32a..87405e6032f 100644 --- a/ntoskrnl/ke/i386/exp.c +++ b/ntoskrnl/ke/i386/exp.c @@ -291,8 +291,8 @@ Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame) if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) { /* Bias the stack for the V86 segments */ - Stack -= (FIELD_OFFSET(KTRAP_FRAME, V86Gs) - - FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs)); + Stack -= sizeof(KTRAP_FRAME) - + FIELD_OFFSET(KTRAP_FRAME, V86Es); } /* Bias the stack for the FPU area */ diff --git a/ntoskrnl/ke/i386/thrdini.c b/ntoskrnl/ke/i386/thrdini.c index 678bedd113e..7ce51632af2 100644 --- a/ntoskrnl/ke/i386/thrdini.c +++ b/ntoskrnl/ke/i386/thrdini.c @@ -369,7 +369,7 @@ KiSwapContextExit(IN PKTHREAD OldThread, Pcr->TSS->Esp0 = (ULONG_PTR)NewThread->InitialStack; if (!((KeGetTrapFrame(NewThread))->EFlags & EFLAGS_V86_MASK)) { - Pcr->TSS->Esp0 -= (FIELD_OFFSET(KTRAP_FRAME, V86Gs) - FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs)); + Pcr->TSS->Esp0 -= sizeof(KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, V86Es); } Pcr->TSS->Esp0 -= NPX_FRAME_LENGTH; Pcr->TSS->IoMapBase = NewProcess->IopmOffset; diff --git a/ntoskrnl/ke/i386/v86vdm.c b/ntoskrnl/ke/i386/v86vdm.c index e629f8bb44e..0421f005217 100644 --- a/ntoskrnl/ke/i386/v86vdm.c +++ b/ntoskrnl/ke/i386/v86vdm.c @@ -467,17 +467,16 @@ ULONG_PTR FASTCALL KiExitV86Mode(IN PKTRAP_FRAME TrapFrame) { + PKPCR Pcr = KeGetPcr(); ULONG_PTR StackFrameUnaligned; PKV8086_STACK_FRAME StackFrame; PKTHREAD Thread; - PKTRAP_FRAME PmTrapFrame; PKV86_FRAME V86Frame; PFX_SAVE_AREA NpxFrame; /* Get the stack frame back */ StackFrameUnaligned = TrapFrame->Esi; StackFrame = (PKV8086_STACK_FRAME)(ROUND_UP(StackFrameUnaligned - 4, 16) + 4); - PmTrapFrame = &StackFrame->TrapFrame; V86Frame = &StackFrame->V86Frame; NpxFrame = &StackFrame->NpxArea; ASSERT((ULONG_PTR)NpxFrame % 16 == 0); @@ -490,7 +489,9 @@ KiExitV86Mode(IN PKTRAP_FRAME TrapFrame) Thread->InitialStack = (PVOID)((ULONG_PTR)V86Frame->ThreadStack + sizeof(FX_SAVE_AREA)); /* Set ESP0 back in the KTSS */ - KeGetPcr()->TSS->Esp0 = (ULONG_PTR)&PmTrapFrame->V86Es; + Pcr->TSS->Esp0 = (ULONG_PTR)Thread->InitialStack; + Pcr->TSS->Esp0 -= sizeof(KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, V86Es); + Pcr->TSS->Esp0 -= NPX_FRAME_LENGTH; /* Restore TEB addresses */ Thread->Teb = V86Frame->ThreadTeb;