From a8d291c0c01ec9696e14417ade7c30d8f2056366 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 29 Aug 2017 15:46:50 +0200 Subject: [PATCH] kernel32: Implement safe search mode for SearchPath. Signed-off-by: Alexandre Julliard --- dlls/kernel32/kernel_private.h | 2 +- dlls/kernel32/module.c | 7 ++-- dlls/kernel32/path.c | 77 ++++++++++++++++++++++++++++++++-- dlls/kernel32/process.c | 2 +- include/winbase.h | 7 ++++ 5 files changed, 85 insertions(+), 10 deletions(-) diff --git a/dlls/kernel32/kernel_private.h b/dlls/kernel32/kernel_private.h index 76611d74fae..73829562879 100644 --- a/dlls/kernel32/kernel_private.h +++ b/dlls/kernel32/kernel_private.h @@ -89,7 +89,7 @@ struct binary_info }; /* module.c */ -extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module ) DECLSPEC_HIDDEN; +extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module, int safe_mode ) DECLSPEC_HIDDEN; extern void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info ) DECLSPEC_HIDDEN; extern BOOL NLS_IsUnicodeOnlyLcid(LCID) DECLSPEC_HIDDEN; diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 9bd11c77b4d..02c94c5f3ff 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -921,7 +921,7 @@ static inline WCHAR *append_path( WCHAR *p, const WCHAR *str ) * Compute the load path to use for a given dll. * Returned pointer must be freed by caller. */ -WCHAR *MODULE_get_dll_load_path( LPCWSTR module ) +WCHAR *MODULE_get_dll_load_path( LPCWSTR module, int safe_mode ) { static const WCHAR pathW[] = {'P','A','T','H',0}; static const WCHAR dotW[] = {'.',0}; @@ -929,7 +929,6 @@ WCHAR *MODULE_get_dll_load_path( LPCWSTR module ) const WCHAR *system_path = get_dll_system_path(); const WCHAR *mod_end = NULL; UNICODE_STRING name, value; - BOOL safe_mode; WCHAR *p, *ret; int len = 0, path_len = 0; @@ -958,7 +957,7 @@ WCHAR *MODULE_get_dll_load_path( LPCWSTR module ) path_len = value.Length; RtlEnterCriticalSection( &dlldir_section ); - safe_mode = get_dll_safe_mode(); + if (safe_mode == -1) safe_mode = get_dll_safe_mode(); if (dll_directory) len += strlenW(dll_directory) + 1; else len += 2; /* current directory */ if ((p = ret = HeapAlloc( GetProcessHeap(), 0, path_len + len * sizeof(WCHAR) ))) @@ -1137,7 +1136,7 @@ static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags ) if (flags & load_library_search_flags) load_path = get_dll_load_path_search_flags( libname->Buffer, flags ); else - load_path = MODULE_get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL ); + load_path = MODULE_get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL, -1 ); if (!load_path) return 0; if (flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)) diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c index ec7c53b34cc..a3897431717 100644 --- a/dlls/kernel32/path.c +++ b/dlls/kernel32/path.c @@ -43,6 +43,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(file); #define MAX_PATHNAME_LEN 1024 +static int path_safe_mode = -1; /* path mode set by SetSearchPathMode */ /* check if a file name is for an executable file (.exe or .com) */ static inline BOOL is_executable( const WCHAR *name ) @@ -752,6 +753,51 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR } +/*********************************************************************** + * get_path_safe_mode + */ +static BOOL get_path_safe_mode(void) +{ + static const WCHAR keyW[] = {'\\','R','e','g','i','s','t','r','y','\\', + 'M','a','c','h','i','n','e','\\', + 'S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\', + 'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r',0}; + static const WCHAR valueW[] = {'S','a','f','e','P','r','o','c','e','s','s','S','e','a','r','c','h','M','o','d','e',0}; + + if (path_safe_mode == -1) + { + char buffer[offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data[sizeof(DWORD)])]; + KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + HANDLE hkey; + DWORD size = sizeof(buffer); + BOOL mode = FALSE; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + RtlInitUnicodeString( &nameW, keyW ); + if (!NtOpenKey( &hkey, KEY_READ, &attr )) + { + RtlInitUnicodeString( &nameW, valueW ); + if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, buffer, size, &size ) && + info->Type == REG_DWORD && info->DataLength == sizeof(DWORD)) + mode = !!*(DWORD *)info->Data; + NtClose( hkey ); + } + InterlockedCompareExchange( &path_safe_mode, mode, -1 ); + } + return path_safe_mode != 0; +} + + /*********************************************************************** * contains_pathW * @@ -991,7 +1037,7 @@ DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen, } else { - if ((dll_path = MODULE_get_dll_load_path( NULL ))) + if ((dll_path = MODULE_get_dll_load_path( NULL, get_path_safe_mode() ))) { ret = RtlDosSearchPath_U( dll_path, name, NULL, buflen * sizeof(WCHAR), buffer, lastpart ) / sizeof(WCHAR); @@ -2075,9 +2121,32 @@ BOOL WINAPI CheckNameLegalDOS8Dot3W(const WCHAR *name, char *oemname, DWORD oemn /************************************************************************* * SetSearchPathMode (KERNEL32.@) */ -BOOL WINAPI SetSearchPathMode(DWORD flags) +BOOL WINAPI SetSearchPathMode( DWORD flags ) { - FIXME("(%x): stub\n", flags); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + int val; + + switch (flags) + { + case BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE: + val = 1; + break; + case BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE: + val = 0; + break; + case BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT: + InterlockedExchange( &path_safe_mode, 2 ); + return TRUE; + default: + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + for (;;) + { + int prev = path_safe_mode; + if (prev == 2) break; /* permanently set */ + if (InterlockedCompareExchange( &path_safe_mode, val, prev ) == prev) return TRUE; + } + SetLastError( ERROR_ACCESS_DENIED ); return FALSE; } diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 909754254e3..292317ce00e 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -1258,7 +1258,7 @@ void CDECL __wine_kernel_init(void) debugstr_w(main_exe_name), debugstr_w(__wine_main_wargv[0]) ); RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath, - MODULE_get_dll_load_path(main_exe_name) ); + MODULE_get_dll_load_path( main_exe_name, -1 )); if (boot_events[0]) { diff --git a/include/winbase.h b/include/winbase.h index f6a28c3e47b..a4d545ecf39 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -1005,6 +1005,12 @@ DECL_WINELIB_TYPE_AW(ENUMRESLANGPROC) #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2 #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4 +/* flags for SetSearchPathMode */ +#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE 0x00001 +#define BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE 0x10000 +#define BASE_SEARCH_PATH_PERMANENT 0x08000 +#define BASE_SEARCH_PATH_INVALID_FLAGS (~0x18001) + typedef PLDT_ENTRY LPLDT_ENTRY; typedef enum _GET_FILEEX_INFO_LEVELS { @@ -2551,6 +2557,7 @@ WINBASEAPI BOOL WINAPI SetProcessAffinityMask(HANDLE,DWORD_PTR); WINBASEAPI BOOL WINAPI SetProcessPriorityBoost(HANDLE,BOOL); WINBASEAPI BOOL WINAPI SetProcessShutdownParameters(DWORD,DWORD); WINBASEAPI BOOL WINAPI SetProcessWorkingSetSize(HANDLE,SIZE_T,SIZE_T); +WINBASEAPI BOOL WINAPI SetSearchPathMode(DWORD); WINADVAPI BOOL WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,SECURITY_DESCRIPTOR_CONTROL,SECURITY_DESCRIPTOR_CONTROL); WINADVAPI BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,BOOL,PACL,BOOL); WINADVAPI BOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR,PSID,BOOL);