public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Improved ASLR
@ 2020-11-25 11:36 Topi Miettinen
  2020-11-25 11:36 ` [PATCH 1/3] csu: randomize location of TCB Topi Miettinen
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Topi Miettinen @ 2020-11-25 11:36 UTC (permalink / raw)
  To: libc-alpha; +Cc: Topi Miettinen

Problem with using sbrk() for allocations is that the location of the
memory is relatively predicatable since it's always located next to
data segment. This series makes malloc() and TCB use mmap() instead,
except when instructed by tunable glibc.malloc.use_sbrk.

Topi Miettinen (3):
  csu: randomize location of TCB
  malloc: use mmap() to improve ASLR
  dl-sysdep: disable remaining calls to sbrk()

 csu/libc-tls.c                          | 48 +++++++++++++++++++++----
 elf/dl-sysdep.c                         | 11 +++++-
 elf/dl-tunables.list                    |  7 ++++
 malloc/arena.c                          | 11 ++++--
 malloc/morecore.c                       | 10 ++++++
 manual/tunables.texi                    |  5 +++
 sysdeps/unix/sysv/linux/dl-sysdep.c     | 10 ++++++
 sysdeps/unix/sysv/linux/mmap64.c        | 19 ++++++++++
 sysdeps/unix/sysv/linux/mmap_internal.h |  5 +++
 9 files changed, 117 insertions(+), 9 deletions(-)


base-commit: aa7e05c3043302403e91b85c4aea39e0aac6c7c8
-- 
2.29.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] csu: randomize location of TCB
  2020-11-25 11:36 [PATCH 0/3] Improved ASLR Topi Miettinen
@ 2020-11-25 11:36 ` Topi Miettinen
  2020-11-25 13:18   ` Adhemerval Zanella
  2020-11-25 17:49   ` Topi Miettinen
  2020-11-25 11:36 ` [PATCH 2/3] malloc: use mmap() to improve ASLR Topi Miettinen
  2020-11-25 11:36 ` [PATCH 3/3] dl-sysdep: disable remaining calls to sbrk() Topi Miettinen
  2 siblings, 2 replies; 7+ messages in thread
From: Topi Miettinen @ 2020-11-25 11:36 UTC (permalink / raw)
  To: libc-alpha; +Cc: Topi Miettinen

Use mmap() for allocating TCB except if instructed by tunable
glibc.malloc.use_sbrk. This makes the location of TCB random instead
of always staying predictably next to data segment. When using mmap(),
improve the logic so that allocation of TCB can be assumed to fail
insted of segfaulting.

--
v2: introduce a tunable to use sbrk()

Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
---
 csu/libc-tls.c                          | 48 +++++++++++++++++++++----
 elf/dl-tunables.list                    |  7 ++++
 manual/tunables.texi                    |  5 +++
 sysdeps/unix/sysv/linux/mmap64.c        | 19 ++++++++++
 sysdeps/unix/sysv/linux/mmap_internal.h |  5 +++
 5 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index c3589f0a7d..38c1e3a532 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -25,11 +25,21 @@
 #include <sys/param.h>
 #include <array_length.h>
 #include <list.h>
+#include <sys/mman.h>
+#include <sysdep.h>
+
+#define HAVE_MMAP_INTERNAL 0
+#include <mmap_internal.h>
 
 #ifdef SHARED
  #error makefile bug, this file is for static only
 #endif
 
+#if HAVE_TUNABLES
+# define TUNABLE_NAMESPACE malloc
+#endif
+#include <elf/dl-tunables.h>
+
 dtv_t _dl_static_dtv[2 + TLS_SLOTINFO_SURPLUS];
 
 
@@ -135,25 +145,51 @@ __libc_setup_tls (void)
 
   /* We have to set up the TCB block which also (possibly) contains
      'errno'.  Therefore we avoid 'malloc' which might touch 'errno'.
-     Instead we use 'sbrk' which would only uses 'errno' if it fails.
-     In this case we are right away out of memory and the user gets
-     what she/he deserves.  */
+     Instead we use '__mmap_internal' (when available) which does not
+     use 'errno', except if instructed by tunable
+     glibc.malloc.use_sbrk to use 'sbrk()' instead. If 'sbrk()' fails,
+     it will access 'errno' with catastrophic results. */
+
+  int error = 0;
+#if HAVE_TUNABLES && HAVE_MMAP_INTERNAL
+  int use_sbrk = 0;
+  use_sbrk = TUNABLE_GET (use_sbrk, int32_t, NULL);
+#endif
+
 #if TLS_TCB_AT_TP
   /* Align the TCB offset to the maximum alignment, as
      _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
      and dl_tls_static_align.  */
   tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align);
