This is the mail archive of the
cygwin-cvs@cygwin.com
mailing list for the Cygwin project.
[newlib-cygwin] Try loading with safe path using LOAD_LIBRARY_SEARCH_SYSTEM32 first
- From: Corinna Vinschen <corinna at sourceware dot org>
- To: cygwin-cvs at sourceware dot org
- Date: 12 Jan 2016 14:25:24 -0000
- Subject: [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
};