summaryrefslogtreecommitdiff
path: root/src/sysdep.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2018-11-11 22:18:47 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2018-11-11 22:20:39 -0800
commitc14eab222c5208ec0650292c3771a3ee632fdb0d (patch)
treeca3ca2cd05505a7edcb1bb062e2a669f870255f5 /src/sysdep.c
parentb87c874aa1016939ccbee4cd3bd1384726cb2220 (diff)
downloademacs-c14eab222c5208ec0650292c3771a3ee632fdb0d.tar.gz
Fix dumping on GNU/Linux ppc64le
Problem reported by Thomas Fitzsimmons (Bug#33174). * src/emacs.c (main): Adjust to sysdep.c changes. * src/sysdep.c (exec_personality): New static var. (disable_address_randomization): Remove, replacing with ... (maybe_disable_address_randomization): ... this new function. Do not set or use an environment variable; use a command-line argument instead, and set the new static var. Migrate the emacs.c personality-change code to here, where it belongs. (emacs_exec_file): Simplify by using new static var.
Diffstat (limited to 'src/sysdep.c')
-rw-r--r--src/sysdep.c73
1 files changed, 47 insertions, 26 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index 7a0c8a8ab85..ddcb594f668 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -150,22 +150,52 @@ static const int baud_convert[] =
#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)
+/* If not -1, the personality that should be restored before exec. */
+static int exec_personality;
+
+/* Try to disable randomization if the current process needs it and
+ does not appear to have it already. */
+int
+maybe_disable_address_randomization (bool dumping, int argc, char **argv)
{
- int pers = personality (0xffffffff);
- if (pers < 0)
- return false;
- int desired_pers = pers | ADDR_NO_RANDOMIZE;
+ /* Undocumented Emacs option used only by this function. */
+ static char const aslr_disabled_option[] = "--__aslr-disabled";
- /* Call 'personality' twice, to detect buggy platforms like WSL
- where 'personality' always returns 0. */
- return (pers != desired_pers
- && personality (desired_pers) == pers
- && personality (0xffffffff) == desired_pers);
+ if (argc < 2 || strcmp (argv[1], aslr_disabled_option) != 0)
+ {
+ bool disable_aslr = dumping;
+# ifdef __PPC64__
+ disable_aslr = true;
+# endif
+ exec_personality = disable_aslr ? personality (0xffffffff) : -1;
+ if (exec_personality & ADDR_NO_RANDOMIZE)
+ exec_personality = -1;
+ if (exec_personality != -1
+ && personality (exec_personality | ADDR_NO_RANDOMIZE) != -1)
+ {
+ char **newargv = malloc ((argc + 2) * sizeof *newargv);
+ if (newargv)
+ {
+ /* Invoke self with undocumented option. */
+ newargv[0] = argv[0];
+ newargv[1] = (char *) aslr_disabled_option;
+ memcpy (&newargv[2], &argv[1], argc * sizeof *newargv);
+ execvp (newargv[0], newargv);
+ }
+
+ /* If malloc or execvp fails, warn and then try anyway. */
+ perror (argv[0]);
+ free (newargv);
+ }
+ }
+ else
+ {
+ /* Our earlier incarnation already disabled ASLR. */
+ argc--;
+ memmove (&argv[1], &argv[2], argc * sizeof *argv);
+ }
+
+ return argc;
}
#endif
@@ -177,21 +207,12 @@ 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);
+ if (exec_personality != -1)
+ personality (exec_personality);
#endif
execve (file, argv, envp);
- int err = errno;
-
-#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
- if (change_personality)
- personality (pers);
-#endif
-
- return err;
+ return errno;
}
/* If FD is not already open, arrange for it to be open with FLAGS. */