From 08fbd82e36254ae06207b62732bc50ee4632a07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Baptiste=20B=C3=A9drune?= Date: Tue, 21 Sep 2021 17:02:24 +0200 Subject: [PATCH] [Backport] Windows: Restrict path for dynamic library loading Based on https://github.com/libusb/libusb/commit/c3deb6dd6440fd467ce12965742f2d7a228b3bbe --- libusb/Makefile.am | 2 +- libusb/os/windows_common.c | 59 ++++++++++++++++ libusb/os/windows_common.h | 48 ++++++------- libusb/os/windows_usb.c | 90 ++++++++++++------------- msvc/libusb_dll.dsp | 4 ++ msvc/libusb_dll_2005.vcproj | 4 ++ msvc/libusb_dll_2010.vcxproj | 1 + msvc/libusb_dll_2010.vcxproj.filters | 3 + msvc/libusb_dll_2012.vcxproj | 1 + msvc/libusb_dll_2012.vcxproj.filters | 3 + msvc/libusb_dll_2013.vcxproj | 1 + msvc/libusb_sources | 1 + msvc/libusb_static.dsp | 4 ++ msvc/libusb_static_2005.vcproj | 4 ++ msvc/libusb_static_2010.vcxproj | 1 + msvc/libusb_static_2010.vcxproj.filters | 3 + msvc/libusb_static_2012.vcxproj | 1 + msvc/libusb_static_2012.vcxproj.filters | 3 + msvc/libusb_static_2013.vcxproj | 1 + 19 files changed, 162 insertions(+), 72 deletions(-) create mode 100644 libusb/os/windows_common.c diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 80e3705e5..142330d63 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -15,7 +15,7 @@ WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \ $(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \ $(POSIX_POLL_SRC) \ - os/threads_posix.c os/threads_windows.c \ + os/threads_posix.c os/threads_windows.c os/windows_common.c \ os/linux_udev.c os/linux_netlink.c if OS_LINUX diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c new file mode 100644 index 000000000..c1aa5e1b8 --- /dev/null +++ b/libusb/os/windows_common.c @@ -0,0 +1,59 @@ +/* + * windows backend for libusb 1.0 + * Copyright © 2009-2012 Pete Batard + * With contributions from Michael Plante, Orin Eman et al. + * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software + * Hash table functions adapted from glibc, by Ulrich Drepper et al. + * Major code testing contribution by Xiaofan Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +#include "libusbi.h" +#include "windows_common.h" + +/* + * Dynamically loads a DLL from the Windows system directory. Unlike the + * LoadLibraryA() function, this function will not search through any + * directories to try and find the library. + */ +HMODULE load_system_library(struct libusb_context *ctx, const char *name) +{ + char library_path[MAX_PATH]; + char *filename_start; + UINT length; + + length = GetSystemDirectoryA(library_path, sizeof(library_path)); + if ((length == 0) || (length >= (UINT)sizeof(library_path))) { + usbi_err(ctx, "program assertion failed - could not get system directory"); + return NULL; + } + + filename_start = library_path + length; + // Append '\' + name + ".dll" + NUL + length += 1 + strlen(name) + 4 + 1; + if (length >= (UINT)sizeof(library_path)) { + usbi_err(ctx, "program assertion failed - library path buffer overflow"); + return NULL; + } + + sprintf(filename_start, "\\%s.dll", name); + return LoadLibraryA(library_path); +} diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 1249ce391..85069b904 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -73,36 +73,36 @@ #ifndef _WIN32_WCE #define DLL_STRINGIFY(dll) #dll #define DLL_GET_MODULE_HANDLE(dll) GetModuleHandleA(DLL_STRINGIFY(dll)) -#define DLL_LOAD_LIBRARY(dll) LoadLibraryA(DLL_STRINGIFY(dll)) #else #define DLL_STRINGIFY(dll) L#dll #define DLL_GET_MODULE_HANDLE(dll) GetModuleHandle(DLL_STRINGIFY(dll)) -#define DLL_LOAD_LIBRARY(dll) LoadLibrary(DLL_STRINGIFY(dll)) #endif -#define DLL_LOAD_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ - do { \ - HMODULE h = DLL_GET_MODULE_HANDLE(dll); \ - if (!h) \ - h = DLL_LOAD_LIBRARY(dll); \ - if (!h) { \ - if (ret_on_failure) { return LIBUSB_ERROR_NOT_FOUND; } \ - else { break; } \ - } \ - prefixname = (__dll_##name##_t)GetProcAddress(h, \ - DLL_STRINGIFY(name)); \ - if (prefixname) break; \ - prefixname = (__dll_##name##_t)GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ - if (prefixname) break; \ - prefixname = (__dll_##name##_t)GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ - if (prefixname) break; \ - if(ret_on_failure) \ - return LIBUSB_ERROR_NOT_FOUND; \ +#define DLL_LOAD_PREFIXNAME(ctx, dll, prefixname, name, ret_on_failure) \ + do { \ + HMODULE h = DLL_GET_MODULE_HANDLE(dll); \ + if (!h) \ + h = load_system_library(ctx, DLL_STRINGIFY(dll)); \ + if (!h) { \ + if (ret_on_failure) { return LIBUSB_ERROR_NOT_FOUND; } \ + else { break; } \ + } \ + prefixname = (__dll_##name##_t)GetProcAddress(h, \ + DLL_STRINGIFY(name)); \ + if (prefixname) break; \ + prefixname = (__dll_##name##_t)GetProcAddress(h, \ + DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ + if (prefixname) break; \ + prefixname = (__dll_##name##_t)GetProcAddress(h, \ + DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ + if (prefixname) break; \ + if(ret_on_failure) \ + return LIBUSB_ERROR_NOT_FOUND; \ } while(0) #define DLL_DECLARE(api, ret, name, args) DLL_DECLARE_PREFIXNAME(api, ret, name, name, args) -#define DLL_LOAD(dll, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, name, name, ret_on_failure) +#define DLL_LOAD(ctx, dll, name, ret_on_failure) DLL_LOAD_PREFIXNAME(ctx, dll, name, name, ret_on_failure) #define DLL_DECLARE_PREFIXED(api, ret, prefix, name, args) DLL_DECLARE_PREFIXNAME(api, ret, prefix##name, name, args) -#define DLL_LOAD_PREFIXED(dll, prefix, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, prefix##name, name, ret_on_failure) +#define DLL_LOAD_PREFIXED(ctx, dll, prefix, name, ret_on_failure) DLL_LOAD_PREFIXNAME(ctx, dll, prefix##name, name, ret_on_failure) + +HMODULE load_system_library(struct libusb_context *ctx, const char *name); diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 31389af04..e0fa868e1 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -306,31 +306,31 @@ static char *sanitize_path(const char *path) /* * Cfgmgr32, User32, OLE32 and SetupAPI DLL functions */ -static int init_dlls(void) +static int init_dlls(struct libusb_context *ctx) { - DLL_LOAD(Cfgmgr32.dll, CM_Get_Parent, TRUE); - DLL_LOAD(Cfgmgr32.dll, CM_Get_Child, TRUE); - DLL_LOAD(Cfgmgr32.dll, CM_Get_Sibling, TRUE); - DLL_LOAD(Cfgmgr32.dll, CM_Get_Device_IDA, TRUE); - DLL_LOAD(Cfgmgr32.dll, CM_Get_Device_ID_Size, TRUE); + DLL_LOAD(ctx, Cfgmgr32.dll, CM_Get_Parent, TRUE); + DLL_LOAD(ctx, Cfgmgr32.dll, CM_Get_Child, TRUE); + DLL_LOAD(ctx, Cfgmgr32.dll, CM_Get_Sibling, TRUE); + DLL_LOAD(ctx, Cfgmgr32.dll, CM_Get_Device_IDA, TRUE); + DLL_LOAD(ctx, Cfgmgr32.dll, CM_Get_Device_ID_Size, TRUE); // Prefixed to avoid conflict with header files - DLL_LOAD_PREFIXED(OLE32.dll, p, CLSIDFromString, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetClassDevsA, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetClassDevsExA, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiEnumDeviceInfo, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiEnumDeviceInterfaces, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetDeviceInterfaceDetailA, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiDestroyDeviceInfoList, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDevRegKey, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiGetDeviceRegistryPropertyA, TRUE); - DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); - DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegQueryValueExW, TRUE); - DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegCloseKey, TRUE); - DLL_LOAD_PREFIXED(User32.dll, p, RegisterClassExA, TRUE); - DLL_LOAD_PREFIXED(User32.dll, p, RegisterDeviceNotificationA, TRUE); - DLL_LOAD_PREFIXED(User32.dll, p, UnregisterDeviceNotification, TRUE); - DLL_LOAD_PREFIXED(User32.dll, p, UnregisterClassA, TRUE); + DLL_LOAD_PREFIXED(ctx, OLE32.dll, p, CLSIDFromString, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiGetClassDevsA, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiGetClassDevsExA, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiEnumDeviceInfo, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiEnumDeviceInterfaces, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiGetDeviceInterfaceDetailA, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiDestroyDeviceInfoList, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiOpenDevRegKey, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiGetDeviceRegistryPropertyA, TRUE); + DLL_LOAD_PREFIXED(ctx, SetupAPI.dll, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); + DLL_LOAD_PREFIXED(ctx, AdvAPI32.dll, p, RegQueryValueExW, TRUE); + DLL_LOAD_PREFIXED(ctx, AdvAPI32.dll, p, RegCloseKey, TRUE); + DLL_LOAD_PREFIXED(ctx, User32.dll, p, RegisterClassExA, TRUE); + DLL_LOAD_PREFIXED(ctx, User32.dll, p, RegisterDeviceNotificationA, TRUE); + DLL_LOAD_PREFIXED(ctx, User32.dll, p, UnregisterDeviceNotification, TRUE); + DLL_LOAD_PREFIXED(ctx, User32.dll, p, UnregisterClassA, TRUE); return LIBUSB_SUCCESS; } @@ -991,10 +991,7 @@ static BOOL is_x64(void) BOOL ret = FALSE; // Detect if we're running a 32 or 64 bit system if (sizeof(uintptr_t) < 8) { - DLL_LOAD_PREFIXED(Kernel32.dll, p, IsWow64Process, FALSE); - if (pIsWow64Process != NULL) { - (*pIsWow64Process)(GetCurrentProcess(), &ret); - } + IsWow64Process(GetCurrentProcess(), &ret); } else { ret = TRUE; } @@ -1703,7 +1700,7 @@ static int windows_init(struct libusb_context *ctx) // NB: concurrent usage supposes that init calls are equally balanced with // exit calls. If init is called more than exit, we will not exit properly if ( ++concurrent_usage == 0 ) { // First init? - get_windows_version(); + get_windows_version(ctx); usbi_dbg(windows_version_str); if (windows_version == WINDOWS_UNSUPPORTED) { usbi_err(ctx, "This version of Windows is NOT supported"); @@ -1722,7 +1719,7 @@ static int windows_init(struct libusb_context *ctx) } // Load DLL imports - if (init_dlls() != LIBUSB_SUCCESS) { + if (init_dlls(ctx) != LIBUSB_SUCCESS) { usbi_err(ctx, "could not resolve DLL functions"); return LIBUSB_ERROR_NOT_FOUND; } @@ -3430,7 +3427,6 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { }, }; - /* * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions */ @@ -3448,13 +3444,13 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx) h = GetModuleHandleA("libusbK"); if (h == NULL) { - h = LoadLibraryA("libusbK"); + h = load_system_library(ctx, "libusbK"); } if (h == NULL) { usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); h = GetModuleHandleA("WinUSB"); if (h == NULL) { - h = LoadLibraryA("WinUSB"); + h = load_system_library(ctx, "WinUSB"); } if (h == NULL) { usbi_warn(ctx, "WinUSB DLL is not available either,\n" "you will not be able to access devices outside of enumeration"); @@ -4549,22 +4545,22 @@ static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, in */ static int hid_init(int sub_api, struct libusb_context *ctx) { - DLL_LOAD(hid.dll, HidD_GetAttributes, TRUE); - DLL_LOAD(hid.dll, HidD_GetHidGuid, TRUE); - DLL_LOAD(hid.dll, HidD_GetPreparsedData, TRUE); - DLL_LOAD(hid.dll, HidD_FreePreparsedData, TRUE); - DLL_LOAD(hid.dll, HidD_GetManufacturerString, TRUE); - DLL_LOAD(hid.dll, HidD_GetProductString, TRUE); - DLL_LOAD(hid.dll, HidD_GetSerialNumberString, TRUE); - DLL_LOAD(hid.dll, HidP_GetCaps, TRUE); - DLL_LOAD(hid.dll, HidD_SetNumInputBuffers, TRUE); - DLL_LOAD(hid.dll, HidD_SetFeature, TRUE); - DLL_LOAD(hid.dll, HidD_GetFeature, TRUE); - DLL_LOAD(hid.dll, HidD_GetPhysicalDescriptor, TRUE); - DLL_LOAD(hid.dll, HidD_GetInputReport, FALSE); - DLL_LOAD(hid.dll, HidD_SetOutputReport, FALSE); - DLL_LOAD(hid.dll, HidD_FlushQueue, TRUE); - DLL_LOAD(hid.dll, HidP_GetValueCaps, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetAttributes, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetHidGuid, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetPreparsedData, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_FreePreparsedData, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetManufacturerString, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetProductString, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetSerialNumberString, TRUE); + DLL_LOAD(ctx, hid.dll, HidP_GetCaps, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_SetNumInputBuffers, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_SetFeature, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetFeature, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetPhysicalDescriptor, TRUE); + DLL_LOAD(ctx, hid.dll, HidD_GetInputReport, FALSE); + DLL_LOAD(ctx, hid.dll, HidD_SetOutputReport, FALSE); + DLL_LOAD(ctx, hid.dll, HidD_FlushQueue, TRUE); + DLL_LOAD(ctx, hid.dll, HidP_GetValueCaps, TRUE); HidD_GetHidGuid(&HID_guid); diff --git a/msvc/libusb_dll.dsp b/msvc/libusb_dll.dsp index f2b15f069..c580b0409 100644 --- a/msvc/libusb_dll.dsp +++ b/msvc/libusb_dll.dsp @@ -135,6 +135,10 @@ SOURCE=..\libusb\os\threads_windows.c # End Source File # Begin Source File +SOURCE=..\libusb\os\windows_common.c +# End Source File +# Begin Source File + SOURCE=..\libusb\os\windows_usb.c # End Source File # End Group diff --git a/msvc/libusb_dll_2005.vcproj b/msvc/libusb_dll_2005.vcproj index 82e5af56e..39b58c487 100644 --- a/msvc/libusb_dll_2005.vcproj +++ b/msvc/libusb_dll_2005.vcproj @@ -373,6 +373,10 @@ RelativePath="..\libusb\os\threads_windows.c" > + + diff --git a/msvc/libusb_dll_2010.vcxproj b/msvc/libusb_dll_2010.vcxproj index 6925b1b89..a4469820f 100644 --- a/msvc/libusb_dll_2010.vcxproj +++ b/msvc/libusb_dll_2010.vcxproj @@ -146,6 +146,7 @@ + diff --git a/msvc/libusb_dll_2010.vcxproj.filters b/msvc/libusb_dll_2010.vcxproj.filters index 7a4578c5b..f1888c655 100644 --- a/msvc/libusb_dll_2010.vcxproj.filters +++ b/msvc/libusb_dll_2010.vcxproj.filters @@ -38,6 +38,9 @@ Source Files + + Source Files + Source Files diff --git a/msvc/libusb_dll_2012.vcxproj b/msvc/libusb_dll_2012.vcxproj index adcad4ad0..8331ae9fe 100644 --- a/msvc/libusb_dll_2012.vcxproj +++ b/msvc/libusb_dll_2012.vcxproj @@ -150,6 +150,7 @@ + diff --git a/msvc/libusb_dll_2012.vcxproj.filters b/msvc/libusb_dll_2012.vcxproj.filters index ccada704b..d05913e31 100644 --- a/msvc/libusb_dll_2012.vcxproj.filters +++ b/msvc/libusb_dll_2012.vcxproj.filters @@ -35,6 +35,9 @@ Source Files + + Source Files + Source Files diff --git a/msvc/libusb_dll_2013.vcxproj b/msvc/libusb_dll_2013.vcxproj index c1b2a0a13..c9da9a241 100644 --- a/msvc/libusb_dll_2013.vcxproj +++ b/msvc/libusb_dll_2013.vcxproj @@ -150,6 +150,7 @@ + diff --git a/msvc/libusb_sources b/msvc/libusb_sources index 308a6663f..32e7d600b 100644 --- a/msvc/libusb_sources +++ b/msvc/libusb_sources @@ -34,5 +34,6 @@ SOURCES=..\core.c \ ..\hotplug.c \ threads_windows.c \ poll_windows.c \ + windows_common.c \ windows_usb.c \ ..\libusb-1.0.rc diff --git a/msvc/libusb_static.dsp b/msvc/libusb_static.dsp index afdbbeddb..59b2b8c14 100644 --- a/msvc/libusb_static.dsp +++ b/msvc/libusb_static.dsp @@ -119,6 +119,10 @@ SOURCE=..\libusb\os\threads_windows.c # End Source File # Begin Source File +SOURCE=..\libusb\os\windows_common.c +# End Source File +# Begin Source File + SOURCE=..\libusb\os\windows_usb.c # End Source File # End Group diff --git a/msvc/libusb_static_2005.vcproj b/msvc/libusb_static_2005.vcproj index f7b8e4590..c1e75f9df 100644 --- a/msvc/libusb_static_2005.vcproj +++ b/msvc/libusb_static_2005.vcproj @@ -313,6 +313,10 @@ RelativePath="..\libusb\os\poll_windows.c" > + + diff --git a/msvc/libusb_static_2010.vcxproj b/msvc/libusb_static_2010.vcxproj index 1958d1172..0bf7d5bd2 100644 --- a/msvc/libusb_static_2010.vcxproj +++ b/msvc/libusb_static_2010.vcxproj @@ -136,6 +136,7 @@ + diff --git a/msvc/libusb_static_2010.vcxproj.filters b/msvc/libusb_static_2010.vcxproj.filters index 5cd806065..1876d253f 100644 --- a/msvc/libusb_static_2010.vcxproj.filters +++ b/msvc/libusb_static_2010.vcxproj.filters @@ -32,6 +32,9 @@ Source Files + + Source Files + Source Files diff --git a/msvc/libusb_static_2012.vcxproj b/msvc/libusb_static_2012.vcxproj index 88605ba24..cc9ef806f 100644 --- a/msvc/libusb_static_2012.vcxproj +++ b/msvc/libusb_static_2012.vcxproj @@ -140,6 +140,7 @@ + diff --git a/msvc/libusb_static_2012.vcxproj.filters b/msvc/libusb_static_2012.vcxproj.filters index 5cd806065..1876d253f 100644 --- a/msvc/libusb_static_2012.vcxproj.filters +++ b/msvc/libusb_static_2012.vcxproj.filters @@ -32,6 +32,9 @@ Source Files + + Source Files + Source Files diff --git a/msvc/libusb_static_2013.vcxproj b/msvc/libusb_static_2013.vcxproj index 05b7bd863..0ccd510c6 100644 --- a/msvc/libusb_static_2013.vcxproj +++ b/msvc/libusb_static_2013.vcxproj @@ -140,6 +140,7 @@ +