overhaul SSP support to use a real canary
authorRich Felker <dalias@aerifal.cx>
Fri, 4 May 2012 00:42:45 +0000 (20:42 -0400)
committerRich Felker <dalias@aerifal.cx>
Fri, 4 May 2012 00:42:45 +0000 (20:42 -0400)
pthread structure has been adjusted to match the glibc/GCC abi for
where the canary is stored on i386 and x86_64. it will need variants
for other archs to provide the added security of the canary's entropy,
but even without that it still works as well as the old "minimal" ssp
support. eventually such changes will be made anyway, since they are
also needed for GCC/C11 thread-local storage support (not yet
implemented).

care is taken not to attempt initializing the thread pointer unless
the program actually uses SSP (by reference to __stack_chk_fail).

src/env/__init_security.c
src/env/__stack_chk_fail.c
src/env/__stack_chk_guard.c [deleted file]
src/internal/pthread_impl.h
src/ldso/dynlink.c
src/thread/pthread_create.c

index 6893a252fa59bab24247a5117ed70df772dff24a..8270f1f43b43804c2696025b52156eac849bd80a 100644 (file)
@@ -8,7 +8,7 @@
 
 #define AUX_CNT 24
 
-void dummy(void)
+void dummy(size_t *auxv)
 {
 }
 weak_alias(dummy, __init_ssp);
@@ -18,7 +18,9 @@ void __init_security(size_t *auxv)
        size_t i, aux[AUX_CNT] = { 0 };
        struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} };
 
-       __init_ssp();
+#ifndef SHARED
+       __init_ssp(auxv);
+#endif
 
        for (; auxv[0]; auxv+=2) if (auxv[0]<AUX_CNT) aux[auxv[0]] = auxv[1];
        if (aux[AT_UID]==aux[AT_EUID] && aux[AT_GID]==aux[AT_EGID]
index bbba35118984a24bbb1a335d89abe2b424881309..c6d0feb999cd8447d2c19af23091964c69f37cf1 100644 (file)
@@ -1,11 +1,20 @@
+#include <string.h>
+#include <inttypes.h>
+#include <elf.h>
 #include "pthread_impl.h"
 #include "atomic.h"
 
-void __init_ssp(void)
+uintptr_t __stack_chk_guard;
+
+void __init_ssp(size_t *auxv)
 {
-#ifndef __PIC__
-       __pthread_self_init();
-#endif
+       size_t i;
+       pthread_t self = __pthread_self_init();
+       uintptr_t canary;
+       for (i=0; auxv[i] && auxv[i]!=AT_RANDOM; i+=2);
+       if (auxv[i]) memcpy(&canary, (void *)auxv[i+1], sizeof canary);
+       else canary = (uintptr_t)&canary * 1103515245;
+       __stack_chk_guard = self->canary = canary;
 }
 
 void __stack_chk_fail(void)
diff --git a/src/env/__stack_chk_guard.c b/src/env/__stack_chk_guard.c
deleted file mode 100644 (file)
index f4c9e4f..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#include <inttypes.h>
-uintptr_t __stack_chk_guard = 0xdecafbad;
index 98d9b22d6f061bab335af1dbeaa65b9339def6ad..5c1b20691003223ebe041d6a2ed73501c83ad68a 100644 (file)
 
 struct pthread {
        struct pthread *self;
+       void *dtv, *unused1, *unused2;
+       uintptr_t sysinfo;
+       uintptr_t canary;
        pid_t tid, pid;
        int tsd_used, errno_val, *errno_ptr;
+       /* All cancellation-related fields must remain together, in order */
        volatile uintptr_t cp_sp, cp_ip;
        volatile int cancel, canceldisable, cancelasync;
        unsigned char *map_base;
index 3f3316aaf4ccde3c4ff7e8880d562484f99efc2a..b51ae77fecb4ab825b6a45f8af9cad7e01a7afff 100644 (file)
@@ -67,8 +67,7 @@ struct dso {
        char buf[];
 };
 
-struct __pthread;
-struct __pthread *__pthread_self_init(void);
+void __init_ssp(size_t *);
 
 static struct dso *head, *tail, *libc;
 static char *env_path, *sys_path, *r_path;
@@ -633,6 +632,8 @@ void *__dynlink(int argc, char **argv)
        debug.state = 0;
        _dl_debug_state();
 
+       if (ssp_used) __init_ssp(auxv);
+
        do_init_fini(tail);
 
        if (!rtld_used) {
@@ -641,8 +642,6 @@ void *__dynlink(int argc, char **argv)
                reclaim((void *)builtin_dsos, 0, sizeof builtin_dsos);
        }
 
-       if (ssp_used) __pthread_self_init();
-
        errno = 0;
        return (void *)aux[AT_ENTRY];
 }
index 0e1dbb2d2e75adcd8299b6b48dc960a5b9c846bc..c3b65ae955ab2b3757a32cf4f1597b87fb669361 100644 (file)
@@ -120,6 +120,7 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo
        new->tsd = (void *)tsd;
        if (attr) new->detached = attr->_a_detach;
        new->unblock_cancel = self->cancel;
+       new->canary = self->canary ^ (uintptr_t)&new;
        stack = (void *)new;
 
        __synccall_lock();