ASLR can allow dyld to be loaded where it overlaps one of the regions that the preloader would like to reserve. That, in turn, can prevent Wine from using the shared user data region. With ASLR disabled, dyld will be loaded immediately after the preloader, which has a defined base address.
This uses an Apple extension to posix_spawn() that allows it to replace the calling process's image, like a more featureful execve(). The flag to disable ASLR is technically private SPI, but has remained stable for many versions of the OS. And the Mac preloader is already stepping over that line.
Signed-off-by: Ken Thomases ken@codeweavers.com --- libs/wine/config.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/libs/wine/config.c b/libs/wine/config.c index 083e263..b1f526c 100644 --- a/libs/wine/config.c +++ b/libs/wine/config.c @@ -33,6 +33,13 @@ #ifdef HAVE_PWD_H #include <pwd.h> #endif +#ifdef __APPLE__ +#include <crt_externs.h> +#include <spawn.h> +#ifndef _POSIX_SPAWN_DISABLE_ASLR +#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +#endif +#endif #include "wine/library.h"
static const char server_config_dir[] = "/.wine"; /* config dir relative to $HOME */ @@ -558,6 +565,15 @@ static void preloader_exec( char **argv, int use_preloader ) new_argv = xmalloc( (last_arg - argv + 2) * sizeof(*argv) ); memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) ); new_argv[0] = full_name; +#ifdef __APPLE__ + { + posix_spawnattr_t attr; + posix_spawnattr_init( &attr ); + posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR ); + posix_spawn( NULL, full_name, NULL, &attr, new_argv, *_NSGetEnviron() ); + posix_spawnattr_destroy( &attr ); + } +#endif execv( full_name, new_argv ); free( new_argv ); free( full_name );
On macOS 10.14 (Mojave), there's a system-wide VM mapping for common system libraries starting at 0x00007fff00000000.
Signed-off-by: Ken Thomases ken@codeweavers.com --- loader/preloader_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/loader/preloader_mac.c b/loader/preloader_mac.c index 83d24af..ff62d32 100644 --- a/loader/preloader_mac.c +++ b/loader/preloader_mac.c @@ -78,7 +78,7 @@ static struct wine_preload_info preload_info[] = { (void *)0x000000010000, 0x00100000 }, /* DOS area */ { (void *)0x000000110000, 0x67ef0000 }, /* low memory area */ { (void *)0x00007ff00000, 0x000f0000 }, /* shared user data */ - { (void *)0x7fff40000000, 0x01ff0000 }, /* top-down allocations + virtual heap */ + { (void *)0x7ffef0000000, 0x01ff0000 }, /* top-down allocations + virtual heap */ #endif /* __i386__ */ { 0, 0 }, /* PE exe range set with WINEPRELOADRESERVE */ { 0, 0 } /* end of list */