-  tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
+  size_t tlsblock_size = tcb_offset + TLS_INIT_TCB_SIZE + max_align;
+#if HAVE_MMAP_INTERNAL
+  if (!use_sbrk)
+    tlsblock = __mmap_internal (NULL, tlsblock_size, PROT_READ | PROT_WRITE,
+				MAP_ANONYMOUS | MAP_PRIVATE, -1, 0, &error);
+  else
+#endif
+    tlsblock = __sbrk (tlsblock_size);
+
 #elif TLS_DTV_AT_TP
   tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
-  tlsblock = __sbrk (tcb_offset + memsz + max_align
-		     + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus));
+  size_t tlsblock_size = tcb_offset + memsz + max_align
+	  + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus);
+#if HAS_MMAP_INTERNAL
+  if (!use_sbrk)
+    tlsblock = __mmap_internal (NULL, tlsblock_size, PROT_READ | PROT_WRITE,
+				MAP_ANONYMOUS | MAP_PRIVATE, -1, 0, &error);
+  else
+#endif
+    tlsblock = __sbrk (tlsblock_size);
+
   tlsblock += TLS_PRE_TCB_SIZE;
 #else
   /* In case a model with a different layout for the TCB and DTV
      is defined add another #elif here and in the following #ifs.  */
 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
 #endif
+  if (error)
+    _startup_fatal ("Cannot allocate TCB");
 
   /* Align the TLS block.  */
   tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index e1d8225128..777ebee788 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -91,6 +91,13 @@ glibc {
       minval: 0
       security_level: SXID_IGNORE
     }
