[PATCH v2 01/22] ntdll: Protect module list access in LdrFindEntryForAddress() with SRW lock.
Paul Gofman
pgofman at codeweavers.com
Tue Oct 5 17:49:07 CDT 2021
Fixes racy access to LDR lists in lookup_function_info().
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/ntdll/actctx.c | 6 ------
dlls/ntdll/loader.c | 21 ++++++++++++++++++---
2 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c
index f9afb655885..bc222dadf27 100644
--- a/dlls/ntdll/actctx.c
+++ b/dlls/ntdll/actctx.c
@@ -705,10 +705,8 @@ static inline const char* debugstr_version(const struct assembly_version *ver)
static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
{
NTSTATUS status;
- ULONG_PTR magic;
LDR_DATA_TABLE_ENTRY *pldr;
- LdrLockLoaderLock(0, NULL, &magic);
status = LdrFindEntryForAddress( module, &pldr );
if (status == STATUS_SUCCESS)
{
@@ -721,7 +719,6 @@ static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsign
}
else status = STATUS_NO_MEMORY;
}
- LdrUnlockLoaderLock(0, magic);
return status;
}
@@ -3301,12 +3298,10 @@ static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
}
else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
{
- ULONG_PTR magic;
LDR_DATA_TABLE_ENTRY *pldr;
if (!*handle) return STATUS_INVALID_PARAMETER;
- LdrLockLoaderLock( 0, NULL, &magic );
if (!LdrFindEntryForAddress( *handle, &pldr ))
{
if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
@@ -3315,7 +3310,6 @@ static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
*handle = pldr->ActivationContext;
}
else status = STATUS_DLL_NOT_FOUND;
- LdrUnlockLoaderLock( 0, magic );
}
else if (!*handle && (class != ActivationContextBasicInformation))
*handle = process_actctx;
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 797d72aedb6..e363c060ab1 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -176,6 +176,10 @@ static PEB_LDR_DATA ldr =
{ &ldr.InMemoryOrderModuleList, &ldr.InMemoryOrderModuleList },
{ &ldr.InInitializationOrderModuleList, &ldr.InInitializationOrderModuleList }
};
+/* Ldr lists are modified with loader locked and exclusive ldr_data_srw_lock held.
+ * Taking shared ldr_data_srw_lock to access the data is required outside of
+ * loader lock only. */
+static RTL_SRWLOCK ldr_data_srw_lock = RTL_SRWLOCK_INIT;
static RTL_BITMAP tls_bitmap;
static RTL_BITMAP tls_expansion_bitmap;
@@ -1245,10 +1249,12 @@ static WINE_MODREF *alloc_module( HMODULE hModule, const UNICODE_STRING *nt_name
wm->ldr.EntryPoint = (char *)hModule + nt->OptionalHeader.AddressOfEntryPoint;
}
+ RtlAcquireSRWLockExclusive( &ldr_data_srw_lock );
InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
&wm->ldr.InLoadOrderLinks);
InsertTailList(&NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList,
&wm->ldr.InMemoryOrderLinks);
+ RtlReleaseSRWLockExclusive( &ldr_data_srw_lock );
/* wait until init is called for inserting into InInitializationOrderModuleList */
if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
@@ -1454,8 +1460,12 @@ static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
}
if (!wm->ldr.InInitializationOrderLinks.Flink)
+ {
+ RtlAcquireSRWLockExclusive( &ldr_data_srw_lock );
InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList,
&wm->ldr.InInitializationOrderLinks);
+ RtlReleaseSRWLockExclusive( &ldr_data_srw_lock );
+ }
/* Call DLL entry point */
if (status == STATUS_SUCCESS)
@@ -1578,13 +1588,14 @@ NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
/******************************************************************
* LdrFindEntryForAddress (NTDLL.@)
*
- * The loader_section must be locked while calling this function
*/
NTSTATUS WINAPI LdrFindEntryForAddress( const void *addr, PLDR_DATA_TABLE_ENTRY *pmod )
{
+ NTSTATUS ret = STATUS_NO_MORE_ENTRIES;
PLIST_ENTRY mark, entry;
PLDR_DATA_TABLE_ENTRY mod;
+ RtlAcquireSRWLockShared( &ldr_data_srw_lock );
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
{
@@ -1593,10 +1604,12 @@ NTSTATUS WINAPI LdrFindEntryForAddress( const void *addr, PLDR_DATA_TABLE_ENTRY
(const char *)addr < (char*)mod->DllBase + mod->SizeOfImage)
{
*pmod = mod;
- return STATUS_SUCCESS;
+ ret = STATUS_SUCCESS;
+ break;
}
}
- return STATUS_NO_MORE_ENTRIES;
+ RtlReleaseSRWLockShared( &ldr_data_srw_lock );
+ return ret;
}
/******************************************************************
@@ -3510,10 +3523,12 @@ void WINAPI LdrShutdownThread(void)
*/
static void free_modref( WINE_MODREF *wm )
{
+ RtlAcquireSRWLockExclusive( &ldr_data_srw_lock );
RemoveEntryList(&wm->ldr.InLoadOrderLinks);
RemoveEntryList(&wm->ldr.InMemoryOrderLinks);
if (wm->ldr.InInitializationOrderLinks.Flink)
RemoveEntryList(&wm->ldr.InInitializationOrderLinks);
+ RtlReleaseSRWLockExclusive( &ldr_data_srw_lock );
TRACE(" unloading %s\n", debugstr_w(wm->ldr.FullDllName.Buffer));
if (!TRACE_ON(module))
--
2.31.1
More information about the wine-devel
mailing list