[LDR] Guard some sections where we grab a lock.

CORE-14532
This commit is contained in:
Mark Jansen 2018-07-29 17:40:42 +02:00
parent 86fe412d5c
commit ad08c6631b
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
2 changed files with 194 additions and 180 deletions

View file

@ -353,73 +353,80 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL,
/* Check if there's a TLD DLL being loaded */ /* Check if there's a TLD DLL being loaded */
OldTldDll = LdrpTopLevelDllBeingLoaded; OldTldDll = LdrpTopLevelDllBeingLoaded;
if (OldTldDll) _SEH2_TRY
{ {
/* This is a recursive load, do something about it? */
if ((ShowSnaps) || (LdrpShowRecursiveLoads) || (LdrpBreakOnRecursiveDllLoads))
{
/* Print out debug messages */
DPRINT1("[%p, %p] LDR: Recursive DLL Load\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread);
DPRINT1("[%p, %p] Previous DLL being loaded \"%wZ\"\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread,
OldTldDll);
DPRINT1("[%p, %p] DLL being requested \"%wZ\"\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread,
DllName);
/* Was it initializing too? */ if (OldTldDll)
if (!LdrpCurrentDllInitializer) {
/* This is a recursive load, do something about it? */
if ((ShowSnaps) || (LdrpShowRecursiveLoads) || (LdrpBreakOnRecursiveDllLoads))
{ {
DPRINT1("[%p, %p] LDR: No DLL Initializer was running\n", /* Print out debug messages */
DPRINT1("[%p, %p] LDR: Recursive DLL Load\n",
Teb->RealClientId.UniqueProcess, Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread); Teb->RealClientId.UniqueThread);
} DPRINT1("[%p, %p] Previous DLL being loaded \"%wZ\"\n",
else Teb->RealClientId.UniqueProcess,
{ Teb->RealClientId.UniqueThread,
DPRINT1("[%p, %p] DLL whose initializer was currently running \"%wZ\"\n", OldTldDll);
Teb->ClientId.UniqueProcess, DPRINT1("[%p, %p] DLL being requested \"%wZ\"\n",
Teb->ClientId.UniqueThread, Teb->RealClientId.UniqueProcess,
&LdrpCurrentDllInitializer->BaseDllName); Teb->RealClientId.UniqueThread,
DllName);
/* Was it initializing too? */
if (!LdrpCurrentDllInitializer)
{
DPRINT1("[%p, %p] LDR: No DLL Initializer was running\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread);
}
else
{
DPRINT1("[%p, %p] DLL whose initializer was currently running \"%wZ\"\n",
Teb->ClientId.UniqueProcess,
Teb->ClientId.UniqueThread,
&LdrpCurrentDllInitializer->BaseDllName);
}
} }
} }
/* Set this one as the TLD DLL being loaded*/
LdrpTopLevelDllBeingLoaded = DllName;
/* Load the DLL */
Status = LdrpLoadDll(RedirectedDll,
SearchPath,
DllCharacteristics,
DllName,
BaseAddress,
TRUE);
if (NT_SUCCESS(Status))
{
Status = STATUS_SUCCESS;
}
else if ((Status != STATUS_NO_SUCH_FILE) &&
(Status != STATUS_DLL_NOT_FOUND) &&
(Status != STATUS_OBJECT_NAME_NOT_FOUND) &&
(Status != STATUS_DLL_INIT_FAILED))
{
DbgPrintEx(DPFLTR_LDR_ID,
DPFLTR_WARNING_LEVEL,
"LDR: %s - failing because LdrpLoadDll(%wZ) returned status %x\n",
__FUNCTION__,
DllName,
Status);
}
} }
_SEH2_FINALLY
/* Set this one as the TLD DLL being loaded*/
LdrpTopLevelDllBeingLoaded = DllName;
/* Load the DLL */
Status = LdrpLoadDll(RedirectedDll,
SearchPath,
DllCharacteristics,
DllName,
BaseAddress,
TRUE);
if (NT_SUCCESS(Status))
{ {
Status = STATUS_SUCCESS; /* Restore the old TLD DLL */
} LdrpTopLevelDllBeingLoaded = OldTldDll;
else if ((Status != STATUS_NO_SUCH_FILE) &&
(Status != STATUS_DLL_NOT_FOUND) &&
(Status != STATUS_OBJECT_NAME_NOT_FOUND) &&
(Status != STATUS_DLL_INIT_FAILED))
{
DbgPrintEx(DPFLTR_LDR_ID,
DPFLTR_WARNING_LEVEL,
"LDR: %s - failing because LdrpLoadDll(%wZ) returned status %x\n",
__FUNCTION__,
DllName,
Status);
}
/* Restore the old TLD DLL */ /* Release the lock */
LdrpTopLevelDllBeingLoaded = OldTldDll; LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
}
/* Release the lock */ _SEH2_END;
LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
/* Do we have a redirect string? */ /* Do we have a redirect string? */
if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2); if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2);

