diff options
| author | Paul Eggert | 2018-11-11 22:18:47 -0800 |
|---|---|---|
| committer | Paul Eggert | 2018-11-11 22:20:39 -0800 |
| commit | c14eab222c5208ec0650292c3771a3ee632fdb0d (patch) | |
| tree | ca3ca2cd05505a7edcb1bb062e2a669f870255f5 /src | |
| parent | b87c874aa1016939ccbee4cd3bd1384726cb2220 (diff) | |
| download | emacs-c14eab222c5208ec0650292c3771a3ee632fdb0d.tar.gz emacs-c14eab222c5208ec0650292c3771a3ee632fdb0d.zip | |
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')
| -rw-r--r-- | src/emacs.c | 23 | ||||
| -rw-r--r-- | src/lisp.h | 7 | ||||
| -rw-r--r-- | src/sysdep.c | 73 |
3 files changed, 53 insertions, 50 deletions
diff --git a/src/emacs.c b/src/emacs.c index 07df191035c..512174d562e 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -706,28 +706,7 @@ main (int argc, char **argv) | |||
| 706 | dumping = false; | 706 | dumping = false; |
| 707 | #endif | 707 | #endif |
| 708 | 708 | ||
| 709 | /* True if address randomization interferes with memory allocation. */ | 709 | argc = maybe_disable_address_randomization (dumping, argc, argv); |
| 710 | # ifdef __PPC64__ | ||
| 711 | bool disable_aslr = true; | ||
| 712 | # else | ||
| 713 | bool disable_aslr = dumping; | ||
| 714 | # endif | ||
| 715 | |||
| 716 | if (disable_aslr && disable_address_randomization () | ||
| 717 | && !getenv ("EMACS_HEAP_EXEC")) | ||
| 718 | { | ||
| 719 | /* Set this so the personality will be reverted before execs | ||
| 720 | after this one, and to work around an re-exec loop on buggy | ||
| 721 | kernels (Bug#32083). */ | ||
| 722 | xputenv ("EMACS_HEAP_EXEC=true"); | ||
| 723 | |||
| 724 | /* Address randomization was enabled, but is now disabled. | ||
| 725 | Re-execute Emacs to get a clean slate. */ | ||
| 726 | execvp (argv[0], argv); | ||
| 727 | |||
| 728 | /* If the exec fails, warn and then try anyway. */ | ||
| 729 | perror (argv[0]); | ||
| 730 | } | ||
| 731 | 710 | ||
| 732 | #ifndef CANNOT_DUMP | 711 | #ifndef CANNOT_DUMP |
| 733 | might_dump = !initialized; | 712 | might_dump = !initialized; |
diff --git a/src/lisp.h b/src/lisp.h index eb6762678c7..383d61274c4 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4325,9 +4325,12 @@ struct tty_display_info; | |||
| 4325 | 4325 | ||
| 4326 | /* Defined in sysdep.c. */ | 4326 | /* Defined in sysdep.c. */ |
| 4327 | #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE | 4327 | #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE |
| 4328 | extern bool disable_address_randomization (void); | 4328 | extern int maybe_disable_address_randomization (bool, int, char **); |
| 4329 | #else | 4329 | #else |
| 4330 | INLINE bool disable_address_randomization (void) { return false; } | 4330 | INLINE void |
| 4331 | maybe_disable_address_randomization (bool dumping, int argc, char **argv) | ||
| 4332 | { | ||
| 4333 | } | ||
| 4331 | #endif | 4334 | #endif |
| 4332 | extern int emacs_exec_file (char const *, char *const *, char *const *); | 4335 | extern int emacs_exec_file (char const *, char *const *, char *const *); |
| 4333 | extern void init_standard_fds (void); | 4336 | extern void init_standard_fds (void); |
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[] = | |||
| 150 | #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE | 150 | #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE |
| 151 | # include <sys/personality.h> | 151 | # include <sys/personality.h> |
| 152 | 152 | ||
| 153 | /* Disable address randomization in the current process. Return true | 153 | /* If not -1, the personality that should be restored before exec. */ |
| 154 | if addresses were randomized but this has been disabled, false | 154 | static int exec_personality; |
| 155 | otherwise. */ | 155 | |
| 156 | bool | 156 | /* Try to disable randomization if the current process needs it and |
| 157 | disable_address_randomization (void) | 157 | does not appear to have it already. */ |
| 158 | int | ||
| 159 | maybe_disable_address_randomization (bool dumping, int argc, char **argv) | ||
| 158 | { | 160 | { |
| 159 | int pers = personality (0xffffffff); | 161 | /* Undocumented Emacs option used only by this function. */ |
| 160 | if (pers < 0) | 162 | static char const aslr_disabled_option[] = "--__aslr-disabled"; |
| 161 | return false; | ||
| 162 | int desired_pers = pers | ADDR_NO_RANDOMIZE; | ||
| 163 | 163 | ||
| 164 | /* Call 'personality' twice, to detect buggy platforms like WSL | 164 | if (argc < 2 || strcmp (argv[1], aslr_disabled_option) != 0) |
| 165 | where 'personality' always returns 0. */ | 165 | { |
| 166 | return (pers != desired_pers | 166 | bool disable_aslr = dumping; |
| 167 | && personality (desired_pers) == pers | 167 | # ifdef __PPC64__ |
| 168 | && personality (0xffffffff) == desired_pers); | 168 | disable_aslr = true; |
| 169 | # endif | ||
| 170 | exec_personality = disable_aslr ? personality (0xffffffff) : -1; | ||
| 171 | if (exec_personality & ADDR_NO_RANDOMIZE) | ||
| 172 | exec_personality = -1; | ||
| 173 | if (exec_personality != -1 | ||
| 174 | && personality (exec_personality | ADDR_NO_RANDOMIZE) != -1) | ||
| 175 | { | ||
| 176 | char **newargv = malloc ((argc + 2) * sizeof *newargv); | ||
| 177 | if (newargv) | ||
| 178 | { | ||
| 179 | /* Invoke self with undocumented option. */ | ||
| 180 | newargv[0] = argv[0]; | ||
| 181 | newargv[1] = (char *) aslr_disabled_option; | ||
| 182 | memcpy (&newargv[2], &argv[1], argc * sizeof *newargv); | ||
| 183 | execvp (newargv[0], newargv); | ||
| 184 | } | ||
| 185 | |||
| 186 | /* If malloc or execvp fails, warn and then try anyway. */ | ||
| 187 | perror (argv[0]); | ||
| 188 | free (newargv); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | else | ||
| 192 | { | ||
| 193 | /* Our earlier incarnation already disabled ASLR. */ | ||
| 194 | argc--; | ||
| 195 | memmove (&argv[1], &argv[2], argc * sizeof *argv); | ||
| 196 | } | ||
| 197 | |||
| 198 | return argc; | ||
| 169 | } | 199 | } |
| 170 | #endif | 200 | #endif |
| 171 | 201 | ||
| @@ -177,21 +207,12 @@ int | |||
| 177 | emacs_exec_file (char const *file, char *const *argv, char *const *envp) | 207 | emacs_exec_file (char const *file, char *const *argv, char *const *envp) |
| 178 | { | 208 | { |
| 179 | #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE | 209 | #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE |
| 180 | int pers = getenv ("EMACS_HEAP_EXEC") ? personality (0xffffffff) : -1; | 210 | if (exec_personality != -1) |
| 181 | bool change_personality = 0 <= pers && pers & ADDR_NO_RANDOMIZE; | 211 | personality (exec_personality); |
| 182 | if (change_personality) | ||
| 183 | personality (pers & ~ADDR_NO_RANDOMIZE); | ||
| 184 | #endif | 212 | #endif |
| 185 | 213 | ||
| 186 | execve (file, argv, envp); | 214 | execve (file, argv, envp); |
| 187 | int err = errno; | 215 | return errno; |
| 188 | |||
| 189 | #ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE | ||
| 190 | if (change_personality) | ||
| 191 | personality (pers); | ||
| 192 | #endif | ||
| 193 | |||
| 194 | return err; | ||
| 195 | } | 216 | } |
| 196 | 217 | ||
| 197 | /* If FD is not already open, arrange for it to be open with FLAGS. */ | 218 | /* If FD is not already open, arrange for it to be open with FLAGS. */ |