https://git.reactos.org/?p=reactos.git;a=commitdiff;h=29721ac552cd104116bbc197b8df1782c72f7710

commit 29721ac552cd104116bbc197b8df1782c72f7710
Author:     Timo Kreuzer <timo.kreu...@reactos.org>
AuthorDate: Wed Dec 11 16:47:28 2024 +0200
Commit:     Timo Kreuzer <timo.kreu...@reactos.org>
CommitDate: Mon Dec 16 16:19:32 2024 +0200

    [NTOS:KE/x64] Fix unwinding in KiUserApcDispatcher
    
    This adds a MACHINE_FRAME to the user mode APC dispatcher stack frame.
---
 dll/ntdll/dispatch/amd64/dispatch.S | 26 ++++++++++++++++++++++++++
 ntoskrnl/ke/amd64/usercall.c        | 18 ++++++++++++------
 sdk/include/ndk/amd64/ketypes.h     |  9 +++++++++
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/dll/ntdll/dispatch/amd64/dispatch.S 
b/dll/ntdll/dispatch/amd64/dispatch.S
index ea08389c919..60b3f22bb58 100644
--- a/dll/ntdll/dispatch/amd64/dispatch.S
+++ b/dll/ntdll/dispatch/amd64/dispatch.S
@@ -33,6 +33,32 @@ PUBLIC LdrInitializeThunk
 
 PUBLIC KiUserApcDispatcher
 .PROC KiUserApcDispatcher
+
+    /* The stack is set up with a UAPC_FRAME, which ends with a MACHINE_FRAME 
*/
+    .PUSHFRAME
+    .ALLOCSTACK CONTEXT_FRAME_LENGTH
+
+    /* The stack points to a CONTEXT structure.
+       Create unwind ops for all nonvolatile registers */
+    .SAVEREG rbx, CxRbx
+    .SAVEREG rbp, CxRbp
+    .SAVEREG rsi, CxRsi
+    .SAVEREG rdi, CxRdi
+    .SAVEREG r12, CxR12
+    .SAVEREG r13, CxR13
+    .SAVEREG r14, CxR14
+    .SAVEREG r15, CxR15
+    .SAVEXMM128 xmm6, CxXmm6
+    .SAVEXMM128 xmm7, CxXmm7
+    .SAVEXMM128 xmm8, CxXmm8
+    .SAVEXMM128 xmm9, CxXmm9
+    .SAVEXMM128 xmm10, CxXmm10
+    .SAVEXMM128 xmm11, CxXmm11
+    .SAVEXMM128 xmm12, CxXmm12
+    .SAVEXMM128 xmm13, CxXmm13
+    .SAVEXMM128 xmm14, CxXmm14
+    .SAVEXMM128 xmm15, CxXmm15
+
     .endprolog
     /* We enter with a 16 byte aligned stack */
 
diff --git a/ntoskrnl/ke/amd64/usercall.c b/ntoskrnl/ke/amd64/usercall.c
index 81f7a81fdfc..bab35e9e40e 100644
--- a/ntoskrnl/ke/amd64/usercall.c
+++ b/ntoskrnl/ke/amd64/usercall.c
@@ -16,8 +16,8 @@
  *
  *  \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
+ *      with the ntdll.KiUserApcDispatcher entrypoint, copying a UAPC_FRAME
+ *      structure with the context from the old trap frame to the threads user
  *      mode stack.
  *
  *  \param ExceptionFrame - Pointer to the Exception Frame
@@ -53,20 +53,22 @@ KiInitializeUserApc(
     _In_ PVOID SystemArgument1,
     _In_ PVOID SystemArgument2)
 {
+    PUAPC_FRAME ApcFrame;
     PCONTEXT Context;
     EXCEPTION_RECORD ExceptionRecord;
 
     /* Sanity check, that the trap frame is from user mode */
     ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode);
 
-    /* Align the user tack to 16 bytes and allocate space for a CONTEXT 
structure */
-    Context = (PCONTEXT)ALIGN_DOWN_POINTER_BY(TrapFrame->Rsp, 16) - 1;
+    /* Allocate a 16 byte aligned UAPC_FRAME structure on the user stack */
+    ApcFrame = (PUAPC_FRAME)ALIGN_DOWN_POINTER_BY(TrapFrame->Rsp - 
sizeof(*ApcFrame), 16);
+    Context = &ApcFrame->Context;
 
     /* Protect with SEH */
     _SEH2_TRY
     {
-        /* Probe the context */
-        ProbeForWrite(Context, sizeof(CONTEXT), 16);
+        /* Probe the user mode APC frame */
+        ProbeForWrite(ApcFrame, sizeof(*ApcFrame), 16);
 
         /* Convert the current trap frame to a context */
         Context->ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
@@ -77,6 +79,10 @@ KiInitializeUserApc(
         Context->P2Home = (ULONG64)SystemArgument1;
         Context->P3Home = (ULONG64)SystemArgument2;
         Context->P4Home = (ULONG64)NormalRoutine;
+
+        /* Set up the machine frame for unwinding */
+        ApcFrame->MachineFrame.Rip = TrapFrame->Rip;
+        ApcFrame->MachineFrame.Rsp = TrapFrame->Rsp;
     }
     _SEH2_EXCEPT(ExceptionRecord = 
*_SEH2_GetExceptionInformation()->ExceptionRecord, EXCEPTION_EXECUTE_HANDLER)
     {
diff --git a/sdk/include/ndk/amd64/ketypes.h b/sdk/include/ndk/amd64/ketypes.h
index 410e0b55cb0..ea9031df667 100644
--- a/sdk/include/ndk/amd64/ketypes.h
+++ b/sdk/include/ndk/amd64/ketypes.h
@@ -1073,6 +1073,15 @@ typedef struct _UCALLOUT_FRAME
     MACHINE_FRAME MachineFrame;
 } UCALLOUT_FRAME, *PUCALLOUT_FRAME; // size = 0x0058
 
+//
+// User side APC dispatcher frame
+//
+typedef struct _UAPC_FRAME
+{
+    CONTEXT Context;
+    MACHINE_FRAME MachineFrame;
+} UAPC_FRAME, *PUAPC_FRAME;
+
 //
 // Stack frame layout for KiUserExceptionDispatcher
 // The name is totally made up

Reply via email to