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
Author: ion
Date: Mon Jul 11 00:12:33 2011
New Revision: 52621
URL: http://svn.reactos.org/svn/reactos?rev=52621&view=rev
Log:
[NTDLL]: Cleanup and half-fix LdrpCheckForLoadedDll, including adding comments for where it's broken. This uses RtlImageNtHeaderEx with much stringent checks as well.
Modified:
trunk/reactos/dll/ntdll/ldr/ldrutils.c
Modified: trunk/reactos/dll/ntdll/ldr/ldrutils.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrutils.c?r…
==============================================================================
--- trunk/reactos/dll/ntdll/ldr/ldrutils.c [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/ldr/ldrutils.c [iso-8859-1] Mon Jul 11 00:12:33 2011
@@ -1394,6 +1394,7 @@
return FALSE;
}
+/* NOTE: This function is b0rked and in the process of being slowly unf*cked */
BOOLEAN
NTAPI
LdrpCheckForLoadedDll(IN PWSTR DllPath,
@@ -1417,12 +1418,14 @@
PVOID ViewBase = NULL;
SIZE_T ViewSize = 0;
PIMAGE_NT_HEADERS NtHeader, NtHeader2;
-
DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
/* Check if a dll name was provided */
- if (!DllName->Buffer || !DllName->Buffer[0]) return FALSE;
-
+ if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE;
+
+ /* FIXME: Warning, "Flag" is used as magic instead of "Static" */
+ /* FIXME: Warning, code does not support redirection at all */
+
/* Look in the hash table if flag was set */
lookinhash:
if (Flag)
@@ -1459,7 +1462,7 @@
while (*wc)
{
/* Check for a slash in the current position*/
- if (*wc == L'\\' || *wc == L'/')
+ if ((*wc == L'\\') || (*wc == L'/'))
{
/* Found the slash, so dll name contains path */
FullPath = TRUE;
@@ -1467,6 +1470,7 @@
/* Setup full dll name string */
FullDllName.Buffer = NameBuf;
+ /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */
Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
DllName->Buffer,
NULL,
@@ -1475,7 +1479,7 @@
NULL);
/* Check if that was successful */
- if (!Length || Length > sizeof(NameBuf) - sizeof(UNICODE_NULL))
+ if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL))))
{
if (ShowSnaps)
{
@@ -1502,18 +1506,22 @@
Flag = TRUE;
goto lookinhash;
}
-
- /* Now go through the InLoadOrder module list */
+
+ /* FIXME: Warning, activation context missing */
+ /* NOTE: From here on down, everything looks good */
+
+ /* Loop the module list */
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
ListEntry = ListHead->Flink;
-
while (ListEntry != ListHead)
{
- /* Get the containing record of the current entry and advance to the next one */
- CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+ /* Get the current entry and advance to the next one */
+ CurEntry = CONTAINING_RECORD(ListEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
ListEntry = ListEntry->Flink;
- /* Check if it's already being unloaded */
+ /* Check if it's being unloaded */
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
/* Check if name matches */
@@ -1523,17 +1531,9 @@
{
/* Found it */
*LdrEntry = CurEntry;
-
- /* Find activation context */
- //Status = RtlFindActivationContextSectionString(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, DllName, NULL);
- //if (!NT_SUCCESS(Status))
- // return FALSE;
- //else
return TRUE;
}
}
-
- /* The DLL was not found in the load order modules list. Perform a complex check */
/* Convert given path to NT path */
if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,
@@ -1551,7 +1551,6 @@
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
Status = NtOpenFile(&FileHandle,
SYNCHRONIZE | FILE_EXECUTE,
&ObjectAttributes,
@@ -1567,7 +1566,9 @@
/* Create a section for this file */
Status = NtCreateSection(&SectionHandle,
- SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
+ SECTION_MAP_READ |
+ SECTION_MAP_EXECUTE |
+ SECTION_MAP_WRITE,
NULL,
NULL,
PAGE_EXECUTE,
@@ -1591,6 +1592,7 @@
ViewShare,
0,
PAGE_EXECUTE);
+
/* Close section handle */
NtClose(SectionHandle);
@@ -1598,52 +1600,51 @@
if (!NT_SUCCESS(Status)) return FALSE;
/* Get pointer to the NT header of this section */
- NtHeader = RtlImageNtHeader(ViewBase);
- if (!NtHeader)
+ Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader);
+ if (!(NT_SUCCESS(Status)) || !(NtHeader))
{
/* Unmap the section and fail */
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
return FALSE;
}
- /* Go through the list of modules */
+ /* Go through the list of modules again */
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
ListEntry = ListHead->Flink;
-
while (ListEntry != ListHead)
{
- CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+ /* Get the current entry and advance to the next one */
+ CurEntry = CONTAINING_RECORD(ListEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
ListEntry = ListEntry->Flink;
- /* Check if it's already being unloaded */
+ /* Check if it's in the process of being unloaded */
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
-
+
+ /* The header is untrusted, use SEH */
_SEH2_TRY
{
/* Check if timedate stamp and sizes match */
- if (CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp &&
- CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage)
+ if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) &&
+ (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage))
{
/* Time, date and size match. Let's compare their headers */
NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
-
if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
{
/* Headers match too! Finally ask the kernel to compare mapped files */
Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
-
if (!NT_SUCCESS(Status))
{
+ /* Almost identical, but not quite, keep trying */
_SEH2_YIELD(continue;)
}
else
{
- /* This is our entry! */
+ /* This is our entry!, unmap and return success */
*LdrEntry = CurEntry;
-
- /* Unmap the section */
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
-
_SEH2_YIELD(return TRUE;)
}
}
@@ -1656,9 +1657,8 @@
_SEH2_END;
}
- /* Unmap the section */
+ /* Unmap the section and fail */
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
-
return FALSE;
}
Author: ion
Date: Mon Jul 11 00:10:27 2011
New Revision: 52620
URL: http://svn.reactos.org/svn/reactos?rev=52620&view=rev
Log:
[RTL]: One day, Microsoft is going to stop using flags that are negatives. Fix boot/etc.
Modified:
trunk/reactos/lib/rtl/image.c
Modified: trunk/reactos/lib/rtl/image.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/image.c?rev=52620&…
==============================================================================
--- trunk/reactos/lib/rtl/image.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/image.c [iso-8859-1] Mon Jul 11 00:10:27 2011
@@ -143,6 +143,7 @@
{
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_DOS_HEADER DosHeader;
+ BOOLEAN WantsRangeCheck;
/* You must want NT Headers, no? */
if (!OutHeaders) return STATUS_INVALID_PARAMETER;
@@ -161,7 +162,8 @@
if (!(Base) || (Base == (PVOID)-1)) return STATUS_INVALID_PARAMETER;
/* Check if the caller wants validation */
- if (Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK)
+ WantsRangeCheck = !(Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK);
+ if (WantsRangeCheck)
{
/* Make sure the image size is at least big enough for the DOS header */
if (Size < sizeof(IMAGE_DOS_HEADER))
@@ -181,7 +183,7 @@
}
/* Check if the caller wants validation */
- if (Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK)
+ if (WantsRangeCheck)
{
/* The offset should fit in the passsed-in size */
if (DosHeader->e_lfanew >= Size)