From 71d8f118da24bb5a31f406e5fba222a324913b05 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sat, 28 Aug 2010 11:22:37 +0000 Subject: [PATCH] * loadlib.h: New header implementing safe LoadLibrary calls. Include throughout files using LoadLibrary function. * cygcheck.cc (dump_sysinfo): Retrieve kernel32.dll handle via GetModuleHandle, rather than using LoadLibrary. * cygpath.cc (get_long_name): Ditto. (do_sysfolders): Append .dll suffix in LoadLibrary call. * ldh.cc (WinMain): Use LoadLibraryExW with DONT_RESOLVE_DLL_REFERENCES to avoid loading malicious library code. * locale.cc (print_locale_with_codeset): Change way to retrieve kernel32.dll path. --- winsup/utils/ChangeLog | 13 ++++++++ winsup/utils/cygcheck.cc | 7 ++--- winsup/utils/cygpath.cc | 5 ++-- winsup/utils/ldh.cc | 2 +- winsup/utils/loadlib.h | 59 +++++++++++++++++++++++++++++++++++++ winsup/utils/locale.cc | 7 +++-- winsup/utils/mkgroup.c | 3 +- winsup/utils/mkpasswd.c | 3 +- winsup/utils/module_info.cc | 3 +- winsup/utils/path.cc | 1 + winsup/utils/ps.cc | 3 +- winsup/utils/regtool.cc | 3 +- winsup/utils/strace.cc | 1 + 13 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 winsup/utils/loadlib.h diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index 507ddd37f..df6e1833d 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,3 +1,16 @@ +2010-08-28 Corinna Vinschen + + * loadlib.h: New header implementing safe LoadLibrary calls. + Include throughout files using LoadLibrary function. + * cygcheck.cc (dump_sysinfo): Retrieve kernel32.dll handle via + GetModuleHandle, rather than using LoadLibrary. + * cygpath.cc (get_long_name): Ditto. + (do_sysfolders): Append .dll suffix in LoadLibrary call. + * ldh.cc (WinMain): Use LoadLibraryExW with DONT_RESOLVE_DLL_REFERENCES + to avoid loading malicious library code. + * locale.cc (print_locale_with_codeset): Change way to retrieve + kernel32.dll path. + 2010-08-26 Corinna Vinschen * cygpath.cc (get_device_name): Prefer the \\.\X: DOS device for diff --git a/winsup/utils/cygcheck.cc b/winsup/utils/cygcheck.cc index 5b15cdfb2..9eb8c5653 100644 --- a/winsup/utils/cygcheck.cc +++ b/winsup/utils/cygcheck.cc @@ -1,7 +1,7 @@ /* cygcheck.cc Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -26,6 +26,7 @@ #include "cygwin/include/mntent.h" #include "cygwin/cygprops.h" #undef cygwin_internal +#include "loadlib.h" #define alloca __builtin_alloca @@ -1409,7 +1410,7 @@ dump_sysinfo () display_error ("dump_sysinfo: GetVersionEx()"); } - HMODULE k32 = LoadLibrary ("kernel32.dll"); + HMODULE k32 = GetModuleHandleW (L"kernel32.dll"); switch (osversion.dwPlatformId) { @@ -1838,8 +1839,6 @@ dump_sysinfo () name); } - if (!FreeLibrary (k32)) - display_error ("dump_sysinfo: FreeLibrary()"); SetErrorMode (prev_mode); if (givehelp) { diff --git a/winsup/utils/cygpath.cc b/winsup/utils/cygpath.cc index 449c5436e..63606a9df 100644 --- a/winsup/utils/cygpath.cc +++ b/winsup/utils/cygpath.cc @@ -28,6 +28,7 @@ details. */ #include #include #include "wide_path.h" +#include "loadlib.h" static const char version[] = "$Revision$"; @@ -452,7 +453,7 @@ get_long_name (const char *filename, DWORD& len) { char *sbuf; wchar_t buf[32768]; - static HINSTANCE k32 = LoadLibrary ("kernel32.dll"); + static HINSTANCE k32 = GetModuleHandleW (L"kernel32.dll"); static DWORD (WINAPI *GetLongPathName) (LPCWSTR, LPWSTR, DWORD) = (DWORD (WINAPI *) (LPCWSTR, LPWSTR, DWORD)) GetProcAddress (k32, "GetLongPathNameW"); if (!GetLongPathName) @@ -610,7 +611,7 @@ do_sysfolders (char option) break; case 'H': - k32 = LoadLibrary ("userenv"); + k32 = LoadLibrary ("userenv.dll"); if (k32) GetProfilesDirectoryAPtrW = (BOOL (*) (LPWSTR, LPDWORD)) GetProcAddress (k32, "GetProfilesDirectoryW"); diff --git a/winsup/utils/ldh.cc b/winsup/utils/ldh.cc index 7bea569f0..db0449f8d 100644 --- a/winsup/utils/ldh.cc +++ b/winsup/utils/ldh.cc @@ -11,7 +11,7 @@ WinMain(HINSTANCE, HINSTANCE, LPSTR, int) cmd += 4; break; } - if (!*cmd || !LoadLibraryW (cmd)) + if (!*cmd || !LoadLibraryExW (cmd, NULL, DONT_RESOLVE_DLL_REFERENCES)) ExitProcess (0x0100); ExitProcess (0x0000); } diff --git a/winsup/utils/loadlib.h b/winsup/utils/loadlib.h new file mode 100644 index 000000000..405b4b28d --- /dev/null +++ b/winsup/utils/loadlib.h @@ -0,0 +1,59 @@ +/* loadlib.h + + Copyright 2010 Red Hat, Inc. + + This file is part of Cygwin. + + This software is a copyrighted work licensed under the terms of the + Cygwin license. Please consult the file "CYGWIN_LICENSE" for + details. */ + +#ifndef _LOADLIB_H +#define _LOADLIB_H + +#include +#include + +/* Load all system libs from the windows system directory by prepending the + full path. This doesn't work for loadling cygwin1.dll. For this case, + instead of prepending the path, make sure that the CWD is removed from + the DLL search path, if possible (XP SP1++, Vista++). */ +static HMODULE +_load_sys_library (const wchar_t *dll) +{ + static BOOL (*set_dll_directory)(LPCWSTR); + static WCHAR sysdir[MAX_PATH]; + static UINT sysdir_len; + + WCHAR dllpath[MAX_PATH]; + + if (!sysdir_len) + { + sysdir_len = GetSystemDirectoryW (sysdir, MAX_PATH); + sysdir[sysdir_len++] = L'\\'; + sysdir[sysdir_len] = L'\0'; + } + if (!set_dll_directory) + { + HMODULE k32 = GetModuleHandleW (L"kernel32.dll"); + if (k32) + set_dll_directory = (BOOL (*)(LPCWSTR)) + GetProcAddress (k32, "SetDllDirectoryW"); + if (!set_dll_directory) + set_dll_directory = (BOOL (*)(LPCWSTR)) -1; + else + set_dll_directory (L""); + } + + if (wcscmp (dll, L"cygwin1.dll") == 0) + return LoadLibraryExW (L"cygwin1.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + + wcscpy (dllpath, sysdir); + wcscpy (dllpath + sysdir_len, dll); + return LoadLibraryExW (dllpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); +} + +#define LoadLibraryW(d) _load_sys_library(d) +#define LoadLibraryA(d) _load_sys_library(L##d) + +#endif /* _LOADLIB_H */ diff --git a/winsup/utils/locale.cc b/winsup/utils/locale.cc index 8dbfd9b30..d6d1064a7 100644 --- a/winsup/utils/locale.cc +++ b/winsup/utils/locale.cc @@ -126,9 +126,10 @@ print_locale_with_codeset (int verbose, loc_t *locale, bool utf8, if (!sysroot) { char sysbuf[PATH_MAX]; - stpcpy (stpcpy (sysbuf, getenv ("SYSTEMROOT")), - "\\system32\\kernel32.dll"); - sysroot = (const char *) cygwin_create_path (CCP_WIN_A_TO_POSIX, sysbuf); + HMODULE k32 = GetModuleHandleW (L"kernel32.dll"); + if (GetModuleFileName (k32, sysbuf, PATH_MAX)) + sysroot = (const char *) cygwin_create_path (CCP_WIN_A_TO_POSIX, + sysbuf); if (!sysroot) sysroot = "kernel32.dll"; } diff --git a/winsup/utils/mkgroup.c b/winsup/utils/mkgroup.c index 19b679ee1..12fe7b957 100644 --- a/winsup/utils/mkgroup.c +++ b/winsup/utils/mkgroup.c @@ -1,7 +1,7 @@ /* mkgroup.c: Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008, 2009 Red Hat, Inc. + 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -28,6 +28,7 @@ #include #include #include +#include "loadlib.h" #define print_win_error(x) _print_win_error(x, __LINE__) diff --git a/winsup/utils/mkpasswd.c b/winsup/utils/mkpasswd.c index 36c462267..9b0d36292 100644 --- a/winsup/utils/mkpasswd.c +++ b/winsup/utils/mkpasswd.c @@ -1,7 +1,7 @@ /* mkpasswd.c: Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, - 2008, 2009 Red Hat, Inc. + 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -28,6 +28,7 @@ #include #include #include +#include "loadlib.h" #define print_win_error(x) _print_win_error(x, __LINE__) diff --git a/winsup/utils/module_info.cc b/winsup/utils/module_info.cc index c0e7079cc..1522b50b3 100644 --- a/winsup/utils/module_info.cc +++ b/winsup/utils/module_info.cc @@ -1,6 +1,6 @@ /* module_info.cc - Copyright 1999,2000,2001 Red Hat, Inc. + Copyright 1999,2000,2001,2010 Red Hat, Inc. Written by Egor Duda @@ -13,6 +13,7 @@ details. */ #include #include #include +#include "loadlib.h" static int psapi_loaded = 0; static HMODULE psapi_module_handle = NULL; diff --git a/winsup/utils/path.cc b/winsup/utils/path.cc index da40b340d..8178eb45a 100644 --- a/winsup/utils/path.cc +++ b/winsup/utils/path.cc @@ -29,6 +29,7 @@ details. */ #ifdef FSTAB_ONLY #include #endif +#include "loadlib.h" #ifndef FSTAB_ONLY /* Used when treating / and \ as equivalent. */ diff --git a/winsup/utils/ps.cc b/winsup/utils/ps.cc index 0b317d2d8..30152eb3a 100644 --- a/winsup/utils/ps.cc +++ b/winsup/utils/ps.cc @@ -1,7 +1,7 @@ /* ps.cc Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2008, 2009 Red Hat, Inc. + 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -23,6 +23,7 @@ details. */ #include #include #include +#include "loadlib.h" /* Maximum possible path length under NT. There's no official define for that value. Note that PATH_MAX is only 4K. */ diff --git a/winsup/utils/regtool.cc b/winsup/utils/regtool.cc index d8a492c37..c51479d60 100644 --- a/winsup/utils/regtool.cc +++ b/winsup/utils/regtool.cc @@ -1,7 +1,7 @@ /* regtool.cc Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009 Red Hat Inc. + 2009, 2010 Red Hat Inc. This file is part of Cygwin. @@ -19,6 +19,7 @@ details. */ #define WINVER 0x0502 #include #include +#include "loadlib.h" #define DEFAULT_KEY_SEPARATOR '\\' diff --git a/winsup/utils/strace.cc b/winsup/utils/strace.cc index 607137e11..2eb3b82db 100644 --- a/winsup/utils/strace.cc +++ b/winsup/utils/strace.cc @@ -26,6 +26,7 @@ details. */ #include "cygwin/include/sys/cygwin.h" #include "path.h" #undef cygwin_internal +#include "loadlib.h" /* we *know* we're being built with GCC */ #define alloca __builtin_alloca