server: Check PE file architecture at mapping creation time.

This commit is contained in:
Alexandre Julliard 2013-11-21 17:29:51 +01:00
parent 55eb7e56e8
commit e8eb781327
4 changed files with 83 additions and 107 deletions

View File

@ -599,32 +599,32 @@ todo_wine
dos_header.e_magic = 0;
status = map_image_section( &nt_header );
todo_wine ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08x\n", status );
dos_header.e_magic = IMAGE_DOS_SIGNATURE;
nt_header.Signature = IMAGE_OS2_SIGNATURE;
status = map_image_section( &nt_header );
todo_wine ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08x\n", status );
nt_header.Signature = 0xdeadbeef;
status = map_image_section( &nt_header );
todo_wine ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08x\n", status );
nt_header.Signature = IMAGE_NT_SIGNATURE;
nt_header.OptionalHeader.Magic = 0xdead;
status = map_image_section( &nt_header );
todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
nt_header.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
nt_header.FileHeader.Machine = 0xdead;
status = map_image_section( &nt_header );
todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
"NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
"NtCreateSection error %08x\n", status );
nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_UNKNOWN;
status = map_image_section( &nt_header );
todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
"NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
"NtCreateSection error %08x\n", status );
switch (orig_machine)
{
@ -634,7 +634,7 @@ todo_wine
case IMAGE_FILE_MACHINE_ARM64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; break;
}
status = map_image_section( &nt_header );
todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
"NtCreateSection error %08x\n", status );
if (nt_header.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
@ -656,7 +656,7 @@ todo_wine
nt64.OptionalHeader.SizeOfImage = nt64.OptionalHeader.SizeOfHeaders + 0x1000;
nt64.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
status = map_image_section( (IMAGE_NT_HEADERS *)&nt64 );
todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
}
else
{
@ -677,7 +677,7 @@ todo_wine
nt32.OptionalHeader.SizeOfImage = nt32.OptionalHeader.SizeOfHeaders + 0x1000;
nt32.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
status = map_image_section( (IMAGE_NT_HEADERS *)&nt32 );
todo_wine ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
}
nt_header.FileHeader.Machine = orig_machine; /* restore it for the next tests */

View File

@ -2000,7 +2000,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
else
{
nts = load_native_dll( load_path, filename, handle, flags, pwm );
if (nts == STATUS_INVALID_FILE_FOR_SECTION)
if (nts == STATUS_INVALID_IMAGE_NOT_MZ)
/* not in PE format, maybe it's a builtin */
nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
}

View File

@ -1031,67 +1031,6 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot
}
/***********************************************************************
* check_architecture
*
* Check the architecture of a PE binary.
*/
static NTSTATUS check_architecture( const IMAGE_NT_HEADERS *nt )
{
static const char *arch;
#ifdef __i386__
if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) return STATUS_SUCCESS;
if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
{
if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL) /* don't warn for a 64-bit exe */
WARN( "loading amd64 dll in 32-bit mode will fail\n" );
return STATUS_INVALID_IMAGE_FORMAT;
}
#elif defined(__x86_64__)
if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) return STATUS_SUCCESS;
if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
{
if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL) /* don't warn for a 32-bit exe */
WARN( "loading 32-bit dll in 64-bit mode will fail\n" );
return STATUS_INVALID_IMAGE_FORMAT;
}
#elif defined(__arm__) && !defined(__ARMEB__)
if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM ||
nt->FileHeader.Machine == IMAGE_FILE_MACHINE_THUMB)
return STATUS_SUCCESS;
if (nt->FileHeader.Machine == IMAGE_FILE_MACHINE_ARMNT)
{
SYSTEM_CPU_INFORMATION sci;
if (SUCCEEDED(NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL )) &&
sci.Architecture == PROCESSOR_ARCHITECTURE_ARM && sci.Level >= 7)
return STATUS_SUCCESS;
}
#endif
switch (nt->FileHeader.Machine)
{
case IMAGE_FILE_MACHINE_UNKNOWN: arch = "Unknown"; break;
case IMAGE_FILE_MACHINE_I860: arch = "I860"; break;
case IMAGE_FILE_MACHINE_I386: arch = "I386"; break;
case IMAGE_FILE_MACHINE_R3000: arch = "R3000"; break;
case IMAGE_FILE_MACHINE_R4000: arch = "R4000"; break;
case IMAGE_FILE_MACHINE_R10000: arch = "R10000"; break;
case IMAGE_FILE_MACHINE_ALPHA: arch = "Alpha"; break;
case IMAGE_FILE_MACHINE_POWERPC: arch = "PowerPC"; break;
case IMAGE_FILE_MACHINE_IA64: arch = "IA-64"; break;
case IMAGE_FILE_MACHINE_ALPHA64: arch = "Alpha-64"; break;
case IMAGE_FILE_MACHINE_AMD64: arch = "AMD-64"; break;
case IMAGE_FILE_MACHINE_ARM: arch = "ARM"; break;
case IMAGE_FILE_MACHINE_ARMNT: arch = "ARMNT"; break;
case IMAGE_FILE_MACHINE_THUMB: arch = "ARM Thumb"; break;
default: arch = wine_dbg_sprintf( "Unknown-%04x", nt->FileHeader.Machine ); break;
}
ERR( "Trying to load PE image for unsupported architecture %s\n", arch );
return STATUS_INVALID_IMAGE_FORMAT;
}
/***********************************************************************
* stat_mapping_file
*
@ -1179,8 +1118,6 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
if (!imports->Size || !imports->VirtualAddress) imports = NULL;
if (check_architecture( nt )) goto error;
/* check for non page-aligned binary */
if (nt->OptionalHeader.SectionAlignment <= page_mask)

