]> code.delx.au - gnu-emacs/commitdiff
Fix port to glibc 2.24 (pre-release) + ppc64
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 20 Jul 2016 07:16:49 +0000 (09:16 +0200)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 20 Jul 2016 07:49:41 +0000 (09:49 +0200)
* 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 <sys/personality.h>.
(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
src/emacs.c
src/lisp.h
src/sysdep.c

index 9ec7893868def87f000489a8a2101f77a691da0b..487115d60c38d4642ab80fcc9e8349490aa218b1 100644 (file)
@@ -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);
index fa7ec017fb53a14f8422d87d5fa43cf768a16ece..53bcc9879a9a5671a47b67e2385286a75fe83e73 100644 (file)
@@ -112,10 +112,6 @@ extern void moncontrol (int mode);
 #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;
@@ -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
index 48c27281643f2f9bbd127ca2a099db2ba344ef9b..39877d7bb4d89cc1b3622211946014923a7f029e 100644 (file)
@@ -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);
index 56142a55cdfd700093d8f36b02442a7cfe37ff36..16541735f036ec31a466411727d5eea3aa856742 100644 (file)
@@ -129,6 +129,48 @@ static const int baud_convert[] =
     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)