Author: tkreuzer
Date: Mon Jul 11 03:36:29 2011
New Revision: 52628
URL:
http://svn.reactos.org/svn/reactos?rev=52628&view=rev
Log:
[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.
Modified:
trunk/reactos/ntoskrnl/include/internal/i386/ke.h
trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] Mon Jul 11 03:36:29
2011
@@ -457,6 +457,7 @@
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);
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Mon Jul 11 03:36:29 2011
@@ -1199,20 +1199,41 @@
#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,
TrapFrame->SegCs & MODE_MASK,
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