diff --git a/cmake/define-test.cmake b/cmake/define-test.cmake index 144b59ce1..cdc45db3a 100644 --- a/cmake/define-test.cmake +++ b/cmake/define-test.cmake @@ -137,7 +137,7 @@ function(define_test) set(ADD_SANDBOX_DEP FALSE) if (DEFINE_TEST_CRITERION_TEST) - list(APPEND DEFINE_TEST_UNWRAPPED_LIBS criterion) + list(APPEND DEFINE_TEST_UNWRAPPED_LIBS ia2_test_runner) if (NOT DEFINE_TEST_NOT_IN_CHECK_IA2) if (LIBIA2_AARCH64) # unless natively AArch64, default to running tests with qemu-aarch64 and a custom LD_LIBRARY_PATH diff --git a/cmake/ia2.cmake b/cmake/ia2.cmake index 970d5a455..90dcb7aac 100644 --- a/cmake/ia2.cmake +++ b/cmake/ia2.cmake @@ -43,13 +43,8 @@ function(add_ia2_compartment NAME TYPE) add_library(${NAME} SHARED) endif() - # The x86 version is missing a dependency here and libs rely on include path overlap to pick up - # criterion header. I want to keep spoofed criterion static for simplicity so we add the -I - # directly here. - if (LIBIA2_AARCH64) - target_include_directories(${NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/misc/spoofed_criterion/include) - endif() + target_include_directories(${NAME} PRIVATE + ${CMAKE_SOURCE_DIR}/misc/test_runner/include) target_compile_definitions(${NAME} PRIVATE IA2_ENABLE=1 PKEY=${ARG_PKEY} @@ -153,10 +148,11 @@ function(create_compile_commands NAME TYPE) # Copy target properties from the real target. We might need to add more properties. target_link_libraries(${COMPILE_COMMAND_TARGET} PRIVATE $) target_include_directories(${COMPILE_COMMAND_TARGET} PRIVATE ${INCLUDE_DIRECTORIES}) - if (LIBIA2_AARCH64) - target_include_directories(${COMPILE_COMMAND_TARGET} PRIVATE - ${CMAKE_SOURCE_DIR}/misc/spoofed_criterion/include) - endif() + # The test runner is a static library that just defines main so we don't link it into + # the libraries defined by tests and instead just add the include flags for its + # assertions + target_include_directories(${COMPILE_COMMAND_TARGET} PRIVATE + ${CMAKE_SOURCE_DIR}/misc/test_runner/include) set(CMAKE_EXPORT_COMPILE_COMMANDS OFF) endfunction() diff --git a/external/b63 b/external/b63 deleted file mode 160000 index df819a781..000000000 --- a/external/b63 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit df819a781435b99f185b6aaae31ca737481b0072 diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt index 6b8ad9342..a9748b291 100644 --- a/misc/CMakeLists.txt +++ b/misc/CMakeLists.txt @@ -1,3 +1 @@ -if (LIBIA2_AARCH64) - add_subdirectory(spoofed_criterion) -endif() +add_subdirectory(test_runner) diff --git a/misc/spoofed_criterion/CMakeLists.txt b/misc/spoofed_criterion/CMakeLists.txt deleted file mode 100644 index 643e251a3..000000000 --- a/misc/spoofed_criterion/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_library(criterion STATIC test_runner.c) -target_include_directories(criterion - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/misc/spoofed_criterion/include/criterion/criterion.h b/misc/spoofed_criterion/include/criterion/criterion.h deleted file mode 100644 index 935f09676..000000000 --- a/misc/spoofed_criterion/include/criterion/criterion.h +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -struct fake_criterion_test { - void (*test)(void); - void (*init)(void); - int exit_code; -}; - -#define Test(suite, name, ...) \ - void fake_criterion_##suite##_##name(void); \ - __attribute__((__section__("fake_criterion_tests"))) struct fake_criterion_test fake_criterion_##suite##_##name##_##test = { \ - .test = fake_criterion_##suite##_##name, \ - ##__VA_ARGS__}; \ - void fake_criterion_##suite##_##name(void) diff --git a/misc/spoofed_criterion/include/criterion/logging.h b/misc/spoofed_criterion/include/criterion/logging.h deleted file mode 100644 index e0016e8a5..000000000 --- a/misc/spoofed_criterion/include/criterion/logging.h +++ /dev/null @@ -1,5 +0,0 @@ -#include -#include - -#define cr_log_info(f, ...) printf(f "\n", ##__VA_ARGS__) -#define cr_log_error(f, ...) fprintf(stderr, f "\n", ##__VA_ARGS__) diff --git a/misc/spoofed_criterion/include/criterion/new/assert.h b/misc/spoofed_criterion/include/criterion/new/assert.h deleted file mode 100644 index 854bbc294..000000000 --- a/misc/spoofed_criterion/include/criterion/new/assert.h +++ /dev/null @@ -1,10 +0,0 @@ -#include - -#define cr_assert assert -#define cr_assert_eq(a, b) cr_assert((a) == (b)) -#define cr_assert_lt(a, b) cr_assert((a) < (b)) -#define cr_fatal(s) \ - do { \ - fprintf(stderr, s "\n"); \ - exit(1); \ - } while (0) diff --git a/misc/spoofed_criterion/test_runner.c b/misc/spoofed_criterion/test_runner.c deleted file mode 100644 index 879abbdf1..000000000 --- a/misc/spoofed_criterion/test_runner.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "include/criterion/criterion.h" -#include -#include -#include -#include - -extern struct fake_criterion_test __start_fake_criterion_tests; -extern struct fake_criterion_test __stop_fake_criterion_tests; - -int main() { - struct fake_criterion_test *test_info = &__start_fake_criterion_tests; - for (; test_info < &__stop_fake_criterion_tests; test_info++) { - if (!test_info->test) { - break; - } - pid_t pid = fork(); - bool in_child = pid == 0; - if (in_child) { - if (test_info->init) { - (*test_info->init)(); - } - (*test_info->test)(); - return 0; - } - // otherwise, in parent - int stat; - pid_t waited_pid = waitpid(pid, &stat, 0); - if (waited_pid < 0) { - perror("waitpid"); - return 2; - } - if WIFSIGNALED(stat) { - fprintf(stderr, "forked test child was terminated by signal %d\n", WTERMSIG(stat)); - return 1; - } - int exit_status = WEXITSTATUS(stat); - if (exit_status != test_info->exit_code) { - fprintf(stderr, "forked test child exited with status %d, but %d was expected\n", exit_status, test_info->exit_code); - return 1; - } - } - return 0; -} diff --git a/misc/test_runner/CMakeLists.txt b/misc/test_runner/CMakeLists.txt new file mode 100644 index 000000000..e49cfcd6b --- /dev/null +++ b/misc/test_runner/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(ia2_test_runner STATIC test_runner.c) +target_include_directories(ia2_test_runner + PRIVATE ${CMAKE_SOURCE_DIR}/runtime/libia2/include) diff --git a/misc/test_runner/include/ia2_test_runner.h b/misc/test_runner/include/ia2_test_runner.h new file mode 100644 index 000000000..398389a99 --- /dev/null +++ b/misc/test_runner/include/ia2_test_runner.h @@ -0,0 +1,66 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +/* + * Tests should include this header without defining the following macro to avoid rewriting function + * pointers that shouldn't be rewritten. + */ +#if !defined(IA2_TEST_RUNNER_SOURCE) +typedef void *ia2_test_fn; +#else +typedef void (*ia2_test_fn)(void); +#endif + +struct fake_criterion_test { + ia2_test_fn test; + ia2_test_fn init; + int exit_code; +}; + +/* + * Placing IA2_{BEGIN,END}_NO_WRAP between the function declaration stops the rewriter from creating a + * direct call gate for the test function or indirect call gates for function pointer expressions + * that reference it like the RHS when initializing struct fake_criterion_test's test field. The + * last line of this macro is the start of the test function's definition and should be followed by { } + */ +#define Test(suite, name, ...) \ + IA2_BEGIN_NO_WRAP \ + void fake_criterion_##suite##_##name(void); \ + IA2_END_NO_WRAP \ + __attribute__((__section__("fake_criterion_tests"))) struct fake_criterion_test fake_criterion_##suite##_##name##_##test = { \ + .test = fake_criterion_##suite##_##name, \ + ##__VA_ARGS__}; \ + void fake_criterion_##suite##_##name(void) + +#define cr_log_info(f, ...) printf(f "\n", ##__VA_ARGS__) +#define cr_log_error(f, ...) fprintf(stderr, f "\n", ##__VA_ARGS__) + +#define cr_assert assert +#define cr_assert_eq(a, b) cr_assert((a) == (b)) +#define cr_assert_lt(a, b) cr_assert((a) < (b)) +#define cr_fatal(s) \ + do { \ + fprintf(stderr, s "\n"); \ + exit(1); \ + } while (0) + +/* + * Configure the signal handler to expect an mpk violation when `expr` is evaluated. If `expr` + * doesn't trigger a fault, the process exits with a non-zero exit status. + */ +#define CHECK_VIOLATION(expr) \ + ({ \ + expect_fault = true; \ + asm volatile("" : : : "memory"); \ + volatile typeof(expr) _tmp = expr; \ + printf("CHECK_VIOLATION: did not seg fault as expected\n"); \ + _exit(1); \ + _tmp; \ + }) + +extern bool expect_fault; diff --git a/misc/test_runner/test_runner.c b/misc/test_runner/test_runner.c new file mode 100644 index 000000000..36290655e --- /dev/null +++ b/misc/test_runner/test_runner.c @@ -0,0 +1,123 @@ +/* Define this macro to make the pointers in struct fake_criterion_test function pointers */ +#define IA2_TEST_RUNNER_SOURCE +#include "include/ia2_test_runner.h" + +#include +#include +#include +#include +#include + +extern struct fake_criterion_test __start_fake_criterion_tests; +extern struct fake_criterion_test __stop_fake_criterion_tests; + +/* This is shared data to allow checking for violations from different compartments */ +bool expect_fault IA2_SHARED_DATA = false; + +/* Create a stack for the signal handler to use since the tests may trigger it from any compartment */ +char sighandler_stack[4 * 1024] IA2_SHARED_DATA __attribute__((aligned(16))) = {0}; + +/* Pointer to the start of the signal handler stack */ +char *sighandler_sp IA2_SHARED_DATA = &sighandler_stack[(4 * 1024) - 8]; + +// This function must be declared naked because it's not necessarily safe for it +// to write to the stack in its prelude (the stack isn't written to when the +// function itself is called because it's only invoked as a signal handler). +#if defined(__x86_64__) +__attribute__((naked)) void handle_segfault(int sig) { + // This asm must preserve %rdi which contains the argument since + // print_mpk_message reads it + __asm__( + // This signal handler is defined in the main binary, but it doesn't run with + // the same pkru state as the interrupted context. This means we have to + // remove all MPK restrictions to ensure can run it correctly. + "xorl %ecx, %ecx\n" + "xorl %edx, %edx\n" + "xorl %eax, %eax\n" + "wrpkru\n" + // Switch the stack to a shared buffer. There's only one u32 argument and + // no returns so we don't need a full callgate wrapper here. + "movq sighandler_sp@GOTPCREL(%rip), %rsp\n" + "movq (%rsp), %rsp\n" + "callq print_mpk_message"); +} +#elif defined(__aarch64__) +#warning "Review test_fault_handler implementation after enabling x18 switching" +void print_mpk_message(int sig); +void handle_segfault(int sig) { + print_mpk_message(sig); +} +#endif + +/* + * The test output is used for manual sanity-checks to ensure check whether a segfault occurred and + * if it was expected or not. + */ +void print_mpk_message(int sig) { + if (sig == SIGSEGV) { + /* segfault happened at the expected place so exit with status code zero */ + const char *ok_msg = "CHECK_VIOLATION: seg faulted as expected\n"; + /* segfault happened at an unexpected place so exit with non-zero status */ + const char *early_fault_msg = "CHECK_VIOLATION: unexpected seg fault\n"; + const char *msg; + if (expect_fault) { + msg = ok_msg; + } else { + msg = early_fault_msg; + } + /* Write directly to stdout since printf is not async-signal-safe */ + write(1, msg, strlen(msg)); + if (!expect_fault) { + _exit(-1); + } + } + _exit(0); +} + +int main() { + struct sigaction act = { + .sa_handler = handle_segfault, + }; + /* + * Installs a signal handler that will be inherited by the child processes created for each + * invocation of the Test macro + */ + sigaction(SIGSEGV, &act, NULL); + struct fake_criterion_test *test_info = &__start_fake_criterion_tests; + for (; test_info < &__stop_fake_criterion_tests; test_info++) { + if (!test_info->test) { + break; + } + pid_t pid = fork(); + bool in_child = pid == 0; + if (in_child) { + /* + * This .c is not rewritten so these indirect callsites have no callgates and their callees must + * not be wrapped. That means the Test macro should not expose function pointer types to + * rewritten source files (i.e. the test sources). + */ + if (test_info->init) { + (*test_info->init)(); + } + (*test_info->test)(); + return 0; + } + // otherwise, in parent + int stat; + pid_t waited_pid = waitpid(pid, &stat, 0); + if (waited_pid < 0) { + perror("waitpid"); + return 2; + } + if WIFSIGNALED(stat) { + fprintf(stderr, "forked test child was terminated by signal %d\n", WTERMSIG(stat)); + return 1; + } + int exit_status = WEXITSTATUS(stat); + if (exit_status != test_info->exit_code) { + fprintf(stderr, "forked test child exited with status %d, but %d was expected\n", exit_status, test_info->exit_code); + return 1; + } + } + return 0; +} diff --git a/runtime/libia2/include/test_fault_handler.h b/runtime/libia2/include/test_fault_handler.h deleted file mode 100644 index 329442cc5..000000000 --- a/runtime/libia2/include/test_fault_handler.h +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* - * This header defines a test framework for detecting MPK violations using - * signal handlers. This file must be included exactly once from a source file - * in the main binary with IA2_DEFINE_TEST_HANDLER defined by the preprocessor. - * This will define the functions and variables used by the test handler, ensure - * it is initialized before main and provide access to the LOG and - * CHECK_VIOLATION macros. Other files which need CHECK_VIOLATION or LOG may - * include the header without defining IA2_DEFINE_TEST_HANDLER. Using - * CHECK_VIOLATION without defining the test handler will trigger a linker error - * when building the shared object. - */ - -#define VA_ARGS(...) , ##__VA_ARGS__ -#define LOG(msg, ...) printf("%s: " msg "\n", __func__ VA_ARGS(__VA_ARGS__)) - -// Configure the signal handler to expect an mpk violation when `expr` is -// evaluated. If `expr` doesn't trigger a fault, this macro manually raises a -// fault with a different message. -#define CHECK_VIOLATION(expr) \ - ({ \ - expect_fault = true; \ - asm volatile("" : : : "memory"); \ - volatile typeof(expr) _tmp = expr; \ - printf("CHECK_VIOLATION: did not seg fault as expected\n"); \ - _exit(1); \ - _tmp; \ - }) - -#ifndef IA2_DEFINE_TEST_HANDLER -extern bool expect_fault; -#else -// This is shared data to allow checking for violations in multiple -// compartments. We avoid using IA2_SHARED_DATA here to avoid including ia2.h -// since that would pull in libia2 as a dependency (the libia2 build generates a -// header included in ia2.h). -bool expect_fault __attribute__((section("ia2_shared_data"))) = false; - -// Create a stack for the signal handler to use -char sighandler_stack[4 * 1024] __attribute__((section("ia2_shared_data"))) -__attribute__((aligned(16))) = {0}; -char *sighandler_sp __attribute__((section("ia2_shared_data"))) = - &sighandler_stack[(4 * 1024) - 8]; - -// This function must be declared naked because it's not necessarily safe for it -// to write to the stack in its prelude (the stack isn't written to when the -// function itself is called because it's only invoked as a signal handler). -#if defined(__x86_64__) -__attribute__((naked)) void handle_segfault(int sig) { - // This asm must preserve %rdi which contains the argument since - // print_mpk_message reads it - __asm__( - // Signal handlers are defined in the main binary, but they don't run with - // the same pkru state as the interrupted context. This means we have to - // remove all MPK restrictions to ensure can run it correctly. - "xorl %ecx, %ecx\n" - "xorl %edx, %edx\n" - "xorl %eax, %eax\n" - "wrpkru\n" - // Switch the stack to a shared buffer. There's only one u32 argument and - // no returns so we don't need a full wrapper here. - "movq sighandler_sp@GOTPCREL(%rip), %rsp\n" - "movq (%rsp), %rsp\n" - "callq print_mpk_message"); -} -#elif defined(__aarch64__) -#warning "Review test_fault_handler implementation after enabling x18 switching" -void print_mpk_message(int sig); -void handle_segfault(int sig) { - print_mpk_message(sig); -} -#endif - -// The test output should be checked to see that the segfault occurred at the -// expected place. -void print_mpk_message(int sig) { - if (sig == SIGSEGV) { - // Write directly to stdout since printf is not async-signal-safe - const char *ok_msg = "CHECK_VIOLATION: seg faulted as expected\n"; - const char *early_fault_msg = "CHECK_VIOLATION: unexpected seg fault\n"; - const char *msg; - if (expect_fault) { - msg = ok_msg; - } else { - msg = early_fault_msg; - } - write(1, msg, strlen(msg)); - if (!expect_fault) { - _exit(-1); - } - } - _exit(0); -} - -// Installs the previously defined signal handler and disables buffering on -// stdout to allow using printf prior to the sighandler -__attribute__((constructor)) void install_segfault_handler(void) { - setbuf(stdout, NULL); - signal(SIGSEGV, handle_segfault); -} -#endif diff --git a/tests/abi/abi.c b/tests/abi/abi.c index 474dd354f..29f415e81 100644 --- a/tests/abi/abi.c +++ b/tests/abi/abi.c @@ -3,7 +3,7 @@ RUN: cat minimal_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ #include "abi.h" -#include +#include // LINKARGS: --wrap=arg1 void arg1(int x) { diff --git a/tests/abi/main.c b/tests/abi/main.c index abc12ba14..d89586af7 100644 --- a/tests/abi/main.c +++ b/tests/abi/main.c @@ -4,7 +4,7 @@ RUN: sh -c 'if [ ! -s "minimal_call_gates_0.ld" ]; then echo "No link args as ex // Check that readelf shows exactly one executable segment -#include +#include #include "abi.h" #include diff --git a/tests/destructors/main.c b/tests/destructors/main.c index 298bfd49e..9f99a5c71 100644 --- a/tests/destructors/main.c +++ b/tests/destructors/main.c @@ -1,12 +1,12 @@ -#include -#include +#include + #include #include #include #include #include "plugin.h" -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + // This test uses two protection keys INIT_RUNTIME(2); diff --git a/tests/destructors/plugin.c b/tests/destructors/plugin.c index 29e47c5eb..ab2d33173 100644 --- a/tests/destructors/plugin.c +++ b/tests/destructors/plugin.c @@ -1,9 +1,9 @@ -#include -#include +#include + #include #include #include "exported_fn.h" -#include "test_fault_handler.h" + #define IA2_COMPARTMENT 2 #include diff --git a/tests/global_fn_ptr/main.c b/tests/global_fn_ptr/main.c index 4cefe7767..16fe1be45 100644 --- a/tests/global_fn_ptr/main.c +++ b/tests/global_fn_ptr/main.c @@ -3,7 +3,7 @@ RUN: sh -c 'if [ ! -s "global_fn_ptr_call_gates_0.ld" ]; then echo "No link args */ #include "operations.h" #include -#include +#include uint32_t add(uint32_t x, uint32_t y) { return x + y; } uint16_t sub(uint16_t x, uint16_t y) { return x - y; } diff --git a/tests/global_fn_ptr/operations.c b/tests/global_fn_ptr/operations.c index 5a05012dd..cd22ee94f 100644 --- a/tests/global_fn_ptr/operations.c +++ b/tests/global_fn_ptr/operations.c @@ -2,7 +2,7 @@ RUN: cat global_fn_ptr_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ #include "operations.h" -#include +#include #include extern Op operations[2]; diff --git a/tests/header_includes/liboption.c b/tests/header_includes/liboption.c index 8e6e0df20..ed0fcf0da 100644 --- a/tests/header_includes/liboption.c +++ b/tests/header_includes/liboption.c @@ -1,7 +1,8 @@ /* RUN: cat header_includes_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include + +#include #include "liboption.h" #include "types.h" diff --git a/tests/header_includes/main.c b/tests/header_includes/main.c index 98fcd0214..ef1c8578d 100644 --- a/tests/header_includes/main.c +++ b/tests/header_includes/main.c @@ -3,8 +3,8 @@ RUN: sh -c 'if [ ! -s "header_includes_call_gates_0.ld" ]; then echo "No link ar */ #include "liboption.h" #include "types.h" -#include -#include +#include + #include INIT_RUNTIME(1); diff --git a/tests/heap_two_keys/main.c b/tests/heap_two_keys/main.c index d007b998b..66ceab222 100644 --- a/tests/heap_two_keys/main.c +++ b/tests/heap_two_keys/main.c @@ -1,16 +1,16 @@ /* RUN: sh -c 'if [ ! -s "heap_two_keys_call_gates_0.ld" ]; then echo "No link args as expected"; exit 0; fi; echo "Unexpected link args"; exit 1;' */ -#include -#include -#include +#include + + #include #include #include #include #include "plugin.h" -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + // This test uses two protection keys INIT_RUNTIME(2); diff --git a/tests/heap_two_keys/plugin.c b/tests/heap_two_keys/plugin.c index 29e67c4c8..1d0951808 100644 --- a/tests/heap_two_keys/plugin.c +++ b/tests/heap_two_keys/plugin.c @@ -1,10 +1,11 @@ /* RUN: cat heap_two_keys_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ +#include #include #include #include "exported_fn.h" -#include "test_fault_handler.h" + #define IA2_COMPARTMENT 2 #include diff --git a/tests/macro_attr/functions.c b/tests/macro_attr/functions.c index ad84673b1..7826f834e 100644 --- a/tests/macro_attr/functions.c +++ b/tests/macro_attr/functions.c @@ -1,7 +1,8 @@ /* RUN: cat macro_attr_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include + +#include #include "functions.h" // LINKARGS: --wrap=f diff --git a/tests/macro_attr/main.c b/tests/macro_attr/main.c index a23205163..a50b9f450 100644 --- a/tests/macro_attr/main.c +++ b/tests/macro_attr/main.c @@ -3,7 +3,7 @@ RUN: sh -c 'if [ ! -s "macro_attr_call_gates_0.ld" ]; then echo "No link args as */ #include "functions.h" #include -#include +#include INIT_RUNTIME(1); #define IA2_COMPARTMENT 1 diff --git a/tests/minimal/main.c b/tests/minimal/main.c index 5fcb5d681..4afc95aaf 100644 --- a/tests/minimal/main.c +++ b/tests/minimal/main.c @@ -4,7 +4,7 @@ RUN: sh -c 'if [ ! -s "minimal_call_gates_0.ld" ]; then echo "No link args as ex // Check that readelf shows exactly one executable segment -#include +#include #include "minimal.h" #include diff --git a/tests/minimal/minimal.c b/tests/minimal/minimal.c index dca720e5f..437a40814 100644 --- a/tests/minimal/minimal.c +++ b/tests/minimal/minimal.c @@ -2,8 +2,9 @@ RUN: cat minimal_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ +#include #include "minimal.h" -#include + // LINKARGS: --wrap=arg1 void arg1(int x) { diff --git a/tests/mmap_loop/main.c b/tests/mmap_loop/main.c index 341a0ab8a..17ef469fb 100644 --- a/tests/mmap_loop/main.c +++ b/tests/mmap_loop/main.c @@ -6,10 +6,10 @@ RUN: sh -c 'if [ ! -s "mmap_loop_call_gates_0.ld" ]; then echo "No link args as #include #include #include -#include +#include + + -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" /* This program tests that mmap and heap allocations are handled properly. diff --git a/tests/permissive_mode/permissive_mode.c b/tests/permissive_mode/permissive_mode.c index f8e18b4ab..4915ac235 100644 --- a/tests/permissive_mode/permissive_mode.c +++ b/tests/permissive_mode/permissive_mode.c @@ -1,7 +1,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -#include +#include #include #include diff --git a/tests/protected_threads/main.c b/tests/protected_threads/main.c index 6582ebb22..f4b512e2e 100644 --- a/tests/protected_threads/main.c +++ b/tests/protected_threads/main.c @@ -7,9 +7,9 @@ RUN: sh -c 'if [ ! -s "protected_threads_call_gates_0.ld" ]; then echo "No link #include #include #include -#define IA2_DEFINE_TEST_HANDLER -#include -#include + +#include + #include INIT_RUNTIME(2); diff --git a/tests/read_config/builtin.c b/tests/read_config/builtin.c index bf0f96483..389a8d239 100644 --- a/tests/read_config/builtin.c +++ b/tests/read_config/builtin.c @@ -1,7 +1,8 @@ /* RUN: cat read_config_call_gates_2.ld | FileCheck --check-prefix=LINKARGS %s */ -#include + +#include #include #include #include diff --git a/tests/read_config/main.c b/tests/read_config/main.c index d6bda5408..b0ee39e81 100644 --- a/tests/read_config/main.c +++ b/tests/read_config/main.c @@ -5,8 +5,8 @@ RUN: cat main.c | FileCheck --match-full-lines --check-prefix=REWRITER %s // Check that readelf shows exactly one executable segment #include "plugin.h" -#include -#include +#include + #include #include #include @@ -14,8 +14,8 @@ RUN: cat main.c | FileCheck --match-full-lines --check-prefix=REWRITER %s // need wrapped function pointer definitions. For now just hack around this by // including plugin.h (which does include the output header) before core.h. #include "core.h" -#define IA2_DEFINE_TEST_HANDLER -#include + + /* This test is modeled after nginx's function pointer usage. In this test, diff --git a/tests/read_config/plugin.c b/tests/read_config/plugin.c index df745223f..9ffa320c4 100644 --- a/tests/read_config/plugin.c +++ b/tests/read_config/plugin.c @@ -7,7 +7,8 @@ We need this because main.c uses LINKARGS checks but not this file. #include "plugin.h" #include "core.h" #include -#include +#include + #include #include diff --git a/tests/recursion/dso.c b/tests/recursion/dso.c index 2241c05df..3104eaaa4 100644 --- a/tests/recursion/dso.c +++ b/tests/recursion/dso.c @@ -2,7 +2,7 @@ RUN: cat recursion_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ #include "recursion_main.h" -#include +#include #include #include diff --git a/tests/recursion/main.c b/tests/recursion/main.c index 555c057dc..67a934261 100644 --- a/tests/recursion/main.c +++ b/tests/recursion/main.c @@ -3,12 +3,12 @@ RUN: cat recursion_call_gates_2.ld | FileCheck --check-prefix=LINKARGS %s */ #include "recursion_dso.h" -#include -#include +#include + #include #include -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + INIT_RUNTIME(2); #define IA2_COMPARTMENT 1 diff --git a/tests/rewrite_fn_ptr_eq/lib.c b/tests/rewrite_fn_ptr_eq/lib.c index 2229abbe5..74b9a536a 100644 --- a/tests/rewrite_fn_ptr_eq/lib.c +++ b/tests/rewrite_fn_ptr_eq/lib.c @@ -1,8 +1,8 @@ /* RUN: cat rewrite_fn_ptr_eq_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include -#include +#include + #include #include #include diff --git a/tests/rewrite_fn_ptr_eq/main.c b/tests/rewrite_fn_ptr_eq/main.c index 05f13733a..7dcf3b024 100644 --- a/tests/rewrite_fn_ptr_eq/main.c +++ b/tests/rewrite_fn_ptr_eq/main.c @@ -1,7 +1,7 @@ /* RUN: cat main.c | FileCheck --match-full-lines --check-prefix=REWRITER %S/main.c */ -#include +#include #include #include #include diff --git a/tests/rewrite_macros/main.c b/tests/rewrite_macros/main.c index 9794c71ac..04f0df78e 100644 --- a/tests/rewrite_macros/main.c +++ b/tests/rewrite_macros/main.c @@ -4,7 +4,7 @@ RUN: cat main.c | FileCheck --match-full-lines --check-prefix=REWRITER %s #include "lib.h" #include #include -#include +#include INIT_RUNTIME(1); #define IA2_COMPARTMENT 1 diff --git a/tests/ro_sharing/main.c b/tests/ro_sharing/main.c index 64722ad92..b1aaa0f73 100644 --- a/tests/ro_sharing/main.c +++ b/tests/ro_sharing/main.c @@ -1,13 +1,13 @@ /* RUN: sh -c 'if [ ! -s "ro_sharing_call_gates_0.ld" ]; then echo "No link args as expected"; exit 0; fi; echo "Unexpected link args"; exit 1;' */ -#include -#include +#include + #include #include #include -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + // This test checks that all RO data mapped in from executable files is shared. // This is needed so that the dynamic linker can read ELF metadata. Read-only diff --git a/tests/ro_sharing/plugin.c b/tests/ro_sharing/plugin.c index f50ab959b..88802f927 100644 --- a/tests/ro_sharing/plugin.c +++ b/tests/ro_sharing/plugin.c @@ -1,8 +1,9 @@ /* RUN: cat ro_sharing_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include "test_fault_handler.h" -#include + +#include + #include #include #include diff --git a/tests/shared_data/access_shared.c b/tests/shared_data/access_shared.c index 434732b08..5e07992b3 100644 --- a/tests/shared_data/access_shared.c +++ b/tests/shared_data/access_shared.c @@ -3,7 +3,8 @@ RUN: cat shared_data_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ #include #include "access_shared.h" -#include +#include + // LINKARGS: --wrap=read_shared uint8_t read_shared(uint8_t *shared) { diff --git a/tests/shared_data/main.c b/tests/shared_data/main.c index 726791aff..976d0961e 100644 --- a/tests/shared_data/main.c +++ b/tests/shared_data/main.c @@ -5,7 +5,7 @@ RUN: sh -c 'if [ ! -s "shared_data_call_gates_0.ld" ]; then echo "No link args a #include #include #include "access_shared.h" -#include +#include INIT_RUNTIME(1); #define IA2_COMPARTMENT 1 diff --git a/tests/should_segfault/main.c b/tests/should_segfault/main.c index 53f4c2ec4..71b077276 100644 --- a/tests/should_segfault/main.c +++ b/tests/should_segfault/main.c @@ -1,14 +1,14 @@ /* RUN: sh -c 'if [ ! -s "should_segfault_call_gates_0.ld" ]; then echo "No link args as expected"; exit 0; fi; echo "Unexpected link args"; exit 1;' */ -#include +#include #include #include #include #include #include -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + INIT_RUNTIME(1); #define IA2_COMPARTMENT 1 @@ -30,4 +30,4 @@ Test(should_segfault, main) { Test(should_segfault, early_fault, .exit_code = 255) { do_early_fault(); print_secret(); -} \ No newline at end of file +} diff --git a/tests/should_segfault/print_secret.c b/tests/should_segfault/print_secret.c index 2d506ccd1..1b86cba92 100644 --- a/tests/should_segfault/print_secret.c +++ b/tests/should_segfault/print_secret.c @@ -1,12 +1,13 @@ /* RUN: cat should_segfault_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include +#include #include #include #include +#include #include "print_secret.h" -#include "test_fault_handler.h" + static bool early_fault = false; diff --git a/tests/sighandler/lib.c b/tests/sighandler/lib.c index e4b02c68b..e35eefc35 100644 --- a/tests/sighandler/lib.c +++ b/tests/sighandler/lib.c @@ -5,9 +5,10 @@ RUN: cat sighandler_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s #include "lib.h" #include #include -#include -#define IA2_DEFINE_TEST_HANDLER -#include +#include + + + #define IA2_COMPARTMENT 2 #include @@ -54,4 +55,4 @@ void install_sighandler_in_lib(bool rewrite) { }; install_sighandler_lib(&h); } -} \ No newline at end of file +} diff --git a/tests/sighandler/main.c b/tests/sighandler/main.c index b61aadfa9..f3f18cbf9 100644 --- a/tests/sighandler/main.c +++ b/tests/sighandler/main.c @@ -7,9 +7,9 @@ We need this because lib.c uses LINKARGS checks but not this file. #include #include #include -#define IA2_DEFINE_TEST_HANDLER -#include -#include + + +#include INIT_RUNTIME(2); #define IA2_COMPARTMENT 1 diff --git a/tests/simple1/main.c b/tests/simple1/main.c index 9c68dee6b..f547a4d3c 100644 --- a/tests/simple1/main.c +++ b/tests/simple1/main.c @@ -2,9 +2,9 @@ RUN: cat main.c | FileCheck --match-full-lines --check-prefix=REWRITER %s RUN: cat simple1_call_gates_0.ld | FileCheck --check-prefix=LINKARGS %s */ -#include -#include -#include +#include + + #include #include #include diff --git a/tests/simple1/simple1.c b/tests/simple1/simple1.c index 155f57282..1245bf85d 100644 --- a/tests/simple1/simple1.c +++ b/tests/simple1/simple1.c @@ -2,7 +2,8 @@ Source rewriter pass is a noop for PKEY=0. RUN: cat simple1_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include + +#include #include #include #include diff --git a/tests/static_addr_taken/lib.c b/tests/static_addr_taken/lib.c index 8d532fb18..389f0e130 100644 --- a/tests/static_addr_taken/lib.c +++ b/tests/static_addr_taken/lib.c @@ -1,5 +1,4 @@ -#include -#include +#include #include #define IA2_COMPARTMENT 2 @@ -22,4 +21,4 @@ static fn_ptr_ty ptrs[3] IA2_SHARED_DATA = { fn_ptr_ty *get_ptrs_in_lib(void) { return ptrs; -} \ No newline at end of file +} diff --git a/tests/static_addr_taken/main.c b/tests/static_addr_taken/main.c index 4db4c951e..57b6ba744 100644 --- a/tests/static_addr_taken/main.c +++ b/tests/static_addr_taken/main.c @@ -1,5 +1,4 @@ -#include -#include +#include #include INIT_RUNTIME(2); @@ -40,4 +39,4 @@ Test(static_addr_taken, call_ptr_from_lib) { for (int i = 0; i < 3; i++) { lib_ptrs[i](); } -} \ No newline at end of file +} diff --git a/tests/structs/main.c b/tests/structs/main.c index 57414c5d2..e5931a985 100644 --- a/tests/structs/main.c +++ b/tests/structs/main.c @@ -2,8 +2,8 @@ RUN: sh -c 'if [ ! -s "structs_call_gates_0.ld" ]; then echo "No link args as expected"; exit 0; fi; echo "Unexpected link args"; exit 1;' */ #include "structs.h" -#include -#include +#include + #include #include diff --git a/tests/structs/structs.c b/tests/structs/structs.c index e97cce861..73ca27eb7 100644 --- a/tests/structs/structs.c +++ b/tests/structs/structs.c @@ -2,7 +2,7 @@ RUN: cat structs_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ #include "structs.h" -#include +#include #include // LINKARGS: --wrap=check_s5 diff --git a/tests/threads/library.c b/tests/threads/library.c index f74ad0b0b..7e3abc5f3 100644 --- a/tests/threads/library.c +++ b/tests/threads/library.c @@ -1,8 +1,8 @@ /* RUN: cat threads_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include -#include +#include + #include "library.h" #include #include diff --git a/tests/threads/main.c b/tests/threads/main.c index cfbc8c6c2..f9f77d773 100644 --- a/tests/threads/main.c +++ b/tests/threads/main.c @@ -1,16 +1,16 @@ /* RUN: sh -c 'if [ ! -s "threads_call_gates_0.ld" ]; then echo "No link args as expected"; exit 0; fi; echo "Unexpected link args"; exit 1;' */ -#include -#include +#include + #include "library.h" #include #include #include #include #include -#define IA2_DEFINE_TEST_HANDLER -#include + + #include INIT_RUNTIME(1); diff --git a/tests/three_keys_minimal/lib_1.c b/tests/three_keys_minimal/lib_1.c index 57f8e569a..ebf85324f 100644 --- a/tests/three_keys_minimal/lib_1.c +++ b/tests/three_keys_minimal/lib_1.c @@ -1,4 +1,4 @@ -#include +#include #include #define IA2_COMPARTMENT 3 diff --git a/tests/three_keys_minimal/lib_2.c b/tests/three_keys_minimal/lib_2.c index 0da24a2ea..f0e4bc150 100644 --- a/tests/three_keys_minimal/lib_2.c +++ b/tests/three_keys_minimal/lib_2.c @@ -1,4 +1,4 @@ -#include +#include #include #define IA2_COMPARTMENT 2 diff --git a/tests/three_keys_minimal/main.c b/tests/three_keys_minimal/main.c index d5b5dc9fa..e13278fd6 100644 --- a/tests/three_keys_minimal/main.c +++ b/tests/three_keys_minimal/main.c @@ -1,7 +1,7 @@ #include "ia2_internal.h" #include "lib_1/lib_1.h" #include "lib_2/lib_2.h" -#include +#include #include INIT_RUNTIME(3); @@ -10,8 +10,8 @@ INIT_RUNTIME(3); #include #include -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + void main_noop(void) { } diff --git a/tests/tls_protected/library.c b/tests/tls_protected/library.c index ff619f756..d238ebd8d 100644 --- a/tests/tls_protected/library.c +++ b/tests/tls_protected/library.c @@ -3,9 +3,9 @@ // Check that readelf shows exactly one executable segment #include "library.h" -#include "test_fault_handler.h" -#include -#include + +#include + #include #include #include diff --git a/tests/tls_protected/main.c b/tests/tls_protected/main.c index 2b58637e8..5f9319ce1 100644 --- a/tests/tls_protected/main.c +++ b/tests/tls_protected/main.c @@ -1,12 +1,12 @@ -#include -#include +#include + #include #include #include #include #include -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + #include INIT_RUNTIME(2); diff --git a/tests/trusted_direct/main.c b/tests/trusted_direct/main.c index 45823ecfb..87ff0bdde 100644 --- a/tests/trusted_direct/main.c +++ b/tests/trusted_direct/main.c @@ -1,16 +1,16 @@ /* RUN: cat trusted_direct_call_gates_0.ld | FileCheck --check-prefix=LINKARGS %s */ -#include -#include +#include + #include #include #include #include #include "plugin.h" -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + // This test checks that an untrusted library can call a trusted main binary. An // MPK violation is triggered from the untrusted library if no arguments are diff --git a/tests/trusted_direct/plugin.c b/tests/trusted_direct/plugin.c index ce0b7b239..0cc9d1407 100644 --- a/tests/trusted_direct/plugin.c +++ b/tests/trusted_direct/plugin.c @@ -1,10 +1,10 @@ /* RUN: cat trusted_direct_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include -#include +#include + #include "exported_fn.h" -#include "test_fault_handler.h" + // LINKARGS: --wrap=start_plugin void start_plugin(void) { diff --git a/tests/trusted_indirect/main.c b/tests/trusted_indirect/main.c index d599488d1..8ca0d80c2 100644 --- a/tests/trusted_indirect/main.c +++ b/tests/trusted_indirect/main.c @@ -2,12 +2,12 @@ RUN: cat main.c | FileCheck --match-full-lines --check-prefix=REWRITER %s RUN: sh -c 'if [ ! -s "trusted_indirect_call_gates_0.ld" ]; then echo "No link args as expected"; exit 0; fi; echo "Unexpected link args"; exit 1;' */ -#include -#include +#include + #include "rand_op.h" #include -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + /* This program tests that a trusted binary can receive and call function pointers from an diff --git a/tests/trusted_indirect/rand_op.c b/tests/trusted_indirect/rand_op.c index 7f5b5d7d1..cc7e54286 100644 --- a/tests/trusted_indirect/rand_op.c +++ b/tests/trusted_indirect/rand_op.c @@ -2,12 +2,12 @@ RUN: cat trusted_indirect_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include -#include -#include +#include + + #include #include "rand_op.h" -#include "test_fault_handler.h" + // This library either returns a pointer to `add` or to `sub`. One of the functions is static and // the other is part of the public API to ensure that both types of cross-compartment function diff --git a/tests/two_keys_minimal/main.c b/tests/two_keys_minimal/main.c index 09518beba..76d26ff3a 100644 --- a/tests/two_keys_minimal/main.c +++ b/tests/two_keys_minimal/main.c @@ -5,14 +5,14 @@ RUN: cat two_keys_minimal_call_gates_2.ld | FileCheck --check-prefix=LINKARGS %s // Check that readelf shows exactly one executable segment -#include -#include +#include + #include #include #include #include "plugin.h" -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + // This test uses two protection keys INIT_RUNTIME(2); diff --git a/tests/two_keys_minimal/plugin.c b/tests/two_keys_minimal/plugin.c index 95ef285e0..b8b84c929 100644 --- a/tests/two_keys_minimal/plugin.c +++ b/tests/two_keys_minimal/plugin.c @@ -4,12 +4,12 @@ RUN: cat two_keys_minimal_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s // Check that readelf shows exactly one executable segment -#include -#include +#include + #include #include #include "exported_fn.h" -#include "test_fault_handler.h" + #define IA2_COMPARTMENT 2 #include diff --git a/tests/two_shared_ranges/main.c b/tests/two_shared_ranges/main.c index c257ec9f0..b3e4027e3 100644 --- a/tests/two_shared_ranges/main.c +++ b/tests/two_shared_ranges/main.c @@ -4,13 +4,13 @@ RUN: cat two_shared_ranges_call_gates_2.ld | FileCheck --check-prefix=LINKARGS % // Check that readelf shows exactly one executable segment -#include -#include +#include + #include #include #include "plugin.h" -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + // This test uses two protection keys INIT_RUNTIME(2); diff --git a/tests/two_shared_ranges/plugin.c b/tests/two_shared_ranges/plugin.c index 17f6d19a2..16faff0e0 100644 --- a/tests/two_shared_ranges/plugin.c +++ b/tests/two_shared_ranges/plugin.c @@ -4,10 +4,11 @@ RUN: cat two_shared_ranges_call_gates_1.ld | FileCheck --check-prefix=LINKARGS % // Check that readelf shows exactly one executable segment -#include + +#include #include #include "exported_fn.h" -#include "test_fault_handler.h" + #define IA2_COMPARTMENT 2 #include diff --git a/tests/untrusted_indirect/foo.c b/tests/untrusted_indirect/foo.c index 2441cb56a..2b0606dcc 100644 --- a/tests/untrusted_indirect/foo.c +++ b/tests/untrusted_indirect/foo.c @@ -1,11 +1,11 @@ /* RUN: cat untrusted_indirect_call_gates_1.ld | FileCheck --check-prefix=LINKARGS %s */ -#include -#include +#include + #include #include "foo.h" -#include "test_fault_handler.h" + extern bool clean_exit; diff --git a/tests/untrusted_indirect/main.c b/tests/untrusted_indirect/main.c index 950b03e59..ae72570ab 100644 --- a/tests/untrusted_indirect/main.c +++ b/tests/untrusted_indirect/main.c @@ -1,13 +1,13 @@ /* RUN: sh -c 'if [ ! -s "untrusted_indirect_call_gates_0.ld" ]; then echo "No link args as expected"; exit 0; fi; echo "Unexpected link args"; exit 1;' */ -#include -#include +#include + #include #include "foo.h" #include -#define IA2_DEFINE_TEST_HANDLER -#include "test_fault_handler.h" + + INIT_RUNTIME(1); #define IA2_COMPARTMENT 1 diff --git a/tools/rewriter/SourceRewriter.cpp b/tools/rewriter/SourceRewriter.cpp index 89bd8e5e3..70509ef85 100644 --- a/tools/rewriter/SourceRewriter.cpp +++ b/tools/rewriter/SourceRewriter.cpp @@ -614,6 +614,7 @@ class FnPtrExpr : public RefactoringCallback { auto *fn_ptr_expr = result.Nodes.getNodeAs("fnPtrExpr"); assert(fn_ptr_expr != nullptr); + auto annotation = fn_ptr_expr->getDecl()->getAttr(); assert(result.SourceManager != nullptr); auto &sm = *result.SourceManager;