This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] Try loading with safe path using LOAD_LIBRARY_SEARCH_SYSTEM32 first


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=15d6f564cde65fedf46423eea0a64d17b299bb2f

commit 15d6f564cde65fedf46423eea0a64d17b299bb2f
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue Jan 12 15:23:14 2016 +0100

    Try loading with safe path using LOAD_LIBRARY_SEARCH_SYSTEM32 first
    
    	* autoload.cc (dll_load): Move safe loading from std_dll_init here.
    	Add code to handle systems supporting LOAD_LIBRARY_SEARCH flags.
    	Add comments to explain what the code is doing.  Fix up comment
    	preceeding this function.
    	(std_dll_init): Move safe loading code to dll_load.
    	* wincap.h (wincaps::has_load_lib_search_flags): New element.
            * wincap.cc: Implement above element throughout.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/autoload.cc | 52 +++++++++++++++++++++++++++++++----------------
 winsup/cygwin/wincap.cc   |  7 +++++++
 winsup/cygwin/wincap.h    |  2 ++
 3 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 836597d..7158e95 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -333,20 +333,44 @@ union retchain
 };
 
 
-/* This function is a workaround for the problem reported here:
+/* This function handles the problem described here:
+
+  http://www.microsoft.com/technet/security/advisory/2269637.mspx
+  https://msdn.microsoft.com/library/ff919712
+
+  It also contains a workaround for the problem reported here:
   http://cygwin.com/ml/cygwin/2011-02/msg00552.html
   and discussed here:
   http://cygwin.com/ml/cygwin-developers/2011-02/threads.html#00007
 
   To wit: winmm.dll calls FreeLibrary in its DllMain and that can result
-  in LoadLibraryExW returning an ERROR_INVALID_ADDRESS.  */
+  in LoadLibraryExW returning an ERROR_INVALID_ADDRESS. */
 static __inline bool
-dll_load (HANDLE& handle, WCHAR *name)
+dll_load (HANDLE& handle, PWCHAR name)
 {
-  HANDLE h = LoadLibraryW (name);
-  if (!h && handle && wincap.use_dont_resolve_hack ()
-      && GetLastError () == ERROR_INVALID_ADDRESS)
-    h = LoadLibraryExW (name, NULL, DONT_RESOLVE_DLL_REFERENCES);
+  HANDLE h;
+
+  /* On systems supporting LOAD_LIBRARY_SEARCH flags, try to load
+     explicitely from the system dir first. */
+  if (wincap.has_load_lib_search_flags ())
+    h = LoadLibraryExW (name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+  if (!h)
+    {
+      WCHAR dll_path[MAX_PATH];
+
+      /* If that failed, try loading with full path, which sometimes
+	 fails for no good reason. */
+      wcpcpy (wcpcpy (dll_path, windows_system_directory), name);
+      h = LoadLibraryW (dll_path);
+      /* If that failed according to the second problem outlined in the
+	 comment preceeding this function. */
+      if (!h && handle && wincap.use_dont_resolve_hack ()
+	  && GetLastError () == ERROR_INVALID_ADDRESS)
+	h = LoadLibraryExW (dll_path, NULL, DONT_RESOLVE_DLL_REFERENCES);
+      /* Last resort: Try loading just by name. */
+      if (!h)
+	h = LoadLibraryW (name);
+    }
   if (!h)
     return false;
   handle = h;
@@ -420,18 +444,15 @@ std_dll_init ()
     {
       fenv_t fpuenv;
       fegetenv (&fpuenv);
-      WCHAR dll_path[MAX_PATH];
       DWORD err = ERROR_SUCCESS;
       int i;
-      /* http://www.microsoft.com/technet/security/advisory/2269637.mspx */
-      wcpcpy (wcpcpy (dll_path, windows_system_directory), dll->name);
       /* MSDN seems to imply that LoadLibrary can fail mysteriously, so,
 	 since there have been reports of this in the mailing list, retry
 	 several times before giving up. */
       for (i = 1; i <= RETRY_COUNT; i++)
 	{
 	  /* If loading the library succeeds, just leave the loop. */
-	  if (dll_load (dll->handle, dll_path))
+	  if (dll_load (dll->handle, dll->name))
 	    break;
 	  /* Otherwise check error code returned by LoadLibrary.  If the
 	     error code is neither NOACCESS nor DLL_INIT_FAILED, break out
@@ -444,15 +465,10 @@ std_dll_init ()
 	}
       if ((uintptr_t) dll->handle <= 1)
 	{
-	  /* If LoadLibrary with full path returns one of the weird errors
-	     reported on the Cygwin mailing list, retry with only the DLL
-	     name.  Only do this when the above retry loop has been exhausted. */
-	  if (i > RETRY_COUNT && dll_load (dll->handle, dll->name))
-	    /* got it with the fallback */;
-	  else if ((func->decoration & 1))
+	  if ((func->decoration & 1))
 	    dll->handle = INVALID_HANDLE_VALUE;
 	  else
-	    api_fatal ("unable to load %W, %E", dll_path);
+	    api_fatal ("unable to load %W, %E", dll->name);
 	}
       fesetenv (&fpuenv);
     }
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 201bd25..f06f8f6 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -52,6 +52,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
   has_processor_groups:false,
   has_broken_prefetchvm:false,
   has_new_pebteb_region:false,
+  has_load_lib_search_flags:false,
 };
 
 wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -86,6 +87,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
   has_processor_groups:false,
   has_broken_prefetchvm:false,
   has_new_pebteb_region:false,
+  has_load_lib_search_flags:false,
 };
 
 wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -120,6 +122,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
   has_processor_groups:false,
   has_broken_prefetchvm:false,
   has_new_pebteb_region:false,
+  has_load_lib_search_flags:true,
 };
 
 wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -154,6 +157,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
   has_processor_groups:true,
   has_broken_prefetchvm:false,
   has_new_pebteb_region:false,
+  has_load_lib_search_flags:true,
 };
 
 wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -188,6 +192,7 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
   has_processor_groups:true,
   has_broken_prefetchvm:false,
   has_new_pebteb_region:false,
+  has_load_lib_search_flags:true,
 };
 
 wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -222,6 +227,7 @@ wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
   has_processor_groups:true,
   has_broken_prefetchvm:true,
   has_new_pebteb_region:false,
+  has_load_lib_search_flags:true,
 };
 
 wincaps wincap_10_1511 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -256,6 +262,7 @@ wincaps wincap_10_1511 __attribute__((section (".cygwin_dll_common"), shared)) =
   has_processor_groups:true,
   has_broken_prefetchvm:false,
   has_new_pebteb_region:true,
+  has_load_lib_search_flags:true,
 };
 
 wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 4508974..ebebd83 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -45,6 +45,7 @@ struct wincaps
   unsigned has_processor_groups				: 1;
   unsigned has_broken_prefetchvm			: 1;
   unsigned has_new_pebteb_region			: 1;
+  unsigned has_load_lib_search_flags			: 1;
 };
 
 class wincapc
@@ -104,6 +105,7 @@ public:
   bool	IMPLEMENT (has_processor_groups)
   bool	IMPLEMENT (has_broken_prefetchvm)
   bool	IMPLEMENT (has_new_pebteb_region)
+  bool	IMPLEMENT (has_load_lib_search_flags)
 
 #undef IMPLEMENT
 };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]