[LDR] Introduce a private heap for the loader.

This ensures we can still do stuff when the process heap is corrupted.
This commit is contained in:
Mark Jansen 2018-10-14 23:16:36 +02:00
parent 34b0516ec4
commit 04ff7481b1
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
3 changed files with 33 additions and 24 deletions

View file

@ -32,6 +32,7 @@ typedef struct _LDRP_TLS_DATA
/* Global data */ /* Global data */
extern RTL_CRITICAL_SECTION LdrpLoaderLock; extern RTL_CRITICAL_SECTION LdrpLoaderLock;
extern BOOLEAN LdrpInLdrInit; extern BOOLEAN LdrpInLdrInit;
extern PVOID LdrpHeap;
extern LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]; extern LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
extern BOOLEAN ShowSnaps; extern BOOLEAN ShowSnaps;
extern UNICODE_STRING LdrpDefaultPath; extern UNICODE_STRING LdrpDefaultPath;

View file

@ -55,6 +55,7 @@ ULONG LdrpNumberOfProcessors;
PVOID NtDllBase; PVOID NtDllBase;
extern LARGE_INTEGER RtlpTimeout; extern LARGE_INTEGER RtlpTimeout;
BOOLEAN RtlpTimeoutDisable; BOOLEAN RtlpTimeoutDisable;
PVOID LdrpHeap;
LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]; LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
LIST_ENTRY LdrpDllNotificationList; LIST_ENTRY LdrpDllNotificationList;
HANDLE LdrpKnownDllObjectDirectory; HANDLE LdrpKnownDllObjectDirectory;
@ -663,7 +664,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
if (Count > 16) if (Count > 16)
{ {
/* Allocate space for all the entries */ /* Allocate space for all the entries */
LdrRootEntry = RtlAllocateHeap(RtlGetProcessHeap(), LdrRootEntry = RtlAllocateHeap(LdrpHeap,
0, 0,
Count * sizeof(*LdrRootEntry)); Count * sizeof(*LdrRootEntry));
if (!LdrRootEntry) return STATUS_NO_MEMORY; if (!LdrRootEntry) return STATUS_NO_MEMORY;
@ -921,7 +922,7 @@ Quickie:
if (LdrRootEntry != LocalArray) if (LdrRootEntry != LocalArray)
{ {
/* Free the array */ /* Free the array */
RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry); RtlFreeHeap(LdrpHeap, 0, LdrRootEntry);
} }
/* Return to caller */ /* Return to caller */
@ -1752,9 +1753,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
&ConfigSize); &ConfigSize);
/* Setup the Heap Parameters */ /* Setup the Heap Parameters */
RtlZeroMemory(&HeapParameters, sizeof(RTL_HEAP_PARAMETERS)); RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
HeapFlags = HEAP_GROWABLE; HeapFlags = HEAP_GROWABLE;
HeapParameters.Length = sizeof(RTL_HEAP_PARAMETERS); HeapParameters.Length = sizeof(HeapParameters);
/* Check if we have Configuration Data */ /* Check if we have Configuration Data */
if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY))) if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)))
@ -1875,8 +1876,15 @@ LdrpInitializeProcess(IN PCONTEXT Context,
Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer); Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
// FIXME: Loader private heap is missing RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
//DPRINT1("Loader private heap is missing\n"); HeapFlags = HEAP_GROWABLE | HEAP_CLASS_1;
HeapParameters.Length = sizeof(HeapParameters);
LdrpHeap = RtlCreateHeap(HeapFlags, 0, 0x10000, 0x6000, 0, &HeapParameters);
if (!LdrpHeap)
{
DPRINT1("Failed to create loader private heap\n");
return STATUS_NO_MEMORY;
}
/* Check for Debug Heap */ /* Check for Debug Heap */
if (OptionsKey) if (OptionsKey)

View file

