[NTOS]: MiFindExportedRoutineByName should validate the ordinal to make sure it's...
authorSir Richard <sir_richard@svn.reactos.org>
Thu, 22 Apr 2010 03:54:09 +0000 (03:54 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Thu, 22 Apr 2010 03:54:09 +0000 (03:54 +0000)
[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

reactos/ntoskrnl/mm/sysldr.c

index 1b08c91..a142516 100644 (file)
@@ -509,6 +509,9 @@ MiFindExportedRoutineByName(IN PVOID DllBase,
     /* 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 @@ MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
     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 @@ MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
         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 @@ MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
             /* Go to the next import */
             ImportDescriptor++;
         }
+#endif
     }
 }
 
@@ -672,7 +698,7 @@ MiSnapThunk(IN PVOID DllBase,
         /* 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 @@ MmUnloadSystemImage(IN PVOID ImageHandle)
                           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 @@ MmUnloadSystemImage(IN PVOID ImageHandle)
     }
 
     /* FIXME: Free the driver */
+    DPRINT1("Leaking driver: %wZ\n", &LdrEntry->BaseDllName);
     //MmFreeSection(LdrEntry->DllBase);
 
     /* Check if we're linked in */
@@ -940,7 +967,7 @@ MiResolveImageReferences(IN PVOID ImageBase,
            __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 @@ MiResolveImageReferences(IN PVOID ImageBase,
         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,10 +1017,12 @@ MiResolveImageReferences(IN PVOID ImageBase,
         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))
@@ -1003,6 +1033,20 @@ MiResolveImageReferences(IN PVOID ImageBase,
             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 */
         if (!(_strnicmp(ImportName, "ntoskrnl", sizeof("ntoskrnl") - 1)) ||
             !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) ||
@@ -1079,7 +1123,7 @@ CheckDllState:
                                     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 @@ CheckDllState:
                 /* 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 @@ CheckDllState:
             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 @@ CheckDllState:
             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 @@ CheckDllState:
         {
             /* 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 @@ CheckDllState:
             LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T);
             NewImports = ExAllocatePoolWithTag(PagedPool,
                                                LoadedImportsSize,
-                                               TAG_LDR_WSTR);
+                                               'TDmM');
             if (NewImports)
             {
                 /* Set count */