From 65c37cee249984884af40d91aa14706d81e128bf Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 26 Aug 2020 13:02:02 +0200 Subject: [PATCH] ntdll: Use exported APIs instead of virtual_map_section() to load PE modules. Signed-off-by: Alexandre Julliard --- dlls/ntdll/loader.c | 75 ++++++++++++++++++---------------- dlls/ntdll/unix/loader.c | 37 +++++++++++++---- dlls/ntdll/unix/unix_private.h | 3 -- dlls/ntdll/unix/virtual.c | 8 ++-- dlls/ntdll/unixlib.h | 7 +--- 5 files changed, 73 insertions(+), 57 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 6ae57971053..d3ade9555b3 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1870,27 +1870,29 @@ static NTSTATUS perform_relocations( void *module, IMAGE_NT_HEADERS *nt, SIZE_T * Build the module data for a mapped dll. */ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module, - const pe_image_info_t *image_info, const struct file_id *id, + const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id, DWORD flags, WINE_MODREF **pwm ) { IMAGE_NT_HEADERS *nt; WINE_MODREF *wm; NTSTATUS status; + SIZE_T map_size; if (!(nt = RtlImageNtHeader( *module ))) return STATUS_INVALID_IMAGE_FORMAT; - if ((status = perform_relocations( *module, nt, image_info->map_size ))) return status; + map_size = (nt->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1); + if ((status = perform_relocations( *module, nt, map_size ))) return status; /* create the MODREF */ - if (!(wm = alloc_module( *module, nt_name, (image_info->image_flags & IMAGE_FLAGS_WineBuiltin) ))) + if (!(wm = alloc_module( *module, nt_name, (image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin) ))) return STATUS_NO_MEMORY; if (id) wm->id = *id; - if (image_info->loader_flags) wm->ldr.Flags |= LDR_COR_IMAGE; - if (image_info->image_flags & IMAGE_FLAGS_ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY; + if (image_info->LoaderFlags) wm->ldr.Flags |= LDR_COR_IMAGE; + if (image_info->u.ImageFlags & IMAGE_FLAGS_ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY; - set_security_cookie( *module, image_info->map_size ); + set_security_cookie( *module, map_size ); /* fixup imports */ @@ -1935,7 +1937,7 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, } SERVER_END_REQ; - if (image_info->image_flags & IMAGE_FLAGS_WineBuiltin) + if (image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin) { if (TRACE_ON(relay)) RELAY_SetupDLL( *module ); } @@ -1945,7 +1947,7 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, } TRACE_(loaddll)( "Loaded %s at %p: %s\n", debugstr_w(wm->ldr.FullDllName.Buffer), *module, - (image_info->image_flags & IMAGE_FLAGS_WineBuiltin) ? "builtin" : "native" ); + (image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin) ? "builtin" : "native" ); wm->ldr.LoadCount = 1; *pwm = wm; @@ -1963,9 +1965,9 @@ static NTSTATUS build_builtin_module( const WCHAR *load_path, const UNICODE_STRI void *module, DWORD flags, WINE_MODREF **pwm ) { NTSTATUS status; - pe_image_info_t image_info = { 0 }; + SECTION_IMAGE_INFORMATION image_info = { 0 }; - image_info.image_flags = IMAGE_FLAGS_WineBuiltin; + image_info.u.ImageFlags = IMAGE_FLAGS_WineBuiltin; status = build_module( load_path, nt_name, &module, &image_info, NULL, flags, pwm ); if (status && module) unix_funcs->unload_builtin_dll( module ); return status; @@ -1974,7 +1976,7 @@ static NTSTATUS build_builtin_module( const WCHAR *load_path, const UNICODE_STRI #ifdef _WIN64 /* convert PE header to 64-bit when loading a 32-bit IL-only module into a 64-bit process */ -static BOOL convert_to_pe64( HMODULE module, const pe_image_info_t *info ) +static BOOL convert_to_pe64( HMODULE module, const SECTION_IMAGE_INFORMATION *info ) { static const ULONG copy_dirs[] = { IMAGE_DIRECTORY_ENTRY_RESOURCE, IMAGE_DIRECTORY_ENTRY_SECURITY, @@ -1986,7 +1988,7 @@ static BOOL convert_to_pe64( HMODULE module, const pe_image_info_t *info ) IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module ); SIZE_T hdr_size = min( sizeof(hdr32), nt->FileHeader.SizeOfOptionalHeader ); IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER *)((char *)&nt->OptionalHeader + hdr_size); - SIZE_T size = info->header_size; + SIZE_T size = min( nt->OptionalHeader.SizeOfHeaders, nt->OptionalHeader.SizeOfImage ); void *addr = module; ULONG i, old_prot; @@ -2025,22 +2027,22 @@ static BOOL convert_to_pe64( HMODULE module, const pe_image_info_t *info ) /* On WoW64 setups, an image mapping can also be created for the other 32/64 CPU */ /* but it cannot necessarily be loaded as a dll, so we need some additional checks */ -static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info ) +static BOOL is_valid_binary( HMODULE module, const SECTION_IMAGE_INFORMATION *info ) { #ifdef __i386__ - return info->machine == IMAGE_FILE_MACHINE_I386; + return info->Machine == IMAGE_FILE_MACHINE_I386; #elif defined(__arm__) - return info->machine == IMAGE_FILE_MACHINE_ARM || - info->machine == IMAGE_FILE_MACHINE_THUMB || - info->machine == IMAGE_FILE_MACHINE_ARMNT; + return info->Machine == IMAGE_FILE_MACHINE_ARM || + info->Machine == IMAGE_FILE_MACHINE_THUMB || + info->Machine == IMAGE_FILE_MACHINE_ARMNT; #elif defined(_WIN64) /* support 32-bit IL-only images on 64-bit */ #ifdef __x86_64__ - if (info->machine == IMAGE_FILE_MACHINE_AMD64) return TRUE; + if (info->Machine == IMAGE_FILE_MACHINE_AMD64) return TRUE; #else - if (info->machine == IMAGE_FILE_MACHINE_ARM64) return TRUE; + if (info->Machine == IMAGE_FILE_MACHINE_ARM64) return TRUE; #endif - if (!info->contains_code) return TRUE; - if (!(info->image_flags & IMAGE_FLAGS_ComPlusNativeReady)) + if (!info->ImageContainsCode) return TRUE; + if (!(info->u.ImageFlags & IMAGE_FLAGS_ComPlusNativeReady)) { /* check COM header directly, ignoring runtime version */ DWORD size; @@ -2216,8 +2218,8 @@ static NTSTATUS get_dll_load_path_search_flags( LPCWSTR module, DWORD flags, WCH * * Open a file for a new dll. Helper for find_dll_file. */ -static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, - void **module, pe_image_info_t *image_info, struct file_id *id ) +static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, + SECTION_IMAGE_INFORMATION *image_info, struct file_id *id ) { FILE_BASIC_INFORMATION info; OBJECT_ATTRIBUTES attr; @@ -2283,14 +2285,15 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, NtUnmapViewOfSection( NtCurrentProcess(), *module ); *module = NULL; } - status = unix_funcs->virtual_map_section( mapping, module, 0, 0, NULL, &len, - 0, PAGE_EXECUTE_READ, image_info ); + NtQuerySection( mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL ); + status = NtMapViewOfSection( mapping, NtCurrentProcess(), module, 0, 0, NULL, &len, + ViewShare, 0, PAGE_EXECUTE_READ ); if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS; NtClose( mapping ); } if (!status && !is_valid_binary( *module, image_info )) { - TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->machine ); + TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->Machine ); NtUnmapViewOfSection( NtCurrentProcess(), *module ); *module = NULL; status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; @@ -2303,7 +2306,7 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, * load_native_dll (internal) */ static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module, - const pe_image_info_t *image_info, const struct file_id *id, + const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id, DWORD flags, WINE_MODREF** pwm ) { return build_module( load_path, nt_name, module, image_info, id, flags, pwm ); @@ -2353,7 +2356,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na const WCHAR *name, *p; NTSTATUS status; void *module = NULL; - pe_image_info_t image_info; + SECTION_IMAGE_INFORMATION image_info; /* Fix the name in case we have a full path and extension */ name = nt_name->Buffer; @@ -2491,7 +2494,7 @@ done: * Search for dll in the specified paths. */ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name, - WINE_MODREF **pwm, void **module, pe_image_info_t *image_info, + WINE_MODREF **pwm, void **module, SECTION_IMAGE_INFORMATION *image_info, struct file_id *id ) { WCHAR *name; @@ -2547,8 +2550,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, const WCHAR *default_ext, - UNICODE_STRING *nt_name, WINE_MODREF **pwm, - void **module, pe_image_info_t *image_info, struct file_id *id ) + UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, + SECTION_IMAGE_INFORMATION *image_info, struct file_id *id ) { WCHAR *ext, *dllname; NTSTATUS status; @@ -2626,7 +2629,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC UNICODE_STRING nt_name; struct file_id id; void *module; - pe_image_info_t image_info; + SECTION_IMAGE_INFORMATION image_info; NTSTATUS nts; TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) ); @@ -2668,7 +2671,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC break; case STATUS_SUCCESS: /* valid PE file */ - if (image_info.image_flags & IMAGE_FLAGS_WineBuiltin) + if (image_info.u.ImageFlags & IMAGE_FLAGS_WineBuiltin) { switch (loadorder) { @@ -2687,7 +2690,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC if (module) NtUnmapViewOfSection( NtCurrentProcess(), module ); break; } - if (!(image_info.image_flags & IMAGE_FLAGS_WineFakeDll)) + if (!(image_info.u.ImageFlags & IMAGE_FLAGS_WineFakeDll)) { switch (loadorder) { @@ -2790,7 +2793,7 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S UNICODE_STRING nt_name; WINE_MODREF *wm; void *module; - pe_image_info_t image_info; + SECTION_IMAGE_INFORMATION image_info; struct file_id id; RtlEnterCriticalSection( &loader_section ); @@ -3431,7 +3434,7 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR entry = (void **)&context->R0; if (!context->Pc) context->Pc = (DWORD_PTR)kernel32_start_process; #elif defined(__aarch64__) - entry = (void **)&context->X0; + entry = (void **)&context->u.s.X0; if (!context->Pc) context->Pc = (DWORD_PTR)kernel32_start_process; #endif diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 6e41781b8fe..6f25f4ae87e 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -896,6 +896,23 @@ static NTSTATUS CDECL load_so_dll( UNICODE_STRING *nt_name, void **module ) } +/* check a PE library architecture */ +static BOOL is_valid_binary( HMODULE module, const SECTION_IMAGE_INFORMATION *info ) +{ +#ifdef __i386__ + return info->Machine == IMAGE_FILE_MACHINE_I386; +#elif defined(__arm__) + return info->Machine == IMAGE_FILE_MACHINE_ARM || + info->Machine == IMAGE_FILE_MACHINE_THUMB || + info->Machine == IMAGE_FILE_MACHINE_ARMNT; +#elif defined(__x86_64__) + /* we don't support 32-bit IL-only builtins yet */ + return info->Machine == IMAGE_FILE_MACHINE_AMD64; +#elif defined(__aarch64__) + return info->Machine == IMAGE_FILE_MACHINE_ARM64; +#endif +} + /* check if the library is the correct architecture */ /* only returns false for a valid library of the wrong arch */ static int check_library_arch( int fd ) @@ -943,7 +960,7 @@ static inline char *prepend( char *buffer, const char *str, size_t len ) * * Open a file for a new dll. Helper for find_dll_file. */ -static NTSTATUS open_dll_file( const char *name, void **module, pe_image_info_t *image_info ) +static NTSTATUS open_dll_file( const char *name, void **module, SECTION_IMAGE_INFORMATION *image_info ) { struct builtin_module *builtin; OBJECT_ATTRIBUTES attr = { sizeof(attr) }; @@ -995,20 +1012,22 @@ static NTSTATUS open_dll_file( const char *name, void **module, pe_image_info_t NtUnmapViewOfSection( NtCurrentProcess(), *module ); *module = NULL; } - status = virtual_map_section( mapping, module, 0, 0, NULL, &len, 0, PAGE_EXECUTE_READ, image_info ); + NtQuerySection( mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL ); + status = NtMapViewOfSection( mapping, NtCurrentProcess(), module, 0, 0, NULL, &len, + ViewShare, 0, PAGE_EXECUTE_READ ); if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS; NtClose( mapping ); if (status) return status; /* ignore non-builtins */ - if (!(image_info->image_flags & IMAGE_FLAGS_WineBuiltin)) + if (!(image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin)) { WARN( "%s found in WINEDLLPATH but not a builtin, ignoring\n", debugstr_a(name) ); status = STATUS_DLL_NOT_FOUND; } - else if (image_info->cpu != client_cpu) + else if (!is_valid_binary( *module, image_info )) { - TRACE( "%s is for CPU %u, continuing search\n", debugstr_a(name), image_info->cpu ); + TRACE( "%s is for arch %x, continuing search\n", debugstr_a(name), image_info->Machine ); status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; } @@ -1026,7 +1045,7 @@ static NTSTATUS open_dll_file( const char *name, void **module, pe_image_info_t /*********************************************************************** * open_builtin_file */ -static NTSTATUS open_builtin_file( char *name, void **module, pe_image_info_t *image_info ) +static NTSTATUS open_builtin_file( char *name, void **module, SECTION_IMAGE_INFORMATION *image_info ) { NTSTATUS status; int fd; @@ -1046,7 +1065,7 @@ static NTSTATUS open_builtin_file( char *name, void **module, pe_image_info_t *i if (!dlopen_dll( name, module )) { memset( image_info, 0, sizeof(*image_info) ); - image_info->image_flags = IMAGE_FLAGS_WineBuiltin; + image_info->u.ImageFlags = IMAGE_FLAGS_WineBuiltin; status = STATUS_SUCCESS; } else @@ -1065,7 +1084,8 @@ static NTSTATUS open_builtin_file( char *name, void **module, pe_image_info_t *i /*********************************************************************** * load_builtin_dll */ -static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, pe_image_info_t *image_info ) +static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, + SECTION_IMAGE_INFORMATION *image_info ) { unsigned int i, pos, len, namelen, maxlen = 0; char *ptr, *file; @@ -1346,7 +1366,6 @@ static struct unix_funcs unix_funcs = get_initial_directory, get_unix_codepage_data, get_locales, - virtual_map_section, virtual_release_address_space, exec_process, set_show_dot_files, diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 7c6bb1417c6..813d65fc22b 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -115,9 +115,6 @@ extern void CDECL get_initial_directory( UNICODE_STRING *dir ) DECLSPEC_HIDDEN; extern void CDECL get_initial_console( HANDLE *handle, HANDLE *std_in, HANDLE *std_out, HANDLE *std_err ) DECLSPEC_HIDDEN; extern USHORT * CDECL get_unix_codepage_data(void) DECLSPEC_HIDDEN; extern void CDECL get_locales( WCHAR *sys, WCHAR *user ) DECLSPEC_HIDDEN; -extern NTSTATUS CDECL virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size, - const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, - ULONG protect, pe_image_info_t *image_info ) DECLSPEC_HIDDEN; extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN; extern NTSTATUS CDECL exec_process( UNICODE_STRING *path, UNICODE_STRING *cmdline, NTSTATUS status ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 11732938546..58c84caab5f 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2181,9 +2181,9 @@ static NTSTATUS map_image_into_view( struct file_view *view, int fd, void *orig_ * * Map a file section into memory. */ -NTSTATUS CDECL virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size, - const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, - ULONG protect, pe_image_info_t *image_info ) +static NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, + SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, + ULONG alloc_type, ULONG protect, pe_image_info_t *image_info ) { NTSTATUS res; mem_size_t full_size; @@ -4163,7 +4163,7 @@ void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMA info->DllCharacteristics = pe_info->dll_charact; info->Machine = pe_info->machine; info->ImageContainsCode = pe_info->contains_code; - info->ImageFlags = pe_info->image_flags & ~(IMAGE_FLAGS_WineBuiltin|IMAGE_FLAGS_WineFakeDll); + info->ImageFlags = pe_info->image_flags; info->LoaderFlags = pe_info->loader_flags; info->ImageFileSize = pe_info->file_size; info->CheckSum = pe_info->checksum; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 7e5eac99a76..0fa5bba4d83 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -27,7 +27,7 @@ struct _DISPATCHER_CONTEXT; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 99 +#define NTDLL_UNIXLIB_VERSION 100 struct unix_funcs { @@ -79,9 +79,6 @@ struct unix_funcs void (CDECL *get_locales)( WCHAR *sys, WCHAR *user ); /* virtual memory functions */ - NTSTATUS (CDECL *virtual_map_section)( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size, - const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, - ULONG protect, pe_image_info_t *image_info ); void (CDECL *virtual_release_address_space)(void); /* thread/process functions */ @@ -93,7 +90,7 @@ struct unix_funcs /* loader functions */ NTSTATUS (CDECL *load_so_dll)( UNICODE_STRING *nt_name, void **module ); NTSTATUS (CDECL *load_builtin_dll)( const WCHAR *name, void **module, - pe_image_info_t *image_info ); + SECTION_IMAGE_INFORMATION *image_info ); NTSTATUS (CDECL *unload_builtin_dll)( void *module ); void (CDECL *init_builtin_dll)( void *module ); NTSTATUS (CDECL *unwind_builtin_dll)( ULONG type, struct _DISPATCHER_CONTEXT *dispatch,