@ -50,7 +50,7 @@ LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut,
} }
/* Allocate the string*/ /* Allocate the string*/
StringOut->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), StringOut->Buffer = RtlAllocateHeap(LdrpHeap,
0, 0,
StringOut->Length + sizeof(WCHAR)); StringOut->Length + sizeof(WCHAR));
if (!StringOut->Buffer) if (!StringOut->Buffer)
@ -88,7 +88,7 @@ LdrpFreeUnicodeString(IN PUNICODE_STRING StringIn)
/* If Buffer is not NULL - free it */ /* If Buffer is not NULL - free it */
if (StringIn->Buffer) if (StringIn->Buffer)
{ {
RtlFreeHeap(RtlGetProcessHeap(), 0, StringIn->Buffer); RtlFreeHeap(LdrpHeap, 0, StringIn->Buffer);
} }
/* Zero it out */ /* Zero it out */
@ -703,7 +703,7 @@ LdrpResolveDllName(PWSTR DllPath,
ULONG BufSize = 500; ULONG BufSize = 500;
/* Allocate space for full DLL name */ /* Allocate space for full DLL name */
FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufSize + sizeof(UNICODE_NULL)); FullDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, BufSize + sizeof(UNICODE_NULL));
if (!FullDllName->Buffer) return FALSE; if (!FullDllName->Buffer) return FALSE;
Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer, Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
@ -721,7 +721,7 @@ LdrpResolveDllName(PWSTR DllPath,
DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer); DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
} }
RtlFreeUnicodeString(FullDllName); LdrpFreeUnicodeString(FullDllName);
return FALSE; return FALSE;
} }
@ -730,16 +730,16 @@ LdrpResolveDllName(PWSTR DllPath,
FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL); FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
/* Allocate a new buffer */ /* Allocate a new buffer */
NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength); NameBuffer = RtlAllocateHeap(LdrpHeap, 0, FullDllName->MaximumLength);
if (!NameBuffer) if (!NameBuffer)
{ {
RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer); RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
return FALSE; return FALSE;
} }
/* Copy over the contents from the previous one and free it */ /* Copy over the contents from the previous one and free it */
RtlCopyMemory(NameBuffer, FullDllName->Buffer, FullDllName->MaximumLength); RtlCopyMemory(NameBuffer, FullDllName->Buffer, FullDllName->MaximumLength);
RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer); RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
FullDllName->Buffer = NameBuffer; FullDllName->Buffer = NameBuffer;
/* Find last backslash */ /* Find last backslash */
@ -766,11 +766,11 @@ LdrpResolveDllName(PWSTR DllPath,
/* Construct base DLL name */ /* Construct base DLL name */
BaseDllName->Length = (ULONG_PTR)p1 - (ULONG_PTR)p2; BaseDllName->Length = (ULONG_PTR)p1 - (ULONG_PTR)p2;
BaseDllName->MaximumLength = BaseDllName->Length + sizeof(UNICODE_NULL); BaseDllName->MaximumLength = BaseDllName->Length + sizeof(UNICODE_NULL);
BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BaseDllName->MaximumLength); BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, BaseDllName->MaximumLength);
if (!BaseDllName->Buffer) if (!BaseDllName->Buffer)
{ {
RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); RtlFreeHeap(LdrpHeap, 0, NameBuffer);
return FALSE; return FALSE;
} }
@ -867,7 +867,7 @@ LdrpCheckForKnownDll(PWSTR DllName,
/* Set up BaseDllName */ /* Set up BaseDllName */
BaseDllName->Length = DllNameUnic.Length; BaseDllName->Length = DllNameUnic.Length;
BaseDllName->MaximumLength = DllNameUnic.MaximumLength; BaseDllName->MaximumLength = DllNameUnic.MaximumLength;
BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), BaseDllName->Buffer = RtlAllocateHeap(LdrpHeap,
0, 0,
DllNameUnic.MaximumLength); DllNameUnic.MaximumLength);
if (!BaseDllName->Buffer) if (!BaseDllName->Buffer)
@ -882,7 +882,7 @@ LdrpCheckForKnownDll(PWSTR DllName,
/* Set up FullDllName */ /* Set up FullDllName */
FullDllName->Length = LdrpKnownDllPath.Length + BaseDllName->Length + sizeof(WCHAR); FullDllName->Length = LdrpKnownDllPath.Length + BaseDllName->Length + sizeof(WCHAR);
FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL); FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength); FullDllName->Buffer = RtlAllocateHeap(LdrpHeap, 0, FullDllName->MaximumLength);
if (!FullDllName->Buffer) if (!FullDllName->Buffer)
{ {
Status = STATUS_NO_MEMORY; Status = STATUS_NO_MEMORY;
@ -932,8 +932,8 @@ Failure:
if (Section) NtClose(Section); if (Section) NtClose(Section);
/* Free string resources */ /* Free string resources */
if (BaseDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer); if (BaseDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, BaseDllName->Buffer);
if (FullDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer); if (FullDllName->Buffer) RtlFreeHeap(LdrpHeap, 0, FullDllName->Buffer);
/* Return status */ /* Return status */
return Status; return Status;
@ -1137,8 +1137,8 @@ SkipCheck:
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Free the name strings and return */ /* Free the name strings and return */
RtlFreeUnicodeString(&FullDllName); LdrpFreeUnicodeString(&FullDllName);
RtlFreeUnicodeString(&BaseDllName); LdrpFreeUnicodeString(&BaseDllName);
return Status; return Status;
} }
} }
@ -1286,7 +1286,7 @@ SkipCheck:
RemoveEntryList(&LdrEntry->HashLinks); RemoveEntryList(&LdrEntry->HashLinks);
/* Remove the LDR Entry */ /* Remove the LDR Entry */
RtlFreeHeap(RtlGetProcessHeap(), 0, LdrEntry ); RtlFreeHeap(LdrpHeap, 0, LdrEntry );
/* Unmap and close section */ /* Unmap and close section */
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
@ -1553,7 +1553,7 @@ LdrpAllocateDataTableEntry(IN PVOID BaseAddress)
if (NtHeader) if (NtHeader)
{ {
/* Allocate an entry */ /* Allocate an entry */
LdrEntry = RtlAllocateHeap(RtlGetProcessHeap(), LdrEntry = RtlAllocateHeap(LdrpHeap,
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
sizeof(LDR_DATA_TABLE_ENTRY)); sizeof(LDR_DATA_TABLE_ENTRY));
@ -1608,7 +1608,7 @@ LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry)
if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName); if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName);
/* Finally free the entry's memory */ /* Finally free the entry's memory */
RtlFreeHeap(RtlGetProcessHeap(), 0, Entry); RtlFreeHeap(LdrpHeap, 0, Entry);
} }
BOOLEAN BOOLEAN