[PATCH v4 2/2] ntdll: Prevent loading Wine system dependencies in place of identically named application DLLs.

Zebediah Figura zfigura at codeweavers.com
Thu Nov 4 16:22:17 CDT 2021


That is, load Wine system dependencies only when they are imported from Wine
builtins or other system dependencies, and do not match a Wine system dependency
by its base name when looking for already-loaded modules.

The reasoning is that it is possible for an application to ship, and expect to
use, a newer version of a MinGW-compiled library, or one with custom patches, or
possibly an unrelated library with the same name. We don't want to offer Wine's
system dependencies in place of the application's, or vice versa.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---

v4: Use a separate field in WINE_MODREF instead of adding a private flag to the
LDR_DATA_TABLE_ENTRY.Flags field.

 dlls/ntdll/loader.c | 47 ++++++++++++++++++++++++++-------------------
 1 file changed, 27 insertions(+), 20 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index a9578ae86bf..9e7fa6f5045 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -135,6 +135,7 @@ typedef struct _wine_modref
     LDR_DATA_TABLE_ENTRY  ldr;
     struct file_id        id;
     ULONG                 CheckSum;
+    BOOL                  system;
 } WINE_MODREF;
 
 static UINT tls_module_count;      /* number of modules with TLS directory */
@@ -186,7 +187,7 @@ static WINE_MODREF *last_failed_modref;
 static LDR_DDAG_NODE *node_ntdll, *node_kernel32;
 
 static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
-                          DWORD flags, WINE_MODREF** pwm );
+                          DWORD flags, WINE_MODREF **pwm, BOOL system );
 static NTSTATUS process_attach( LDR_DDAG_NODE *node, LPVOID lpReserved );
 static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
                                     DWORD exp_size, DWORD ordinal, LPCWSTR load_path );
@@ -505,21 +506,22 @@ static WINE_MODREF *get_modref( HMODULE hmod )
  * Find a module from its base name.
  * The loader_section must be locked while calling this function
  */
