Author: sir_richard Date: Thu Apr 22 05:54:09 2010 New Revision: 46987
URL: http://svn.reactos.org/svn/reactos?rev=46987&view=rev Log: [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.
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=46... ============================================================================== --- trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] Thu Apr 22 05:54:09 2010 @@ -509,6 +509,9 @@ /* Otherwise, this is the ordinal */ Ordinal = OrdinalTable[Mid];
+ /* Validate the ordinal */ + if (Ordinal >= ExportDirectory->NumberOfFunctions) return NULL; + /* Resolve the address and write it */ ExportTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfFunctions); @@ -554,9 +557,9 @@ ULONG_PTR OldBaseTop, Delta; PLDR_DATA_TABLE_ENTRY LdrEntry; PLIST_ENTRY NextEntry; - ULONG ImportSize; + ULONG ImportSize, i; + PULONG_PTR ImageThunk; PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor; - PULONG ImageThunk;
/* Calculate the top and delta */ OldBaseTop = (ULONG_PTR)OldBase + Size - 1; @@ -571,8 +574,30 @@ LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, 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 */ + i = ImportSize; ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, @@ -605,6 +630,7 @@ /* Go to the next import */ ImportDescriptor++; } +#endif } }
@@ -672,7 +698,7 @@ /* Get the hint and check if it's valid */ Hint = NameImport->Hint; 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 */ Ordinal = OrdinalTable[Hint]; @@ -843,7 +869,7 @@ NULL);
/* 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 */ ASSERT(LdrEntry->LoadCount != 0); @@ -870,6 +896,7 @@ }
/* FIXME: Free the driver */ + DPRINT1("Leaking driver: %wZ\n", &LdrEntry->BaseDllName); //MmFreeSection(LdrEntry->DllBase);
/* Check if we're linked in */ @@ -940,7 +967,7 @@ __FUNCTION__, ImageBase, ImageFileDirectory);
/* Assume no imports */ - *LoadImports = (PVOID)-2; + *LoadImports = MM_SYSLDR_NO_IMPORTS;
/* Get the import descriptor */ ImportDescriptor = RtlImageDirectoryEntryToData(ImageBase, @@ -965,11 +992,12 @@ LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T); LoadedImports = ExAllocatePoolWithTag(PagedPool, LoadedImportsSize, - TAG_LDR_WSTR); + 'TDmM'); if (LoadedImports) { /* Zero it */ RtlZeroMemory(LoadedImports, LoadedImportsSize); + LoadedImports->Count = ImportCount; } } else @@ -989,15 +1017,31 @@ GdiLink = GdiLink | !(_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 | ((_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 */ if ((GdiLink) && (NormalLink)) { /* It's not, it's importing stuff it shouldn't be! */ + MiDereferenceImports(LoadedImports); + if (LoadedImports) ExFreePool(LoadedImports); + 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; @@ -1079,7 +1123,7 @@ sizeof(UNICODE_NULL); DllName.Buffer = ExAllocatePoolWithTag(NonPagedPool, DllName.MaximumLength, - TAG_LDR_WSTR); + 'TDmM'); if (DllName.Buffer) { /* Setup the base length and copy it */ @@ -1091,13 +1135,13 @@ /* Now add the import name and null-terminate it */ RtlAppendStringToString((PSTRING)&DllName, (PSTRING)&NameString); - DllName.Buffer[(DllName.MaximumLength - 1) / sizeof(WCHAR)] = UNICODE_NULL; + DllName.Buffer[(DllName.MaximumLength - 1) / sizeof(WCHAR)] = UNICODE_NULL;
/* Load the image */ Status = MmLoadSystemImage(&DllName, NamePrefix, NULL, - 0, + FALSE, (PVOID)&DllEntry, &DllBase); if (NT_SUCCESS(Status)) @@ -1160,8 +1204,8 @@ if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)) { /* Add the entry */ - LoadedImports->Entry[LoadedImports->Count] = LdrEntry; - LoadedImports->Count++; + LoadedImports->Entry[ImportCount] = LdrEntry; + ImportCount++; } }
@@ -1230,7 +1274,8 @@ if (LoadedImports->Entry[i]) { /* 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++; } } @@ -1240,7 +1285,7 @@ { /* Free the list and set it to no imports */ ExFreePoolWithTag(LoadedImports, TAG_LDR_WSTR); - LoadedImports = (PVOID)-2; + LoadedImports = MM_SYSLDR_NO_IMPORTS; } else if (ImportCount == 1) { @@ -1254,7 +1299,7 @@ LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T); NewImports = ExAllocatePoolWithTag(PagedPool, LoadedImportsSize, - TAG_LDR_WSTR); + 'TDmM'); if (NewImports) { /* Set count */