[NTOS:KE:X64] Simplify KiInitializeUserApc

This commit is contained in:
Timo Kreuzer 2018-02-10 19:52:46 +01:00
parent aaa86d078e
commit 52d1bb5ec9

View file

@ -11,7 +11,8 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/*! \name KiInitializeUserApc /*!
* \name KiInitializeUserApc
* *
* \brief * \brief
* Prepares the current trap frame (which must have come from user mode) * Prepares the current trap frame (which must have come from user mode)
@ -19,12 +20,16 @@
* record with the context from the old trap frame to the threads user * record with the context from the old trap frame to the threads user
* mode stack. * mode stack.
* *
* \param ExceptionFrame * \param ExceptionFrame - Pointer to the Exception Frame
* \param TrapFrame *
* \param NormalRoutine * \param TrapFrame Pointer to the Trap Frame.
* \param NormalContext *
* \param SystemArgument1 * \param NormalRoutine - Pointer to the NormalRoutine to call.
* \param SystemArgument2 *
* \param NormalContext - Pointer to the context to send to the Normal Routine.
*
* \param SystemArgument[1-2]
* Pointer to a set of two parameters that contain untyped data.
* *
* \remarks * \remarks
* This function is called from KiDeliverApc, when the trap frame came * This function is called from KiDeliverApc, when the trap frame came
@ -48,67 +53,56 @@ KiInitializeUserApc(
_In_ PVOID SystemArgument1, _In_ PVOID SystemArgument1,
_In_ PVOID SystemArgument2) _In_ PVOID SystemArgument2)
{ {
CONTEXT Context; PCONTEXT Context;
ULONG64 AlignedRsp, Stack; EXCEPTION_RECORD ExceptionRecord;
EXCEPTION_RECORD SehExceptRecord;
/* Sanity check, that the trap frame is from user mode */ /* Sanity check, that the trap frame is from user mode */
ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode); ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode);
/* Convert the current trap frame to a context */ /* Align the user tack to 16 bytes and allocate space for a CONTEXT structure */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; Context = (PCONTEXT)ALIGN_DOWN_POINTER_BY(TrapFrame->Rsp, 16) - 1;
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
/* We jump to KiUserApcDispatcher in ntdll */
TrapFrame->Rip = (ULONG64)KeUserApcDispatcher;
/* Setup Ring 3 segments */
TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
/* Sanitize EFLAGS, enable interrupts */
TrapFrame->EFlags = (Context.EFlags & EFLAGS_USER_SANITIZE);
TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
/* Set parameters for KiUserApcDispatcher */
Context.P1Home = (ULONG64)NormalContext;
Context.P2Home = (ULONG64)SystemArgument1;
Context.P3Home = (ULONG64)SystemArgument2;
Context.P4Home = (ULONG64)NormalRoutine;
/* Check if thread has IOPL and force it enabled if so */
//if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= EFLAGS_IOPL;
/* Align Stack to 16 bytes and allocate space */
AlignedRsp = Context.Rsp & ~15;
Stack = AlignedRsp - sizeof(CONTEXT);
TrapFrame->Rsp = Stack;
/* The stack must be 16 byte aligned for KiUserApcDispatcher */
ASSERT((Stack & 15) == 0);
/* Protect with SEH */ /* Protect with SEH */
_SEH2_TRY _SEH2_TRY
{ {
/* Probe the stack */ /* Probe the context */
ProbeForWrite((PCONTEXT)Stack, sizeof(CONTEXT), 8); ProbeForWrite(Context, sizeof(CONTEXT), 16);
/* Copy the context */ /* Convert the current trap frame to a context */
RtlCopyMemory((PCONTEXT)Stack, &Context, sizeof(CONTEXT)); Context->ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
KeTrapFrameToContext(TrapFrame, ExceptionFrame, Context);
/* Set parameters for KiUserApcDispatcher */
Context->P1Home = (ULONG64)NormalContext;
Context->P2Home = (ULONG64)SystemArgument1;
Context->P3Home = (ULONG64)SystemArgument2;
Context->P4Home = (ULONG64)NormalRoutine;
} }
_SEH2_EXCEPT((RtlCopyMemory(&SehExceptRecord, _SEH2_GetExceptionInformation()->ExceptionRecord, sizeof(EXCEPTION_RECORD)), EXCEPTION_EXECUTE_HANDLER)) _SEH2_EXCEPT(ExceptionRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord, EXCEPTION_EXECUTE_HANDLER)
{ {
/* Dispatch the exception */ /* Dispatch the exception */
SehExceptRecord.ExceptionAddress = (PVOID)TrapFrame->Rip; ExceptionRecord.ExceptionAddress = (PVOID)TrapFrame->Rip;
KiDispatchException(&SehExceptRecord, KiDispatchException(&ExceptionRecord,
ExceptionFrame, ExceptionFrame,
TrapFrame, TrapFrame,
UserMode, UserMode,
TRUE); TRUE);
} }
_SEH2_END; _SEH2_END;
/* Set the stack pointer to the context record */
TrapFrame->Rsp = (ULONG64)Context;
/* We jump to KiUserApcDispatcher in ntdll */
TrapFrame->Rip = (ULONG64)KeUserApcDispatcher;
/* Setup Ring 3 segments */
TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
/* Sanitize EFLAGS, enable interrupts */
TrapFrame->EFlags &= EFLAGS_USER_SANITIZE;
TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
} }