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
This commit is contained in:
Vlad Tsyrklevich 2018-04-04 17:53:33 +00:00
parent 4703a3f5c4
commit 1781d105ed
7 changed files with 120 additions and 0 deletions

View File

@ -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)

View File

@ -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")

View File

@ -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;
}

View File

@ -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

View File

@ -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")

View File

@ -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 <asm/prctl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/prctl.h>
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;

View File

@ -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 <stdio.h>
#include <stdlib.h>
#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;
}