View file

@ -2488,146 +2488,153 @@ LdrpLoadDll(IN BOOLEAN Redirected,
/* Check for init flag and acquire lock */ /* Check for init flag and acquire lock */
if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock); if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
/* Show debug message */ _SEH2_TRY
if (ShowSnaps)
{ {
DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n", /* Show debug message */
&RawDllName, if (ShowSnaps)
DllPath ? DllPath : L"");
}
/* Check if the DLL is already loaded */
if (!LdrpCheckForLoadedDll(DllPath,
&RawDllName,
FALSE,
Redirected,
&LdrEntry))
{
/* Map it */
Status = LdrpMapDll(DllPath,
DllPath,
NameBuffer,
DllCharacteristics,
FALSE,
Redirected,
&LdrEntry);
if (!NT_SUCCESS(Status)) goto Quickie;
/* FIXME: Need to mark the DLL range for the stack DB */
//RtlpStkMarkDllRange(LdrEntry);
/* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
if ((DllCharacteristics) &&
(*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
{ {
/* This is not a DLL, so remove such data */ DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
LdrEntry->EntryPoint = NULL; &RawDllName,
LdrEntry->Flags &= ~LDRP_IMAGE_DLL; DllPath ? DllPath : L"");
} }
/* Make sure it's a DLL */ /* Check if the DLL is already loaded */
if (LdrEntry->Flags & LDRP_IMAGE_DLL) if (!LdrpCheckForLoadedDll(DllPath,
&RawDllName,
FALSE,
Redirected,
&LdrEntry))
{ {
/* Check if this is a .NET Image */ /* Map it */
if (!(LdrEntry->Flags & LDRP_COR_IMAGE)) Status = LdrpMapDll(DllPath,
{ DllPath,
/* Walk the Import Descriptor */ NameBuffer,
Status = LdrpWalkImportDescriptor(DllPath, LdrEntry); DllCharacteristics,
} FALSE,
Redirected,
/* Update load count, unless it's locked */ &LdrEntry);
if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
/* Check if we failed */
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
_SEH2_LEAVE;
/* FIXME: Need to mark the DLL range for the stack DB */
//RtlpStkMarkDllRange(LdrEntry);
/* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
if ((DllCharacteristics) &&
(*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
{ {
/* Clear entrypoint, and insert into list */ /* This is not a DLL, so remove such data */
LdrEntry->EntryPoint = NULL; LdrEntry->EntryPoint = NULL;
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
&LdrEntry->InInitializationOrderLinks); }
/* Cancel the load */ /* Make sure it's a DLL */
if (LdrEntry->Flags & LDRP_IMAGE_DLL)
{
/* Check if this is a .NET Image */
if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
{
/* Walk the Import Descriptor */
Status = LdrpWalkImportDescriptor(DllPath, LdrEntry);
}
/* Update load count, unless it's locked */
if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
/* Clear entrypoint, and insert into list */
LdrEntry->EntryPoint = NULL;
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
&LdrEntry->InInitializationOrderLinks);
/* Cancel the load */
LdrpClearLoadInProgress();
/* Unload the DLL */
if (ShowSnaps)
{
DbgPrint("LDR: Unloading %wZ due to error %x walking "
"import descriptors\n",
DllName,
Status);
}
LdrUnloadDll(LdrEntry->DllBase);
/* Return the error */
_SEH2_LEAVE;
}
}
else if (LdrEntry->LoadCount != 0xFFFF)
{
/* Increase load count */
LdrEntry->LoadCount++;
}
/* Insert it into the list */
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
&LdrEntry->InInitializationOrderLinks);
/* If we have to run the entrypoint, make sure the DB is ready */
if (CallInit && LdrpLdrDatabaseIsSetup)
{
/* Notify Shim Engine */
if (g_ShimsEnabled)
{
VOID (NTAPI* SE_DllLoaded)(PLDR_DATA_TABLE_ENTRY) = RtlDecodeSystemPointer(g_pfnSE_DllLoaded);
SE_DllLoaded(LdrEntry);
}
/* Run the init routine */
Status = LdrpRunInitializeRoutines(NULL);
if (!NT_SUCCESS(Status))
{
/* Failed, unload the DLL */
if (ShowSnaps)
{
DbgPrint("LDR: Unloading %wZ because either its init "
"routine or one of its static imports failed; "
"status = 0x%08lx\n",
DllName,
Status);
}
LdrUnloadDll(LdrEntry->DllBase);
}
}
else
{
/* The DB isn't ready, which means we were loaded because of a forwarder */
Status = STATUS_SUCCESS;
}
}
else
{
/* We were already loaded. Are we a DLL? */
if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
{
/* Increase load count */
LdrEntry->LoadCount++;
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
/* Clear the load in progress */
LdrpClearLoadInProgress(); LdrpClearLoadInProgress();
/* Unload the DLL */
if (ShowSnaps)
{
DbgPrint("LDR: Unloading %wZ due to error %x walking "
"import descriptors\n",
DllName,
Status);
}
LdrUnloadDll(LdrEntry->DllBase);
/* Return the error */
goto Quickie;
} }
} else
else if (LdrEntry->LoadCount != 0xFFFF)
{
/* Increase load count */
LdrEntry->LoadCount++;
}
/* Insert it into the list */
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
&LdrEntry->InInitializationOrderLinks);
/* If we have to run the entrypoint, make sure the DB is ready */
if (CallInit && LdrpLdrDatabaseIsSetup)
{
/* Notify Shim Engine */
if (g_ShimsEnabled)
{ {
VOID (NTAPI* SE_DllLoaded)(PLDR_DATA_TABLE_ENTRY) = RtlDecodeSystemPointer(g_pfnSE_DllLoaded); /* Not a DLL, just increase the load count */
SE_DllLoaded(LdrEntry); if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
} }
}
/* Run the init routine */
Status = LdrpRunInitializeRoutines(NULL);
if (!NT_SUCCESS(Status))
{
/* Failed, unload the DLL */
if (ShowSnaps)
{
DbgPrint("LDR: Unloading %wZ because either its init "
"routine or one of its static imports failed; "
"status = 0x%08lx\n",
DllName,
Status);
}
LdrUnloadDll(LdrEntry->DllBase);
}
}
else
{
/* The DB isn't ready, which means we were loaded because of a forwarder */
Status = STATUS_SUCCESS;
}
} }
else _SEH2_FINALLY
{ {
/* We were already loaded. Are we a DLL? */ /* Release the lock */
if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF)) if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
{
/* Increase load count */
LdrEntry->LoadCount++;
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
/* Clear the load in progress */
LdrpClearLoadInProgress();
}
else
{
/* Not a DLL, just increase the load count */
if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
}
} }
_SEH2_END;
Quickie:
/* Release the lock */
if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
/* Check for success */ /* Check for success */
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))