Index: compiler-rt/lib/safestack/CMakeLists.txt =================================================================== --- compiler-rt/lib/safestack/CMakeLists.txt +++ compiler-rt/lib/safestack/CMakeLists.txt @@ -12,8 +12,6 @@ ARCHS ${arch} SOURCES ${SAFESTACK_SOURCES} $ - $ - $ CFLAGS ${SAFESTACK_CFLAGS} PARENT_TARGET safestack) endforeach() Index: compiler-rt/lib/safestack/safestack.cc =================================================================== --- compiler-rt/lib/safestack/safestack.cc +++ compiler-rt/lib/safestack/safestack.cc @@ -14,21 +14,16 @@ // //===----------------------------------------------------------------------===// +#include "safestack_platform.h" +#include "safestack_util.h" + #include -#include -#include -#include -#include -#include -#include +#include #include -#include -#if !defined(__NetBSD__) -#include -#endif #include "interception/interception.h" -#include "sanitizer_common/sanitizer_common.h" + +using namespace safestack; namespace { @@ -98,20 +93,20 @@ __thread size_t unsafe_stack_size = 0; __thread size_t unsafe_stack_guard = 0; -using namespace __sanitizer; - inline void *unsafe_stack_alloc(size_t size, size_t guard) { - CHECK_GE(size + guard, size); - void *addr = MmapOrDie(size + guard, "unsafe_stack_alloc"); - MprotectNoAccess((uptr)addr, (uptr)guard); + SFS_CHECK(size + guard >= size); + void *addr = mmap(nullptr, RoundUpTo(size + guard, pageSize), + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + SFS_CHECK(MAP_FAILED != addr); + mprotect(addr, guard, PROT_NONE); return (char *)addr + guard; } inline void unsafe_stack_setup(void *start, size_t size, size_t guard) { - CHECK_GE((char *)start + size, (char *)start); - CHECK_GE((char *)start + guard, (char *)start); + SFS_CHECK((char *)start + size >= (char *)start); + SFS_CHECK((char *)start + guard >= (char *)start); void *stack_ptr = (char *)start + size; - CHECK_EQ((((size_t)stack_ptr) & (kStackAlign - 1)), 0); + SFS_CHECK((((size_t)stack_ptr) & (kStackAlign - 1)) == 0); __safestack_unsafe_stack_ptr = stack_ptr; unsafe_stack_start = start; @@ -156,7 +151,7 @@ void *stack_base; size_t size; pid_t pid; - tid_t tid; + pid_t tid; }; /// Linked list of unsafe stacks for threads that are exiting. We delay @@ -168,7 +163,7 @@ /// this thread is terminated. libc can call functions in safestack-instrumented /// code (like free) after thread-specific data destructors have run. void thread_cleanup_handler(void *_iter) { - CHECK_NE(unsafe_stack_start, nullptr); + SFS_CHECK(unsafe_stack_start != nullptr); pthread_setspecific(thread_cleanup_key, NULL); pthread_mutex_lock(&thread_stacks_mutex); @@ -179,17 +174,15 @@ pthread_mutex_unlock(&thread_stacks_mutex); pid_t pid = getpid(); - tid_t tid = GetTid(); + pid_t tid = GetTid(); // Free stacks for dead threads thread_stack_ll **stackp = &temp_stacks; while (*stackp) { thread_stack_ll *stack = *stackp; - int error; if (stack->pid != pid || - (internal_iserror(TgKill(stack->pid, stack->tid, 0), &error) && - error == ESRCH)) { - UnmapOrDie(stack->stack_base, stack->size); + (-1 == TgKill(stack->pid, stack->tid, 0) && errno == ESRCH)) { + munmap(stack->stack_base, stack->size); *stackp = stack->next; free(stack); } else @@ -236,9 +229,9 @@ pthread_attr_destroy(&tmpattr); } - CHECK_NE(size, 0); - CHECK_EQ((size & (kStackAlign - 1)), 0); - CHECK_EQ((guard & (pageSize - 1)), 0); + SFS_CHECK(size); + SFS_CHECK((size & (kStackAlign - 1)) == 0); + SFS_CHECK((guard & (pageSize - 1)) == 0); void *addr = unsafe_stack_alloc(size, guard); struct tinfo *tinfo = @@ -252,12 +245,13 @@ return REAL(pthread_create)(thread, attr, thread_start, tinfo); } -BlockingMutex interceptor_init_lock(LINKER_INITIALIZED); +pthread_mutex_t interceptor_init_mutex = PTHREAD_MUTEX_INITIALIZER; bool interceptors_inited = false; void EnsureInterceptorsInitialized() { - BlockingMutexLock lock(&interceptor_init_lock); - if (interceptors_inited) return; + MutexLock lock(interceptor_init_mutex); + if (interceptors_inited) + return; // Initialize pthread interceptors for thread allocation INTERCEPT_FUNCTION(pthread_create); @@ -271,6 +265,8 @@ __attribute__((constructor(0))) #endif void __safestack_init() { + pageSize = sysconf(_SC_PAGESIZE); + // Determine the stack size for the main thread. size_t size = kDefaultUnsafeStackSize; size_t guard = 4096; @@ -283,7 +279,6 @@ void *addr = unsafe_stack_alloc(size, guard); unsafe_stack_setup(addr, size, guard); - pageSize = sysconf(_SC_PAGESIZE); // Setup the cleanup handler pthread_key_create(&thread_cleanup_key, thread_cleanup_handler); Index: compiler-rt/lib/safestack/safestack_platform.h =================================================================== --- /dev/null +++ compiler-rt/lib/safestack/safestack_platform.h @@ -0,0 +1,60 @@ +//===-- safestack_platform.h ----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements platform specific parts of SafeStack runtime. +// +//===----------------------------------------------------------------------===// + +#ifndef SAFESTACK_PLATFORM_H +#define SAFESTACK_PLATFORM_H + +#include "sanitizer_common/sanitizer_platform.h" + +#include +#include +#include + +namespace safestack { + +inline pid_t GetTid() { +#if SANITIZER_NETBSD + return _lwp_self(); +#elif SANITIZER_FREEBSD + long Tid; + thr_self(&Tid); + return Tid; +#elif SANITIZER_OPENBSD + return syscall(SYS_getthrid); +#elif SANITIZER_SOLARIS + return thr_self(); +#else + return syscall(SYS_gettid); +#endif +} + +inline int TgKill(pid_t pid, pid_t tid, int sig) { +#if SANITIZER_NETBSD + (void)pid; + return _lwp_kill(tid, sig); +#elif SANITIZER_LINUX + return syscall(SYS_tgkill, pid, tid, sig); +#elif SANITIZER_FREEBSD + return syscall(SYS_thr_kill2, pid, tid, sig); +#elif SANITIZER_OPENBSD + (void)pid; + return syscall(SYSCALL(thrkill), tid, sig, nullptr); +#elif SANITIZER_SOLARIS + (void)pid; + return thr_kill(tid, sig); +#endif +} + +} // namespace safestack + +#endif // SAFESTACK_PLATFORM_H Index: compiler-rt/lib/safestack/safestack_util.h =================================================================== --- /dev/null +++ compiler-rt/lib/safestack/safestack_util.h @@ -0,0 +1,50 @@ +//===-- safestack_util.h --------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility code for SafeStack implementation. +// +//===----------------------------------------------------------------------===// + +#ifndef SAFESTACK_UTIL_H +#define SAFESTACK_UTIL_H + +#include +#include +#include + +namespace safestack { + +#define SFS_CHECK(a) \ + do { \ + if (!(a)) { \ + fprintf(stderr, "safestack CHECK failed: %s:%d %s\n", __FILE__, \ + __LINE__, #a); \ + abort(); \ + }; \ + } while (false) + +inline size_t RoundUpTo(size_t size, size_t boundary) { + SFS_CHECK((boundary & (boundary - 1)) == 0); + return (size + boundary - 1) & ~(boundary - 1); +} + +class MutexLock { + public: + explicit MutexLock(pthread_mutex_t &mutex) : mutex_(&mutex) { + pthread_mutex_lock(mutex_); + } + ~MutexLock() { pthread_mutex_unlock(mutex_); } + + private: + pthread_mutex_t *mutex_ = nullptr; +}; + +} // namespace safestack + +#endif // SAFESTACK_UTIL_H