From 205e34f422a7d170d8a1e53c2cfe6f38e7ea8659 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 18 Jan 2019 01:53:37 +0000 Subject: [safestack] Remove dependency of SafeStack on sanitizer_common Summary: SafeStack needs just few functions from there, but sanitizer_common introduces conflicts with other runtimes, e.g. SCUDO. Reviewers: eugenis, kcc, cryptoad Subscribers: mgorny, krytarowski, fedor.sergeev, jfb, llvm-commits Differential Revision: https://reviews.llvm.org/D56886 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@351506 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/safestack/CMakeLists.txt | 2 -- lib/safestack/safestack.cc | 61 +++++++++++++++++--------------------- lib/safestack/safestack_platform.h | 60 +++++++++++++++++++++++++++++++++++++ lib/safestack/safestack_util.h | 50 +++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 35 deletions(-) create mode 100644 lib/safestack/safestack_platform.h create mode 100644 lib/safestack/safestack_util.h (limited to 'lib/safestack') diff --git a/lib/safestack/CMakeLists.txt b/lib/safestack/CMakeLists.txt index cc874a3fe..aa259e8d6 100644 --- a/lib/safestack/CMakeLists.txt +++ b/lib/safestack/CMakeLists.txt @@ -12,8 +12,6 @@ foreach(arch ${SAFESTACK_SUPPORTED_ARCH}) ARCHS ${arch} SOURCES ${SAFESTACK_SOURCES} $ - $ - $ CFLAGS ${SAFESTACK_CFLAGS} PARENT_TARGET safestack) endforeach() diff --git a/lib/safestack/safestack.cc b/lib/safestack/safestack.cc index 78c88f56a..1fd32c0ff 100644 --- a/lib/safestack/safestack.cc +++ b/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; // TODO: To make accessing the unsafe stack pointer faster, we plan to // eventually store it directly in the thread control block data structure on @@ -98,20 +93,20 @@ __thread void *unsafe_stack_start = nullptr; __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 @@ struct thread_stack_ll { 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 @@ pthread_mutex_t thread_stacks_mutex = PTHREAD_MUTEX_INITIALIZER; /// 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 @@ void thread_cleanup_handler(void *_iter) { 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 @@ INTERCEPTOR(int, pthread_create, pthread_t *thread, 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 @@ INTERCEPTOR(int, pthread_create, pthread_t *thread, 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); @@ -273,6 +267,8 @@ extern "C" __attribute__((visibility("default"))) __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; @@ -285,7 +281,6 @@ void __safestack_init() { 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); diff --git a/lib/safestack/safestack_platform.h b/lib/safestack/safestack_platform.h new file mode 100644 index 000000000..051e23beb --- /dev/null +++ b/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 diff --git a/lib/safestack/safestack_util.h b/lib/safestack/safestack_util.h new file mode 100644 index 000000000..416b6c59e --- /dev/null +++ b/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 -- cgit v1.2.1