diff mbox series

[RFC,1/3] csu: randomize location of TCB

Message ID 20201004130938.64575-2-toiwoton@gmail.com
State New
Headers show
Series Improved ALSR | expand

Commit Message

Topi Miettinen Oct. 4, 2020, 1:09 p.m. UTC
Let's use mmap() for TCB, which makes the location of TCB random
instead of always staying predictably next to data segment. Also
improve the logic so that allocation of TCB can be assumed to fail
insted of segfaulting.

RFC: make independent of Linux.

Signed-off-by: Topi Miettinen <toiwoton@gmail.com>
---
 csu/libc-tls.c                          | 20 ++++++++++++++------
 sysdeps/unix/sysv/linux/mmap64.c        | 19 +++++++++++++++++++
 sysdeps/unix/sysv/linux/mmap_internal.h |  3 +++
 3 files changed, 36 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index 06e76bd395..59700c3a95 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -24,6 +24,9 @@ 
 #include <stdio.h>
 #include <sys/param.h>
 #include <array_length.h>
+#include <sys/mman.h>
+#include <sysdep.h>
+#include <mmap_internal.h>
 
 #ifdef SHARED
  #error makefile bug, this file is for static only
@@ -134,25 +137,30 @@  __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 'internal_mmap' which does not use 'errno'. */
+
+  int error = 0;
+
 #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);
+  tlsblock = __mmap_internal (NULL, tcb_offset + TLS_INIT_TCB_SIZE + max_align,
+			      PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0, &error);
 #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));
+  tlsblock = __mmap_internal (NULL, tcb_offset + memsz + max_align
+			      + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus),
+			      PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0, &error);
   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/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..00fc14902e 100644
--- a/sysdeps/unix/sysv/linux/mmap_internal.h
+++ b/sysdeps/unix/sysv/linux/mmap_internal.h
@@ -46,4 +46,7 @@  static uint64_t page_unit;
   INLINE_SYSCALL_CALL (__nr, __addr, __len, __prot, __flags, __fd, __offset)
 #endif
 
+/* 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  */