diff --git a/README.md b/README.md index 05e7c92e..8065567b 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,9 @@ Wine. All those differences are also documented on the Included bug fixes and improvements ----------------------------------- -**Bug fixes and features included in the next upcoming release [1]:** +**Bug fixes and features included in the next upcoming release [2]:** +* Check architecture before trying to load libraries ([Wine Bug #38021](https://bugs.winehq.org/show_bug.cgi?id=38021)) * Forward exitcode from child process when in wineconsole diff --git a/debian/changelog b/debian/changelog index a1e0a491..a75da0f0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,6 @@ wine-staging (1.7.48) UNRELEASED; urgency=low * Added patch to forward exitcode from child process when in wineconsole. + * Added patch to check architecture before trying to load libraries. * Removed patch to allow to enable/disable InsertMode in wineconsole settings (accepted upstream). * Removed patch to improve IoGetDeviceObjectPointer stub to appease SecuROM diff --git a/patches/ntdll-DllRedirects/0005-ntdll-Implement-loader-redirection-scheme.patch b/patches/ntdll-DllRedirects/0005-ntdll-Implement-loader-redirection-scheme.patch index 58023da5..1f9b5ab2 100644 --- a/patches/ntdll-DllRedirects/0005-ntdll-Implement-loader-redirection-scheme.patch +++ b/patches/ntdll-DllRedirects/0005-ntdll-Implement-loader-redirection-scheme.patch @@ -1,4 +1,4 @@ -From ea4f613ec5b7e4cdc5cb9d850f66c194af9eb5e6 Mon Sep 17 00:00:00 2001 +From a76e0d5f4e8211975ede9f1bf65522a31114112a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 13 Dec 2014 05:34:48 +0100 Subject: ntdll: Implement loader redirection scheme. @@ -8,10 +8,10 @@ Subject: ntdll: Implement loader redirection scheme. 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index e1444d2..c392f72 100644 +index 0486517..7877f04 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c -@@ -87,6 +87,7 @@ struct builtin_load_info +@@ -85,6 +85,7 @@ struct builtin_load_info { const WCHAR *load_path; const WCHAR *filename; @@ -19,7 +19,7 @@ index e1444d2..c392f72 100644 NTSTATUS status; WINE_MODREF *wm; }; -@@ -112,7 +113,8 @@ static WINE_MODREF *cached_modref; +@@ -110,7 +111,8 @@ static WINE_MODREF *cached_modref; static WINE_MODREF *current_modref; static WINE_MODREF *last_failed_modref; @@ -29,7 +29,7 @@ index e1444d2..c392f72 100644 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved ); static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, DWORD ordinal, LPCWSTR load_path ); -@@ -438,7 +440,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS +@@ -436,7 +438,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS if (!(wm = find_basename_module( mod_name ))) { TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward ); @@ -38,7 +38,7 @@ index e1444d2..c392f72 100644 !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) { if (process_attach( wm, NULL ) != STATUS_SUCCESS) -@@ -587,7 +589,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d +@@ -585,7 +587,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d { ascii_to_unicode( buffer, name, len ); buffer[len] = 0; @@ -47,7 +47,7 @@ index e1444d2..c392f72 100644 } else /* need to allocate a larger buffer */ { -@@ -595,7 +597,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d +@@ -593,7 +595,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d if (!ptr) return NULL; ascii_to_unicode( ptr, name, len ); ptr[len] = 0; @@ -56,7 +56,7 @@ index e1444d2..c392f72 100644 RtlFreeHeap( GetProcessHeap(), 0, ptr ); } -@@ -906,7 +908,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) +@@ -909,7 +911,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) * Allocate a WINE_MODREF structure and add it to the process list * The loader_section must be locked while calling this function. */ @@ -65,7 +65,7 @@ index e1444d2..c392f72 100644 { WINE_MODREF *wm; const WCHAR *p; -@@ -929,7 +931,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename ) +@@ -932,7 +934,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename ) wm->ldr.TimeDateStamp = 0; wm->ldr.ActivationContext = 0; @@ -74,7 +74,7 @@ index e1444d2..c392f72 100644 if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++; else p = wm->ldr.FullDllName.Buffer; RtlInitUnicodeString( &wm->ldr.BaseDllName, p ); -@@ -1546,7 +1548,7 @@ static void load_builtin_callback( void *module, const char *filename ) +@@ -1549,7 +1551,7 @@ static void load_builtin_callback( void *module, const char *filename ) return; } @@ -83,7 +83,7 @@ index e1444d2..c392f72 100644 RtlFreeHeap( GetProcessHeap(), 0, fullname ); if (!wm) { -@@ -1602,8 +1604,8 @@ static void load_builtin_callback( void *module, const char *filename ) +@@ -1605,8 +1607,8 @@ static void load_builtin_callback( void *module, const char *filename ) /****************************************************************************** * load_native_dll (internal) */ @@ -94,7 +94,7 @@ index e1444d2..c392f72 100644 { void *module; HANDLE mapping; -@@ -1627,7 +1629,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file, +@@ -1630,7 +1632,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file, /* create the MODREF */ @@ -103,7 +103,7 @@ index e1444d2..c392f72 100644 { status = STATUS_NO_MEMORY; goto done; -@@ -1689,8 +1691,8 @@ done: +@@ -1692,8 +1694,8 @@ done: /*********************************************************************** * load_builtin_dll */ @@ -114,7 +114,7 @@ index e1444d2..c392f72 100644 { char error[256], dllname[MAX_PATH]; const WCHAR *name, *p; -@@ -1710,6 +1712,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file, +@@ -1713,6 +1715,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file, */ info.load_path = load_path; info.filename = NULL; @@ -122,7 +122,7 @@ index e1444d2..c392f72 100644 info.status = STATUS_SUCCESS; info.wm = NULL; -@@ -2028,14 +2031,14 @@ overflow: +@@ -2153,14 +2156,14 @@ overflow: return STATUS_BUFFER_TOO_SMALL; } @@ -137,9 +137,9 @@ index e1444d2..c392f72 100644 +static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, LPCWSTR fakemodule, + DWORD flags, WINE_MODREF** pwm ) { + BOOL data = flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE); enum loadorder loadorder; - WCHAR buffer[32]; -@@ -2072,6 +2075,25 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ +@@ -2198,6 +2201,25 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ } main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress ); @@ -165,7 +165,7 @@ index e1444d2..c392f72 100644 loadorder = get_load_order( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL, filename ); if (handle && is_fake_dll( handle )) -@@ -2094,22 +2116,22 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ +@@ -2220,22 +2242,22 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ if (!handle) nts = STATUS_DLL_NOT_FOUND; else { @@ -193,7 +193,7 @@ index e1444d2..c392f72 100644 if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT && (MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS)) { -@@ -2119,7 +2141,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ +@@ -2245,7 +2267,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ nts = STATUS_DLL_NOT_FOUND; } if (nts == STATUS_DLL_NOT_FOUND && loadorder != LO_BUILTIN) @@ -202,7 +202,7 @@ index e1444d2..c392f72 100644 break; } -@@ -2152,7 +2174,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrLoadDll(LPCWSTR path_name, DWORD flags, +@@ -2278,7 +2300,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrLoadDll(LPCWSTR path_name, DWORD flags, RtlEnterCriticalSection( &loader_section ); if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; @@ -211,7 +211,7 @@ index e1444d2..c392f72 100644 if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) { -@@ -3115,7 +3137,7 @@ void __wine_process_init(void) +@@ -3241,7 +3263,7 @@ void __wine_process_init(void) /* setup the load callback and create ntdll modref */ wine_dll_set_callback( load_builtin_callback ); @@ -221,5 +221,5 @@ index e1444d2..c392f72 100644 MESSAGE( "wine: could not load kernel32.dll, status %x\n", status ); exit(1); -- -1.9.1 +2.4.5 diff --git a/patches/ntdll-DllRedirects/definition b/patches/ntdll-DllRedirects/definition index 217c6984..530aa808 100644 --- a/patches/ntdll-DllRedirects/definition +++ b/patches/ntdll-DllRedirects/definition @@ -1,2 +1,3 @@ Fixes: Support for loader dll redirections +Depends: ntdll-Loader_Machine_Type Category: stable diff --git a/patches/ntdll-Loader_Machine_Type/0001-ntdll-Check-architecture-before-loading-module.patch b/patches/ntdll-Loader_Machine_Type/0001-ntdll-Check-architecture-before-loading-module.patch new file mode 100644 index 00000000..b4c69374 --- /dev/null +++ b/patches/ntdll-Loader_Machine_Type/0001-ntdll-Check-architecture-before-loading-module.patch @@ -0,0 +1,206 @@ +From a9e0627c59b5ddf2f91d5ceea61a0401afc27ce4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 18 Jul 2015 04:52:55 +0200 +Subject: ntdll: Check architecture before loading module. + +--- + dlls/ntdll/loader.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 131 insertions(+), 8 deletions(-) + +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index bef0ab1..0486517 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -1911,6 +1911,108 @@ done: + return status; + } + ++#if defined(__i386__) ++#define CURRENT_ARCH IMAGE_FILE_MACHINE_I386 ++#elif defined(__x86_64__) ++#define CURRENT_ARCH IMAGE_FILE_MACHINE_AMD64 ++#elif defined(__arm__) ++#define CURRENT_ARCH IMAGE_FILE_MACHINE_ARM ++#elif defined(__aarch64__) ++#define CURRENT_ARCH IMAGE_FILE_MACHINE_ARM64 ++#endif ++ ++/*********************************************************************** ++ * get_machine_type (internal) ++ * ++ * Determines the machine type of a module. Based on the code in ++ * dlls/kernel32/module.c. ++ */ ++static WORD get_machine_type( HANDLE hfile ) ++{ ++ union ++ { ++ struct ++ { ++ unsigned char magic[4]; ++ unsigned char class; ++ unsigned char data; ++ unsigned char version; ++ unsigned char ignored[9]; ++ unsigned short type; ++ unsigned short machine; ++ } elf; ++ struct ++ { ++ unsigned int magic; ++ unsigned int cputype; ++ unsigned int cpusubtype; ++ unsigned int filetype; ++ } macho; ++ IMAGE_DOS_HEADER mz; ++ } header; ++ ++ IO_STATUS_BLOCK io; ++ LARGE_INTEGER offset; ++ ++ /* Seek to the start of the file and read the header information. */ ++ offset.QuadPart = 0; ++ if (NtReadFile( hfile, 0, NULL, 0, &io, &header, sizeof(header), &offset, NULL )) return 0; ++ if (io.Information < sizeof(header)) return 0; ++ ++ if (!memcmp( header.elf.magic, "\177ELF", 4 )) ++ { ++#ifdef WORDS_BIGENDIAN ++ if (header.elf.data == 1) ++#else ++ if (header.elf.data == 2) ++#endif ++ { ++ header.elf.machine = RtlUshortByteSwap( header.elf.machine ); ++ } ++ ++ switch(header.elf.machine) ++ { ++ case 3: return IMAGE_FILE_MACHINE_I386; ++ case 20: return IMAGE_FILE_MACHINE_POWERPC; ++ case 40: return IMAGE_FILE_MACHINE_ARMNT; ++ case 50: return IMAGE_FILE_MACHINE_IA64; ++ case 62: return IMAGE_FILE_MACHINE_AMD64; ++ case 183: return IMAGE_FILE_MACHINE_ARM64; ++ default: return 0; ++ } ++ } ++ /* Mach-o File with Endian set to Big Endian or Little Endian */ ++ else if (header.macho.magic == 0xfeedface || header.macho.magic == 0xcefaedfe || ++ header.macho.magic == 0xfeedfacf || header.macho.magic == 0xcffaedfe) ++ { ++ if (header.macho.magic == 0xcefaedfe || header.macho.magic == 0xcffaedfe) ++ header.macho.cputype = RtlUlongByteSwap( header.macho.cputype ); ++ ++ switch(header.macho.cputype) ++ { ++ case 0x00000007: return IMAGE_FILE_MACHINE_I386; ++ case 0x01000007: return IMAGE_FILE_MACHINE_AMD64; ++ case 0x0000000c: return IMAGE_FILE_MACHINE_ARMNT; ++ case 0x0100000c: return IMAGE_FILE_MACHINE_ARM64; ++ case 0x00000012: return IMAGE_FILE_MACHINE_POWERPC; ++ default: return 0; ++ } ++ } ++ /* Not ELF, try DOS */ ++ else if (header.mz.e_magic == IMAGE_DOS_SIGNATURE) ++ { ++ IMAGE_NT_HEADERS32 ext_header; ++ ++ offset.QuadPart = header.mz.e_lfanew; ++ if (NtReadFile( hfile, 0, NULL, 0, &io, &ext_header, sizeof(ext_header), &offset, NULL )) return 0; ++ if (io.Information < sizeof(ext_header)) return 0; ++ ++ if (!memcmp( &ext_header.Signature, "PE\0\0", 4 )) ++ return ext_header.FileHeader.Machine; ++ } ++ ++ return 0; ++} + + /*********************************************************************** + * find_dll_file +@@ -1918,7 +2020,8 @@ done: + * Find the file (or already loaded module) for a given dll name. + */ + static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, +- WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle ) ++ WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle, ++ BOOL check_arch) + { + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; +@@ -1964,12 +2067,15 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, + + if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH) + { +- /* we need to search for it */ +- len = RtlDosSearchPath_U( load_path, libname, NULL, *size, filename, &file_part ); +- if (len) ++ while (load_path) + { ++ /* we need to search for it */ ++ len = RtlDosSearchPath_U( load_path, libname, NULL, *size, filename, &file_part ); ++ if (!len) break; ++ + if (len >= *size) goto overflow; +- if ((*pwm = find_fullname_module( filename )) || !handle) goto found; ++ if ((*pwm = find_fullname_module( filename ))) goto found; ++ if (!handle) goto next; + + if (!RtlDosPathNameToNtPathName_U( filename, &nt_name, NULL, NULL )) + { +@@ -1983,7 +2089,23 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE )) *handle = 0; +- goto found; ++ #ifdef CURRENT_ARCH ++ if (*handle && check_arch) ++ { ++ WORD machine_type = get_machine_type( *handle ); ++ if (machine_type && machine_type != CURRENT_ARCH) ++ { ++ FIXME( "skipping %s because of wrong architecture\n", debugstr_w(filename) ); ++ NtClose( *handle ); ++ *handle = 0; ++ } ++ } ++ #endif ++ if (*handle) goto found; ++ ++ next: ++ load_path = strchrW(load_path, ';'); ++ if (load_path) load_path++; + } + + /* not found */ +@@ -2040,6 +2162,7 @@ overflow: + */ + static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm ) + { ++ BOOL data = flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE); + enum loadorder loadorder; + WCHAR buffer[32]; + WCHAR *filename; +@@ -2055,7 +2178,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ + size = sizeof(buffer); + for (;;) + { +- nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle ); ++ nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle, !data ); + if (nts == STATUS_SUCCESS) break; + if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename ); + if (nts != STATUS_BUFFER_TOO_SMALL) return nts; +@@ -2192,7 +2315,7 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S + size = sizeof(buffer); + for (;;) + { +- status = find_dll_file( load_path, name->Buffer, filename, &size, &wm, NULL ); ++ status = find_dll_file( load_path, name->Buffer, filename, &size, &wm, NULL, TRUE ); + if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename ); + if (status != STATUS_BUFFER_TOO_SMALL) break; + /* grow the buffer and retry */ +-- +2.4.5 + diff --git a/patches/ntdll-Loader_Machine_Type/definition b/patches/ntdll-Loader_Machine_Type/definition new file mode 100644 index 00000000..2f6d9a3f --- /dev/null +++ b/patches/ntdll-Loader_Machine_Type/definition @@ -0,0 +1 @@ +Fixes: [38021] Check architecture before trying to load libraries diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 9a055576..4c5ad2b1 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -161,6 +161,7 @@ patch_enable_all () enable_ntdll_Heap_FreeLists="$1" enable_ntdll_Hide_Wine_Exports="$1" enable_ntdll_Junction_Points="$1" + enable_ntdll_Loader_Machine_Type="$1" enable_ntdll_NtQueryEaFile="$1" enable_ntdll_NtQuerySection="$1" enable_ntdll_NtSetLdtEntries="$1" @@ -549,6 +550,9 @@ patch_enable () ntdll-Junction_Points) enable_ntdll_Junction_Points="$2" ;; + ntdll-Loader_Machine_Type) + enable_ntdll_Loader_Machine_Type="$2" + ;; ntdll-NtQueryEaFile) enable_ntdll_NtQueryEaFile="$2" ;; @@ -1707,6 +1711,13 @@ if test "$enable_ntdll_Junction_Points" -eq 1; then enable_ntdll_NtQueryEaFile=1 fi +if test "$enable_ntdll_DllRedirects" -eq 1; then + if test "$enable_ntdll_Loader_Machine_Type" -gt 1; then + abort "Patchset ntdll-Loader_Machine_Type disabled, but ntdll-DllRedirects depends on that." + fi + enable_ntdll_Loader_Machine_Type=1 +fi + if test "$enable_ntdll_CLI_Images" -eq 1; then if test "$enable_mscoree_CorValidateImage" -gt 1; then abort "Patchset mscoree-CorValidateImage disabled, but ntdll-CLI_Images depends on that." @@ -3270,6 +3281,21 @@ if test "$enable_ntdll_DeviceType_Systemroot" -eq 1; then ) >> "$patchlist" fi +# Patchset ntdll-Loader_Machine_Type +# | +# | This patchset fixes the following Wine bugs: +# | * [#38021] Check architecture before trying to load libraries +# | +# | Modified files: +# | * dlls/ntdll/loader.c +# | +if test "$enable_ntdll_Loader_Machine_Type" -eq 1; then + patch_apply ntdll-Loader_Machine_Type/0001-ntdll-Check-architecture-before-loading-module.patch + ( + echo '+ { "Michael Müller", "ntdll: Check architecture before loading module.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-DllRedirects # | # | Modified files: