https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d40ff3ca985daf8ea9927…
commit d40ff3ca985daf8ea9927d9902282f6aa813824b
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Fri May 22 11:18:39 2020 +0200
Commit: Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Sat Jun 6 08:42:22 2020 +0200
[NTOS:KE] Split KiCheckForSListFault into its own function. CORE-15723
This avoids SEH in a trap handler.
See the following commit for more details.
---
ntoskrnl/ke/i386/traphdlr.c | 114 ++++++++++++++++++++++++--------------------
1 file changed, 62 insertions(+), 52 deletions(-)
diff --git a/ntoskrnl/ke/i386/traphdlr.c b/ntoskrnl/ke/i386/traphdlr.c
index 8ef4031b601..0614efc398b 100644
--- a/ntoskrnl/ke/i386/traphdlr.c
+++ b/ntoskrnl/ke/i386/traphdlr.c
@@ -1216,56 +1216,11 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
KiTrapReturn(TrapFrame);
}
-DECLSPEC_NORETURN
-VOID
+BOOLEAN
FASTCALL
-KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
+KiCheckForSListFault(PKTRAP_FRAME TrapFrame)
{
- PKTHREAD Thread;
- BOOLEAN StoreInstruction;
- ULONG_PTR Cr2;
- NTSTATUS Status;
-
- /* Save trap frame */
- KiEnterTrap(TrapFrame);
-
- /* Check if this is the base frame */
- Thread = KeGetCurrentThread();
- if (KeGetTrapFrame(Thread) != TrapFrame)
- {
- /* It isn't, check if this is a second nested frame */
- if (((ULONG_PTR)KeGetTrapFrame(Thread) - (ULONG_PTR)TrapFrame) <=
- FIELD_OFFSET(KTRAP_FRAME, EFlags))
- {
- /* The stack is somewhere in between frames, we need to fix it */
- UNIMPLEMENTED_FATAL();
- }
- }
-
- /* Save CR2 */
- Cr2 = __readcr2();
-
- /* Enable interrupts */
- _enable();
-
- /* Interpret the error code */
- StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
-
- /* Check if we came in with interrupts disabled */
- if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
- {
- /* This is completely illegal, bugcheck the system */
- KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
- Cr2,
- (ULONG_PTR)-1,
- TrapFrame->ErrCode,
- TrapFrame->Eip,
- TrapFrame);
- }
-
- /* Check for S-List fault
-
- Explanation: An S-List fault can occur due to a race condition between 2
+ /* Explanation: An S-List fault can occur due to a race condition between 2
threads simultaneously trying to pop an element from the S-List. After
thread 1 has read the pointer to the top element on the S-List it is
preempted and thread 2 calls InterlockedPopEntrySlist on the same S-List,
@@ -1329,7 +1284,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* The S-List pointer is not valid! */
- goto NotSListFault;
+ return FALSE;
}
_SEH2_END;
ResumeAddress = KeUserPopEntrySListResume;
@@ -1353,11 +1308,66 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
/* Restart the operation */
TrapFrame->Eip = (ULONG_PTR)ResumeAddress;
- /* Continue execution */
- KiEoiHelper(TrapFrame);
+ return TRUE;
}
}
-NotSListFault:
+
+ return FALSE;
+}
+
+DECLSPEC_NORETURN
+VOID
+FASTCALL
+KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
+{
+ PKTHREAD Thread;
+ BOOLEAN StoreInstruction;
+ ULONG_PTR Cr2;
+ NTSTATUS Status;
+
+ /* Save trap frame */
+ KiEnterTrap(TrapFrame);
+
+ /* Check if this is the base frame */
+ Thread = KeGetCurrentThread();
+ if (KeGetTrapFrame(Thread) != TrapFrame)
+ {
+ /* It isn't, check if this is a second nested frame */
+ if (((ULONG_PTR)KeGetTrapFrame(Thread) - (ULONG_PTR)TrapFrame) <=
+ FIELD_OFFSET(KTRAP_FRAME, EFlags))
+ {
+ /* The stack is somewhere in between frames, we need to fix it */
+ UNIMPLEMENTED_FATAL();
+ }
+ }
+
+ /* Save CR2 */
+ Cr2 = __readcr2();
+
+ /* Enable interrupts */
+ _enable();
+
+ /* Interpret the error code */
+ StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
+
+ /* Check if we came in with interrupts disabled */
+ if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
+ {
+ /* This is completely illegal, bugcheck the system */
+ KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
+ Cr2,
+ (ULONG_PTR)-1,
+ TrapFrame->ErrCode,
+ TrapFrame->Eip,
+ TrapFrame);
+ }
+
+ /* Check for S-List fault */
+ if (KiCheckForSListFault(TrapFrame))
+ {
+ /* Continue execution */
+ KiEoiHelper(TrapFrame);
+ }
/* Call the access fault handler */
Status = MmAccessFault(TrapFrame->ErrCode,