glibc 2.24 -- Release blockers

Message ID 57883236.3050801@cs.ucla.edu
State New, archived
Headers

Commit Message

Paul Eggert July 15, 2016, 12:45 a.m. UTC
  On 07/14/2016 01:27 PM, Florian Weimer wrote:
> GDB does this to disable randomization: 

Thanks. Emacs disables ASLR by invoking the 'setfattr -n user.pax.flags 
-v er' shell command on the Emacs executable before running it ('paxctl 
+a' on older systems). Does this approach not work on ppc64? If not, 
what shell command would work?

As a fallback, Emacs calls personality (PER_LINUX32 | ADDR_NO_RANDOMIZE) 
early on. Perhaps the PER_LINUX32 persona does not work on ppc64? If so, 
please try the attached patch against the emacs-25 branch, on ppc64 and 
ppc64le; this causes Emacs to simply turn on the ADDR_NO_RANDOMIZE flag 
instead. If this doesn't work, perhaps we need to migrate this 
personality-flag-setting into alloc.c's malloc_initialize_hook function, 
so that it operates before 'main' starts up.
  

Comments

Florian Weimer July 15, 2016, 10:52 a.m. UTC | #1
On 07/15/2016 02:45 AM, Paul Eggert wrote:
> On 07/14/2016 01:27 PM, Florian Weimer wrote:
>> GDB does this to disable randomization:
>
> Thanks. Emacs disables ASLR by invoking the 'setfattr -n user.pax.flags
> -v er' shell command on the Emacs executable before running it ('paxctl
> +a' on older systems). Does this approach not work on ppc64? If not,
> what shell command would work?

I have never seen these commands before.  On mainline Linux, you need to 
use setarch (perhaps from a shell script wrapper), and this calls 
personality internally.

Sinny wrapped the build with setarch on ppc64, and it worked.

> As a fallback, Emacs calls personality (PER_LINUX32 | ADDR_NO_RANDOMIZE)
> early on. Perhaps the PER_LINUX32 persona does not work on ppc64? If so,
> please try the attached patch against the emacs-25 branch, on ppc64 and
> ppc64le; this causes Emacs to simply turn on the ADDR_NO_RANDOMIZE flag
> instead. If this doesn't work, perhaps we need to migrate this
> personality-flag-setting into alloc.c's malloc_initialize_hook function,
> so that it operates before 'main' starts up.

The problem is that this happens at dump time only, while the issue 
occurs when running the dumped Emacs.  Furthermore, the personality 
system call (or at least ADDR_NO_RANDOMIZE) only applies to new process 
images, it does not affected the randomization decisions made at load 
time for the current process.

Thanks,
Florian
  
Dmitry V. Levin July 15, 2016, 11:32 a.m. UTC | #2
On Fri, Jul 15, 2016 at 12:52:33PM +0200, Florian Weimer wrote:
> On 07/15/2016 02:45 AM, Paul Eggert wrote:
> >On 07/14/2016 01:27 PM, Florian Weimer wrote:
> >>GDB does this to disable randomization:
> >
> >Thanks. Emacs disables ASLR by invoking the 'setfattr -n user.pax.flags
> >-v er' shell command on the Emacs executable before running it ('paxctl
> >+a' on older systems). Does this approach not work on ppc64? If not,
> >what shell command would work?
> 
> I have never seen these commands before.  On mainline Linux, you need to 
> use setarch (perhaps from a shell script wrapper), and this calls 
> personality internally.

One has to use personality(personality(0xffffffff)|ADDR_NO_RANDOMIZE)
approach as implemented in GDB, a simple shell script wrapper cannot
implement this.

user.pax.flags is a PaX specific, mainline linux kernel doesn't recognize
this attribute.
  
Florian Weimer July 15, 2016, 11:47 a.m. UTC | #3
On 07/15/2016 01:32 PM, Dmitry V. Levin wrote:
> On Fri, Jul 15, 2016 at 12:52:33PM +0200, Florian Weimer wrote:
>> On 07/15/2016 02:45 AM, Paul Eggert wrote:
>>> On 07/14/2016 01:27 PM, Florian Weimer wrote:
>>>> GDB does this to disable randomization:
>>>
>>> Thanks. Emacs disables ASLR by invoking the 'setfattr -n user.pax.flags
>>> -v er' shell command on the Emacs executable before running it ('paxctl
>>> +a' on older systems). Does this approach not work on ppc64? If not,
>>> what shell command would work?
>>
>> I have never seen these commands before.  On mainline Linux, you need to
>> use setarch (perhaps from a shell script wrapper), and this calls
>> personality internally.
>
> One has to use personality(personality(0xffffffff)|ADDR_NO_RANDOMIZE)
> approach as implemented in GDB, a simple shell script wrapper cannot
> implement this.