View File

@ -39,6 +39,7 @@
#include "file.h"
#include "handle.h"
#include "thread.h"
#include "process.h"
#include "request.h"
#include "security.h"
@ -60,6 +61,7 @@ struct mapping
mem_size_t size; /* mapping size */
int protect; /* protection flags */
struct fd *fd; /* fd for mapped file */
enum cpu_type cpu; /* client CPU (for PE image mapping) */
int header_size; /* size of headers (for PE image mapping) */
client_ptr_t base; /* default base addr (for PE image mapping) */
struct ranges *committed; /* list of committed ranges in this mapping */
@ -366,7 +368,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
}
/* retrieve the mapping parameters for an executable (PE) image */
static int get_image_params( struct mapping *mapping, int unix_fd, int protect )
static unsigned int get_image_params( struct mapping *mapping, int unix_fd, int protect )
{
IMAGE_DOS_HEADER dos;
IMAGE_SECTION_HEADER *sec = NULL;
@ -385,15 +387,48 @@ static int get_image_params( struct mapping *mapping, int unix_fd, int protect )
/* load the headers */
if (pread( unix_fd, &dos, sizeof(dos), 0 ) != sizeof(dos)) goto error;
if (dos.e_magic != IMAGE_DOS_SIGNATURE) goto error;
if (pread( unix_fd, &dos, sizeof(dos), 0 ) != sizeof(dos)) return STATUS_INVALID_IMAGE_NOT_MZ;
if (dos.e_magic != IMAGE_DOS_SIGNATURE) return STATUS_INVALID_IMAGE_NOT_MZ;
pos = dos.e_lfanew;
size = pread( unix_fd, &nt, sizeof(nt), pos );
if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) goto error;
if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) return STATUS_INVALID_IMAGE_FORMAT;
/* zero out Optional header in the case it's not present or partial */
if (size < sizeof(nt)) memset( (char *)&nt + size, 0, sizeof(nt) - size );
if (nt.Signature != IMAGE_NT_SIGNATURE) goto error;
if (nt.Signature != IMAGE_NT_SIGNATURE)
{
if (*(WORD *)&nt.Signature == IMAGE_OS2_SIGNATURE) return STATUS_INVALID_IMAGE_NE_FORMAT;
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)
{
@ -407,8 +442,6 @@ static int get_image_params( struct mapping *mapping, int unix_fd, int protect )
mapping->base = nt.opt.hdr64.ImageBase;
mapping->header_size = nt.opt.hdr64.SizeOfHeaders;
break;
default:
goto error;
}
/* load the section headers */
@ -426,12 +459,11 @@ static int get_image_params( struct mapping *mapping, int unix_fd, int protect )
mapping->protect = protect;
free( sec );
return 1;
return 0;
error:
free( sec );
set_error( STATUS_INVALID_FILE_FOR_SECTION );
return 0;
return STATUS_INVALID_FILE_FOR_SECTION;
}
static struct object *create_mapping( struct directory *root, const struct unicode_str *name,
@ -494,8 +526,10 @@ static struct object *create_mapping( struct directory *root, const struct unico
if ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error;
if (protect & VPROT_IMAGE)
{
if (!get_image_params( mapping, unix_fd, protect )) goto error;
return &mapping->obj;
unsigned int err = get_image_params( mapping, unix_fd, protect );
if (!err) return &mapping->obj;
set_error( err );
goto error;
}
if (fstat( unix_fd, &st ) == -1)
{
@ -680,29 +714,34 @@ DECL_HANDLER(get_mapping_info)
struct mapping *mapping;
struct fd *fd;
if ((mapping = get_mapping_obj( current->process, req->handle, req->access )))
if (!(mapping = get_mapping_obj( current->process, req->handle, req->access ))) return;
if ((mapping->protect & VPROT_IMAGE) && mapping->cpu != current->process->cpu)
{
reply->size = mapping->size;
reply->protect = mapping->protect;
reply->header_size = mapping->header_size;
reply->base = mapping->base;
reply->shared_file = 0;
if ((fd = get_obj_fd( &mapping->obj )))
{
if (!is_fd_removable(fd))
reply->mapping = alloc_handle( current->process, mapping, 0, 0 );
release_object( fd );
}
if (mapping->shared_file)
{
if (!(reply->shared_file = alloc_handle( current->process, mapping->shared_file,
GENERIC_READ|GENERIC_WRITE, 0 )))
{
if (reply->mapping) close_handle( current->process, reply->mapping );
}
}
set_error( STATUS_INVALID_IMAGE_FORMAT );
release_object( mapping );
return;
}
reply->size = mapping->size;
reply->protect = mapping->protect;
reply->header_size = mapping->header_size;
reply->base = mapping->base;
reply->shared_file = 0;
if ((fd = get_obj_fd( &mapping->obj )))
{
if (!is_fd_removable(fd)) reply->mapping = alloc_handle( current->process, mapping, 0, 0 );
release_object( fd );
}
if (mapping->shared_file)
{
if (!(reply->shared_file = alloc_handle( current->process, mapping->shared_file,
GENERIC_READ|GENERIC_WRITE, 0 )))
{
if (reply->mapping) close_handle( current->process, reply->mapping );
}
}
release_object( mapping );
}
/* get a range of committed pages in a file mapping */