about summary refs log tree commit diff
diff options
context:
space:
mode:
-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();