-static WINE_MODREF *find_basename_module( LPCWSTR name )
+static WINE_MODREF *find_basename_module( const WCHAR *name, BOOL system )
 {
     PLIST_ENTRY mark, entry;
     UNICODE_STRING name_str;
 
     RtlInitUnicodeString( &name_str, name );
 
-    if (cached_modref && RtlEqualUnicodeString( &name_str, &cached_modref->ldr.BaseDllName, TRUE ))
+    if (cached_modref && RtlEqualUnicodeString( &name_str, &cached_modref->ldr.BaseDllName, TRUE )
+            && system == cached_modref->system)
         return cached_modref;
 
     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
     {
-        LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-        if (RtlEqualUnicodeString( &name_str, &mod->BaseDllName, TRUE ))
+        WINE_MODREF *mod = CONTAINING_RECORD(entry, WINE_MODREF, ldr.InLoadOrderLinks);
+        if (RtlEqualUnicodeString( &name_str, &mod->ldr.BaseDllName, TRUE ) && system == mod->system)
         {
             cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
             return cached_modref;
@@ -714,6 +716,8 @@ static NTSTATUS walk_node_dependencies( LDR_DDAG_NODE *node, void *context,
  */
 static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWSTR load_path )
 {
+    WINE_MODREF *imp = get_modref( module );
+    BOOL system = imp->system || (imp->ldr.Flags & LDR_WINE_INTERNAL);
     const IMAGE_EXPORT_DIRECTORY *exports;
     DWORD exp_size;
     WINE_MODREF *wm;
@@ -733,10 +737,10 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
     if (!wcschr( mod_name, '.' ))
         memcpy( mod_name + (end - forward), L".dll", sizeof(L".dll") );
 
-    if (!(wm = find_basename_module( mod_name )))
+    if (!(wm = find_basename_module( mod_name, system )))
     {
         TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
-        if (load_dll( load_path, mod_name, L".dll", 0, &wm ) == STATUS_SUCCESS &&
+        if (load_dll( load_path, mod_name, L".dll", 0, &wm, system ) == STATUS_SUCCESS &&
             !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
         {
             if (!imports_fixup_done && current_modref)
@@ -903,6 +907,7 @@ void * WINAPI RtlFindExportedRoutineByName( HMODULE module, const char *name )
  */
 static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path, WINE_MODREF **pwm )
 {
+    BOOL system = current_modref->system || (current_modref->ldr.Flags & LDR_WINE_INTERNAL);
     NTSTATUS status;
     WINE_MODREF *wmImp;
     HMODULE imp_mod;
@@ -936,7 +941,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP
     {
         ascii_to_unicode( buffer, name, len );
         buffer[len] = 0;
-        status = load_dll( load_path, buffer, L".dll", 0, &wmImp );
+        status = load_dll( load_path, buffer, L".dll", 0, &wmImp, system );
     }
     else  /* need to allocate a larger buffer */
     {
@@ -944,7 +949,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP
         if (!ptr) return FALSE;
         ascii_to_unicode( ptr, name, len );
         ptr[len] = 0;
-        status = load_dll( load_path, ptr, L".dll", 0, &wmImp );
+        status = load_dll( load_path, ptr, L".dll", 0, &wmImp, system );
         RtlFreeHeap( GetProcessHeap(), 0, ptr );
     }
 
@@ -1216,7 +1221,7 @@ static NTSTATUS fixup_imports_ilonly( WINE_MODREF *wm, LPCWSTR load_path, void *
     prev = current_modref;
     current_modref = wm;
     assert( !wm->ldr.DdagNode->Dependencies.Tail );
-    if (!(status = load_dll( load_path, L"mscoree.dll", NULL, 0, &imp ))
+    if (!(status = load_dll( load_path, L"mscoree.dll", NULL, 0, &imp, FALSE ))
           && !add_module_dependency_after( wm->ldr.DdagNode, imp->ldr.DdagNode, NULL ))
         status = STATUS_NO_MEMORY;
     current_modref = prev;
@@ -2902,7 +2907,7 @@ done:
  */
 static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
                                UNICODE_STRING *nt_name, WINE_MODREF **pwm, HANDLE *mapping,
-                               SECTION_IMAGE_INFORMATION *image_info, struct file_id *id )
+                               SECTION_IMAGE_INFORMATION *image_info, struct file_id *id, BOOL system )
 {
     WCHAR *ext, *dllname;
     NTSTATUS status;
@@ -2943,7 +2948,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con
         else
         {
             if (status != STATUS_SXS_KEY_NOT_FOUND) goto done;
-            if ((*pwm = find_basename_module( libname )) != NULL)
+            if ((*pwm = find_basename_module( libname, system )) != NULL)
             {
                 status = STATUS_SUCCESS;
                 goto done;
@@ -2976,7 +2981,7 @@ done:
  * The loader_section must be locked while calling this function.
  */
 static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
-                          DWORD flags, WINE_MODREF** pwm )
+                          DWORD flags, WINE_MODREF **pwm, BOOL system )
 {
     UNICODE_STRING nt_name;
     struct file_id id;
@@ -2987,10 +2992,10 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
 
     TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
 
-    if (system_dll_path.Buffer)
-        nts = find_dll_file( system_dll_path.Buffer, libname, default_ext, &nt_name, pwm, &mapping, &image_info, &id );
+    if (system && system_dll_path.Buffer)
+        nts = find_dll_file( system_dll_path.Buffer, libname, default_ext, &nt_name, pwm, &mapping, &image_info, &id, TRUE );
     if (nts)
-        nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &mapping, &image_info, &id );
+        nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &mapping, &image_info, &id, FALSE );
 
     if (*pwm)  /* found already loaded module */
     {
@@ -3027,6 +3032,8 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
         break;
     }
 
+    (*pwm)->system = system;
+
     if (NtCurrentTeb64())
         NtCurrentTeb64()->Tib.ArbitraryUserPointer = prev;
     else
@@ -3084,7 +3091,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrLoadDll(LPCWSTR path_name, DWORD flags,
 
     RtlEnterCriticalSection( &loader_section );
 
-    nts = load_dll( path_name, libname->Buffer, L".dll", flags, &wm );
+    nts = load_dll( path_name, libname->Buffer, L".dll", flags, &wm, FALSE );
 
     if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
     {
@@ -3159,7 +3166,7 @@ NTSTATUS WINAPI LdrGetDllHandleEx( ULONG flags, LPCWSTR load_path, ULONG *dll_ch
 
     RtlEnterCriticalSection( &loader_section );
 
-    status = find_dll_file( load_path, name->Buffer, L".dll", &nt_name, &wm, &mapping, &image_info, &id );
+    status = find_dll_file( load_path, name->Buffer, L".dll", &nt_name, &wm, &mapping, &image_info, &id, FALSE );
 
     if (wm) *base = wm->ldr.DllBase;
     else
@@ -3860,7 +3867,7 @@ static void init_wow64( CONTEXT *context )
         NTSTATUS status;
         static const WCHAR wow64_path[] = L"C:\\windows\\system32\\wow64.dll";
 
-        if ((status = load_dll( NULL, wow64_path, NULL, 0, &wm )))
+        if ((status = load_dll( NULL, wow64_path, NULL, 0, &wm, FALSE )))
         {
             ERR( "could not load %s, status %x\n", debugstr_w(wow64_path), status );
             NtTerminateProcess( GetCurrentProcess(), status );
@@ -4010,7 +4017,7 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
 
         if (NtCurrentTeb()->WowTebOffset) init_wow64( context );
 
-        if ((status = load_dll( NULL, L"kernel32.dll", NULL, 0, &kernel32 )) != STATUS_SUCCESS)
+        if ((status = load_dll( NULL, L"kernel32.dll", NULL, 0, &kernel32, FALSE )) != STATUS_SUCCESS)
         {
             MESSAGE( "wine: could not load kernel32.dll, status %x\n", status );
             NtTerminateProcess( GetCurrentProcess(), status );
-- 
2.33.0




More information about the wine-devel mailing list