/* * Copyright (c) 2021, Idan Horowitz * * SPDX-License-Identifier: BSD-2-Clause */ #ifdef __clang__ # pragma clang optimize off #else # pragma GCC optimize("O0") #endif #include #include #include static void signal_handler(int) { // We execute this syscall in order to force the kernel to perform the syscall precondition validation which // checks that we have correctly set up the stack region to match our currently implemented protections. getuid(); _exit(0); } #ifdef __clang__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Winfinite-recursion" #endif static size_t infinite_recursion(size_t input) { return infinite_recursion(input) + 1; } #ifdef __clang__ # pragma clang diagnostic pop #endif // This test can only pass with sigaltstack correctly enabled, as otherwise the SIGSEGV signal handler itself would also fault due to the overflown stack. TEST_CASE(success_case) { static u8 alt_stack[SIGSTKSZ]; stack_t ss = { .ss_sp = alt_stack, .ss_flags = 0, .ss_size = SIGSTKSZ, }; auto res = sigaltstack(&ss, nullptr); EXPECT_EQ(res, 0); struct sigaction sa; sa.sa_handler = signal_handler; sa.sa_flags = SA_ONSTACK; res = sigfillset(&sa.sa_mask); EXPECT_EQ(res, 0); res = sigaction(SIGSEGV, &sa, 0); EXPECT_EQ(res, 0); (void)infinite_recursion(0); FAIL("Infinite recursion finished successfully"); }