Would you please elaborate?

In my testing, the ADDR_NO_RANDOMIZE bit is inherited by subprocesses 
(which is a problem in itself, of course, because it disables hardening 
in network helpers used by Emacs).

Thanks,
Florian
  
Dmitry V. Levin July 15, 2016, 12:14 p.m. UTC | #4
On Fri, Jul 15, 2016 at 01:47:33PM +0200, Florian Weimer wrote:
> On 07/15/2016 01:32 PM, Dmitry V. Levin wrote:
> >On Fri, Jul 15, 2016 at 12:52:33PM +0200, Florian Weimer wrote:
> >>On 07/15/2016 02:45 AM, Paul Eggert wrote:
> >>>On 07/14/2016 01:27 PM, Florian Weimer wrote:
> >>>>GDB does this to disable randomization:
> >>>
> >>>Thanks. Emacs disables ASLR by invoking the 'setfattr -n user.pax.flags
> >>>-v er' shell command on the Emacs executable before running it ('paxctl
> >>>+a' on older systems). Does this approach not work on ppc64? If not,
> >>>what shell command would work?
> >>
> >>I have never seen these commands before.  On mainline Linux, you need to
> >>use setarch (perhaps from a shell script wrapper), and this calls
> >>personality internally.
> >
> >One has to use personality(personality(0xffffffff)|ADDR_NO_RANDOMIZE)
> >approach as implemented in GDB, a simple shell script wrapper cannot
> >implement this.
> 
> Would you please elaborate?

I mean setarch(8) is not versatile enough, it just rewrites personality
flags.  For example,

$ strace -qq -epersonality \
  setarch linux64 --sticky-timeouts setarch linux64 --addr-no-randomize true
personality(PER_LINUX|STICKY_TIMEOUTS)  = 0 (PER_LINUX)
personality(PER_LINUX|ADDR_NO_RANDOMIZE) = 0x4000000 (PER_LINUX|STICKY_TIMEOUTS)
  
Florian Weimer July 15, 2016, 12:23 p.m. UTC | #5
On 07/15/2016 02:14 PM, Dmitry V. Levin wrote:

> I mean setarch(8) is not versatile enough, it just rewrites personality
> flags.  For example,
>
> $ strace -qq -epersonality \
>   setarch linux64 --sticky-timeouts setarch linux64 --addr-no-randomize true
> personality(PER_LINUX|STICKY_TIMEOUTS)  = 0 (PER_LINUX)
> personality(PER_LINUX|ADDR_NO_RANDOMIZE) = 0x4000000 (PER_LINUX|STICKY_TIMEOUTS)

Ah, you mean that setarch is not cumulative and removes personality 
flags which have not been specified?

Thanks,
Florian
  
Dmitry V. Levin July 15, 2016, 12:33 p.m. UTC | #6
On Fri, Jul 15, 2016 at 02:23:37PM +0200, Florian Weimer wrote:
> On 07/15/2016 02:14 PM, Dmitry V. Levin wrote:
> 
> >I mean setarch(8) is not versatile enough, it just rewrites personality
> >flags.  For example,
> >
> >$ strace -qq -epersonality \
> >  setarch linux64 --sticky-timeouts setarch linux64 --addr-no-randomize 
> >  true
> >personality(PER_LINUX|STICKY_TIMEOUTS)  = 0 (PER_LINUX)
> >personality(PER_LINUX|ADDR_NO_RANDOMIZE) = 0x4000000 
> >(PER_LINUX|STICKY_TIMEOUTS)
> 
> Ah, you mean that setarch is not cumulative and removes personality 
> flags which have not been specified?

Yes, setarch is not cumulative.
  

Patch

From 86bbd2df5a8d8833fe6565bfdf5730fb4f429102 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Fri, 15 Jul 2016 02:20:13 +0200
Subject: [PATCH] Port to glibc 2.24 (pre-release) + ppc64

Inspired by a suggestion by Florian Weimer in:
https://sourceware.org/ml/libc-alpha/2016-07/msg00425.html
* configure.ac (HAVE_PERSONALITY_ADDR_NO_RANDOMIZE):
Rename from HAVE_PERSONALITY_LINUX32, and check for
ADDR_NO_RANDOMIZE (the crucial thing) instead of for LINUX32.
All uses changed.
* src/emacs.c (main) [HAVE_PERSONALITY_ADDR_NO_RANDOMIZE]:
Use ADDR_NO_RANDOMIZE from personality.h rather than inventing the
flag ourselves.  Just set that flag, rather than also setting the
persona.
---
 admin/CPP-DEFINES |  2 +-
 configure.ac      | 20 +++++++++++---------
 src/emacs.c       | 29 +++++++++++++++--------------
 3 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES
