From 93a416ddfd5390bd6bd1e01c500fe69a4791296d Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Mon, 11 Jul 2011 03:36:29 +0000 Subject: [PATCH] [NTOSKRNL] Implement the "SLIST hack". It checks whether the access to the Next member of the first list item of an iSList caused the exception, this can happen, when a concurrent thread pops the first entry and frees its memory between the point where the address of the entry is loaded and the access to it. This is done before the call to MmAccessFault to handle the theoretical scenario of a guard page exception being triggered by the fault, which we don't want to be handled. Currently only kernel mode is handled. svn path=/trunk/; revision=52628 --- reactos/ntoskrnl/include/internal/i386/ke.h | 1 + reactos/ntoskrnl/ke/i386/traphdlr.c | 37 ++++++++++++++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index 8e701abac7c..fa8ea3f8b84 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -457,6 +457,7 @@ extern VOID __cdecl KiTrap08(VOID); extern VOID __cdecl KiTrap13(VOID); extern VOID __cdecl KiFastCallEntry(VOID); extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID); +extern VOID NTAPI ExpInterlockedPopEntrySListResume(VOID); extern VOID __cdecl CopyParams(VOID); extern VOID __cdecl ReadBatch(VOID); extern VOID __cdecl FrRestore(VOID); diff --git a/reactos/ntoskrnl/ke/i386/traphdlr.c b/reactos/ntoskrnl/ke/i386/traphdlr.c index 1f5cd46bf4b..e733cba8519 100644 --- a/reactos/ntoskrnl/ke/i386/traphdlr.c +++ b/reactos/ntoskrnl/ke/i386/traphdlr.c @@ -1199,6 +1199,35 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame) #endif } + /* Check for S-LIST fault in kernel mode */ + if (TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) + { + PSLIST_HEADER SListHeader; + + /* Sanity check that the assembly is correct: + This must be mov ebx, [eax] + Followed by cmpxchg8b [ebp] */ + ASSERT((((UCHAR*)TrapFrame->Eip)[0] == 0x8B) && + (((UCHAR*)TrapFrame->Eip)[1] == 0x18) && + (((UCHAR*)TrapFrame->Eip)[2] == 0x0F) && + (((UCHAR*)TrapFrame->Eip)[3] == 0xC7) && + (((UCHAR*)TrapFrame->Eip)[4] == 0x4D) && + (((UCHAR*)TrapFrame->Eip)[5] == 0x00)); + + /* Get the pointer to the SLIST_HEADER */ + SListHeader = (PSLIST_HEADER)TrapFrame->Ebp; + + /* Check if the Next member of the SLIST_HEADER was changed */ + if (SListHeader->Next.Next != (PSLIST_ENTRY)TrapFrame->Eax) + { + /* Restart the operation */ + TrapFrame->Eip = (ULONG_PTR)ExpInterlockedPopEntrySListResume; + + /* Continue execution */ + KiEoiHelper(TrapFrame); + } + } + /* Call the access fault handler */ Status = MmAccessFault(TrapFrame->ErrCode & 1, (PVOID)Cr2, @@ -1206,14 +1235,6 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame) TrapFrame); if (NT_SUCCESS(Status)) KiEoiHelper(TrapFrame); - /* Check for S-LIST fault */ - if (TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) - { - /* Not yet implemented */ - UNIMPLEMENTED; - while (TRUE); - } - /* Check for syscall fault */ #if 0 if ((TrapFrame->Eip == (ULONG_PTR)CopyParams) ||