https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d40ff3ca985daf8ea9927d...
commit d40ff3ca985daf8ea9927d9902282f6aa813824b Author: Thomas Faber thomas.faber@reactos.org AuthorDate: Fri May 22 11:18:39 2020 +0200 Commit: Thomas Faber thomas.faber@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,