[NTDLL/LDR]

- Improve LdrpCheckForKnownDll by adding parameters validation, return status value, better failure paths handling.

svn path=/trunk/; revision=54606
This commit is contained in:
Aleksey Bragin 2011-12-07 17:51:18 +00:00
parent eb919ba888
commit 9a63c24e07
2 changed files with 76 additions and 20 deletions

View file

@ -59,6 +59,7 @@ BOOLEAN NTAPI LdrpCallInitRoutine(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddres
NTSTATUS NTAPI LdrpInitializeProcess(PCONTEXT Context, PVOID SystemArgument1); NTSTATUS NTAPI LdrpInitializeProcess(PCONTEXT Context, PVOID SystemArgument1);
VOID NTAPI LdrpInitFailure(NTSTATUS Status); VOID NTAPI LdrpInitFailure(NTSTATUS Status);
VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry); VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry);
VOID NTAPI LdrpEnsureLoaderLockIsHeld();
/* ldrpe.c */ /* ldrpe.c */
NTSTATUS NTSTATUS

View file

@ -663,12 +663,13 @@ LdrpFetchAddressOfEntryPoint(IN PVOID ImageBase)
return (PVOID)EntryPoint; return (PVOID)EntryPoint;
} }
/* NOTE: This function is broken, wrong number of parameters, no SxS, etc */ /* NOTE: This function is partially missing SxS */
HANDLE NTSTATUS
NTAPI NTAPI
LdrpCheckForKnownDll(PWSTR DllName, LdrpCheckForKnownDll(PWSTR DllName,
PUNICODE_STRING FullDllName, PUNICODE_STRING FullDllName,
PUNICODE_STRING BaseDllName) PUNICODE_STRING BaseDllName,
HANDLE *SectionHandle)
{ {
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE Section = NULL; HANDLE Section = NULL;
@ -677,9 +678,35 @@ LdrpCheckForKnownDll(PWSTR DllName,
PCHAR p1; PCHAR p1;
PWCHAR p2; PWCHAR p2;
/* Zero initialize provided parameters */
if (SectionHandle) *SectionHandle = 0;
if (FullDllName)
{
FullDllName->Length = 0;
FullDllName->MaximumLength = 0;
FullDllName->Buffer = NULL;
}
if (BaseDllName)
{
BaseDllName->Length = 0;
BaseDllName->MaximumLength = 0;
BaseDllName->Buffer = NULL;
}
/* If any of these three params are missing then fail */
if (!SectionHandle || !FullDllName || !BaseDllName)
return STATUS_INVALID_PARAMETER;
/* Check the Loader Lock */
LdrpEnsureLoaderLockIsHeld();
/* Upgrade DllName to a unicode string */ /* Upgrade DllName to a unicode string */
RtlInitUnicodeString(&DllNameUnic, DllName); RtlInitUnicodeString(&DllNameUnic, DllName);
/* FIXME: Missing RtlComputePrivatizedDllName_U related functionality */
/* Get the activation context */ /* Get the activation context */
Status = RtlFindActivationContextSectionString(0, Status = RtlFindActivationContextSectionString(0,
NULL, NULL,
@ -691,13 +718,21 @@ LdrpCheckForKnownDll(PWSTR DllName,
if (Status == STATUS_SXS_SECTION_NOT_FOUND || if (Status == STATUS_SXS_SECTION_NOT_FOUND ||
Status == STATUS_SXS_KEY_NOT_FOUND) Status == STATUS_SXS_KEY_NOT_FOUND)
{ {
/* NOTE: Here it's beneficial to allocate one big unicode string
using LdrpAllocateUnicodeString instead of fragmenting the heap
with two allocations as it's done now. */
/* 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(RtlGetProcessHeap(),
0, 0,
DllNameUnic.MaximumLength); DllNameUnic.MaximumLength);
if (!BaseDllName->Buffer) return NULL; if (!BaseDllName->Buffer)
{
Status = STATUS_NO_MEMORY;
goto Failure;
}
/* Copy the contents there */ /* Copy the contents there */
RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength); RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength);
@ -708,9 +743,8 @@ LdrpCheckForKnownDll(PWSTR DllName,
FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength); FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength);
if (!FullDllName->Buffer) if (!FullDllName->Buffer)
{ {
/* Free base name and fail */ Status = STATUS_NO_MEMORY;
RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer); goto Failure;
return NULL;
} }
RtlMoveMemory(FullDllName->Buffer, LdrpKnownDllPath.Buffer, LdrpKnownDllPath.Length); RtlMoveMemory(FullDllName->Buffer, LdrpKnownDllPath.Buffer, LdrpKnownDllPath.Length);
@ -741,19 +775,26 @@ LdrpCheckForKnownDll(PWSTR DllName,
&ObjectAttributes); &ObjectAttributes);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Opening failed, free resources */ /* Clear status in case it was just not found */
Section = NULL; if (Status == STATUS_OBJECT_NAME_NOT_FOUND) Status = STATUS_SUCCESS;
RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer); goto Failure;
RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
}
}
else
{
if (!NT_SUCCESS(Status)) Section = NULL;
} }
/* Return section handle */ /* Pass section handle to the caller and return success */
return Section; *SectionHandle = Section;
return STATUS_SUCCESS;
}
Failure:
/* Close section object if it was opened */
if (Section) NtClose(Section);
/* Free string resources */
if (BaseDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
if (FullDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
/* Return status */
return Status;
} }
NTSTATUS NTSTATUS
@ -893,9 +934,23 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
} }
/* Try to find a Known DLL */ /* Try to find a Known DLL */
SectionHandle = LdrpCheckForKnownDll(DllName, Status = LdrpCheckForKnownDll(DllName,
&FullDllName, &FullDllName,
&BaseDllName); &BaseDllName,
&SectionHandle);
if (!NT_SUCCESS(Status) && (Status != STATUS_DLL_NOT_FOUND))
{
/* Failure */
DbgPrintEx(81, //DPFLTR_LDR_ID,
0,
"LDR: %s - call to LdrpCheckForKnownDll(\"%ws\", ...) failed with status %x\n",
__FUNCTION__,
DllName,
Status);
return Status;
}
} }
SkipCheck: SkipCheck: