[compiler-rt] r239763 - Protection against stack-based memory corruption errors using SafeStack: compiler-rt runtime support library

Anna Zaks ganna at apple.com
Tue Jun 16 11:35:50 PDT 2015


Very exciting to see this!  

The commit has caused one test failure on darwin:
http://lab.llvm.org:8080/green/view/All/job/clang-stage1-cmake-RA_check/4796/console

Failing Tests (1):
    SafeStack :: pthread.c

Will you be able to investigate?

Thanks!
Anna.
> On Jun 15, 2015, at 2:08 PM, Peter Collingbourne <peter at pcc.me.uk> wrote:
> 
> Author: pcc
> Date: Mon Jun 15 16:08:47 2015
> New Revision: 239763
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=239763&view=rev
> Log:
> Protection against stack-based memory corruption errors using SafeStack: compiler-rt runtime support library
> 
> This patch adds runtime support for the Safe Stack protection to compiler-rt
> (see http://reviews.llvm.org/D6094 for the detailed description of the
> Safe Stack).
> 
> This patch is our implementation of the safe stack on top of compiler-rt. The
> patch adds basic runtime support for the safe stack to compiler-rt that
> manages unsafe stack allocation/deallocation for each thread.
> 
> Original patch by Volodymyr Kuznetsov and others at the Dependable Systems
> Lab at EPFL; updates and upstreaming by myself.
> 
> Differential Revision: http://reviews.llvm.org/D6096
> 
> Added:
>    compiler-rt/trunk/lib/safestack/
>    compiler-rt/trunk/lib/safestack/CMakeLists.txt
>    compiler-rt/trunk/lib/safestack/safestack.cc
>    compiler-rt/trunk/test/safestack/
>    compiler-rt/trunk/test/safestack/CMakeLists.txt
>    compiler-rt/trunk/test/safestack/buffer-copy-vla.c
>    compiler-rt/trunk/test/safestack/buffer-copy.c
>    compiler-rt/trunk/test/safestack/init.c
>    compiler-rt/trunk/test/safestack/lit.cfg
>    compiler-rt/trunk/test/safestack/lit.site.cfg.in
>    compiler-rt/trunk/test/safestack/lto.c
>    compiler-rt/trunk/test/safestack/overflow.c
>    compiler-rt/trunk/test/safestack/pthread-cleanup.c
>    compiler-rt/trunk/test/safestack/pthread.c
>    compiler-rt/trunk/test/safestack/utils.h
> Modified:
>    compiler-rt/trunk/CMakeLists.txt
>    compiler-rt/trunk/cmake/config-ix.cmake
>    compiler-rt/trunk/lib/CMakeLists.txt
>    compiler-rt/trunk/test/CMakeLists.txt
> 
> Modified: compiler-rt/trunk/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=239763&r1=239762&r2=239763&view=diff
> ==============================================================================
> --- compiler-rt/trunk/CMakeLists.txt (original)
> +++ compiler-rt/trunk/CMakeLists.txt Mon Jun 15 16:08:47 2015
> @@ -207,6 +207,7 @@ append_list_if(COMPILER_RT_HAS_FNO_EXCEP
> append_list_if(COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG -fomit-frame-pointer SANITIZER_COMMON_CFLAGS)
> append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COMMON_CFLAGS)
> append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)
> +append_list_if(COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG -fno-sanitize=safe-stack SANITIZER_COMMON_CFLAGS)
> append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)
> append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections SANITIZER_COMMON_CFLAGS)
> append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)
> 
> Modified: compiler-rt/trunk/cmake/config-ix.cmake
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/config-ix.cmake?rev=239763&r1=239762&r2=239763&view=diff
> ==============================================================================
> --- compiler-rt/trunk/cmake/config-ix.cmake (original)
> +++ compiler-rt/trunk/cmake/config-ix.cmake Mon Jun 15 16:08:47 2015
> @@ -19,6 +19,7 @@ check_cxx_compiler_flag(-fno-exceptions
> check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)
> check_cxx_compiler_flag(-funwind-tables      COMPILER_RT_HAS_FUNWIND_TABLES_FLAG)
> check_cxx_compiler_flag(-fno-stack-protector COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG)
> +check_cxx_compiler_flag(-fno-sanitize=safe-stack COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG)
> check_cxx_compiler_flag(-fvisibility=hidden  COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG)
> check_cxx_compiler_flag(-fno-rtti            COMPILER_RT_HAS_FNO_RTTI_FLAG)
> check_cxx_compiler_flag(-ffreestanding       COMPILER_RT_HAS_FFREESTANDING_FLAG)
> @@ -256,6 +257,7 @@ filter_available_targets(PROFILE_SUPPORT
> filter_available_targets(TSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
> filter_available_targets(UBSAN_SUPPORTED_ARCH x86_64 i386 i686 arm aarch64 mips
>   mipsel mips64 mips64el powerpc64 powerpc64le)
> +filter_available_targets(SAFESTACK_SUPPORTED_ARCH x86_64 i386 i686)
> 
> if(ANDROID)
>   set(OS_NAME "Android")
> @@ -334,3 +336,10 @@ endif()
> if("${LLVM_NATIVE_ARCH}" STREQUAL "Mips")
>   set(COMPILER_RT_HAS_MSSE3_FLAG FALSE)
> endif()
> +
> +if (SAFESTACK_SUPPORTED_ARCH AND
> +    OS_NAME MATCHES "Darwin|Linux|FreeBSD")
> +  set(COMPILER_RT_HAS_SAFESTACK TRUE)
> +else()
> +  set(COMPILER_RT_HAS_SAFESTACK FALSE)
> +endif()
> 
> Modified: compiler-rt/trunk/lib/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/CMakeLists.txt?rev=239763&r1=239762&r2=239763&view=diff
> ==============================================================================
> --- compiler-rt/trunk/lib/CMakeLists.txt (original)
> +++ compiler-rt/trunk/lib/CMakeLists.txt Mon Jun 15 16:08:47 2015
> @@ -34,3 +34,6 @@ if(COMPILER_RT_HAS_TSAN)
>   add_subdirectory(tsan/dd)
> endif()
> 
> +if(COMPILER_RT_HAS_SAFESTACK)
> +  add_subdirectory(safestack)
> +endif()
> 
> Added: compiler-rt/trunk/lib/safestack/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/safestack/CMakeLists.txt?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/lib/safestack/CMakeLists.txt (added)
> +++ compiler-rt/trunk/lib/safestack/CMakeLists.txt Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,28 @@
> +add_custom_target(safestack)
> +
> +set(SAFESTACK_SOURCES safestack.cc)
> +
> +include_directories(..)
> +
> +set(SAFESTACK_CFLAGS ${SANITIZER_COMMON_CFLAGS})
> +
> +if(APPLE)
> +  # Build universal binary on APPLE.
> +  add_compiler_rt_osx_static_runtime(clang_rt.safestack_osx
> +    ARCH ${SAFESTACK_SUPPORTED_ARCH}
> +    SOURCES ${SAFESTACK_SOURCES}
> +            $<TARGET_OBJECTS:RTInterception.osx>
> +            $<TARGET_OBJECTS:RTSanitizerCommon.osx>
> +    CFLAGS ${SAFESTACK_CFLAGS})
> +  add_dependencies(safestack clang_rt.safestack_osx)
> +else()
> +  # Otherwise, build separate libraries for each target.
> +  foreach(arch ${SAFESTACK_SUPPORTED_ARCH})
> +    add_compiler_rt_runtime(clang_rt.safestack-${arch} ${arch} STATIC
> +      SOURCES ${SAFESTACK_SOURCES}
> +              $<TARGET_OBJECTS:RTInterception.${arch}>
> +              $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
> +      CFLAGS ${SAFESTACK_CFLAGS})
> +    add_dependencies(safestack clang_rt.safestack-${arch})
> +  endforeach()
> +endif()
> 
> Added: compiler-rt/trunk/lib/safestack/safestack.cc
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/safestack/safestack.cc?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/lib/safestack/safestack.cc (added)
> +++ compiler-rt/trunk/lib/safestack/safestack.cc Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,236 @@
> +//===-- safestack.cc ------------------------------------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the runtime support for the safe stack protection
> +// mechanism. The runtime manages allocation/deallocation of the unsafe stack
> +// for the main thread, as well as all pthreads that are created/destroyed
> +// during program execution.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include <limits.h>
> +#include <pthread.h>
> +#include <stddef.h>
> +#include <sys/resource.h>
> +#include <sys/user.h>
> +
> +#include "interception/interception.h"
> +#include "sanitizer_common/sanitizer_common.h"
> +
> +// TODO: The runtime library does not currently protect the safe stack. The
> +// protection of the (safe) stack can be provided by two alternative features
> +// that requires C library support:
> +//
> +// 1) Protection via hardware segmentation on x32 architectures: the (safe)
> +// stack segment (implicitly accessed via the %ss segment register) can be
> +// separated from the data segment (implicitly accessed via the %ds segment
> +// register). Dereferencing a pointer to the safe segment would result in a
> +// segmentation fault.
> +//
> +// 2) Protection via information hiding on 64 bit architectures: the location of
> +// the safe stack can be randomized through secure mechanisms, and the leakage
> +// of the stack pointer can be prevented. Currently, libc can leak the stack
> +// pointer in several ways (e.g. in longjmp, signal handling, user-level context
> +// switching related functions, etc.). These can be fixed in libc and in other
> +// low-level libraries, by either eliminating the escaping/dumping of the stack
> +// pointer (i.e., %rsp) when that's possible, or by using encryption/PTR_MANGLE
> +// (XOR-ing the dumped stack pointer with another secret we control and protect
> +// better). (This is already done for setjmp in glibc.) Furthermore, a static
> +// machine code level verifier can be ran after code generation to make sure
> +// that the stack pointer is never written to memory, or if it is, its written
> +// on the safe stack.
> +//
> +// Finally, while the Unsafe Stack pointer is currently stored in a thread local
> +// variable, with libc support it could be stored in the TCB (thread control
> +// block) as well, eliminating another level of indirection. Alternatively,
> +// dedicating a separate register for storing it would also be possible.
> +
> +/// Minimum stack alignment for the unsafe stack.
> +const unsigned kStackAlign = 16;
> +
> +/// Default size of the unsafe stack. This value is only used if the stack
> +/// size rlimit is set to infinity.
> +const unsigned kDefaultUnsafeStackSize = 0x2800000;
> +
> +// TODO: To make accessing the unsafe stack pointer faster, we plan to
> +// eventually store it directly in the thread control block data structure on
> +// platforms where this structure is pointed to by %fs or %gs. This is exactly
> +// the same mechanism as currently being used by the traditional stack
> +// protector pass to store the stack guard (see getStackCookieLocation()
> +// function above). Doing so requires changing the tcbhead_t struct in glibc
> +// on Linux and tcb struct in libc on FreeBSD.
> +//
> +// For now, store it in a thread-local variable.
> +extern "C" {
> +__attribute__((visibility(
> +    "default"))) __thread void *__safestack_unsafe_stack_ptr = nullptr;
> +}
> +
> +// Per-thread unsafe stack information. It's not frequently accessed, so there
> +// it can be kept out of the tcb in normal thread-local variables.
> +static __thread void *unsafe_stack_start = nullptr;
> +static __thread size_t unsafe_stack_size = 0;
> +static __thread size_t unsafe_stack_guard = 0;
> +
> +static 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);
> +  return (char *)addr + guard;
> +}
> +
> +static 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);
> +  void *stack_ptr = (char *)start + size;
> +  CHECK_EQ((((size_t)stack_ptr) & (kStackAlign - 1)), 0);
> +
> +  __safestack_unsafe_stack_ptr = stack_ptr;
> +  unsafe_stack_start = start;
> +  unsafe_stack_size = size;
> +  unsafe_stack_guard = guard;
> +}
> +
> +static void unsafe_stack_free() {
> +  if (unsafe_stack_start) {
> +    UnmapOrDie((char *)unsafe_stack_start - unsafe_stack_guard,
> +               unsafe_stack_size + unsafe_stack_guard);
> +  }
> +  unsafe_stack_start = nullptr;
> +}
> +
> +/// Thread data for the cleanup handler
> +static pthread_key_t thread_cleanup_key;
> +
> +/// Safe stack per-thread information passed to the thread_start function
> +struct tinfo {
> +  void *(*start_routine)(void *);
> +  void *start_routine_arg;
> +
> +  void *unsafe_stack_start;
> +  size_t unsafe_stack_size;
> +  size_t unsafe_stack_guard;
> +};
> +
> +/// Wrap the thread function in order to deallocate the unsafe stack when the
> +/// thread terminates by returning from its main function.
> +static void *thread_start(void *arg) {
> +  struct tinfo *tinfo = (struct tinfo *)arg;
> +
> +  void *(*start_routine)(void *) = tinfo->start_routine;
> +  void *start_routine_arg = tinfo->start_routine_arg;
> +
> +  // Setup the unsafe stack; this will destroy tinfo content
> +  unsafe_stack_setup(tinfo->unsafe_stack_start, tinfo->unsafe_stack_size,
> +                     tinfo->unsafe_stack_guard);
> +
> +  // Make sure out thread-specific destructor will be called
> +  // FIXME: we can do this only any other specific key is set by
> +  // intercepting the pthread_setspecific function itself
> +  pthread_setspecific(thread_cleanup_key, (void *)1);
> +
> +  return start_routine(start_routine_arg);
> +}
> +
> +/// Thread-specific data destructor
> +static void thread_cleanup_handler(void *_iter) {
> +  // We want to free the unsafe stack only after all other destructors
> +  // have already run. We force this function to be called multiple times.
> +  // User destructors that might run more then PTHREAD_DESTRUCTOR_ITERATIONS-1
> +  // times might still end up executing after the unsafe stack is deallocated.
> +  size_t iter = (size_t)_iter;
> +  if (iter < PTHREAD_DESTRUCTOR_ITERATIONS) {
> +    pthread_setspecific(thread_cleanup_key, (void *)(iter + 1));
> +  } else {
> +    // This is the last iteration
> +    unsafe_stack_free();
> +  }
> +}
> +
> +/// Intercept thread creation operation to allocate and setup the unsafe stack
> +INTERCEPTOR(int, pthread_create, pthread_t *thread,
> +            const pthread_attr_t *attr,
> +            void *(*start_routine)(void*), void *arg) {
> +
> +  size_t size = 0;
> +  size_t guard = 0;
> +
> +  if (attr != NULL) {
> +    pthread_attr_getstacksize(attr, &size);
> +    pthread_attr_getguardsize(attr, &guard);
> +  } else {
> +    // get pthread default stack size
> +    pthread_attr_t tmpattr;
> +    pthread_attr_init(&tmpattr);
> +    pthread_attr_getstacksize(&tmpattr, &size);
> +    pthread_attr_getguardsize(&tmpattr, &guard);
> +    pthread_attr_destroy(&tmpattr);
> +  }
> +
> +  CHECK_NE(size, 0);
> +  CHECK_EQ((size & (kStackAlign - 1)), 0);
> +  CHECK_EQ((guard & (PAGE_SIZE - 1)), 0);
> +
> +  void *addr = unsafe_stack_alloc(size, guard);
> +  struct tinfo *tinfo =
> +      (struct tinfo *)(((char *)addr) + size - sizeof(struct tinfo));
> +  tinfo->start_routine = start_routine;
> +  tinfo->start_routine_arg = arg;
> +  tinfo->unsafe_stack_start = addr;
> +  tinfo->unsafe_stack_size = size;
> +  tinfo->unsafe_stack_guard = guard;
> +
> +  return REAL(pthread_create)(thread, attr, thread_start, tinfo);
> +}
> +
> +extern "C" __attribute__((visibility("default")))
> +#if !SANITIZER_CAN_USE_PREINIT_ARRAY
> +// On ELF platforms, the constructor is invoked using .preinit_array (see below)
> +__attribute__((constructor(0)))
> +#endif
> +void __safestack_init() {
> +  // Determine the stack size for the main thread.
> +  size_t size = kDefaultUnsafeStackSize;
> +  size_t guard = 4096;
> +
> +  struct rlimit limit;
> +  if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur != RLIM_INFINITY)
> +    size = limit.rlim_cur;
> +
> +  // Allocate unsafe stack for main thread
> +  void *addr = unsafe_stack_alloc(size, guard);
> +
> +  unsafe_stack_setup(addr, size, guard);
> +
> +  // Initialize pthread interceptors for thread allocation
> +  INTERCEPT_FUNCTION(pthread_create);
> +
> +  // Setup the cleanup handler
> +  pthread_key_create(&thread_cleanup_key, thread_cleanup_handler);
> +}
> +
> +#if SANITIZER_CAN_USE_PREINIT_ARRAY
> +// On ELF platforms, run safestack initialization before any other constructors.
> +// On other platforms we use the constructor attribute to arrange to run our
> +// initialization early.
> +extern "C" {
> +__attribute__((section(".preinit_array"),
> +               used)) void (*__safestack_preinit)(void) = __safestack_init;
> +}
> +#endif
> +
> +extern "C"
> +    __attribute__((visibility("default"))) void *__get_unsafe_stack_start() {
> +  return unsafe_stack_start;
> +}
> +
> +extern "C"
> +    __attribute__((visibility("default"))) void *__get_unsafe_stack_ptr() {
> +  return __safestack_unsafe_stack_ptr;
> +}
> 
> Modified: compiler-rt/trunk/test/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/CMakeLists.txt?rev=239763&r1=239762&r2=239763&view=diff
> ==============================================================================
> --- compiler-rt/trunk/test/CMakeLists.txt (original)
> +++ compiler-rt/trunk/test/CMakeLists.txt Mon Jun 15 16:08:47 2015
> @@ -58,6 +58,9 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
>     add_subdirectory(ubsan)
>   endif()
>   add_subdirectory(cfi)
> +  if(COMPILER_RT_HAS_SAFESTACK)
> +    add_subdirectory(safestack)
> +  endif()
> endif()
> 
> if(COMPILER_RT_STANDALONE_BUILD)
> 
> Added: compiler-rt/trunk/test/safestack/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/CMakeLists.txt?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/CMakeLists.txt (added)
> +++ compiler-rt/trunk/test/safestack/CMakeLists.txt Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,29 @@
> +set(SAFESTACK_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
> +set(SAFESTACK_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
> +
> +set(SAFESTACK_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
> +if(NOT COMPILER_RT_STANDALONE_BUILD)
> +  list(APPEND SAFESTACK_TEST_DEPS safestack)
> +
> +  # Some tests require LTO, so add a dependency on the relevant LTO plugin.
> +  if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR)
> +    list(APPEND SAFESTACK_TEST_DEPS
> +      LLVMgold
> +    )
> +  endif()
> +  if(APPLE)
> +    list(APPEND SAFESTACK_TEST_DEPS
> +      LTO
> +    )
> +  endif()
> +endif()
> +
> +configure_lit_site_cfg(
> +  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
> +  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
> +  )
> +
> +add_lit_testsuite(check-safestack "Running the SafeStack tests"
> +  ${CMAKE_CURRENT_BINARY_DIR}
> +  DEPENDS ${SAFESTACK_TEST_DEPS})
> +set_target_properties(check-safestack PROPERTIES FOLDER "SafeStack tests")
> 
> Added: compiler-rt/trunk/test/safestack/buffer-copy-vla.c
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/buffer-copy-vla.c?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/buffer-copy-vla.c (added)
> +++ compiler-rt/trunk/test/safestack/buffer-copy-vla.c Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,26 @@
> +// RUN: %clang_safestack %s -o %t
> +// RUN: %run %t
> +
> +#include "utils.h"
> +
> +// Test that loads/stores work correctly for VLAs on the unsafe stack.
> +
> +int main(int argc, char **argv)
> +{
> +  int i = 128;
> +  break_optimization(&i);
> +  char buffer[i];
> +
> +  // check that we can write to a buffer
> +  for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
> +    buffer[i] = argv[0][i];
> +  buffer[i] = '\0';
> +
> +  break_optimization(buffer);
> +
> +  // check that we can read from a buffer
> +  for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
> +    if (buffer[i] != argv[0][i])
> +      return 1;
> +  return 0;
> +}
> 
> Added: compiler-rt/trunk/test/safestack/buffer-copy.c
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/buffer-copy.c?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/buffer-copy.c (added)
> +++ compiler-rt/trunk/test/safestack/buffer-copy.c Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,25 @@
> +// RUN: %clang_safestack %s -o %t
> +// RUN: %run %t
> +
> +#include "utils.h"
> +
> +// Test that loads/stores work correctly for variables on the unsafe stack.
> +
> +int main(int argc, char **argv)
> +{
> +  int i;
> +  char buffer[128];
> +
> +  // check that we can write to a buffer
> +  for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
> +    buffer[i] = argv[0][i];
> +  buffer[i] = '\0';
> +
> +  break_optimization(buffer);
> +
> +  // check that we can read from a buffer
> +  for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
> +    if (buffer[i] != argv[0][i])
> +      return 1;
> +  return 0;
> +}
> 
> Added: compiler-rt/trunk/test/safestack/init.c
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/init.c?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/init.c (added)
> +++ compiler-rt/trunk/test/safestack/init.c Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,9 @@
> +// RUN: %clang_safestack %s -o %t
> +// RUN: %run %t
> +
> +// Basic smoke test for the runtime library.
> +
> +int main(int argc, char **argv)
> +{
> +  return 0;
> +}
> 
> Added: compiler-rt/trunk/test/safestack/lit.cfg
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/lit.cfg?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/lit.cfg (added)
> +++ compiler-rt/trunk/test/safestack/lit.cfg Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,24 @@
> +# -*- Python -*-
> +
> +import os
> +
> +# Setup config name.
> +config.name = 'SafeStack'
> +
> +# Setup source root.
> +config.test_source_root = os.path.dirname(__file__)
> +
> +# Test suffixes.
> +config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.ll', '.test']
> +
> +# Add clang substitutions.
> +config.substitutions.append( ("%clang_nosafestack ", config.clang + " -O0 -fno-sanitize=safe-stack ") )
> +config.substitutions.append( ("%clang_safestack ", config.clang + " -O0 -fsanitize=safe-stack ") )
> +
> +if config.lto_supported:
> +  config.available_features.add('lto')
> +  config.substitutions.append((r"%clang_lto_safestack ", ' '.join(config.lto_launch + [config.clang] + config.lto_flags + ['-flto -fsanitize=safe-stack '])))
> +
> +# SafeStack tests are currently supported on Linux, FreeBSD and Darwin only.
> +if config.host_os not in ['Linux', 'FreeBSD', 'Darwin']:
> +   config.unsupported = True
> 
> Added: compiler-rt/trunk/test/safestack/lit.site.cfg.in
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/lit.site.cfg.in?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/lit.site.cfg.in (added)
> +++ compiler-rt/trunk/test/safestack/lit.site.cfg.in Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,8 @@
> +## Autogenerated by LLVM/Clang configuration.
> +# Do not edit!
> +
> +# Load common config for all compiler-rt lit tests.
> +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
> +
> +# Load tool-specific config that would do the real work.
> +lit_config.load_config(config, "@SAFESTACK_LIT_SOURCE_DIR@/lit.cfg")
> 
> Added: compiler-rt/trunk/test/safestack/lto.c
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/lto.c?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/lto.c (added)
> +++ compiler-rt/trunk/test/safestack/lto.c Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,12 @@
> +// REQUIRES: lto
> +
> +// RUN: %clang_lto_safestack %s -o %t
> +// RUN: %run %t
> +
> +// Test that safe stack works with LTO.
> +
> +int main() {
> +  char c[] = "hello world";
> +  puts(c);
> +  return 0;
> +}
> 
> Added: compiler-rt/trunk/test/safestack/overflow.c
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/overflow.c?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/overflow.c (added)
> +++ compiler-rt/trunk/test/safestack/overflow.c Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,23 @@
> +// RUN: %clang_safestack %s -o %t
> +// RUN: %run %t
> +
> +// RUN: %clang_nosafestack -fno-stack-protector %s -o %t
> +// RUN: not %run %t
> +
> +// Test that buffer overflows on the unsafe stack do not affect variables on the
> +// safe stack.
> +
> +__attribute__((noinline))
> +void fct(volatile int *buffer)
> +{
> +  memset(buffer - 1, 0, 7 * sizeof(int));
> +}
> +
> +int main(int argc, char **argv)
> +{
> +  int value1 = 42;
> +  int buffer[5];
> +  int value2 = 42;
> +  fct(buffer);
> +  return value1 != 42 || value2 != 42;
> +}
> 
> Added: compiler-rt/trunk/test/safestack/pthread-cleanup.c
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/pthread-cleanup.c?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/pthread-cleanup.c (added)
> +++ compiler-rt/trunk/test/safestack/pthread-cleanup.c Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,31 @@
> +// RUN: %clang_safestack %s -pthread -o %t
> +// RUN: not --crash %run %t
> +
> +// Test that unsafe stacks are deallocated correctly on thread exit.
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <pthread.h>
> +
> +enum { kBufferSize = (1 << 15) };
> +
> +void *t1_start(void *ptr)
> +{
> +  char buffer[kBufferSize];
> +  return buffer;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +  pthread_t t1;
> +  char *buffer = NULL;
> +
> +  if (pthread_create(&t1, NULL, t1_start, NULL))
> +    abort();
> +  if (pthread_join(t1, &buffer))
> +    abort();
> +
> +  // should segfault here
> +  memset(buffer, 0, kBufferSize);
> +  return 0;
> +}
> 
> Added: compiler-rt/trunk/test/safestack/pthread.c
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/pthread.c?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/pthread.c (added)
> +++ compiler-rt/trunk/test/safestack/pthread.c Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,40 @@
> +// RUN: %clang_safestack %s -pthread -o %t
> +// RUN: %run %t
> +
> +// Test that pthreads receive their own unsafe stack.
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <pthread.h>
> +#include "utils.h"
> +
> +static int ptr_test = 42;
> +
> +void *t1_start(void *ptr)
> +{
> +  if (ptr != &ptr_test)
> +    abort();
> +
> +  // safe stack
> +  int val = ptr_test * 5;
> +
> +  // unsafe stack
> +  char buffer[8096]; // two pages
> +  memset(buffer, val, sizeof (buffer));
> +  break_optimization(buffer);
> +
> +  return ptr;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +  pthread_t t1;
> +  void *ptr = NULL;
> +  if (pthread_create(&t1, NULL, t1_start, &ptr_test))
> +    abort();
> +  if (pthread_join(t1, &ptr))
> +    abort();
> +  if (ptr != &ptr_test)
> +    abort();
> +  return 0;
> +}
> 
> Added: compiler-rt/trunk/test/safestack/utils.h
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/safestack/utils.h?rev=239763&view=auto
> ==============================================================================
> --- compiler-rt/trunk/test/safestack/utils.h (added)
> +++ compiler-rt/trunk/test/safestack/utils.h Mon Jun 15 16:08:47 2015
> @@ -0,0 +1,8 @@
> +#ifndef UTILS_H
> +#define UTILS_H
> +
> +static inline void break_optimization(void *arg) {
> +  __asm__ __volatile__("" : : "r" (arg) : "memory");
> +}
> +
> +#endif
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150616/ae9ae937/attachment.html>


More information about the llvm-commits mailing list