]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix dumping on GNU/Linux ppc64le
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 12 Nov 2018 06:18:47 +0000 (22:18 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 12 Nov 2018 06:20:39 +0000 (22:20 -0800)
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.

src/emacs.c
src/lisp.h
src/sysdep.c

index 07df191035c80e6361ee038ea12a7688e1438a23..512174d562e601d67caebc5a136e40b045bc1f1c 100644 (file)
@@ -706,28 +706,7 @@ main (int argc, char **argv)
   dumping = false;
 #endif
 
-  /* True if address randomization interferes with memory allocation.  */
-# ifdef __PPC64__
-  bool disable_aslr = true;
-# else
-  bool disable_aslr = dumping;
-# endif
-
-  if (disable_aslr && disable_address_randomization ()
-      && !getenv ("EMACS_HEAP_EXEC"))
-    {
-      /* Set this so the personality will be reverted before execs
-        after this one, and to work around an re-exec loop on buggy
-        kernels (Bug#32083).  */
-      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]);
-    }
+  argc = maybe_disable_address_randomization (dumping, argc, argv);
 
 #ifndef CANNOT_DUMP
   might_dump = !initialized;
index eb6762678c7f5da03bb56e04aa21f43c229cdfb0..383d61274c43b223d4554db8e77532a9602677ca 100644 (file)
@@ -4325,9 +4325,12 @@ struct tty_display_info;
 
 /* Defined in sysdep.c.  */
 #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
-extern bool disable_address_randomization (void);
+extern int maybe_disable_address_randomization (bool, int, char **);
 #else
-INLINE bool disable_address_randomization (void) { return false; }
+INLINE void
+maybe_disable_address_randomization (bool dumping, int argc, char **argv)
+{
+}
 #endif
 extern int emacs_exec_file (char const *, char *const *, char *const *);
 extern void init_standard_fds (void);
index 7a0c8a8ab85c048243695983fab893ff4f276b41..ddcb594f6681735d2a15e9ef5359de0e1b194cc9 100644 (file)
@@ -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.  */