From d86cd4da6761e175a5cdc95725f8c7fdb0ba1410 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Wed, 29 Jan 2025 20:00:17 -0800 Subject: [PATCH] Don't use incompatible LOAD_LIBRARY_SEARCH flags when using LOAD_WITH_ALTERED_SEARCH_PATH --- .../NativeLibrary.NativeAot.cs | 20 ++++++++-------- src/coreclr/vm/nativelibrary.cpp | 23 +++++++++++-------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs index 3abe04a60385e6..8037acd3f65ed8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs @@ -67,6 +67,11 @@ internal static IntPtr LoadBySearch(Assembly callingAssembly, bool searchAssembl IntPtr ret; int loadWithAlteredPathFlags = LoadWithAlteredSearchPathFlag; + const int loadLibrarySearchFlags = (int)DllImportSearchPath.UseDllDirectoryForDependencies + | (int)DllImportSearchPath.ApplicationDirectory + | (int)DllImportSearchPath.UserDirectories + | (int)DllImportSearchPath.System32 + | (int)DllImportSearchPath.SafeDirectories; bool libNameIsRelativePath = !Path.IsPathFullyQualified(libraryName); // P/Invokes are often declared with variations on the actual library name. @@ -80,14 +85,8 @@ internal static IntPtr LoadBySearch(Assembly callingAssembly, bool searchAssembl if (!libNameIsRelativePath) { - int flags = loadWithAlteredPathFlags; - if ((dllImportSearchPathFlags & (int)DllImportSearchPath.UseDllDirectoryForDependencies) != 0) - { - // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR is the only flag affecting absolute path. Don't OR the flags - // unconditionally as all absolute path P/Invokes could then lose LOAD_WITH_ALTERED_SEARCH_PATH. - flags |= dllImportSearchPathFlags; - } - + // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set. + int flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags); ret = LoadLibraryHelper(currLibNameVariation, flags, ref errorTracker); if (ret != IntPtr.Zero) { @@ -96,9 +95,12 @@ internal static IntPtr LoadBySearch(Assembly callingAssembly, bool searchAssembl } else if ((callingAssembly != null) && searchAssemblyDirectory) { + // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set. + int flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags); + // Try to load the module alongside the assembly where the PInvoke was declared. // For PInvokes where the DllImportSearchPath.AssemblyDirectory is specified, look next to the application. - ret = LoadLibraryHelper(Path.Combine(AppContext.BaseDirectory, currLibNameVariation), loadWithAlteredPathFlags | dllImportSearchPathFlags, ref errorTracker); + ret = LoadLibraryHelper(Path.Combine(AppContext.BaseDirectory, currLibNameVariation), flags, ref errorTracker); if (ret != IntPtr.Zero) { return ret; diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index 0f429c49a2951e..ab97367aa678c1 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -476,6 +476,7 @@ namespace NATIVE_LIBRARY_HANDLE hmod = NULL; SString path{ pAssembly->GetPEAssembly()->GetPath() }; + _ASSERTE(!Path::IsRelative(path)); SString::Iterator lastPathSeparatorIter = path.End(); if (PEAssembly::FindLastPathSeparator(path, lastPathSeparatorIter)) @@ -656,6 +657,14 @@ namespace AppDomain* pDomain = GetAppDomain(); DWORD loadWithAlteredPathFlags = GetLoadWithAlteredSearchPathFlag(); + DWORD loadLibrarySearchFlags = 0; +#ifdef TARGET_WINDOWS + loadLibrarySearchFlags = LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR + | LOAD_LIBRARY_SEARCH_APPLICATION_DIR + | LOAD_LIBRARY_SEARCH_USER_DIRS + | LOAD_LIBRARY_SEARCH_SYSTEM32 + | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS; +#endif bool libNameIsRelativePath = Path::IsRelative(wszLibName); // P/Invokes are often declared with variations on the actual library name. @@ -689,14 +698,8 @@ namespace if (!libNameIsRelativePath) { - DWORD flags = loadWithAlteredPathFlags; - if ((dllImportSearchPathFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) != 0) - { - // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR is the only flag affecting absolute path. Don't OR the flags - // unconditionally as all absolute path P/Invokes could then lose LOAD_WITH_ALTERED_SEARCH_PATH. - flags |= dllImportSearchPathFlags; - } - + // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set. + DWORD flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags); hmod = LocalLoadLibraryHelper(currLibNameVariation, flags, pErrorTracker); if (hmod != NULL) { @@ -705,7 +708,9 @@ namespace } else if ((callingAssembly != nullptr) && searchAssemblyDirectory) { - hmod = LoadFromPInvokeAssemblyDirectory(callingAssembly, currLibNameVariation, loadWithAlteredPathFlags | dllImportSearchPathFlags, pErrorTracker); + // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set. + DWORD flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags); + hmod = LoadFromPInvokeAssemblyDirectory(callingAssembly, currLibNameVariation, flags, pErrorTracker); if (hmod != NULL) { return hmod;