https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2221df213f40ec1b6d62a…
commit 2221df213f40ec1b6d62a0747863c9e0c891a97c
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri Feb 18 03:20:24 2022 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Fri Feb 18 20:24:49 2022 +0100
[FREELDR] Add cleanup in PE-image-handling-related failure code paths.
---
boot/freeldr/freeldr/disk/scsiport.c | 25 ++++++---
boot/freeldr/freeldr/include/peloader.h | 5 ++
boot/freeldr/freeldr/lib/peloader.c | 82 ++++++++++++++++++-----------
boot/freeldr/freeldr/ntldr/winldr.c | 93 ++++++++++++++++++++++++++-------
4 files changed, 148 insertions(+), 57 deletions(-)
diff --git a/boot/freeldr/freeldr/disk/scsiport.c b/boot/freeldr/freeldr/disk/scsiport.c
index d23fe58a76e..0699f69f6a6 100644
--- a/boot/freeldr/freeldr/disk/scsiport.c
+++ b/boot/freeldr/freeldr/disk/scsiport.c
@@ -1653,7 +1653,7 @@ LoadBootDeviceDriver(VOID)
Success = PeLdrLoadImage(NtBootDdPath, LoaderBootDriver, &ImageBase);
if (!Success)
{
- /* That's OK. File simply doesn't exist */
+ /* That's OK, file simply doesn't exist */
return ESUCCESS;
}
@@ -1661,7 +1661,11 @@ LoadBootDeviceDriver(VOID)
Success = PeLdrAllocateDataTableEntry(&ModuleListHead, "ntbootdd.sys",
"NTBOOTDD.SYS", ImageBase,
&BootDdDTE);
if (!Success)
+ {
+ /* Cleanup and bail out */
+ MmFreeMemory(ImageBase);
return EIO;
+ }
/* Add the PE part of freeldr.sys to the list of loaded executables, it
contains ScsiPort* exports, imported by ntbootdd.sys */
@@ -1669,20 +1673,27 @@ LoadBootDeviceDriver(VOID)
"FREELDR.SYS", &__ImageBase,
&FreeldrDTE);
if (!Success)
{
- RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
+ /* Cleanup and bail out */
+ PeLdrFreeDataTableEntry(BootDdDTE);
+ MmFreeMemory(ImageBase);
return EIO;
}
/* Fix imports */
Success = PeLdrScanImportDescriptorTable(&ModuleListHead, "",
BootDdDTE);
+ if (!Success)
+ {
+ /* Cleanup and bail out */
+ PeLdrFreeDataTableEntry(FreeldrDTE);
+ PeLdrFreeDataTableEntry(BootDdDTE);
+ MmFreeMemory(ImageBase);
+ return EIO;
+ }
- /* Now unlinkt the DTEs, they won't be valid later */
+ /* Now unlink the DTEs, they won't be valid later */
RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
RemoveEntryList(&FreeldrDTE->InLoadOrderLinks);
- if (!Success)
- return EIO;
-
/* Change imports to PA */
ImportTable =
(PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE->DllBase),
TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize);
@@ -1705,7 +1716,7 @@ LoadBootDeviceDriver(VOID)
NtHeaders->OptionalHeader.ImageBase -
(ULONG_PTR)BootDdDTE->DllBase,
"FreeLdr",
TRUE,
- TRUE, /* in case of conflict still return
success */
+ TRUE, /* In case of conflict still return
success */
FALSE);
if (!Success)
return EIO;
diff --git a/boot/freeldr/freeldr/include/peloader.h
b/boot/freeldr/freeldr/include/peloader.h
index 63ffa80471a..1f67ed3bbac 100644
--- a/boot/freeldr/freeldr/include/peloader.h
+++ b/boot/freeldr/freeldr/include/peloader.h
@@ -40,6 +40,11 @@ PeLdrAllocateDataTableEntry(
IN PVOID BasePA,
OUT PLDR_DATA_TABLE_ENTRY *NewEntry);
+VOID
+PeLdrFreeDataTableEntry(
+ // _In_ PLIST_ENTRY ModuleListHead,
+ _In_ PLDR_DATA_TABLE_ENTRY Entry);
+
BOOLEAN
PeLdrScanImportDescriptorTable(
IN OUT PLIST_ENTRY ModuleListHead,
diff --git a/boot/freeldr/freeldr/lib/peloader.c b/boot/freeldr/freeldr/lib/peloader.c
index b768aa9dea8..f97639e4cec 100644
--- a/boot/freeldr/freeldr/lib/peloader.c
+++ b/boot/freeldr/freeldr/lib/peloader.c
@@ -115,7 +115,7 @@ PeLdrpBindImportName(
// DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize,
ProcessForwards);
/* Check passed DllBase param */
- if(DllBase == NULL)
+ if (DllBase == NULL)
{
WARN("DllBase == NULL!\n");
return FALSE;
@@ -368,7 +368,7 @@ PeLdrpLoadAndScanReferencedDll(
Success = PeLdrLoadImage(FullDllName, LoaderBootDriver, &BasePA);
if (!Success)
{
- ERR("PeLdrLoadImage() failed\n");
+ ERR("PeLdrLoadImage('%s') failed\n", FullDllName);
return Success;
}
@@ -380,7 +380,9 @@ PeLdrpLoadAndScanReferencedDll(
DataTableEntry);
if (!Success)
{
- ERR("PeLdrAllocateDataTableEntry() failed\n");
+ /* Cleanup and bail out */
+ ERR("PeLdrAllocateDataTableEntry('%s') failed\n",
FullDllName);
+ MmFreeMemory(BasePA);
return Success;
}
@@ -392,7 +394,10 @@ PeLdrpLoadAndScanReferencedDll(
Success = PeLdrScanImportDescriptorTable(ModuleListHead, DirectoryPath,
*DataTableEntry);
if (!Success)
{
+ /* Cleanup and bail out */
ERR("PeLdrScanImportDescriptorTable() failed\n");
+ PeLdrFreeDataTableEntry(*DataTableEntry);
+ MmFreeMemory(BasePA);
return Success;
}
@@ -603,7 +608,7 @@ PeLdrAllocateDataTableEntry(
PIMAGE_NT_HEADERS NtHeaders;
USHORT Length;
- TRACE("PeLdrAllocateDataTableEntry(, '%s', '%s', %p)\n",
+ TRACE("PeLdrAllocateDataTableEntry('%s', '%s', %p)\n",
BaseDllName, FullDllName, BasePA);
/* Allocate memory for a data table entry, zero-initialize it */
@@ -706,6 +711,20 @@ PeLdrAllocateDataTableEntry(
return TRUE;
}
+VOID
+PeLdrFreeDataTableEntry(
+ // _In_ PLIST_ENTRY ModuleListHead,
+ _In_ PLDR_DATA_TABLE_ENTRY Entry)
+{
+ // ASSERT(ModuleListHead);
+ ASSERT(Entry);
+
+ RemoveEntryList(&Entry->InLoadOrderLinks);
+ FrLdrHeapFree(VaToPa(Entry->FullDllName.Buffer), TAG_WLDR_NAME);
+ FrLdrHeapFree(VaToPa(Entry->BaseDllName.Buffer), TAG_WLDR_NAME);
+ FrLdrHeapFree(Entry, TAG_WLDR_DTE);
+}
+
/*
* PeLdrLoadImage loads the specified image from the file (it doesn't
* perform any additional operations on the filename, just directly
@@ -730,13 +749,13 @@ PeLdrLoadImage(
LARGE_INTEGER Position;
ULONG i, BytesRead;
- TRACE("PeLdrLoadImage(%s, %ld)\n", FileName, MemoryType);
+ TRACE("PeLdrLoadImage('%s', %ld)\n", FileName, MemoryType);
/* Open the image file */
Status = ArcOpen((PSTR)FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
- WARN("ArcOpen(FileName: '%s') failed. Status: %u\n", FileName,
Status);
+ WARN("ArcOpen('%s') failed. Status: %u\n", FileName, Status);
return FALSE;
}
@@ -744,8 +763,7 @@ PeLdrLoadImage(
Status = ArcRead(FileId, HeadersBuffer, SECTOR_SIZE * 2, &BytesRead);
if (Status != ESUCCESS)
{
- ERR("ArcRead(File: '%s') failed. Status: %u\n", FileName,
Status);
- UiMessageBox("Error reading from file.");
+ ERR("ArcRead('%s') failed. Status: %u\n", FileName, Status);
ArcClose(FileId);
return FALSE;
}
@@ -755,7 +773,6 @@ PeLdrLoadImage(
if (!NtHeaders)
{
ERR("No NT header found in \"%s\"\n", FileName);
- UiMessageBox("Error: No NT header found.");
ArcClose(FileId);
return FALSE;
}
@@ -764,7 +781,6 @@ PeLdrLoadImage(
if (((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ==
0))
{
ERR("Not an executable image \"%s\"\n", FileName);
- UiMessageBox("Not an executable image.");
ArcClose(FileId);
return FALSE;
}
@@ -773,26 +789,25 @@ PeLdrLoadImage(
NumberOfSections = NtHeaders->FileHeader.NumberOfSections;
SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
- /* Try to allocate this memory, if fails - allocate somewhere else */
+ /* Try to allocate this memory; if it fails, allocate somewhere else */
PhysicalBase = MmAllocateMemoryAtAddress(NtHeaders->OptionalHeader.SizeOfImage,
(PVOID)((ULONG)NtHeaders->OptionalHeader.ImageBase &
(KSEG0_BASE - 1)),
MemoryType);
if (PhysicalBase == NULL)
{
- /* It's ok, we don't panic - let's allocate again at any other
"low" place */
+ /* Don't fail, allocate again at any other "low" place */
PhysicalBase = MmAllocateMemoryWithType(NtHeaders->OptionalHeader.SizeOfImage,
MemoryType);
if (PhysicalBase == NULL)
{
ERR("Failed to alloc %lu bytes for image %s\n",
NtHeaders->OptionalHeader.SizeOfImage, FileName);
- UiMessageBox("Failed to alloc pages for image.");
ArcClose(FileId);
return FALSE;
}
}
- /* This is the real image base - in form of a virtual address */
+ /* This is the real image base, in form of a virtual address */
VirtualBase = PaToVa(PhysicalBase);
TRACE("Base PA: 0x%X, VA: 0x%X\n", PhysicalBase, VirtualBase);
@@ -805,10 +820,10 @@ PeLdrLoadImage(
Status = ArcRead(FileId, (PUCHAR)PhysicalBase + sizeof(HeadersBuffer),
NtHeaders->OptionalHeader.SizeOfHeaders - sizeof(HeadersBuffer), &BytesRead);
if (Status != ESUCCESS)
{
- ERR("ArcRead(File: '%s') failed. Status: %u\n", FileName,
Status);
- UiMessageBox("Error reading headers.");
+ ERR("ArcRead('%s') failed. Status: %u\n", FileName,
Status);
+ // UiMessageBox("Error reading headers.");
ArcClose(FileId);
- return FALSE;
+ goto Failure;
}
}
@@ -824,9 +839,6 @@ PeLdrLoadImage(
/* Load the first section */
SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
- /* Fill output parameters */
- *ImageBasePA = PhysicalBase;
-
/* Walk through each section and read it (check/fix any possible
bad situations, if they arise) */
for (i = 0; i < NumberOfSections; i++)
@@ -868,7 +880,7 @@ PeLdrLoadImage(
}
}
- /* Size of data is less than the virtual size - fill up the remainder with zeroes
*/
+ /* Size of data is less than the virtual size: fill up the remainder with zeroes
*/
if (SizeOfRawData < VirtualSize)
{
TRACE("PeLdrLoadImage(): SORD %d < VS %d\n", SizeOfRawData,
VirtualSize);
@@ -878,25 +890,35 @@ PeLdrLoadImage(
SectionHeader++;
}
- /* We are done with the file - close it */
+ /* We are done with the file, close it */
ArcClose(FileId);
- /* If loading failed - return right now */
+ /* If loading failed, return right now */
if (Status != ESUCCESS)
- return FALSE;
+ goto Failure;
/* Relocate the image, if it needs it */
if (NtHeaders->OptionalHeader.ImageBase != (ULONG_PTR)VirtualBase)
{
WARN("Relocating %p -> %p\n",
NtHeaders->OptionalHeader.ImageBase, VirtualBase);
- return (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase,
- (ULONG_PTR)VirtualBase -
(ULONG_PTR)PhysicalBase,
- "FreeLdr",
- TRUE,
- TRUE, /* in case of conflict still
return success */
- FALSE);
+ Status = LdrRelocateImageWithBias(PhysicalBase,
+ (ULONG_PTR)VirtualBase -
(ULONG_PTR)PhysicalBase,
+ "FreeLdr",
+ ESUCCESS,
+ ESUCCESS, /* In case of conflict still return
success */
+ ENOEXEC);
+ if (Status != ESUCCESS)
+ goto Failure;
}
+ /* Fill output parameters */
+ *ImageBasePA = PhysicalBase;
+
TRACE("PeLdrLoadImage() done, PA = %p\n", *ImageBasePA);
return TRUE;
+
+Failure:
+ /* Cleanup and bail out */
+ MmFreeMemory(PhysicalBase);
+ return FALSE;
}
diff --git a/boot/freeldr/freeldr/ntldr/winldr.c b/boot/freeldr/freeldr/ntldr/winldr.c
index 2721ce4f0ed..3e7abaa51f4 100644
--- a/boot/freeldr/freeldr/ntldr/winldr.c
+++ b/boot/freeldr/freeldr/ntldr/winldr.c
@@ -333,7 +333,9 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
Success = PeLdrAllocateDataTableEntry(LoadOrderListHead, DllName, DllName,
DriverBase, DriverDTE);
if (!Success)
{
+ /* Cleanup and bail out */
ERR("PeLdrAllocateDataTableEntry('%s') failed\n", DllName);
+ MmFreeMemory(DriverBase);
return FALSE;
}
@@ -345,7 +347,10 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
Success = PeLdrScanImportDescriptorTable(LoadOrderListHead, FullPath, *DriverDTE);
if (!Success)
{
+ /* Cleanup and bail out */
ERR("PeLdrScanImportDescriptorTable('%s') failed\n",
FullPath);
+ PeLdrFreeDataTableEntry(*DriverDTE);
+ MmFreeMemory(DriverBase);
return FALSE;
}
@@ -482,7 +487,7 @@ WinLdrDetectVersion(VOID)
}
static
-BOOLEAN
+PVOID
LoadModule(
IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PCCH Path,
@@ -495,7 +500,7 @@ LoadModule(
BOOLEAN Success;
CHAR FullFileName[MAX_PATH];
CHAR ProgressString[256];
- PVOID BaseAddress = NULL;
+ PVOID BaseAddress;
RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...",
File);
if (!SosEnabled) UiDrawProgressBarCenter(Percentage, 100, ProgressString);
@@ -508,15 +513,10 @@ LoadModule(
if (!Success)
{
ERR("PeLdrLoadImage('%s') failed\n", File);
- return FALSE;
+ return NULL;
}
TRACE("%s loaded successfully at %p\n", File, BaseAddress);
- /*
- * Cheat about the base DLL name if we are loading
- * the Kernel Debugger Transport DLL, to make the
- * PE loader happy.
- */
Success = PeLdrAllocateDataTableEntry(&LoaderBlock->LoadOrderListHead,
ImportName,
FullFileName,
@@ -524,10 +524,13 @@ LoadModule(
Dte);
if (!Success)
{
+ /* Cleanup and bail out */
ERR("PeLdrAllocateDataTableEntry('%s') failed\n",
FullFileName);
+ MmFreeMemory(BaseAddress);
+ BaseAddress = NULL;
}
- return Success;
+ return BaseAddress;
}
static
@@ -541,7 +544,8 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
BOOLEAN Success;
PCSTR Option;
ULONG OptionLength;
- PLDR_DATA_TABLE_ENTRY HalDTE, KdComDTE = NULL;
+ PVOID KernelBase, HalBase, KdDllBase = NULL;
+ PLDR_DATA_TABLE_ENTRY HalDTE, KdDllDTE = NULL;
CHAR DirPath[MAX_PATH];
CHAR HalFileName[MAX_PATH];
CHAR KernelFileName[MAX_PATH];
@@ -585,17 +589,33 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
TRACE("HAL file = '%s' ; Kernel file = '%s'\n",
HalFileName, KernelFileName);
+ /*
+ * Load the core NT files: Kernel, HAL and KD transport DLL.
+ * Cheat about their base DLL name so as to satisfy the imports/exports,
+ * even if the corresponding underlying files do not have the same names
+ * -- this happens e.g. with UP vs. MP kernel, standard vs. ACPI hal, or
+ * different KD transport DLLs.
+ */
+
/* Load the Kernel */
- if (!LoadModule(LoaderBlock, DirPath, KernelFileName, "ntoskrnl.exe",
LoaderSystemCode, KernelDTE, 30))
+ KernelBase = LoadModule(LoaderBlock, DirPath, KernelFileName,
+ "ntoskrnl.exe", LoaderSystemCode, KernelDTE, 30);
+ if (!KernelBase)
{
- ERR("LoadModule() failed for %s\n", KernelFileName);
+ ERR("LoadModule('%s') failed\n", KernelFileName);
+ UiMessageBox("Could not load %s", KernelFileName);
return FALSE;
}
/* Load the HAL */
- if (!LoadModule(LoaderBlock, DirPath, HalFileName, "hal.dll",
LoaderHalCode, &HalDTE, 45))
+ HalBase = LoadModule(LoaderBlock, DirPath, HalFileName,
+ "hal.dll", LoaderHalCode, &HalDTE, 45);
+ if (!HalBase)
{
- ERR("LoadModule() failed for %s\n", HalFileName);
+ ERR("LoadModule('%s') failed\n", HalFileName);
+ UiMessageBox("Could not load %s", HalFileName);
+ PeLdrFreeDataTableEntry(*KernelDTE);
+ MmFreeMemory(KernelBase);
return FALSE;
}
@@ -651,10 +671,12 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
* Load the transport DLL. Override the base DLL name of the
* loaded transport DLL to the default "KDCOM.DLL" name.
*/
- if (!LoadModule(LoaderBlock, DirPath, KdDllName, "kdcom.dll",
LoaderSystemCode, &KdComDTE, 60))
+ KdDllBase = LoadModule(LoaderBlock, DirPath, KdDllName,
+ "kdcom.dll", LoaderSystemCode,
&KdDllDTE, 60);
+ if (!KdDllBase)
{
/* The transport DLL being optional, just ignore the failure */
- WARN("LoadModule() failed for %s\n", KdDllName);
+ WARN("LoadModule('%s') failed\n", KdDllName);
}
}
}
@@ -730,11 +752,42 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
}
/* Load all referenced DLLs for Kernel, HAL and Kernel Debugger Transport DLL */
- Success = PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead,
DirPath, *KernelDTE);
- Success &= PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead,
DirPath, HalDTE);
- if (KdComDTE)
+ Success = PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead,
DirPath, *KernelDTE);
+ if (!Success)
+ {
+ UiMessageBox("Could not load %s", KernelFileName);
+ goto Quit;
+ }
+ Success = PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead,
DirPath, HalDTE);
+ if (!Success)
+ {
+ UiMessageBox("Could not load %s", HalFileName);
+ goto Quit;
+ }
+ if (KdDllDTE)
+ {
+ Success = PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead,
DirPath, KdDllDTE);
+ if (!Success)
+ {
+ UiMessageBox("Could not load %s", KdDllName);
+ goto Quit;
+ }
+ }
+
+Quit:
+ if (!Success)
{
- Success &=
PeLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath,
KdComDTE);
+ /* Cleanup and bail out */
+ if (KdDllDTE)
+ PeLdrFreeDataTableEntry(KdDllDTE);
+ if (KdDllBase) // Optional
+ MmFreeMemory(KdDllBase);
+
+ PeLdrFreeDataTableEntry(HalDTE);
+ MmFreeMemory(HalBase);
+
+ PeLdrFreeDataTableEntry(*KernelDTE);
+ MmFreeMemory(KernelBase);
}
return Success;