https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4f49a9c792b8334a5ad8d6daaecd26dde6870f3c

commit 4f49a9c792b8334a5ad8d6daaecd26dde6870f3c
Author:     Thomas Faber <[email protected]>
AuthorDate: Fri May 22 22:34:56 2020 +0200
Commit:     Thomas Faber <[email protected]>
CommitDate: Sat Jun 6 08:44:30 2020 +0200

    [NTOS:KE] Save ExceptionList in the assembly version of KiEnterTrap. 
CORE-15723
    
    If SEH is used in a C trap handler, the exception frame will be
    registered before the call to KiEnterTrap, which means we save
    the wrong trap handler. We'll therefore also restore this wrong
    frame for the excepting code, resulting in a stale SEH chain.
    
    We avoid this problem by saving the handler in the assembly
    trap entry code instead of from C. While SEH in a C trap handler
    should now theoretically be safe, we still forbid it through
    asserts in the C KiEnterTrap variants to make any potential
    future problems more obvious. Should this functionality be
    needed at some point and deemed safe, these asserts can then be
    removed.
---
 ntoskrnl/include/internal/i386/asmmacro.S |  4 ++++
 ntoskrnl/include/internal/i386/trap_x.h   | 24 ++++++++++++++++++------
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/ntoskrnl/include/internal/i386/asmmacro.S 
b/ntoskrnl/include/internal/i386/asmmacro.S
index f7af217cc9f..543ce3f1bc4 100644
--- a/ntoskrnl/include/internal/i386/asmmacro.S
+++ b/ntoskrnl/include/internal/i386/asmmacro.S
@@ -207,6 +207,10 @@ set_sane_segs:
         mov fs, ax
     endif
 
+    /* Save ExceptionList, since the C handler might use SEH */
+    mov eax, fs:[KPCR_EXCEPTION_LIST]
+    mov [esp + KTRAP_FRAME_EXCEPTION_LIST], eax
+
 #if DBG
     /* Keep the frame chain intact */
     mov eax, [esp + KTRAP_FRAME_EIP]
diff --git a/ntoskrnl/include/internal/i386/trap_x.h 
b/ntoskrnl/include/internal/i386/trap_x.h
index 06443c9dc90..cd79c2a40c4 100644
--- a/ntoskrnl/include/internal/i386/trap_x.h
+++ b/ntoskrnl/include/internal/i386/trap_x.h
@@ -349,8 +349,12 @@ FORCEINLINE
 VOID
 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
 {
-    /* Save exception list */
-    TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+    PVOID ExceptionList;
+
+    /* Check exception list */
+    ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+    ASSERTMSG("V86 trap handler must not register an SEH frame\n",
+              ExceptionList == TrapFrame->ExceptionList);
 
     /* Save DR7 and check for debugging */
     TrapFrame->Dr7 = __readdr(7);
@@ -368,8 +372,12 @@ FORCEINLINE
 VOID
 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
 {
-    /* Save exception list and terminate it */
-    TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+    PVOID ExceptionList;
+
+    /* Check exception list and terminate it */
+    ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+    ASSERTMSG("Interrupt handler must not register an SEH frame\n",
+              ExceptionList == TrapFrame->ExceptionList);
     KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
 
     /* Default to debugging disabled */
@@ -398,8 +406,12 @@ FORCEINLINE
 VOID
 KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
 {
-    /* Save exception list */
-    TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+    PVOID ExceptionList;
+
+    /* Check exception list */
+    ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+    ASSERTMSG("Trap handler must not register an SEH frame\n",
+              ExceptionList == TrapFrame->ExceptionList);
 
     /* Default to debugging disabled */
     TrapFrame->Dr7 = 0;

Reply via email to