From 63750fd4ed4ff8bb9b3ff8868d4e36e3422adb21 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 20 Jul 2016 09:16:49 +0200 Subject: [PATCH] Fix port to glibc 2.24 (pre-release) + ppc64 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * src/callproc.c (child_setup): Use emacs_exec_file so that ASLR is enabled in the child process. * src/emacs.c: Move some personality details into sys/sysdep.c. Do not include . (main): Disable ASLR earlier, so that we don’t chdir twice. * src/lisp.h (disable_address_randomization): New decl. * src/sysdep.c (disable_address_randomization) [HAVE_PERSONALITY_ADDR_NO_RANDOMIZE]: Move personality details here from emacs.c. (emacs_exec_file): New function. --- src/callproc.c | 4 ++-- src/emacs.c | 48 ++++++++++++++++++++++++------------------------ src/lisp.h | 6 ++++++ src/sysdep.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 26 deletions(-) diff --git a/src/callproc.c b/src/callproc.c index 9ec7893868d..487115d60c3 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -1317,8 +1317,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, setpgid (0, 0); tcsetpgrp (0, pid); - execve (new_argv[0], new_argv, env); - exec_failed (new_argv[0], errno); + int errnum = emacs_exec_file (new_argv[0], new_argv, env); + exec_failed (new_argv[0], errnum); #else /* MSDOS */ pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); diff --git a/src/emacs.c b/src/emacs.c index fa7ec017fb5..53bcc9879a9 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -112,10 +112,6 @@ extern void moncontrol (int mode); #include #endif -#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE -#include -#endif - static const char emacs_version[] = PACKAGE_VERSION; static const char emacs_copyright[] = COPYRIGHT; static const char emacs_bugreport[] = PACKAGE_BUGREPORT; @@ -685,6 +681,30 @@ main (int argc, char **argv) stack_base = &dummy; + dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0 + || strcmp (argv[argc - 1], "bootstrap") == 0); + + /* True if address randomization interferes with memory allocaiton. */ +# ifdef __PPC64__ + bool disable_aslr = true; +# else + bool disable_aslr = dumping; +# endif + + if (disable_aslr && disable_address_randomization ()) + { + /* Set this so the personality will be reverted before execs + after this one. */ + xputenv ("EMACS_HEAP_EXEC=true"); + + /* Address randomization was enabled, but is now disabled. + Re-execute Emacs to get a clean slate. */ + execvp (argv[0], argv); + + /* If the exec fails, warn and then try anyway. */ + perror (argv[0]); + } + #ifndef CANNOT_DUMP might_dump = !initialized; #endif @@ -793,26 +813,6 @@ main (int argc, char **argv) } } - dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0 - || strcmp (argv[argc - 1], "bootstrap") == 0); - -#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE - if (dumping) - { - int pers = personality (0xffffffff); - if (! (pers & ADDR_NO_RANDOMIZE) - && 0 <= personality (pers | ADDR_NO_RANDOMIZE)) - { - /* Address randomization was enabled, but is now disabled. - Re-execute Emacs to get a clean slate. */ - execvp (argv[0], argv); - - /* If the exec fails, warn and then try without a clean slate. */ - perror (argv[0]); - } - } -#endif - #if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK) && !defined (CYGWIN) /* Extend the stack space available. Don't do that if dumping, since some systems (e.g. DJGPP) might define a smaller stack diff --git a/src/lisp.h b/src/lisp.h index 48c27281643..39877d7bb4d 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4261,6 +4261,12 @@ struct tty_display_info; struct terminal; /* Defined in sysdep.c. */ +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE +extern bool disable_address_randomization (void); +#else +INLINE bool disable_address_randomization (void) { return false; } +#endif +extern int emacs_exec_file (char const *, char *const *, char *const *); extern void init_standard_fds (void); extern char *emacs_get_current_dir_name (void); extern void stuff_char (char c); diff --git a/src/sysdep.c b/src/sysdep.c index 56142a55cdf..16541735f03 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -129,6 +129,48 @@ static const int baud_convert[] = 1800, 2400, 4800, 9600, 19200, 38400 }; +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE +# include + +/* Disable address randomization in the current process. Return true + if addresses were randomized but this has been disabled, false + otherwise. */ +bool +disable_address_randomization (void) +{ + bool disabled = false; + int pers = personality (0xffffffff); + disabled = (! (pers & ADDR_NO_RANDOMIZE) + && 0 <= personality (pers | ADDR_NO_RANDOMIZE)); + return disabled; +} +#endif + +/* Execute the program in FILE, with argument vector ARGV and environ + ENVP. Return an error number if unsuccessful. This is like execve + except it reenables ASLR in the executed program if necessary, and + on error it returns an error number rather than -1. */ +int +emacs_exec_file (char const *file, char *const *argv, char *const *envp) +{ +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE + int pers = getenv ("EMACS_HEAP_EXEC") ? personality (0xffffffff) : -1; + bool change_personality = 0 <= pers && pers & ADDR_NO_RANDOMIZE; + if (change_personality) + personality (pers & ~ADDR_NO_RANDOMIZE); +#endif + + execve (file, argv, envp); + int err = errno; + +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE + if (change_personality) + personality (pers); +#endif + + return err; +} + /* If FD is not already open, arrange for it to be open with FLAGS. */ static void force_open (int fd, int flags) -- 2.39.2