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.
This commit is contained in:
Paul Eggert 2018-11-11 22:18:47 -08:00
parent b87c874aa1
commit c14eab222c
3 changed files with 54 additions and 51 deletions

View 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;

View 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);

View 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)
{
int pers = personality (0xffffffff);
if (pers < 0)
return false;
int desired_pers = pers | ADDR_NO_RANDOMIZE;
/* If not -1, the personality that should be restored before exec. */
static int exec_personality;
/* 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);
/* 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)
{
/* Undocumented Emacs option used only by this function. */
static char const aslr_disabled_option[] = "--__aslr-disabled";
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. */