+    use_sbrk {
+      type: INT_32
+      minval: 0
+      maxval: 1
+      default: 0
+      security_level: SXID_IGNORE
+    }
   }
   cpu {
     hwcap_mask {
diff --git a/manual/tunables.texi b/manual/tunables.texi
index d72d7a5ec0..46132900e3 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -227,6 +227,11 @@ pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size
 passed to @code{malloc} for the largest bin size to enable.
 @end deftp
 
+@deftp Tunable glibc.malloc.use_sbrk
+A value of 1 instructs @theglibc{} to use @code{sbrk()} for memory
+allocation instead of @code{mmap()}.
+@end deftp
+
 @node Dynamic Linking Tunables
 @section Dynamic Linking Tunables
 @cindex dynamic linking tunables
diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c
index 8074deb466..11f7c3f99b 100644
--- a/sysdeps/unix/sysv/linux/mmap64.c
+++ b/sysdeps/unix/sysv/linux/mmap64.c
@@ -67,3 +67,22 @@ weak_alias (__mmap64, mmap)
 weak_alias (__mmap64, __mmap)
 libc_hidden_def (__mmap)
 #endif
+
+void *
+__mmap_internal (void *addr, size_t len, int prot, int flags, int fd, off64_t offset, int *error)
+{
+  unsigned long int ret;
+#ifdef __NR_mmap2
+  ret = INTERNAL_SYSCALL_CALL (mmap2, addr, len, prot, flags, fd,
+			     (off_t) (offset / MMAP2_PAGE_UNIT));
+#else
+  ret = INTERNAL_SYSCALL_CALL (mmap, addr, len, prot, flags, fd, offset);
+#endif
+  if (INTERNAL_SYSCALL_ERROR_P(ret))
+    {
+      *error = ret;
+      return MAP_FAILED;
+    }
+
+  return (void *) ret;
+}
diff --git a/sysdeps/unix/sysv/linux/mmap_internal.h b/sysdeps/unix/sysv/linux/mmap_internal.h
index d53f0c642a..6e90f6f71e 100644
--- a/sysdeps/unix/sysv/linux/mmap_internal.h
+++ b/sysdeps/unix/sysv/linux/mmap_internal.h
@@ -46,4 +46,9 @@ static uint64_t page_unit;
   INLINE_SYSCALL_CALL (__nr, __addr, __len, __prot, __flags, __fd, __offset)
 #endif
 
+#undef HAVE_MMAP_INTERNAL
+#define HAVE_MMAP_INTERNAL 1
+/* Internal version of mmap() which doesn't attempt to access errno */
+void *__mmap_internal (void *addr, size_t len, int prot, int flags, int fd, off64_t offset, int *error);
+
 #endif /* MMAP_INTERNAL_LINUX_H  */
-- 
2.29.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/3] malloc: use mmap() to improve ASLR
  2020-11-25 11:36 [PATCH 0/3] Improved ASLR Topi Miettinen
  2020-11-25 11:36 ` [PATCH 1/3] csu: randomize location of TCB Topi Miettinen
@ 2020-11-25 11:36 ` Topi Miettinen
  2020-11-25 11:36 ` [PATCH 3/3] dl-sysdep: disable remaining calls to sbrk() Topi Miettinen
  2 siblings, 0 replies; 7+ messages in thread
From: Topi Miettinen @ 2020-11-25 11:36 UTC (permalink / raw)
  To: libc-alpha; +Cc: Topi Miettinen

sbrk() returns rather predictable allocations because they are located
close to the data segment. Let's use mmap() instead, except if
instructed by a tunable.

--
v2: use tunable

Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
---
 malloc/arena.c    | 11 +++++++++--
 malloc/morecore.c | 10 ++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/malloc/arena.c b/malloc/arena.c
index 202daf15b0..129e231bae 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -295,14 +295,21 @@ ptmalloc_init (void)
 
 #ifdef SHARED
   /* In case this libc copy is in a non-default namespace, never use brk.
-     Likewise if dlopened from statically linked program.  */
+     Likewise if dlopened from statically linked program.
+     Otherwise the use of brk is controlled by a tunable
+     glibc.malloc.use_sbrk. */
   Dl_info di;
   struct link_map *l;
 
   if (_dl_open_hook != NULL
       || (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0
-          && l->l_ns != LM_ID_BASE))
+          && l->l_ns != LM_ID_BASE)
+#if HAVE_TUNABLES
+      || !TUNABLE_GET (use_sbrk, int32_t, NULL)
+#endif
+      )
     __morecore = __failing_morecore;
+
 #endif
 
   thread_arena = &main_arena;
diff --git a/malloc/morecore.c b/malloc/morecore.c
index 72e655f84f..d5da5ffc45 100644
--- a/malloc/morecore.c
+++ b/malloc/morecore.c
@@ -38,12 +38,22 @@ libc_hidden_proto (__sbrk)
 # define NULL 0
 #endif
 
+#if HAVE_TUNABLES
+# define TUNABLE_NAMESPACE malloc
+#endif
+#include <elf/dl-tunables.h>
+
 /* Allocate INCREMENT more bytes of data space,
    and return the start of data space, or NULL on errors.
    If INCREMENT is negative, shrink data space.  */
 void *
 __default_morecore (ptrdiff_t increment)
 {
+  /* Tunable glibc.malloc.use_sbrk controls use of 'sbrk()'. */
+#if HAVE_TUNABLES
+  if (!TUNABLE_GET (use_sbrk, int32_t, NULL))
+    return NULL;
+#endif
   void *result = (void *) __sbrk (increment);
   if (result == (void *) -1)
     return NULL;
-- 
2.29.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/3] dl-sysdep: disable remaining calls to sbrk()
  2020-11-25 11:36 [PATCH 0/3] Improved ASLR Topi Miettinen
  2020-11-25 11:36 ` [PATCH 1/3] csu: randomize location of TCB Topi Miettinen
  2020-11-25 11:36 ` [PATCH 2/3] malloc: use mmap() to improve ASLR Topi Miettinen
@ 2020-11-25 11:36 ` Topi Miettinen
  2 siblings, 0 replies; 7+ messages in thread
From: Topi Miettinen @ 2020-11-25 11:36 UTC (permalink / raw)
  To: libc-alpha; +Cc: Topi Miettinen

When sbrk() is not used for memory allocations, there's no need to
initialize the break anymore.

--
v2: use tunable

Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
---
 elf/dl-sysdep.c                     | 11 ++++++++++-
 sysdeps/unix/sysv/linux/dl-sysdep.c | 10 ++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index 854570821c..406b3a3809 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -44,6 +44,10 @@
 #include <libc-internal.h>
 #include <tls.h>
 
+#if HAVE_TUNABLES
+# undef TUNABLE_NAMESPACE
+# define TUNABLE_NAMESPACE malloc
+#endif
 #include <dl-tunables.h>
 #include <dl-auxv.h>
 
@@ -234,7 +238,12 @@ _dl_sysdep_start (void **start_argptr,
   if (GLRO(dl_platform) != NULL)
     GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
 
-  if (__sbrk (0) == _end)
+  /* Tunable glibc.malloc.use_sbrk controls use of 'sbrk()'. */
+  if (
+#if HAVE_TUNABLES
+      TUNABLE_GET (use_sbrk, int32_t, NULL) &&
+#endif
+      __sbrk (0) == _end)
     /* The dynamic linker was run as a program, and so the initial break
        starts just after our bss, at &_end.  The malloc in dl-minimal.c
        will consume the rest of this page, so tell the kernel to move the
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
index 90c9b1db2d..625e6cb759 100644
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
@@ -27,14 +27,24 @@
 #include <ldsodefs.h>
 #include <not-cancel.h>
 
+#if HAVE_TUNABLES
+# undef TUNABLE_NAMESPACE
+# define TUNABLE_NAMESPACE malloc
+#endif
+
 #ifdef SHARED
 # define DL_SYSDEP_INIT frob_brk ()
 
 static inline void
 frob_brk (void)
 {
+  /* Tunable glibc.malloc.use_sbrk controls use of 'sbrk()'. */
+#if HAVE_TUNABLES
+  if (TUNABLE_GET (use_sbrk, int32_t, NULL))
+#endif
   __brk (0);			/* Initialize the break.  */
 }
+# undef TUNABLE_NAMESPACE
 
 # include <elf/dl-sysdep.c>
 #endif
-- 
2.29.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] csu: randomize location of TCB
  2020-11-25 11:36 ` [PATCH 1/3] csu: randomize location of TCB Topi Miettinen
@ 2020-11-25 13:18   ` Adhemerval Zanella
  2020-11-25 13:43     ` Topi Miettinen
  2020-11-25 17:49   ` Topi Miettinen
  1 sibling, 1 reply; 7+ messages in thread
