diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 6c211b158c5..3b688cbde18 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -67,6 +67,7 @@ server_EXTRADEFS = \ -DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\" unix_loader_EXTRADEFS = \ + -DBINDIR=\"${bindir}\" \ -DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\" \ -DBIN_TO_DATADIR=\"`$(MAKEDEP) -R ${bindir} ${datadir}/wine`\" diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index 6c5f722b2a6..cd867e60284 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -1074,6 +1074,7 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd ) static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd, const char *unixdir, char *winedebug, const pe_image_info_t *pe_info ) { + const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64); pid_t pid; int stdin_fd = -1, stdout_fd = -1; char **argv; @@ -1103,7 +1104,8 @@ static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int soc if (winedebug) putenv( winedebug ); if (unixdir) chdir( unixdir ); - exec_wineloader( argv, socketfd, pe_info ); + unix_funcs->exec_wineloader( argv, socketfd, is_child_64bit, + pe_info->base, pe_info->base + pe_info->map_size ); _exit(1); } @@ -1533,12 +1535,14 @@ NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status ) if (!status) { + const int is_child_64bit = (pe_info.cpu == CPU_x86_64 || pe_info.cpu == CPU_ARM64); char **argv = build_argv( &strW, 2 ); if (argv) { do { - status = exec_wineloader( argv, socketfd[0], &pe_info ); + status = unix_funcs->exec_wineloader( argv, socketfd[0], is_child_64bit, + pe_info.base, pe_info.base + pe_info.map_size ); } #ifdef __APPLE__ while (errno == ENOTSUP && terminate_main_thread()); diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 28ac490d142..99e7b2a6476 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -121,12 +121,6 @@ static const enum cpu_type client_cpu = CPU_ARM64; #error Unsupported CPU #endif -#if defined(linux) || defined(__APPLE__) -static const BOOL use_preloader = TRUE; -#else -static const BOOL use_preloader = FALSE; -#endif - static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); const char *build_dir = NULL; @@ -1229,119 +1223,6 @@ int server_pipe( int fd[2] ) } -/*********************************************************************** - * preloader_exec - */ -static void preloader_exec( char **argv ) -{ - if (use_preloader) - { - static const char *preloader = "wine-preloader"; - char *p; - - if (!(p = strrchr( argv[1], '/' ))) p = argv[1]; - else p++; - - if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader"; - argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 ); - memcpy( argv[0], argv[1], p - argv[1] ); - strcpy( argv[0] + (p - argv[1]), preloader ); - -#ifdef __APPLE__ - { - posix_spawnattr_t attr; - posix_spawnattr_init( &attr ); - posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR ); - posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() ); - posix_spawnattr_destroy( &attr ); - } -#endif - execv( argv[0], argv ); - free( argv[0] ); - } - execv( argv[1], argv + 1 ); -} - - -/*********************************************************************** - * exec_wineloader - * - * argv[0] and argv[1] must be reserved for the preloader and loader respectively. - */ -NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info ) -{ - const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64); - const char *path, *loader = argv0; - const char *loader_env = getenv( "WINELOADER" ); - char *p, preloader_reserve[64], socket_env[64]; - ULONGLONG res_start = pe_info->base; - ULONGLONG res_end = pe_info->base + pe_info->map_size; - - if (!is_win64 ^ !is_child_64bit) - { - /* remap WINELOADER to the alternate 32/64-bit version if necessary */ - if (loader_env) - { - int len = strlen( loader_env ); - char *env = malloc( sizeof("WINELOADER=") + len + 2 ); - - if (!env) return STATUS_NO_MEMORY; - strcpy( env, "WINELOADER=" ); - strcat( env, loader_env ); - if (is_child_64bit) - { - strcat( env, "64" ); - } - else - { - len += sizeof("WINELOADER=") - 1; - if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0; - } - loader = env; - putenv( env ); - } - else loader = is_child_64bit ? "wine64" : "wine"; - } - - signal( SIGPIPE, SIG_DFL ); - - sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd ); - sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x", - (ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end ); - - putenv( preloader_reserve ); - putenv( socket_env ); - - if (build_dir) - { - argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" ); - preloader_exec( argv ); - return STATUS_INVALID_IMAGE_FORMAT; - } - - if ((p = strrchr( loader, '/' ))) loader = p + 1; - - argv[1] = build_path( bin_dir, loader ); - preloader_exec( argv ); - - argv[1] = getenv( "WINELOADER" ); - if (argv[1]) preloader_exec( argv ); - - if ((path = getenv( "PATH" ))) - { - for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" )) - { - argv[1] = build_path( p, loader ); - preloader_exec( argv ); - } - } - - argv[1] = build_path( BINDIR, loader ); - preloader_exec( argv ); - return STATUS_INVALID_IMAGE_FORMAT; -} - - /*********************************************************************** * exec_wineserver * diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index ab23b99f6f7..427eeaf4137 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef HAVE_PWD_H # include #endif @@ -50,6 +51,11 @@ # undef GetCurrentThread # include # include +# include +# include +# ifndef _POSIX_SPAWN_DISABLE_ASLR +# define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +# endif #endif #include "ntstatus.h" @@ -76,6 +82,14 @@ extern int __wine_main_argc; extern char **__wine_main_argv; extern char **__wine_main_environ; +#if defined(linux) || defined(__APPLE__) +static const BOOL use_preloader = TRUE; +#else +static const BOOL use_preloader = FALSE; +#endif + +static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); + static int main_argc; static char **main_argv; static char **main_envp; @@ -344,6 +358,121 @@ static void CDECL get_dll_path( const char ***paths, SIZE_T *maxlen ) } +static void preloader_exec( char **argv ) +{ + if (use_preloader) + { + static const char *preloader = "wine-preloader"; + char *p; + + if (!(p = strrchr( argv[1], '/' ))) p = argv[1]; + else p++; + + if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader"; + argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 ); + memcpy( argv[0], argv[1], p - argv[1] ); + strcpy( argv[0] + (p - argv[1]), preloader ); + +#ifdef __APPLE__ + { + posix_spawnattr_t attr; + posix_spawnattr_init( &attr ); + posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR ); + posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() ); + posix_spawnattr_destroy( &attr ); + } +#endif + execv( argv[0], argv ); + free( argv[0] ); + } + execv( argv[1], argv + 1 ); +} + +static NTSTATUS loader_exec( const char *loader, char **argv, int is_child_64bit ) +{ + char *p, *path; + + if (build_dir) + { + argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" ); + preloader_exec( argv ); + return STATUS_INVALID_IMAGE_FORMAT; + } + + if ((p = strrchr( loader, '/' ))) loader = p + 1; + + argv[1] = build_path( bin_dir, loader ); + preloader_exec( argv ); + + argv[1] = getenv( "WINELOADER" ); + if (argv[1]) preloader_exec( argv ); + + if ((path = getenv( "PATH" ))) + { + for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" )) + { + argv[1] = build_path( p, loader ); + preloader_exec( argv ); + } + } + + argv[1] = build_path( BINDIR, loader ); + preloader_exec( argv ); + return STATUS_INVALID_IMAGE_FORMAT; +} + + +/*********************************************************************** + * exec_wineloader + * + * argv[0] and argv[1] must be reserved for the preloader and loader respectively. + */ +static NTSTATUS CDECL exec_wineloader( char **argv, int socketfd, int is_child_64bit, + ULONGLONG res_start, ULONGLONG res_end ) +{ + const char *loader = argv0; + const char *loader_env = getenv( "WINELOADER" ); + char preloader_reserve[64], socket_env[64]; + + if (!is_win64 ^ !is_child_64bit) + { + /* remap WINELOADER to the alternate 32/64-bit version if necessary */ + if (loader_env) + { + int len = strlen( loader_env ); + char *env = malloc( sizeof("WINELOADER=") + len + 2 ); + + if (!env) return STATUS_NO_MEMORY; + strcpy( env, "WINELOADER=" ); + strcat( env, loader_env ); + if (is_child_64bit) + { + strcat( env, "64" ); + } + else + { + len += sizeof("WINELOADER=") - 1; + if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0; + } + loader = env; + putenv( env ); + } + else loader = is_child_64bit ? "wine64" : "wine"; + } + + signal( SIGPIPE, SIG_DFL ); + + sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd ); + sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x", + (ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end ); + + putenv( preloader_reserve ); + putenv( socket_env ); + + return loader_exec( loader, argv, is_child_64bit ); +} + + /************************************************************************* * map_so_dll * @@ -619,6 +748,7 @@ static struct unix_funcs unix_funcs = get_version, get_build_id, get_host_version, + exec_wineloader, map_so_dll, mmap_add_reserved_area, mmap_remove_reserved_area, diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index b1f319ae622..e7767fd5aac 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -36,6 +36,10 @@ struct unix_funcs const char * (CDECL *get_build_id)(void); void (CDECL *get_host_version)( const char **sysname, const char **release ); + /* loader functions */ + NTSTATUS (CDECL *exec_wineloader)( char **argv, int socketfd, int is_child_64bit, + ULONGLONG res_start, ULONGLONG res_end ); + /* virtual memory functions */ NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module ); void (CDECL *mmap_add_reserved_area)( void *addr, SIZE_T size );