From f9bd73c4d653b4483b0ec39da948787cf00916b6 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 30 Jan 2018 10:47:32 +0100 Subject: [PATCH] server: Allow creating image mappings for all supported CPU platforms. Signed-off-by: Alexandre Julliard --- dlls/kernel32/tests/loader.c | 21 +++-------- server/mapping.c | 71 +++++++++++++++++------------------- server/thread.c | 6 +++ server/thread.h | 1 + 4 files changed, 47 insertions(+), 52 deletions(-) diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index fe2957c8261..56bf1f4824a 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -49,6 +49,7 @@ struct PROCESS_BASIC_INFORMATION_PRIVATE static LONG *child_failures; static WORD cb_count; static DWORD page_size; +static BOOL is_wow64; static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const LARGE_INTEGER *, ULONG, ULONG, HANDLE ); @@ -289,12 +290,15 @@ static BOOL query_image_section( int id, const char *dll_name, const IMAGE_NT_HE entry_point = (char *)(ULONG_PTR)nt32->OptionalHeader.ImageBase + nt32->OptionalHeader.AddressOfEntryPoint; truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER32); } + todo_wine_if (entry_point == (void *)0x81231234 ) ok( (char *)image.TransferAddress == (char *)entry_point, "%u: TransferAddress wrong %p / %p (%08x)\n", id, image.TransferAddress, entry_point, nt_header->OptionalHeader.AddressOfEntryPoint ); ok( image.ZeroBits == 0, "%u: ZeroBits wrong %08x\n", id, image.ZeroBits ); + todo_wine_if (entry_point == (void *)0x81231234 ) ok( image.MaximumStackSize == max_stack || broken(truncated), "%u: MaximumStackSize wrong %lx / %lx\n", id, image.MaximumStackSize, max_stack ); + todo_wine_if (entry_point == (void *)0x81231234 ) ok( image.CommittedStackSize == commit_stack || broken(truncated), "%u: CommittedStackSize wrong %lx / %lx\n", id, image.CommittedStackSize, commit_stack ); if (truncated) @@ -424,7 +428,7 @@ static NTSTATUS map_image_section( const IMAGE_NT_HEADERS *nt_header, int line ) { ok( mod != NULL, "%u: loading failed err %u\n", line, GetLastError() ); } - else + else todo_wine_if (is_wow64) { ok( !mod, "%u: loading succeeded\n", line ); ok( GetLastError() == ERROR_BAD_EXE_FORMAT, "%u: wrong error %u\n", line, GetLastError() ); @@ -869,9 +873,7 @@ static void test_Loader(void) if (nt_header.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { IMAGE_NT_HEADERS64 nt64; - BOOL is_wow64 = FALSE; - if (pIsWow64Process) pIsWow64Process( GetCurrentProcess(), &is_wow64 ); memset( &nt64, 0, sizeof(nt64) ); nt64.Signature = IMAGE_NT_SIGNATURE; nt64.FileHeader.Machine = orig_machine; @@ -896,7 +898,6 @@ static void test_Loader(void) section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ ); - todo_wine_if(!is_wow64) ok( status == (is_wow64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_INVALID_IMAGE_WIN_64), "NtCreateSection error %08x\n", status ); @@ -906,13 +907,11 @@ static void test_Loader(void) case IMAGE_FILE_MACHINE_ARMNT: nt64.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; break; } status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ ); - todo_wine_if(!is_wow64) ok( status == (is_wow64 ? STATUS_INVALID_IMAGE_FORMAT : STATUS_INVALID_IMAGE_WIN_64), "NtCreateSection error %08x\n", status ); nt64.FileHeader.Machine = nt_header.FileHeader.Machine; status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ ); - todo_wine ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), "NtCreateSection error %08x\n", status ); @@ -920,7 +919,6 @@ static void test_Loader(void) nt64.OptionalHeader.AddressOfEntryPoint = 0x1000; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ ); - todo_wine ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), "NtCreateSection error %08x\n", status ); @@ -928,7 +926,6 @@ static void test_Loader(void) nt64.OptionalHeader.AddressOfEntryPoint = 0; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ ); - todo_wine ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), "NtCreateSection error %08x\n", status ); @@ -936,7 +933,6 @@ static void test_Loader(void) nt64.OptionalHeader.AddressOfEntryPoint = 0; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ ); - todo_wine ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), "NtCreateSection error %08x\n", status ); @@ -944,7 +940,6 @@ static void test_Loader(void) nt64.OptionalHeader.AddressOfEntryPoint = 0; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt64, __LINE__ ); - todo_wine ok( status == (is_wow64 ? STATUS_SUCCESS : STATUS_INVALID_IMAGE_WIN_64), "NtCreateSection error %08x\n", status ); } @@ -989,35 +984,30 @@ static void test_Loader(void) nt32.FileHeader.Machine = nt_header.FileHeader.Machine; status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ ); - todo_wine ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status ); nt32.OptionalHeader.SizeOfCode = 0; nt32.OptionalHeader.AddressOfEntryPoint = 0x1000; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ ); - todo_wine ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status ); nt32.OptionalHeader.SizeOfCode = 0; nt32.OptionalHeader.AddressOfEntryPoint = 0; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ ); - todo_wine ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status ); nt32.OptionalHeader.SizeOfCode = 0x1000; nt32.OptionalHeader.AddressOfEntryPoint = 0; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ ); - todo_wine ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status ); nt32.OptionalHeader.SizeOfCode = 0; nt32.OptionalHeader.AddressOfEntryPoint = 0; section.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE; status = map_image_section( (IMAGE_NT_HEADERS *)&nt32, __LINE__ ); - todo_wine ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status ); } @@ -3236,6 +3226,7 @@ START_TEST(loader) pIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process"); pResolveDelayLoadedAPI = (void *)GetProcAddress(kernel32, "ResolveDelayLoadedAPI"); + if (pIsWow64Process) pIsWow64Process( GetCurrentProcess(), &is_wow64 ); GetSystemInfo( &si ); page_size = si.dwPageSize; dos_header.e_magic = IMAGE_DOS_SIGNATURE; diff --git a/server/mapping.c b/server/mapping.c index d12d01d31c3..b86ac9a4f9f 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -136,7 +136,6 @@ struct mapping mem_size_t size; /* mapping size */ unsigned int flags; /* SEC_* flags */ struct fd *fd; /* fd for mapped file */ - enum cpu_type cpu; /* client CPU (for PE image mapping) */ pe_image_info_t image; /* image info (for PE image mapping) */ struct ranges *committed; /* list of committed ranges in this mapping */ struct shared_map *shared; /* temp file for shared PE mapping */ @@ -540,6 +539,7 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s } nt; off_t pos; int size; + unsigned int cpu_mask = get_supported_cpu_mask(); /* load the headers */ @@ -559,38 +559,25 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s return STATUS_INVALID_IMAGE_PROTECT; } - mapping->cpu = current->process->cpu; - switch (mapping->cpu) - { - case CPU_x86: - if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_I386) return STATUS_INVALID_IMAGE_FORMAT; - if (nt.opt.hdr32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; - break; - case CPU_x86_64: - if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) return STATUS_INVALID_IMAGE_FORMAT; - if (nt.opt.hdr64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; - break; - case CPU_POWERPC: - if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_POWERPC) return STATUS_INVALID_IMAGE_FORMAT; - if (nt.opt.hdr32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; - break; - case CPU_ARM: - if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARM && - nt.FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB && - nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARMNT) return STATUS_INVALID_IMAGE_FORMAT; - if (nt.opt.hdr32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; - break; - case CPU_ARM64: - if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARM64) return STATUS_INVALID_IMAGE_FORMAT; - if (nt.opt.hdr64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; - break; - default: - return STATUS_INVALID_IMAGE_FORMAT; - } - switch (nt.opt.hdr32.Magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + switch (nt.FileHeader.Machine) + { + case IMAGE_FILE_MACHINE_I386: + if (cpu_mask & (CPU_FLAG(CPU_x86) | CPU_FLAG(CPU_x86_64))) break; + return STATUS_INVALID_IMAGE_FORMAT; + case IMAGE_FILE_MACHINE_ARM: + case IMAGE_FILE_MACHINE_THUMB: + case IMAGE_FILE_MACHINE_ARMNT: + if (cpu_mask & (CPU_FLAG(CPU_ARM) | CPU_FLAG(CPU_ARM64))) break; + return STATUS_INVALID_IMAGE_FORMAT; + case IMAGE_FILE_MACHINE_POWERPC: + if (cpu_mask & CPU_FLAG(CPU_POWERPC)) break; + return STATUS_INVALID_IMAGE_FORMAT; + default: + return STATUS_INVALID_IMAGE_FORMAT; + } mapping->image.base = nt.opt.hdr32.ImageBase; mapping->image.entry_point = nt.opt.hdr32.ImageBase + nt.opt.hdr32.AddressOfEntryPoint; mapping->image.map_size = ROUND_SIZE( nt.opt.hdr32.SizeOfImage ); @@ -604,7 +591,20 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s mapping->image.header_size = nt.opt.hdr32.SizeOfHeaders; mapping->image.checksum = nt.opt.hdr32.CheckSum; break; + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + if (!(cpu_mask & CPU_64BIT_MASK)) return STATUS_INVALID_IMAGE_WIN_64; + switch (nt.FileHeader.Machine) + { + case IMAGE_FILE_MACHINE_AMD64: + if (cpu_mask & (CPU_FLAG(CPU_x86) | CPU_FLAG(CPU_x86_64))) break; + return STATUS_INVALID_IMAGE_FORMAT; + case IMAGE_FILE_MACHINE_ARM64: + if (cpu_mask & (CPU_FLAG(CPU_ARM) | CPU_FLAG(CPU_ARM64))) break; + return STATUS_INVALID_IMAGE_FORMAT; + default: + return STATUS_INVALID_IMAGE_FORMAT; + } mapping->image.base = nt.opt.hdr64.ImageBase; mapping->image.entry_point = nt.opt.hdr64.ImageBase + nt.opt.hdr64.AddressOfEntryPoint; mapping->image.map_size = ROUND_SIZE( nt.opt.hdr64.SizeOfImage ); @@ -618,7 +618,11 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s mapping->image.header_size = nt.opt.hdr64.SizeOfHeaders; mapping->image.checksum = nt.opt.hdr64.CheckSum; break; + + default: + return STATUS_INVALID_IMAGE_FORMAT; } + mapping->image.image_charact = nt.FileHeader.Characteristics; mapping->image.machine = nt.FileHeader.Machine; mapping->image.zerobits = 0; /* FIXME */ @@ -901,13 +905,6 @@ DECL_HANDLER(get_mapping_info) return; } - if ((mapping->flags & SEC_IMAGE) && mapping->cpu != current->process->cpu) - { - set_error( STATUS_INVALID_IMAGE_FORMAT ); - release_object( mapping ); - return; - } - if (mapping->shared) reply->shared_file = alloc_handle( current->process, mapping->shared->file, GENERIC_READ|GENERIC_WRITE, 0 ); diff --git a/server/thread.c b/server/thread.c index e313dfe5fdb..2cf5054738a 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1234,6 +1234,12 @@ int is_cpu_supported( enum cpu_type cpu ) return 0; } +/* return the cpu mask for supported cpus */ +unsigned int get_supported_cpu_mask(void) +{ + return supported_cpus & get_prefix_cpu_mask(); +} + /* create a new thread */ DECL_HANDLER(new_thread) { diff --git a/server/thread.h b/server/thread.h index 09d8260d717..3cb7cb6cf15 100644 --- a/server/thread.h +++ b/server/thread.h @@ -128,6 +128,7 @@ extern struct thread_snapshot *thread_snap( int *count ); extern struct token *thread_get_impersonation_token( struct thread *thread ); extern int set_thread_affinity( struct thread *thread, affinity_t affinity ); extern int is_cpu_supported( enum cpu_type cpu ); +extern unsigned int get_supported_cpu_mask(void); /* ptrace functions */