From: Adhemerval Zanella @ 2020-11-25 13:18 UTC (permalink / raw)
  To: Topi Miettinen, libc-alpha



On 25/11/2020 08:36, Topi Miettinen via Libc-alpha wrote:
> Use mmap() for allocating TCB except if instructed by tunable
> glibc.malloc.use_sbrk. This makes the location of TCB random instead
> of always staying predictably next to data segment. When using mmap(),
> improve the logic so that allocation of TCB can be assumed to fail
> insted of segfaulting.
> 
> --
> v2: introduce a tunable to use sbrk()
> 
> Signed-off-by: Topi Miettinen <toiwoton@gmail.com>

Could you address the points I raised on your first version [1]
first?

[1] https://sourceware.org/pipermail/libc-alpha/2020-November/119988.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] csu: randomize location of TCB
  2020-11-25 13:18   ` Adhemerval Zanella
@ 2020-11-25 13:43     ` Topi Miettinen
  0 siblings, 0 replies; 7+ messages in thread
From: Topi Miettinen @ 2020-11-25 13:43 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha

On 25.11.2020 15.18, Adhemerval Zanella wrote:
> 
> 
> On 25/11/2020 08:36, Topi Miettinen via Libc-alpha wrote:
>> Use mmap() for allocating TCB except if instructed by tunable
>> glibc.malloc.use_sbrk. This makes the location of TCB random instead
>> of always staying predictably next to data segment. When using mmap(),
>> improve the logic so that allocation of TCB can be assumed to fail
>> insted of segfaulting.
>>
>> --
>> v2: introduce a tunable to use sbrk()
>>
>> Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
> 
> Could you address the points I raised on your first version [1]
> first?
> 
> [1] https://sourceware.org/pipermail/libc-alpha/2020-November/119988.html

Sorry, I'm not subscribed to the list, so I missed your review. I'll 
refactor mmap() and __mmap_internal().

-Topi

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] csu: randomize location of TCB
  2020-11-25 11:36 ` [PATCH 1/3] csu: randomize location of TCB Topi Miettinen
  2020-11-25 13:18   ` Adhemerval Zanella
@ 2020-11-25 17:49   ` Topi Miettinen
  1 sibling, 0 replies; 7+ messages in thread
From: Topi Miettinen @ 2020-11-25 17:49 UTC (permalink / raw)
  To: Topi Miettinen via Libc-alpha

On 25.11.2020 13.36, Topi Miettinen wrote:
> Use mmap() for allocating TCB except if instructed by tunable
> glibc.malloc.use_sbrk. This makes the location of TCB random instead
> of always staying predictably next to data segment. When using mmap(),
> improve the logic so that allocation of TCB can be assumed to fail
> insted of segfaulting.
> 
> --
> v2: introduce a tunable to use sbrk()

I missed that tunables parsing uses sbrk() to allocate memory for a copy 
of GLIBC_TUNABLES environment variable in tunables_strdup(). If the 
variable is set, but kernel returns ENOSYS for brk() system call, every 
command immediately fails:
$ GLIBC_TUNABLES=glibc.malloc.use_sbrk=1 ls
sbrk() failure while processing tunables

Some ideas:
- replace sbrk() with mmap(): up to 4095 bytes may be lost
- directly modify the environment variable, assuming that it will only 
be shortened

-Topi

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-11-25 17:49 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-25 11:36 [PATCH 0/3] Improved ASLR Topi Miettinen
2020-11-25 11:36 ` [PATCH 1/3] csu: randomize location of TCB Topi Miettinen
2020-11-25 13:18   ` Adhemerval Zanella
2020-11-25 13:43     ` Topi Miettinen
2020-11-25 17:49   ` Topi Miettinen
2020-11-25 11:36 ` [PATCH 2/3] malloc: use mmap() to improve ASLR Topi Miettinen
2020-11-25 11:36 ` [PATCH 3/3] dl-sysdep: disable remaining calls to sbrk() Topi Miettinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).