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);
#include <sys/resource.h>
#endif
-#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
-#include <sys/personality.h>
-#endif
-
static const char emacs_version[] = PACKAGE_VERSION;
static const char emacs_copyright[] = COPYRIGHT;
static const char emacs_bugreport[] = PACKAGE_BUGREPORT;
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
}
}
- 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
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);
1800, 2400, 4800, 9600, 19200, 38400
};
+#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
+# include <sys/personality.h>
+
+/* 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)