summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-05-03 20:42:45 -0400
committerRich Felker <dalias@aerifal.cx>2012-05-03 20:42:45 -0400
commit58aa5f45ed3282751ae118c107ff008d4df765dc (patch)
tree94859368fee26181f59f2b98911f1c46d146d25b /src
parente765239f334d670e1b68289a2fcaa6b82a3b9666 (diff)
downloadmusl-58aa5f45ed3282751ae118c107ff008d4df765dc.tar.gz
overhaul SSP support to use a real canary
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).
Diffstat (limited to 'src')
-rw-r--r--src/env/__init_security.c6
-rw-r--r--src/env/__stack_chk_fail.c17
-rw-r--r--src/env/__stack_chk_guard.c2
-rw-r--r--src/internal/pthread_impl.h4
-rw-r--r--src/ldso/dynlink.c7
-rw-r--r--src/thread/pthread_create.c1
6 files changed, 25 insertions, 12 deletions
diff --git a/src/env/__init_security.c b/src/env/__init_security.c
index 6893a252..8270f1f4 100644
--- a/src/env/__init_security.c
+++ b/src/env/__init_security.c
@@ -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]
diff --git a/src/env/__stack_chk_fail.c b/src/env/__stack_chk_fail.c
index bbba3511..c6d0feb9 100644
--- a/src/env/__stack_chk_fail.c
+++ b/src/env/__stack_chk_fail.c
@@ -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
index f4c9e4f5..00000000
--- a/src/env/__stack_chk_guard.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#include <inttypes.h>
-uintptr_t __stack_chk_guard = 0xdecafbad;
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index 98d9b22d..5c1b2069 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -22,8 +22,12 @@
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;
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 3f3316aa..b51ae77f 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -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];
}
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 0e1dbb2d..c3b65ae9 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -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();