[NTOS]: MiFindExportedRoutineByName should validate the ordinal to make sure it's not higher than the function count.

[NTOS]: Use MM_SYSLDR_ defines instead of magic pointer casts. Use appropriate pool tags.
[NTOS]: Set the LoadedImport count early-on during image referencing, so that failure will correctly de-reference the imports. By setting it to zero, failures would've leaked driver-dependent DLLs already loaded but now useless.
[NTOS]: Do the same checks as Windows to avoid drivers linked with user-mode DLLs.
[NTOS]: Allow "coverage" and "irt" to be linked with Win32K drivers as well.
[NTOS]: When the linker is fixed not to generate corrupt drivers, add the appropriate code to scan IMAGE_DIRECTORY_ENTRY_IAT for updating thunks. A hack exists in ReactOS now to permit loading these hacked drivers, but Windows is not so generous and will crash with a ReactOS driver.

svn path=/trunk/; revision=46987
This commit is contained in:
Sir Richard 2010-04-22 03:54:09 +00:00
parent 6463764d66
commit 0f570fe34c

View file

@ -509,6 +509,9 @@ MiFindExportedRoutineByName(IN PVOID DllBase,
/* Otherwise, this is the ordinal */ /* Otherwise, this is the ordinal */
Ordinal = OrdinalTable[Mid]; Ordinal = OrdinalTable[Mid];
/* Validate the ordinal */
if (Ordinal >= ExportDirectory->NumberOfFunctions) return NULL;
/* Resolve the address and write it */ /* Resolve the address and write it */
ExportTable = (PULONG)((ULONG_PTR)DllBase + ExportTable = (PULONG)((ULONG_PTR)DllBase +
ExportDirectory->AddressOfFunctions); ExportDirectory->AddressOfFunctions);
@ -554,9 +557,9 @@ MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
ULONG_PTR OldBaseTop, Delta; ULONG_PTR OldBaseTop, Delta;
PLDR_DATA_TABLE_ENTRY LdrEntry; PLDR_DATA_TABLE_ENTRY LdrEntry;
PLIST_ENTRY NextEntry; PLIST_ENTRY NextEntry;
ULONG ImportSize; ULONG ImportSize, i;
PULONG_PTR ImageThunk;
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor; PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
PULONG ImageThunk;
/* Calculate the top and delta */ /* Calculate the top and delta */
OldBaseTop = (ULONG_PTR)OldBase + Size - 1; OldBaseTop = (ULONG_PTR)OldBase + Size - 1;
@ -571,8 +574,30 @@ MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
LdrEntry = CONTAINING_RECORD(NextEntry, LdrEntry = CONTAINING_RECORD(NextEntry,
LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks); InLoadOrderLinks);
#ifdef _WORKING_LINKER_
/* Get the IAT */
ImageThunk = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_IAT,
&ImportSize);
if (!ImageThunk) continue;
/* Make sure we have an IAT */
DPRINT("[Mm0]: Updating thunks in: %wZ\n", &LdrEntry->BaseDllName);
for (i = 0; i < ImportSize; i++, ImageThunk++)
{
/* Check if it's within this module */
if ((*ImageThunk >= (ULONG_PTR)OldBase) && (*ImageThunk <= OldBaseTop))
{
/* Relocate it */
DPRINT("[Mm0]: Updating IAT at: %p. Old Entry: %p. New Entry: %p.\n",
ImageThunk, *ImageThunk, *ImageThunk + Delta);
*ImageThunk += Delta;
}
}
#else
/* Get the import table */ /* Get the import table */
i = ImportSize;
ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase, ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
TRUE, TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_IMPORT,
@ -605,6 +630,7 @@ MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
/* Go to the next import */ /* Go to the next import */
ImportDescriptor++; ImportDescriptor++;
} }
#endif
} }
} }
@ -672,7 +698,7 @@ MiSnapThunk(IN PVOID DllBase,
/* Get the hint and check if it's valid */ /* Get the hint and check if it's valid */
Hint = NameImport->Hint; Hint = NameImport->Hint;
if ((Hint < ExportDirectory->NumberOfNames) && if ((Hint < ExportDirectory->NumberOfNames) &&
!(strcmp((PCHAR) NameImport->Name, (PCHAR)DllBase + NameTable[Hint]))) !(strcmp((PCHAR)NameImport->Name, (PCHAR)DllBase + NameTable[Hint])))
{ {
/* We have a match, get the ordinal number from here */ /* We have a match, get the ordinal number from here */
Ordinal = OrdinalTable[Hint]; Ordinal = OrdinalTable[Hint];
@ -843,7 +869,7 @@ MmUnloadSystemImage(IN PVOID ImageHandle)
NULL); NULL);
/* Check if this driver was loaded at boot and didn't get imports parsed */ /* Check if this driver was loaded at boot and didn't get imports parsed */
if (LdrEntry->LoadedImports == (PVOID)-1) goto Done; if (LdrEntry->LoadedImports == MM_SYSLDR_BOOT_LOADED) goto Done;
/* We should still be alive */ /* We should still be alive */
ASSERT(LdrEntry->LoadCount != 0); ASSERT(LdrEntry->LoadCount != 0);
@ -870,6 +896,7 @@ MmUnloadSystemImage(IN PVOID ImageHandle)
} }
/* FIXME: Free the driver */ /* FIXME: Free the driver */
DPRINT1("Leaking driver: %wZ\n", &LdrEntry->BaseDllName);
//MmFreeSection(LdrEntry->DllBase); //MmFreeSection(LdrEntry->DllBase);
/* Check if we're linked in */ /* Check if we're linked in */
@ -940,7 +967,7 @@ MiResolveImageReferences(IN PVOID ImageBase,
__FUNCTION__, ImageBase, ImageFileDirectory); __FUNCTION__, ImageBase, ImageFileDirectory);
/* Assume no imports */ /* Assume no imports */
*LoadImports = (PVOID)-2; *LoadImports = MM_SYSLDR_NO_IMPORTS;
/* Get the import descriptor */ /* Get the import descriptor */
ImportDescriptor = RtlImageDirectoryEntryToData(ImageBase, ImportDescriptor = RtlImageDirectoryEntryToData(ImageBase,
@ -965,11 +992,12 @@ MiResolveImageReferences(IN PVOID ImageBase,
LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T); LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T);
LoadedImports = ExAllocatePoolWithTag(PagedPool, LoadedImports = ExAllocatePoolWithTag(PagedPool,
LoadedImportsSize, LoadedImportsSize,
TAG_LDR_WSTR); 'TDmM');
if (LoadedImports) if (LoadedImports)
{ {
/* Zero it */ /* Zero it */
RtlZeroMemory(LoadedImports, LoadedImportsSize); RtlZeroMemory(LoadedImports, LoadedImportsSize);
LoadedImports->Count = ImportCount;
} }
} }
else else
@ -989,10 +1017,12 @@ MiResolveImageReferences(IN PVOID ImageBase,
GdiLink = GdiLink | GdiLink = GdiLink |
!(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)); !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1));
/* We can also allow dxapi */ /* We can also allow dxapi (for Windows compat, allow IRT and coverage )*/
NormalLink = NormalLink | NormalLink = NormalLink |
((_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) && ((_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) &&
(_strnicmp(ImportName, "dxapi", sizeof("dxapi") - 1))); (_strnicmp(ImportName, "dxapi", sizeof("dxapi") - 1)) &&
(_strnicmp(ImportName, "coverage", sizeof("coverage") - 1)) &&
(_strnicmp(ImportName, "irt", sizeof("irt") - 1)));
/* Check if this is a valid GDI driver */ /* Check if this is a valid GDI driver */
if ((GdiLink) && (NormalLink)) if ((GdiLink) && (NormalLink))
@ -1003,6 +1033,20 @@ MiResolveImageReferences(IN PVOID ImageBase,
return STATUS_PROCEDURE_NOT_FOUND; return STATUS_PROCEDURE_NOT_FOUND;
} }
/* Check for user-mode printer or video card drivers, which don't belong */
if (!(_strnicmp(ImportName, "ntdll", sizeof("ntdll") - 1)) ||
!(_strnicmp(ImportName, "winsrv", sizeof("winsrv") - 1)) ||
!(_strnicmp(ImportName, "advapi32", sizeof("advapi32") - 1)) ||
!(_strnicmp(ImportName, "kernel32", sizeof("kernel32") - 1)) ||
!(_strnicmp(ImportName, "user32", sizeof("user32") - 1)) ||
!(_strnicmp(ImportName, "gdi32", sizeof("gdi32") - 1)))
{
/* This is not kernel code */
MiDereferenceImports(LoadedImports);
if (LoadedImports) ExFreePool(LoadedImports);
return STATUS_PROCEDURE_NOT_FOUND;
}
/* Check if this is a "core" import, which doesn't get referenced */ /* Check if this is a "core" import, which doesn't get referenced */
if (!(_strnicmp(ImportName, "ntoskrnl", sizeof("ntoskrnl") - 1)) || if (!(_strnicmp(ImportName, "ntoskrnl", sizeof("ntoskrnl") - 1)) ||
!(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) || !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) ||
@ -1079,7 +1123,7 @@ CheckDllState:
sizeof(UNICODE_NULL); sizeof(UNICODE_NULL);
DllName.Buffer = ExAllocatePoolWithTag(NonPagedPool, DllName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
DllName.MaximumLength, DllName.MaximumLength,
TAG_LDR_WSTR); 'TDmM');
if (DllName.Buffer) if (DllName.Buffer)
{ {
/* Setup the base length and copy it */ /* Setup the base length and copy it */
@ -1091,13 +1135,13 @@ CheckDllState:
/* Now add the import name and null-terminate it */ /* Now add the import name and null-terminate it */
RtlAppendStringToString((PSTRING)&DllName, RtlAppendStringToString((PSTRING)&DllName,
(PSTRING)&NameString); (PSTRING)&NameString);
DllName.Buffer[(DllName.MaximumLength - 1) / sizeof(WCHAR)] = UNICODE_NULL; DllName.Buffer[(DllName.MaximumLength - 1) / sizeof(WCHAR)] = UNICODE_NULL;
/* Load the image */ /* Load the image */
Status = MmLoadSystemImage(&DllName, Status = MmLoadSystemImage(&DllName,
NamePrefix, NamePrefix,
NULL, NULL,
0, FALSE,
(PVOID)&DllEntry, (PVOID)&DllEntry,
&DllBase); &DllBase);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
@ -1160,8 +1204,8 @@ CheckDllState:
if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)) if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS))
{ {
/* Add the entry */ /* Add the entry */
LoadedImports->Entry[LoadedImports->Count] = LdrEntry; LoadedImports->Entry[ImportCount] = LdrEntry;
LoadedImports->Count++; ImportCount++;
} }
} }
@ -1230,7 +1274,8 @@ CheckDllState:
if (LoadedImports->Entry[i]) if (LoadedImports->Entry[i])
{ {
/* Got an entry, OR it with 1 in case it's the single entry */ /* Got an entry, OR it with 1 in case it's the single entry */
ImportEntry = (PVOID)((ULONG_PTR)LoadedImports->Entry[i] | 1); ImportEntry = (PVOID)((ULONG_PTR)LoadedImports->Entry[i] |
MM_SYSLDR_SINGLE_ENTRY);
ImportCount++; ImportCount++;
} }
} }
@ -1240,7 +1285,7 @@ CheckDllState:
{ {
/* Free the list and set it to no imports */ /* Free the list and set it to no imports */
ExFreePoolWithTag(LoadedImports, TAG_LDR_WSTR); ExFreePoolWithTag(LoadedImports, TAG_LDR_WSTR);
LoadedImports = (PVOID)-2; LoadedImports = MM_SYSLDR_NO_IMPORTS;
} }
else if (ImportCount == 1) else if (ImportCount == 1)
{ {
@ -1254,7 +1299,7 @@ CheckDllState:
LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T); LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T);
NewImports = ExAllocatePoolWithTag(PagedPool, NewImports = ExAllocatePoolWithTag(PagedPool,
LoadedImportsSize, LoadedImportsSize,
TAG_LDR_WSTR); 'TDmM');
if (NewImports) if (NewImports)
{ {
/* Set count */ /* Set count */