From 35593a4eafa10872b22a5516bdfb623096e5dc67 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Sat, 24 Jun 2017 11:11:46 -0400 Subject: [PATCH] HBSD: Randomize top of per-thread stacks The per-thread stack implementation in libthr supplies a hint to mmap(2). ASLR will get applied to it, it could be hardened still. Provide additional hardening by randomizing the size of the per-thread stack guard provided by libthr. This will effectively randomize the top of the per-thread stack at a page-level granularity. Additional entropy could be provided by introducing a random-sized gap, thus getting better than page-level granularity. Signed-off-by: Shawn Webb Sponsored-by: SoldierX (cherry picked from commit ff0cec6dcb44843b3e5f7590105e284c56c4e3ed) --- lib/libthr/thread/thr_init.c | 15 ++++++++++++++- lib/libthr/thread/thr_private.h | 12 ++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c index 2f62619ce07..4660627ef86 100644 --- a/lib/libthr/thread/thr_init.c +++ b/lib/libthr/thread/thr_init.c @@ -439,6 +439,7 @@ init_private(void) size_t len; int mib[2]; char *env, *env_bigstack, *env_splitstack; + unsigned int npages; _thr_umutex_init(&_mutex_static_lock); _thr_umutex_init(&_cond_static_lock); @@ -477,7 +478,6 @@ init_private(void) sysctlbyname("kern.smp.cpus", &_thr_is_smp, &len, NULL, 0); _thr_is_smp = (_thr_is_smp > 1); _thr_page_size = getpagesize(); - _thr_guard_default = (2 * 1024 * 1024); _pthread_attr_default.guardsize_attr = _thr_guard_default; _pthread_attr_default.stacksize_attr = _thr_stack_default; env = getenv("LIBPTHREAD_SPINLOOPS"); @@ -490,6 +490,19 @@ init_private(void) if (env) _thr_queuefifo = atoi(env); TAILQ_INIT(&_thr_atfork_list); + /* + * Initialize the random-sized stack guard + * conservatively. + */ + mib[0] = CTL_KERN; + mib[1] = KERN_ARND; + len = sizeof(npages); + npages = 0; + sysctl(mib, 2, &npages, &len, NULL, 0); + npages %= GUARD_MAX_PAGES; + if (npages < GUARD_MIN_PAGES) + npages = GUARD_DEFAULT_SIZE; + _thr_guard_default = npages * PAGE_SIZE; } init_once = 1; } diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index e61ee99dcb7..78a74a32256 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -101,6 +101,18 @@ TAILQ_HEAD(mutex_queue, pthread_mutex); #define THR_ASSERT(cond, msg) #endif +#ifndef GUARD_DEFAULT_SIZE +#define GUARD_DEFAULT_SIZE 512 +#endif + +#ifndef GUARD_MIN_PAGES +#define GUARD_MIN_PAGES 256 +#endif + +#ifndef GUARD_MAX_PAGES +#define GUARD_MAX_PAGES 1024 +#endif + #ifdef PIC # define STATIC_LIB_REQUIRE(name) #else