From aaa86d078e7519a7eba4592eed08a82848bd6065 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sat, 10 Feb 2018 18:47:29 +0100 Subject: [PATCH] [NTOS:KE:X64] Move KiInitializeUserApc to usercall.c --- ntoskrnl/ke/amd64/stubs.c | 102 ------------------------------- ntoskrnl/ke/amd64/usercall.c | 114 +++++++++++++++++++++++++++++++++++ ntoskrnl/ntos.cmake | 5 +- 3 files changed, 117 insertions(+), 104 deletions(-) create mode 100644 ntoskrnl/ke/amd64/usercall.c diff --git a/ntoskrnl/ke/amd64/stubs.c b/ntoskrnl/ke/amd64/stubs.c index fee659737b9..185d68988de 100644 --- a/ntoskrnl/ke/amd64/stubs.c +++ b/ntoskrnl/ke/amd64/stubs.c @@ -243,108 +243,6 @@ KiIdleLoop(VOID) } } - -/*! \name KiInitializeUserApc - * - * \brief - * Prepares the current trap frame (which must have come from user mode) - * with the ntdll.KiUserApcDispatcher entrypoint, copying a CONTEXT - * record with the context from the old trap frame to the threads user - * mode stack. - * - * \param ExceptionFrame - * \param TrapFrame - * \param NormalRoutine - * \param NormalContext - * \param SystemArgument1 - * \param SystemArgument2 - * - * \remarks - * This function is called from KiDeliverApc, when the trap frame came - * from user mode. This happens before a systemcall or interrupt exits back - * to usermode or when a thread is started from PspUserThreadstartup. - * The trap exit code will then leave to KiUserApcDispatcher which in turn - * calls the NormalRoutine, passing NormalContext, SystemArgument1 and - * SystemArgument2 as parameters. When that function returns, it calls - * NtContinue to return back to the kernel, where the old context that was - * saved on the usermode stack is restored and execution is transferred - * back to usermode, where the original trap originated from. - * - *--*/ -VOID -NTAPI -KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame, - IN PKTRAP_FRAME TrapFrame, - IN PKNORMAL_ROUTINE NormalRoutine, - IN PVOID NormalContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2) -{ - CONTEXT Context = { 0 }; - ULONG64 AlignedRsp, Stack; - EXCEPTION_RECORD SehExceptRecord; - - /* Sanity check, that the trap frame is from user mode */ - ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode); - - /* Convert the current trap frame to a context */ - Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; - 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 */ - _SEH2_TRY - { - /* Probe the stack */ - ProbeForWrite((PCONTEXT)Stack, sizeof(CONTEXT), 8); - - /* Copy the context */ - RtlCopyMemory((PCONTEXT)Stack, &Context, sizeof(CONTEXT)); - } - _SEH2_EXCEPT((RtlCopyMemory(&SehExceptRecord, _SEH2_GetExceptionInformation()->ExceptionRecord, sizeof(EXCEPTION_RECORD)), EXCEPTION_EXECUTE_HANDLER)) - { - /* Dispatch the exception */ - SehExceptRecord.ExceptionAddress = (PVOID)TrapFrame->Rip; - KiDispatchException(&SehExceptRecord, - ExceptionFrame, - TrapFrame, - UserMode, - TRUE); - } - _SEH2_END; -} - VOID NTAPI KiSwapProcess(IN PKPROCESS NewProcess, diff --git a/ntoskrnl/ke/amd64/usercall.c b/ntoskrnl/ke/amd64/usercall.c new file mode 100644 index 00000000000..61861d521b7 --- /dev/null +++ b/ntoskrnl/ke/amd64/usercall.c @@ -0,0 +1,114 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - 2.0 + (https ://spdx.org/licenses/GPL-2.0+) + * PURPOSE: AMD64 User-mode Callout Mechanisms (APC and Win32K Callbacks) + * COPYRIGHT: Timo Kreuzer(timo.kreuzer@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/*! \name KiInitializeUserApc +* +* \brief +* Prepares the current trap frame (which must have come from user mode) +* with the ntdll.KiUserApcDispatcher entrypoint, copying a CONTEXT +* record with the context from the old trap frame to the threads user +* mode stack. +* +* \param ExceptionFrame +* \param TrapFrame +* \param NormalRoutine +* \param NormalContext +* \param SystemArgument1 +* \param SystemArgument2 +* +* \remarks +* This function is called from KiDeliverApc, when the trap frame came +* from user mode. This happens before a systemcall or interrupt exits back +* to usermode or when a thread is started from PspUserThreadstartup. +* The trap exit code will then leave to KiUserApcDispatcher which in turn +* calls the NormalRoutine, passing NormalContext, SystemArgument1 and +* SystemArgument2 as parameters. When that function returns, it calls +* NtContinue to return back to the kernel, where the old context that was +* saved on the usermode stack is restored and execution is transferred +* back to usermode, where the original trap originated from. +* +*--*/ +VOID +NTAPI +KiInitializeUserApc( + _In_ PKEXCEPTION_FRAME ExceptionFrame, + _Inout_ PKTRAP_FRAME TrapFrame, + _In_ PKNORMAL_ROUTINE NormalRoutine, + _In_ PVOID NormalContext, + _In_ PVOID SystemArgument1, + _In_ PVOID SystemArgument2) +{ + CONTEXT Context; + ULONG64 AlignedRsp, Stack; + EXCEPTION_RECORD SehExceptRecord; + + /* Sanity check, that the trap frame is from user mode */ + ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode); + + /* Convert the current trap frame to a context */ + Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; + 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 */ + _SEH2_TRY + { + /* Probe the stack */ + ProbeForWrite((PCONTEXT)Stack, sizeof(CONTEXT), 8); + + /* Copy the context */ + RtlCopyMemory((PCONTEXT)Stack, &Context, sizeof(CONTEXT)); + } + _SEH2_EXCEPT((RtlCopyMemory(&SehExceptRecord, _SEH2_GetExceptionInformation()->ExceptionRecord, sizeof(EXCEPTION_RECORD)), EXCEPTION_EXECUTE_HANDLER)) + { + /* Dispatch the exception */ + SehExceptRecord.ExceptionAddress = (PVOID)TrapFrame->Rip; + KiDispatchException(&SehExceptRecord, + ExceptionFrame, + TrapFrame, + UserMode, + TRUE); + } + _SEH2_END; +} diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index e6c059fdb49..c69c284cdf2 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -325,11 +325,12 @@ elseif(ARCH STREQUAL "amd64") ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/kiinit.c ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/krnlinit.c ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/spinlock.c - ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/stubs.c ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/thrdini.c ${REACTOS_SOURCE_DIR}/ntoskrnl/mm/amd64/init.c ${REACTOS_SOURCE_DIR}/ntoskrnl/mm/amd64/page.c - ${REACTOS_SOURCE_DIR}/ntoskrnl/ps/amd64/psctx.c) + ${REACTOS_SOURCE_DIR}/ntoskrnl/ps/amd64/psctx.c + ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/stubs.c + ${REACTOS_SOURCE_DIR}/ntoskrnl/ke/amd64/usercall.c) elseif(ARCH STREQUAL "arm") list(APPEND ASM_SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/ex/arm/ioport.s