Serenity Operating System
1/*
2 * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Platform.h>
8
9#if defined(AK_COMPILER_CLANG)
10# pragma clang optimize off
11#else
12# pragma GCC optimize("O0")
13#endif
14
15#include <LibTest/TestCase.h>
16#include <signal.h>
17#include <unistd.h>
18
19static void signal_handler(int)
20{
21 // We execute this syscall in order to force the kernel to perform the syscall precondition validation which
22 // checks that we have correctly set up the stack region to match our currently implemented protections.
23 getuid();
24 _exit(0);
25}
26
27#pragma GCC diagnostic push
28#pragma GCC diagnostic ignored "-Winfinite-recursion"
29static size_t infinite_recursion(size_t input)
30{
31 return infinite_recursion(input) + 1;
32}
33#pragma GCC diagnostic pop
34
35// This test can only pass with sigaltstack correctly enabled, as otherwise the SIGSEGV signal handler itself would also fault due to the overflown stack.
36TEST_CASE(success_case)
37{
38 static u8 alt_stack[SIGSTKSZ];
39 stack_t ss = {
40 .ss_sp = alt_stack,
41 .ss_flags = 0,
42 .ss_size = SIGSTKSZ,
43 };
44 auto res = sigaltstack(&ss, nullptr);
45 EXPECT_EQ(res, 0);
46
47 struct sigaction sa;
48 sa.sa_handler = signal_handler;
49 sa.sa_flags = SA_ONSTACK;
50 res = sigfillset(&sa.sa_mask);
51 EXPECT_EQ(res, 0);
52 res = sigaction(SIGSEGV, &sa, 0);
53 EXPECT_EQ(res, 0);
54
55 (void)infinite_recursion(0);
56 FAIL("Infinite recursion finished successfully");
57}