Don't invoke error handlers when the callee errors. I originally made a forced unwind out of a compartment invoke the caller's error handler (if it existed) with a special error code. The idea was that you could use error handlers to jump to recovery paths, rather than checking return values. This seemed like a good idea at the time, but turned out to be a mistake. The only code that has ever used this behaviour was the test suite. Other error handlers have special-case logic to check if this is the reason and ignore it if so. It also added a lot of confusing control flow in the switcher, which is bad because the switcher is the core of the TCB. Fixes #302
diff --git a/sdk/core/switcher/entry.S b/sdk/core/switcher/entry.S index 80af180..8ef9cca 100644 --- a/sdk/core/switcher/entry.S +++ b/sdk/core/switcher/entry.S
@@ -485,24 +485,11 @@ csrw CSR_MSHWMB, x1 #endif cspecialw mepcc, ct2 - csb zero, TrustedStack_offset_inForcedUnwind(csp) // c2 is csp, which will be loaded last and will overwrite the trusted // stack pointer with the thread's stack pointer. reloadRegisters c1, cgp, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, csp mret -// If we detect an invalid entry and there is no error handler installed, we want -// to resume rather than unwind. -.Linvalid_entry: -// Mark this threads as in the middle of a forced unwind. - li a0, 1 - csb a0, TrustedStack_offset_inForcedUnwind(ctp) -// Make sure we don't leak anything to the compartment. -// Registers might been used by the call and therefore need zeroing. - zeroAllRegistersExcept a0, s0, s1, sp, a2, gp -// Store an error value in return registers, which will be passed to the -// caller on unwind. a1 is zeroed by zeroAllRegistersExcept. - li a0, -1 // We are starting a forced unwind. This is reached either when we are unable // to run an error handler, or when we do run an error handler and it instructs // us to return. This treats all register values as undefined on entry. @@ -510,57 +497,32 @@ // Pop the trusted stack frame. cjal .Lpop_trusted_stack_frame cmove cra, ca2 -.Lout_of_trusted_stack: - cmove ct0, csp - // Fetch the trusted stack pointer. - cspecialr csp, mtdc - // csp now points to the save reg frame that we can use. - // Spill all of the registers that we want to propagate to the caller: - // c1(cra), c2(csp), c3(cgp), c8(cs0), c9(cs1), c10(ca0), c11(ca1) - csc ct0, TrustedStack_offset_csp(csp) - spillRegisters c1, cgp, c8, c9, c10, c11 - // Store an unsealed version of cra in the mepcc slot, where it will be - // used for mret later. mret requires an unsealed capability in mepcc, so - // we have to unseal it if it is sealed. - LoadCapPCC cs0, compartment_switcher_sealing_key - // ca2 at this point was loaded by .Lpop_trusted_stack_frame from the pcc - // in the trusted stack and so should always be sealed as a sentry type. - cgettype gp, cra - csetaddr cs0, cs0, gp - cunseal cra, cra, cs0 - csc cra, TrustedStack_offset_mepcc(csp) - clw t0, TrustedStack_offset_mstatus(csp) - // If gp==2 then the we need to disable interrupts on return, otherwise we - // need to enable them. The interrupt enable bit is bit 7. We want to set - // bit 7 if interrupts are enabled, clear it if they are disabled, but not - // toggle any other bits. - // Clear the interrupt enable bit unconditionally - andi t0, t0, ~0x80 - // Set it again if we should have interrupts enabled - li a3, 2 - beq gp, a3, .Ldo_not_enable - ori t0, t0, 0x80 -.Ldo_not_enable: - csw t0, TrustedStack_offset_mstatus(csp) + // Zero all registers apart from RA, GP, SP and return args. + // cra, cs0, cs1, and cgp were restored from the compartment's stack + // csp restored from the trusted stack. + // ca0, used for first return value + // ca1, used for second return value + zeroAllRegistersExcept ra, sp, gp, s0, s1, a0, a1 + li a0, -ECOMPARTMENTFAIL + li a1, 0 + cret - // Zero all registers that we aren't explicitly restoring to avoid leaks - // from the faulting callee to the caller. - csc cnull, TrustedStack_offset_c4(csp) - csc cnull, TrustedStack_offset_c5(csp) - csc cnull, TrustedStack_offset_c6(csp) - csc cnull, TrustedStack_offset_c7(csp) - csc cnull, TrustedStack_offset_c12(csp) - csc cnull, TrustedStack_offset_c13(csp) - csc cnull, TrustedStack_offset_c14(csp) - csc cnull, TrustedStack_offset_c15(csp) - // Mark this threads as in the middle of a forced unwind. - li a0, 1 - csb a0, TrustedStack_offset_inForcedUnwind(csp) - // Spill a fake status and cap cause (CHERI fault, no cause) - li a0, 0x1c - csw a0, TrustedStack_offset_mcause(csp) - csrw mtval, zero - // Fall through to handle error + +// If we have run out of trusted stack, then just restore the caller's state +// and return an error value. +.Lout_of_trusted_stack: + // Restore the spilled values + clc cs0, SPILL_SLOT_cs0(csp) + clc cs1, SPILL_SLOT_cs1(csp) + clc cra, SPILL_SLOT_pcc(csp) + clc cgp, SPILL_SLOT_cgp(csp) + cincoffset csp, csp, SPILL_SLOT_SIZE + // Set the return registers + li a0, -ENOTENOUGHTRUSTEDSTACK + li a1, 0 + // Zero everything else + zeroAllRegistersExcept ra, sp, gp, s0, s1, a0, a1 + cret // If we have a possibly recoverable error, see if we have a useful error // handler. At this point, the register state will have been saved in the @@ -600,7 +562,7 @@ // See if we can find a handler: clhu tp, TrustedStack_offset_frameoffset(csp) li t1, TrustedStack_offset_frames - beq tp, t1, .Lend_of_stack + beq tp, t1, .Lreset_mepcc_and_install_context addi tp, tp, -TrustedStackFrame_size // ctp points to the current available trusted stack frame. @@ -649,7 +611,7 @@ // A value of 0xffff indicates no error handler // Give up if there is no error handler for this compartment. li s1, 0xffff - beq s0, s1, .Lno_handler_found + beq s0, s1, .Lforce_unwind // The stack may have had its tag cleared at this point, so for stackless // handlers we need to restore the on-entry stack. @@ -677,10 +639,6 @@ .Lhandler_found: - // If we have found a handler, mark this threads as no longer on the - // force-unwind path. Any future fault will trigger a forced unwind. - csb zero, TrustedStack_offset_inForcedUnwind(csp) - // Increment the handler invocation count. clhu s1, TrustedStackFrame_offset_errorHandlerCount(ctp) addi s1, s1, 1 @@ -816,23 +774,11 @@ j .Lhandle_error -// We have reached the end of the stack. If we are in a forced unwind then we -// just install the context, if we've gone off the top of the stack then we -// should report this gracefully. -.Lend_of_stack: - clb a2, TrustedStack_offset_inForcedUnwind(csp) - bnez a2, .Lreset_mepcc_and_install_context // Value 24 is reserved for custom use. .Lset_mcause_and_exit_thread: csrw mcause, 24 j .Lthread_exit -// No handler was found. If we are in the middle of unwinding, then we want to -// just install the context but if this is a fault then we keep going up the -// stack. -.Lno_handler_found: - clb a2, TrustedStack_offset_inForcedUnwind(csp) - beqz a2, .Lforce_unwind // The continue-resume path expects the location that we will mret to to be // in ct2. If we're just resuming, then resume from the stashed link // register value.
diff --git a/sdk/core/switcher/trusted-stack-assembly.h b/sdk/core/switcher/trusted-stack-assembly.h index 0511ac1..02fc248 100644 --- a/sdk/core/switcher/trusted-stack-assembly.h +++ b/sdk/core/switcher/trusted-stack-assembly.h
@@ -28,12 +28,12 @@ // Size of everything up to this point # define TSTACK_REGFRAME_SZ (19 * 8) -// frameoffset, inForcedUnwind and padding +// frameoffset and padding # define TSTACK_HEADER_SZ 16 #else // Size of everything up to this point # define TSTACK_REGFRAME_SZ ((17 * 8) + (2 * 4)) -// frameoffset, inForcedUnwind and padding +// frameoffset and padding # define TSTACK_HEADER_SZ 8 #endif // The basic trusted stack is the size of the save area, 8 bytes of state for @@ -47,7 +47,6 @@ TSTACK_REGFRAME_SZ + TSTACK_HEADER_SZ) EXPORT_ASSEMBLY_OFFSET(TrustedStack, frameoffset, TSTACK_REGFRAME_SZ) EXPORT_ASSEMBLY_OFFSET(TrustedStack, threadID, TSTACK_REGFRAME_SZ + 2) -EXPORT_ASSEMBLY_OFFSET(TrustedStack, inForcedUnwind, TSTACK_REGFRAME_SZ + 4) EXPORT_ASSEMBLY_OFFSET(TrustedStackFrame, csp, 0) EXPORT_ASSEMBLY_OFFSET(TrustedStackFrame, calleeExportTable, 8)
diff --git a/sdk/core/switcher/tstack.h b/sdk/core/switcher/tstack.h index 0875249..45af06e 100644 --- a/sdk/core/switcher/tstack.h +++ b/sdk/core/switcher/tstack.h
@@ -59,17 +59,12 @@ * The ID of the current thread. Never modified during execution. */ uint16_t threadID; - /** - * Flag indicating whether this thread is in the process of a forced - * unwind. If so, this is one, otherwise it is zero. - */ - uint8_t inForcedUnwind; // Padding up to multiple of 16-bytes. uint8_t padding[ #ifdef CONFIG_MSHWM - 11 + 12 #else - 3 + 4 #endif ]; /**
diff --git a/sdk/include/errno.h b/sdk/include/errno.h index 07cf199..35aa193 100644 --- a/sdk/include/errno.h +++ b/sdk/include/errno.h
@@ -89,6 +89,7 @@ #define ENOTRECOVERABLE 131 // State not recoverable. #define EOVERFLOW 139 // Value too large to be stored in data type. #define ENOTENOUGHSTACK 140 // Insufficient stack space for cross-compartment call. +#define ENOTENOUGHTRUSTEDSTACK 141 // Insufficient stack space for cross-compartment call. #define EWOULDBLOCK EAGAIN // Operation would block. #define ENOTSUP EOPNOTSUPP // Not supported. #define __ELASTERROR 2000 // Users can add values starting here.
diff --git a/sdk/include/fail-simulator-on-error.h b/sdk/include/fail-simulator-on-error.h index da8f4eb..d26dceb 100644 --- a/sdk/include/fail-simulator-on-error.h +++ b/sdk/include/fail-simulator-on-error.h
@@ -67,11 +67,6 @@ DebugErrorHandler::log( "Thread exit CSP={}, PCC={}", stackCapability, frame->pcc); } - else if (exceptionCode == CHERI::CauseCode::None) - { - // An unwind occurred from a called compartment, just resume. - return ErrorRecoveryBehaviour::InstallContext; - } else { // An unexpected error -- log it and end the simulation
diff --git a/tests/allocator-test.cc b/tests/allocator-test.cc index c64eaac..97f19c9 100644 --- a/tests/allocator-test.cc +++ b/tests/allocator-test.cc
@@ -615,7 +615,7 @@ /** * Allocator test entry point. */ -void test_allocator() +int test_allocator() { GlobalConstructors::run(); @@ -682,4 +682,5 @@ TEST(quotaLeft == MALLOC_QUOTA, "After alloc and free from 0x100000-byte quota, {} bytes left", quotaLeft); + return 0; }
diff --git a/tests/check_pointer-test.cc b/tests/check_pointer-test.cc index a678de8..c079185 100644 --- a/tests/check_pointer-test.cc +++ b/tests/check_pointer-test.cc
@@ -128,7 +128,8 @@ "with a raw capability."); } -void test_check_pointer() +int test_check_pointer() { check_pointer_strict_mode(&object); + return 0; }
diff --git a/tests/compartment_calls-test.cc b/tests/compartment_calls-test.cc index 68fa93f..2f0cff1 100644 --- a/tests/compartment_calls-test.cc +++ b/tests/compartment_calls-test.cc
@@ -44,7 +44,7 @@ TEST(ret == 0, "compartment_call_inner returend {}", ret); } -void test_compartment_call() +int test_compartment_call() { bool outTestFailed = false; int ret = 0; @@ -67,10 +67,9 @@ csp); test_number_of_arguments(); - ret = test_incorrect_export_table_with_handler(nullptr); - TEST(ret == -1, "Test incorrect entry point with error handler failed"); test_incorrect_export_table(nullptr, &outTestFailed); TEST(outTestFailed == false, "Test incorrect entry point without error handler failed"); + return 0; }
diff --git a/tests/compartment_calls.h b/tests/compartment_calls.h index a93c81d..b740f31 100644 --- a/tests/compartment_calls.h +++ b/tests/compartment_calls.h
@@ -43,6 +43,6 @@ bool *outTestFailed); __cheri_compartment( "compartment_calls_inner_with_" - "handler") int test_incorrect_export_table_with_handler(__cheri_callback void (*fn)()); + "handler") int test_incorrect_export_table_with_handler(__cheri_callback int (*fn)()); __cheri_compartment("compartment_calls_outer") void compartment_call_outer(); -constexpr int ConstantValue = 0x41414141; \ No newline at end of file +constexpr int ConstantValue = 0x41414141;
diff --git a/tests/compartment_calls_inner_with_handler.cc b/tests/compartment_calls_inner_with_handler.cc deleted file mode 100644 index d82ca8f..0000000 --- a/tests/compartment_calls_inner_with_handler.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright Microsoft and CHERIoT Contributors. -// SPDX-License-Identifier: MIT - -#define TEST_NAME "Compartment calls (inner compartment)" -#include "compartment_calls.h" -#include "tests.hh" -#include <cheri.hh> -#include <errno.h> -#include <tuple> - -using namespace CHERI; - -extern "C" ErrorRecoveryBehaviour -compartment_error_handler(ErrorState *frame, size_t mcause, size_t mtval) -{ - return ErrorRecoveryBehaviour::ForceUnwind; -} - -int test_incorrect_export_table_with_handler(__cheri_callback void (*fn)()) -{ - /* - * Trigger a cross-compartment call with an invalid export entry. - */ - - debug_log( - "test an incorrect export table entry with error handler installed"); - - fn(); - - TEST(false, "Should be unreachable"); - - return 0; -} \ No newline at end of file
diff --git a/tests/crash_recovery-test.cc b/tests/crash_recovery-test.cc index 884c8d5..0254654 100644 --- a/tests/crash_recovery-test.cc +++ b/tests/crash_recovery-test.cc
@@ -36,7 +36,7 @@ return ErrorRecoveryBehaviour::InstallContext; } -void test_crash_recovery() +int test_crash_recovery() { debug_log("Calling crashy compartment indirectly"); test_crash_recovery_outer(0); @@ -46,30 +46,34 @@ "nested call crashed"); debug_log("Calling crashy compartment to fault and unwind"); - test_crash_recovery_inner(0); + void *ret = test_crash_recovery_inner(0); check_stack(); - debug_log("Calling crashy compartment returned (crashes: {})", crashes); - TEST(crashes == 1, "Failed to notice crash"); + debug_log("Calling crashy compartment returned ({})", ret); + TEST(crashes == 0, "Should not have crashed"); + TEST(ret != nullptr, "Failed to notice crash"); debug_log("Calling crashy compartment to return normally"); - test_crash_recovery_inner(1); + ret = test_crash_recovery_inner(1); check_stack(); debug_log("Calling crashy compartment returned (crashes: {})", crashes); - TEST(crashes == 1, "Should not have crashed"); + TEST(crashes == 0, "Should not have crashed"); + TEST(ret == nullptr, "Failed to notice crash"); debug_log("Returning normally from crash test"); debug_log("Calling crashy compartment to double fault and unwind"); - test_crash_recovery_inner(2); + ret = test_crash_recovery_inner(2); check_stack(); debug_log("Calling crashy compartment returned (crashes: {})", crashes); - TEST(crashes == 2, "Failed to notice crash"); + TEST(crashes == 0, "Should not have crashed"); + TEST(ret != nullptr, "Failed to notice crash"); debug_log( "Calling crashy compartment to corrupt CSP in stack pointer and unwind"); - test_crash_recovery_inner(3); + ret = test_crash_recovery_inner(3); check_stack(); debug_log("Calling crashy compartment returned (crashes: {})", crashes); - TEST(crashes == 3, "Failed to notice crash"); + TEST(crashes == 0, "Should not have crashed"); + TEST(ret != nullptr, "Failed to notice crash"); ptraddr_t handlerCount = switcher_handler_invocation_count_reset(); TEST(handlerCount == crashes * 2, @@ -90,5 +94,6 @@ // does not return and so will not generate code following it. asm volatile("c.unimp"); } - TEST(crashes == 3 + MaxCrashes, "Failed to notice crash"); + TEST(crashes == MaxCrashes, "Failed to notice crash"); + return 0; }
diff --git a/tests/debug-test.c b/tests/debug-test.c index 03c008c..9be9854 100644 --- a/tests/debug-test.c +++ b/tests/debug-test.c
@@ -1,7 +1,7 @@ #include <compartment.h> #include <debug.h> -__cheri_compartment("debug_test") void test_debug_c() +__cheri_compartment("debug_test") int test_debug_c() { unsigned char x = 'c'; _Bool t = true; @@ -22,4 +22,5 @@ CHERIOT_INVARIANT(true, "Testing C++ invariant failure"); CHERIOT_INVARIANT( true, "Testing C++ invariant failure: 42:{}", 42, 1, 3, 4, "oops"); + return 0; }
diff --git a/tests/debug-test.cc b/tests/debug-test.cc index e44bb65..5828f38 100644 --- a/tests/debug-test.cc +++ b/tests/debug-test.cc
@@ -2,7 +2,7 @@ #include <compartment.h> #include <debug.h> -void test_debug_cxx() +int test_debug_cxx() { unsigned char x = 'c'; CHERIOT_DEBUG_LOG("Debug messages", @@ -19,4 +19,5 @@ CHERIOT_INVARIANT(true, "Testing C++ invariant failure"); CHERIOT_INVARIANT( true, "Testing C++ invariant failure: 42:{}", 42, 1, 3, 4, "oops"); + return 0; }
diff --git a/tests/eventgroup-test.cc b/tests/eventgroup-test.cc index aed68c1..12cebed 100644 --- a/tests/eventgroup-test.cc +++ b/tests/eventgroup-test.cc
@@ -25,7 +25,7 @@ } } // namespace -void test_eventgroup() +int test_eventgroup() { EventGroup *group; @@ -70,4 +70,5 @@ ret = eventgroup_clear(&t, group, &bits, 0b100); TEST(ret == 0, "Failed to clear event group bits: {}", ret); TEST(bits == 0b1000, "Bits should be 0b1000, but is {}", bits); + return 0; }
diff --git a/tests/futex-test.cc b/tests/futex-test.cc index 970253f..4abfe6c 100644 --- a/tests/futex-test.cc +++ b/tests/futex-test.cc
@@ -21,7 +21,7 @@ true); #endif -void test_futex() +int test_futex() { static uint32_t futex; int ret; @@ -185,4 +185,5 @@ "PI futex with a zero thread ID returned {}, should be {}", ret, -EINVAL); + return 0; }
diff --git a/tests/list-test.cc b/tests/list-test.cc index 7db652e..5ea7700 100644 --- a/tests/list-test.cc +++ b/tests/list-test.cc
@@ -63,7 +63,7 @@ */ ds::linked_list::Sentinel<LinkedObject::ObjectRing> objects = {}; -void test_list() +int test_list() { debug_log("Testing the list implementation."); @@ -238,4 +238,5 @@ heapAtEnd); debug_log("Done testing the list."); + return 0; }
diff --git a/tests/locks-test.cc b/tests/locks-test.cc index 7b8db43..d85fea2 100644 --- a/tests/locks-test.cc +++ b/tests/locks-test.cc
@@ -396,7 +396,7 @@ } // namespace -void test_locks() +int test_locks() { test_lock(flagLock); test_lock(flagLockPriorityInherited); @@ -412,4 +412,5 @@ test_ticket_lock_ordering(); test_ticket_lock_overflow(); test_recursive_mutex(); + return 0; }
diff --git a/tests/misc-test.cc b/tests/misc-test.cc index 28352b1..f537067 100644 --- a/tests/misc-test.cc +++ b/tests/misc-test.cc
@@ -170,7 +170,7 @@ permissions); } -void test_misc() +int test_misc() { check_timeouts(); check_memchr(); @@ -200,4 +200,5 @@ void, test_word, true, false, false, false), 4, {Permission::Global, Permission::Load}); + return 0; }
diff --git a/tests/mmio-test.cc b/tests/mmio-test.cc index 4b090e5..bfffdc1 100644 --- a/tests/mmio-test.cc +++ b/tests/mmio-test.cc
@@ -14,7 +14,7 @@ p); } -void test_mmio() +int test_mmio() { check_permissions( MMIO_CAPABILITY_WITH_PERMISSIONS(Uart, uart, false, false, false, false), @@ -74,4 +74,5 @@ Permission::Store, Permission::LoadStoreCapability, Permission::LoadMutable}); + return 0; }
diff --git a/tests/multiwaiter-test.cc b/tests/multiwaiter-test.cc index b899be9..d0f380f 100644 --- a/tests/multiwaiter-test.cc +++ b/tests/multiwaiter-test.cc
@@ -14,7 +14,7 @@ using namespace CHERI; using namespace thread_pool; -void test_multiwaiter() +int test_multiwaiter() { static uint32_t futex = 0; static uint32_t futex2 = 0; @@ -130,4 +130,5 @@ free(queueMemory); multiwaiter_delete(MALLOC_CAPABILITY, mw); + return 0; }
diff --git a/tests/queue-test.cc b/tests/queue-test.cc index 5239f19..da18b87 100644 --- a/tests/queue-test.cc +++ b/tests/queue-test.cc
@@ -185,10 +185,11 @@ debug_log("All FreeRTOS queue tests successful"); } -void test_queue() +int test_queue() { test_queue_unsealed(); test_queue_sealed(); test_queue_freertos(); debug_log("All queue tests successful"); + return 0; }
diff --git a/tests/stack-test.cc b/tests/stack-test.cc index 95659c0..c814bf9 100644 --- a/tests/stack-test.cc +++ b/tests/stack-test.cc
@@ -125,7 +125,7 @@ * - compartment stack with incorrect permissions * - invalid compartment stack */ -void test_stack() +int test_stack() { int ret = test_with_small_stack(144); TEST(ret == 0, @@ -178,4 +178,5 @@ expect_handler(false); test_stack_invalid_on_call(callback); + return 0; }
diff --git a/tests/static_sealing-test.cc b/tests/static_sealing-test.cc index 9730719..046d704 100644 --- a/tests/static_sealing-test.cc +++ b/tests/static_sealing-test.cc
@@ -15,9 +15,10 @@ test, 42); -void test_static_sealing() +int test_static_sealing() { // Get a pointer to it and ask for it to be unsealed. Sealed<TestType> value{STATIC_SEALED_VALUE(test)}; test_static_sealed_object(value); + return 0; }
diff --git a/tests/stdio-test.cc b/tests/stdio-test.cc index a23aa0b..b7f2ac2 100644 --- a/tests/stdio-test.cc +++ b/tests/stdio-test.cc
@@ -3,7 +3,7 @@ #include "tests.hh" #include <stdio.h> -void test_stdio() +int test_stdio() { debug_log("Printing 'Hello, world!' to stdout"); printf("Hello, world!\n"); @@ -19,4 +19,5 @@ TEST(strcmp(buffer, "-42") == 0, "snprintf(\"%d\", -42) gave {}", std::string_view{buffer, BufferSize}); + return 0; }
diff --git a/tests/test-runner.cc b/tests/test-runner.cc index f599156..0c85f14 100644 --- a/tests/test-runner.cc +++ b/tests/test-runner.cc
@@ -11,6 +11,9 @@ namespace { + /// Have we detected a crash in any of the compartments? + volatile bool crashDetected = false; + /** * Read the cycle counter. */ @@ -33,16 +36,28 @@ */ void run_timed(const char *msg, auto &&fn) { - int startCycles = rdcycle(); - fn(); + bool failed = false; + int startCycles = rdcycle(); + if constexpr (std::is_same_v<std::invoke_result_t<decltype(fn)>, void>) + { + fn(); + } + else + { + failed = (fn() != 0); + } int cycles = rdcycle(); - debug_log("{} finished in {} cycles", msg, cycles - startCycles); + + if (failed) + { + debug_log("{} failed", msg); + crashDetected = true; + } + else + debug_log("{} finished in {} cycles", msg, cycles - startCycles); } } // namespace -/// Have we detected a crash in any of the compartments? -volatile bool crashDetected = false; - extern "C" enum ErrorRecoveryBehaviour compartment_error_handler(struct ErrorState *frame, size_t mcause, size_t mtval) {
diff --git a/tests/tests.hh b/tests/tests.hh index c805bde..14780ed 100644 --- a/tests/tests.hh +++ b/tests/tests.hh
@@ -5,25 +5,25 @@ #include <debug.hh> #include <thread.h> -__cheri_compartment("eventgroup_test") void test_eventgroup(); -__cheri_compartment("mmio_test") void test_mmio(); -__cheri_compartment("allocator_test") void test_allocator(); -__cheri_compartment("thread_pool_test") void test_thread_pool(); -__cheri_compartment("futex_test") void test_futex(); -__cheri_compartment("queue_test") void test_queue(); -__cheri_compartment("locks_test") void test_locks(); -__cheri_compartment("list_test") void test_list(); -__cheri_compartment("crash_recovery_test") void test_crash_recovery(); -__cheri_compartment("multiwaiter_test") void test_multiwaiter(); -__cheri_compartment("stack_test") void test_stack(); -__cheri_compartment("compartment_calls_test") void test_compartment_call(); -__cheri_compartment("check_pointer_test") void test_check_pointer(); -__cheri_compartment("misc_test") void test_misc(); -__cheri_compartment("static_sealing_test") void test_static_sealing(); -__cheri_compartment("stdio_test") void test_stdio(); -__cheri_compartment("debug_test") void test_debug_cxx(); -__cheri_compartment("debug_test") void test_debug_c(); -__cheri_compartment("unwind_cleanup_test") void test_unwind_cleanup(); +__cheri_compartment("eventgroup_test") int test_eventgroup(); +__cheri_compartment("mmio_test") int test_mmio(); +__cheri_compartment("allocator_test") int test_allocator(); +__cheri_compartment("thread_pool_test") int test_thread_pool(); +__cheri_compartment("futex_test") int test_futex(); +__cheri_compartment("queue_test") int test_queue(); +__cheri_compartment("locks_test") int test_locks(); +__cheri_compartment("list_test") int test_list(); +__cheri_compartment("crash_recovery_test") int test_crash_recovery(); +__cheri_compartment("multiwaiter_test") int test_multiwaiter(); +__cheri_compartment("stack_test") int test_stack(); +__cheri_compartment("compartment_calls_test") int test_compartment_call(); +__cheri_compartment("check_pointer_test") int test_check_pointer(); +__cheri_compartment("misc_test") int test_misc(); +__cheri_compartment("static_sealing_test") int test_static_sealing(); +__cheri_compartment("stdio_test") int test_stdio(); +__cheri_compartment("debug_test") int test_debug_cxx(); +__cheri_compartment("debug_test") int test_debug_c(); +__cheri_compartment("unwind_cleanup_test") int test_unwind_cleanup(); // Simple tests don't need a separate compartment. void test_global_constructors();
diff --git a/tests/thread_pool-test.cc b/tests/thread_pool-test.cc index 4499d09..52a08e0 100644 --- a/tests/thread_pool-test.cc +++ b/tests/thread_pool-test.cc
@@ -44,7 +44,7 @@ return ErrorRecoveryBehaviour::InstallContext; } -void test_thread_pool() +int test_thread_pool() { // We can't share stack variables, so create a heap allocation that we can // capture as an explicit pointer. @@ -137,7 +137,7 @@ Timeout t{3}; thread_sleep(&t); TEST(interrupted, "Worker thread was not interrupted"); - return; + return 0; static cheriot::atomic<uint32_t> barrier{3}; auto barrierWait = []() { uint32_t value = barrier--; @@ -156,4 +156,5 @@ async(barrierWait); barrierWait(); debug_log("Thread pool quiesced"); + return 0; }
diff --git a/tests/unwind_cleanup-test.cc b/tests/unwind_cleanup-test.cc index 6cbf390..e368562 100644 --- a/tests/unwind_cleanup-test.cc +++ b/tests/unwind_cleanup-test.cc
@@ -127,7 +127,7 @@ } // namespace -void test_unwind_cleanup() +int test_unwind_cleanup() { test_setjmp(); test_on_error(); @@ -140,4 +140,5 @@ test_from_stack_overflow(); test_from_trap(); debug_log("Test unwind_cleanup passed"); + return 0; }
diff --git a/tests/xmake.lua b/tests/xmake.lua index df7727b..7ecc6cb 100644 --- a/tests/xmake.lua +++ b/tests/xmake.lua
@@ -79,8 +79,6 @@ test("stack") compartment("compartment_calls_inner") add_files("compartment_calls_inner.cc") -compartment("compartment_calls_inner_with_handler") - add_files("compartment_calls_inner_with_handler.cc") test("compartment_calls") test("check_pointer") -- Test various APIs that are too small to deserve their own test file @@ -119,7 +117,7 @@ add_deps("multiwaiter_test") add_deps("ccompile_test") add_deps("stack_test", "stack_integrity_thread") - add_deps("compartment_calls_test", "compartment_calls_inner", "compartment_calls_inner_with_handler") + add_deps("compartment_calls_test", "compartment_calls_inner") add_deps("check_pointer_test") add_deps("misc_test") add_deps("stdio_test")