https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e923912f946b729bfa0151...
commit e923912f946b729bfa01515ab40bce01d9b54431 Author: Timo Kreuzer timo.kreuzer@reactos.org AuthorDate: Mon Aug 8 09:30:49 2022 +0200 Commit: Timo Kreuzer timo.kreuzer@reactos.org CommitDate: Thu Nov 24 21:17:58 2022 +0200
[NTOS] Fix unwinding through KiThreadStartup --- ntoskrnl/ke/amd64/ctxswitch.S | 57 +++++++++++++++++++++++++++++++------------ ntoskrnl/ke/amd64/thrdini.c | 15 +++++++++--- ntoskrnl/ke/amd64/trap.S | 19 +++++++++++---- 3 files changed, 67 insertions(+), 24 deletions(-)
diff --git a/ntoskrnl/ke/amd64/ctxswitch.S b/ntoskrnl/ke/amd64/ctxswitch.S index 17a87e7c023..829026ce49c 100644 --- a/ntoskrnl/ke/amd64/ctxswitch.S +++ b/ntoskrnl/ke/amd64/ctxswitch.S @@ -10,6 +10,7 @@ /* INCLUDES ******************************************************************/
#include <ksamd64.inc> +#include <trapamd64.inc>
/* * BOOLEAN @@ -70,10 +71,7 @@ PUBLIC KiThreadStartup * mov [rsp + SfP3Home], r8 * mov [rsp + SfP4Home], r9 */ - - /* Terminate the unwind chain, by setting rbp as frame pointer, - which contains 0 */ - .setframe rbp, 0 + .allocstack (5 * 8) .endprolog
/* Clear all the non-volatile registers, so the thread won't be tempted to @@ -101,21 +99,50 @@ PUBLIC KiThreadStartup mov r8, [rsp + SfP3Home] /* ? */ call qword ptr [rsp + SfP4Home] /* SystemRoutine */
- /* The thread returned. If it was a user-thread, we have a return address - and all is well, otherwise this is very bad. */ - mov rcx, [rsp + SfReturn] - or rcx, rcx - jnz .leave + /* Return to the exit code */ + add rsp, 5 * 8 + ret +.ENDP + +PUBLIC KiInvalidSystemThreadStartupExit +.PROC KiInvalidSystemThreadStartupExit + .endprolog + + /* This is invalid! */ + int HEX(2C) + nop +.ENDP + +PUBLIC KiUserThreadStartupExit +.PROC KiUserThreadStartupExit + .allocstack (KEXCEPTION_FRAME_LENGTH - 8) + .savereg rbp, ExRbp + .savereg rbx, ExRbx + .savereg rdi, ExRdi + .savereg rsi, ExRsi + .savereg r12, ExR12 + .savereg r13, ExR13 + .savereg r14, ExR14 + .savereg r15, ExR15 + .savexmm128 xmm6, ExXmm6 + .savexmm128 xmm7, ExXmm7 + .savexmm128 xmm8, ExXmm8 + .savexmm128 xmm9, ExXmm9 + .savexmm128 xmm10, ExXmm10 + .savexmm128 xmm11, ExXmm11 + .savexmm128 xmm12, ExXmm12 + .savexmm128 xmm13, ExXmm13 + .savexmm128 xmm14, ExXmm14 + .savexmm128 xmm15, ExXmm15 + .endprolog
- /* A system thread returned...this is very bad! */ - int 3 + /* Restore the exception frame */ + RESTORE_EXCEPTION_STATE
-.leave: - /* It was a user thread, set our trapframe for the System Call Exit Dispatcher */ - lea rcx, [rsp + 6 * 8 + KEXCEPTION_FRAME_LENGTH] + /* Point rcx to the trap frame */ + lea rcx, [rsp + 8]
/* Return to the trap exit code */ - add rsp, 5 * 8 ret .ENDP
diff --git a/ntoskrnl/ke/amd64/thrdini.c b/ntoskrnl/ke/amd64/thrdini.c index 044ac7c6396..b2119c6e8a3 100644 --- a/ntoskrnl/ke/amd64/thrdini.c +++ b/ntoskrnl/ke/amd64/thrdini.c @@ -13,6 +13,10 @@ #define NDEBUG #include <debug.h>
+extern void KiInvalidSystemThreadStartupExit(void); +extern void KiUserThreadStartupExit(void); +extern void KiServiceExit3(void); + typedef struct _KUINIT_FRAME { KSWITCH_FRAME CtxSwitchFrame; @@ -98,8 +102,11 @@ KiInitializeContextThread(IN PKTHREAD Thread, /* Terminate the Exception Handler List */ TrapFrame->ExceptionFrame = 0;
- /* We return to ... */ - StartFrame->Return = (ULONG64)KiServiceExit2; + /* KiThreadStartup returns to KiUserThreadStartupExit */ + StartFrame->Return = (ULONG64)KiUserThreadStartupExit; + + /* KiUserThreadStartupExit returns to KiServiceExit3 */ + InitFrame->ExceptionFrame.Return = (ULONG64)KiServiceExit3; } else { @@ -121,8 +128,8 @@ KiInitializeContextThread(IN PKTHREAD Thread, /* No NPX State */ Thread->NpxState = 0xA;
- /* We have no return address! */ - StartFrame->Return = 0; + /* This must never return! */ + StartFrame->Return = (ULONG64)KiInvalidSystemThreadStartupExit; }
/* Set up the Context Switch Frame */ diff --git a/ntoskrnl/ke/amd64/trap.S b/ntoskrnl/ke/amd64/trap.S index 63dacf8166b..3e13d2b5eb4 100644 --- a/ntoskrnl/ke/amd64/trap.S +++ b/ntoskrnl/ke/amd64/trap.S @@ -930,16 +930,27 @@ PUBLIC KiServiceExit2 .PROC KiServiceExit2 .ENDPROLOG
+ // FIXME: this should probably also restore an exception frame + + mov rsp, rcx +.ENDP + +PUBLIC KiServiceExit3 +.PROC KiServiceExit3 + .PUSHFRAME + .ALLOCSTACK (KTRAP_FRAME_LENGTH - MachineFrameLength) + .ENDPROLOG + #if DBG /* Get the current IRQL and compare it to the trap frame */ mov rax, cr8 - cmp byte ptr [rcx + KTRAP_FRAME_PreviousIrql], al + cmp byte ptr [rsp + KTRAP_FRAME_PreviousIrql], al je KiServiceExit2_ok1 int HEX(2C)
KiServiceExit2_ok1: /* Check if this is a user mode exit */ - mov ah, byte ptr [rcx + KTRAP_FRAME_SegCs] + mov ah, byte ptr [rsp + KTRAP_FRAME_SegCs] test ah, 1 jz KiServiceExit2_kernel
@@ -951,10 +962,8 @@ KiServiceExit2_ok1: KiServiceExit2_kernel: #endif
- mov rbp, rcx - mov rsp, rcx - /* Return */ + mov rbp, rsp ExitTrap TF_SAVE_ALL .ENDP