From 1781d105ed9a5ef5b877923a8e347425b928b2cd Mon Sep 17 00:00:00 2001 From: Vlad Tsyrklevich Date: Wed, 4 Apr 2018 17:53:33 +0000 Subject: [PATCH] Add simple runtime tests for shadowcallstack Summary: ShadowCallStack does not yet have a runtime provided by compiler-rt, but this change includes simple tests that make use of a very minimal runtime in test/shadowcallstack/minimal_runtime.h Reviewers: pcc, kcc, delcypher, eugenis, filcab Reviewed By: pcc Subscribers: kubamracek, mgorny, delcypher, llvm-commits, #sanitizers, kcc Differential Revision: https://reviews.llvm.org/D44803 llvm-svn: 329210 --- compiler-rt/test/CMakeLists.txt | 3 ++ compiler-rt/test/shadowcallstack/CMakeLists.txt | 13 ++++++++ compiler-rt/test/shadowcallstack/init.c | 16 ++++++++++ compiler-rt/test/shadowcallstack/lit.cfg | 19 ++++++++++++ compiler-rt/test/shadowcallstack/lit.site.cfg.in | 7 +++++ compiler-rt/test/shadowcallstack/minimal_runtime.h | 26 ++++++++++++++++ compiler-rt/test/shadowcallstack/overflow.c | 36 ++++++++++++++++++++++ 7 files changed, 120 insertions(+) create mode 100644 compiler-rt/test/shadowcallstack/CMakeLists.txt create mode 100644 compiler-rt/test/shadowcallstack/init.c create mode 100644 compiler-rt/test/shadowcallstack/lit.cfg create mode 100644 compiler-rt/test/shadowcallstack/lit.site.cfg.in create mode 100644 compiler-rt/test/shadowcallstack/minimal_runtime.h create mode 100644 compiler-rt/test/shadowcallstack/overflow.c diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt index ab16f42..fa2031a 100644 --- a/compiler-rt/test/CMakeLists.txt +++ b/compiler-rt/test/CMakeLists.txt @@ -78,6 +78,9 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS) if(COMPILER_RT_BUILD_XRAY) compiler_rt_test_runtime(xray) endif() + # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests + # include their own minimal runtime + add_subdirectory(shadowcallstack) endif() if(COMPILER_RT_STANDALONE_BUILD) diff --git a/compiler-rt/test/shadowcallstack/CMakeLists.txt b/compiler-rt/test/shadowcallstack/CMakeLists.txt new file mode 100644 index 0000000..f8fd835b --- /dev/null +++ b/compiler-rt/test/shadowcallstack/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SHADOWCALLSTACK_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(SHADOWCALLSTACK_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +set(SHADOWCALLSTACK_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + ) + +add_lit_testsuite(check-shadowcallstack "Running the ShadowCallStack tests" + ${CMAKE_CURRENT_BINARY_DIR}) +set_target_properties(check-shadowcallstack PROPERTIES FOLDER "Compiler-RT Misc") diff --git a/compiler-rt/test/shadowcallstack/init.c b/compiler-rt/test/shadowcallstack/init.c new file mode 100644 index 0000000..8dad6bd --- /dev/null +++ b/compiler-rt/test/shadowcallstack/init.c @@ -0,0 +1,16 @@ +// RUN: %clang_scs -D INCLUDE_RUNTIME %s -o %t +// RUN: %run %t + +// RUN: %clang_scs %s -o %t +// RUN: not --crash %run %t + +// Basic smoke test for the runtime + +#ifdef INCLUDE_RUNTIME +#include "minimal_runtime.h" +#endif + +int main(int argc, char **argv) { + printf("In main.\n"); + return 0; +} diff --git a/compiler-rt/test/shadowcallstack/lit.cfg b/compiler-rt/test/shadowcallstack/lit.cfg new file mode 100644 index 0000000..1642bdc --- /dev/null +++ b/compiler-rt/test/shadowcallstack/lit.cfg @@ -0,0 +1,19 @@ +# -*- Python -*- + +import os + +# Setup config name. +config.name = 'ShadowCallStack' + +# 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_noscs ", config.clang + " -O0 -fno-sanitize=shadow-call-stack ") ) +config.substitutions.append( ("%clang_scs ", config.clang + " -O0 -fsanitize=shadow-call-stack ") ) + +if config.host_os not in ['Linux'] or config.target_arch != 'x86_64': + config.unsupported = True diff --git a/compiler-rt/test/shadowcallstack/lit.site.cfg.in b/compiler-rt/test/shadowcallstack/lit.site.cfg.in new file mode 100644 index 0000000..4582f36 --- /dev/null +++ b/compiler-rt/test/shadowcallstack/lit.site.cfg.in @@ -0,0 +1,7 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# 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, "@SHADOWCALLSTACK_LIT_SOURCE_DIR@/lit.cfg") diff --git a/compiler-rt/test/shadowcallstack/minimal_runtime.h b/compiler-rt/test/shadowcallstack/minimal_runtime.h new file mode 100644 index 0000000..75d95ec --- /dev/null +++ b/compiler-rt/test/shadowcallstack/minimal_runtime.h @@ -0,0 +1,26 @@ +// A shadow call stack runtime is not yet included with compiler-rt, provide a +// minimal runtime to allocate a shadow call stack and assign %gs to point at +// it. + +#pragma once + +#include +#include +#include +#include + +int arch_prctl(int code, void *addr); + +__attribute__((no_sanitize("shadow-call-stack"))) +static void __shadowcallstack_init() { + void *stack = mmap(NULL, 8192, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (stack == MAP_FAILED) + abort(); + + if (arch_prctl(ARCH_SET_GS, stack)) + abort(); +} + +__attribute__((section(".preinit_array"), used)) + void (*__shadowcallstack_preinit)(void) = __shadowcallstack_init; diff --git a/compiler-rt/test/shadowcallstack/overflow.c b/compiler-rt/test/shadowcallstack/overflow.c new file mode 100644 index 0000000..b7b29a1 --- /dev/null +++ b/compiler-rt/test/shadowcallstack/overflow.c @@ -0,0 +1,36 @@ +// RUN: %clang_noscs %s -o %t +// RUN: %run %t 3 | FileCheck %s +// RUN: %run %t 12 | FileCheck -check-prefix=OVERFLOW_SUCCESS %s + +// RUN: %clang_scs %s -o %t +// RUN: %run %t 3 | FileCheck %s +// RUN: not --crash %run %t 12 + +// Test that a stack overflow fails as expected + +#include +#include + +#include "minimal_runtime.h" + +void print_and_exit(void) { +// CHECK-NOT: Stack overflow successful. +// OVERFLOW_SUCCESS: Stack overflow successful. + printf("Stack overflow successful.\n"); + exit(0); +} + +int main(int argc, char **argv) +{ + if (argc != 2) + exit(1); + + void *addrs[4]; + const int iterations = atoi(argv[1]); + for (int i = 0; i < iterations; i++) + addrs[i] = &print_and_exit; + + printf("Returning.\n"); + + return 0; +} -- 2.7.4