index 796b57d..d404dee 100644
--- a/admin/CPP-DEFINES
+++ b/admin/CPP-DEFINES
@@ -237,7 +237,7 @@  HAVE_NET_IF_DL_H
 HAVE_NET_IF_H
 HAVE_NLIST_H
 HAVE_OTF_GET_VARIATION_GLYPHS
-HAVE_PERSONALITY_LINUX32
+HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
 HAVE_PNG
 HAVE_PNG_H
 HAVE_POSIX_MEMALIGN
diff --git a/configure.ac b/configure.ac
index 678e98e..9da23d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1615,15 +1615,17 @@  AC_CHECK_HEADERS_ONCE(
   sys/resource.h
   sys/utsname.h pwd.h utmp.h util.h)
 
-AC_MSG_CHECKING(if personality LINUX32 can be set)
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/personality.h>]], [[personality (PER_LINUX32)]])],
-               emacs_cv_personality_linux32=yes,
-	       emacs_cv_personality_linux32=no)
-AC_MSG_RESULT($emacs_cv_personality_linux32)
-
-if test $emacs_cv_personality_linux32 = yes; then
-  AC_DEFINE(HAVE_PERSONALITY_LINUX32, 1,
-            [Define to 1 if personality LINUX32 can be set.])
+AC_CACHE_CHECK([if personality ADDR_NO_RANDOMIZE flag exists],
+  [emacs_cv_personality_addr_no_randomize],
+  [AC_COMPILE_IFELSE(
+     [AC_LANG_PROGRAM([[#include <sys/personality.h>]],
+		      [[personality (personality (0xffffffff)
+				     | ADDR_NO_RANDOMIZE)]])],
+     [emacs_cv_personality_addr_no_randomize=yes],
+     [emacs_cv_personality_addr_no_randomize=no])])
+if test $emacs_cv_personality_addr_no_randomize = yes; then
+  AC_DEFINE([HAVE_PERSONALITY_ADDR_NO_RANDOMIZE], [1],
+            [Define to 1 if personality flag ADDR_NO_RANDOMIZE exists.])
 fi
 
 # Note that Solaris has sys/sysinfo.h which defines struct
diff --git a/src/emacs.c b/src/emacs.c
index 5c187e7..fcf68a3 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -106,7 +106,7 @@  extern void moncontrol (int mode);
 #include <sys/resource.h>
 #endif
 
-#ifdef HAVE_PERSONALITY_LINUX32
+#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
 #include <sys/personality.h>
 #endif
 
@@ -784,24 +784,25 @@  main (int argc, char **argv)
   dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0
 			     || strcmp (argv[argc - 1], "bootstrap") == 0);
 
-#ifdef HAVE_PERSONALITY_LINUX32
+#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
   if (dumping && ! getenv ("EMACS_HEAP_EXEC"))
     {
-      /* Set this so we only do this once.  */
-      xputenv ("EMACS_HEAP_EXEC=true");
-
-      /* A flag to turn off address randomization which is introduced
-         in linux kernel shipped with fedora core 4 */
-#define ADD_NO_RANDOMIZE 0x0040000
-      personality (PER_LINUX32 | ADD_NO_RANDOMIZE);
-#undef  ADD_NO_RANDOMIZE
+      /* Disable address randomization if possible, as it interferes
+	 with dumping.  */
+      int pers = personality (0xffffffff);
+      if (0 <= pers && (pers & ADDR_NO_RANDOMIZE) == 0
+	  && 0 <= personality (pers | ADDR_NO_RANDOMIZE))
+	{
+	  /* Set this so we only do this once.  */
+	  xputenv ("EMACS_HEAP_EXEC=true");
 
-      execvp (argv[0], argv);
+	  execvp (argv[0], argv);
 
-      /* If the exec fails, try to dump anyway.  */
-      emacs_perror (argv[0]);
+	  /* If the exec fails, try to dump anyway.  */
+	  emacs_perror (argv[0]);
+	}
     }
-#endif /* HAVE_PERSONALITY_LINUX32 */
+#endif
 
 #if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK) && !defined (CYGWIN)
   /* Extend the stack space available.  Don't do that if dumping,
-- 
2.5.5