1*71db0c75SAndroid Build Coastguard Worker //===-- Unittests for sigaltstack -----------------------------------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker
9*71db0c75SAndroid Build Coastguard Worker #include "hdr/signal_macros.h"
10*71db0c75SAndroid Build Coastguard Worker #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
11*71db0c75SAndroid Build Coastguard Worker #include "src/errno/libc_errno.h"
12*71db0c75SAndroid Build Coastguard Worker #include "src/signal/linux/signal_utils.h"
13*71db0c75SAndroid Build Coastguard Worker #include "src/signal/raise.h"
14*71db0c75SAndroid Build Coastguard Worker #include "src/signal/sigaction.h"
15*71db0c75SAndroid Build Coastguard Worker #include "src/signal/sigaltstack.h"
16*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/ErrnoSetterMatcher.h"
17*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h"
18*71db0c75SAndroid Build Coastguard Worker
19*71db0c75SAndroid Build Coastguard Worker #include <stdint.h>
20*71db0c75SAndroid Build Coastguard Worker #include <sys/syscall.h>
21*71db0c75SAndroid Build Coastguard Worker
22*71db0c75SAndroid Build Coastguard Worker constexpr int LOCAL_VAR_SIZE = 512;
23*71db0c75SAndroid Build Coastguard Worker constexpr int ALT_STACK_SIZE = SIGSTKSZ + LOCAL_VAR_SIZE * 2;
24*71db0c75SAndroid Build Coastguard Worker static uint8_t alt_stack[ALT_STACK_SIZE];
25*71db0c75SAndroid Build Coastguard Worker
26*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
27*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
28*71db0c75SAndroid Build Coastguard Worker
29*71db0c75SAndroid Build Coastguard Worker static bool good_stack;
handler(int)30*71db0c75SAndroid Build Coastguard Worker static void handler(int) {
31*71db0c75SAndroid Build Coastguard Worker // Allocate a large stack variable so that it does not get optimized
32*71db0c75SAndroid Build Coastguard Worker // out or mapped to a register.
33*71db0c75SAndroid Build Coastguard Worker uint8_t var[LOCAL_VAR_SIZE];
34*71db0c75SAndroid Build Coastguard Worker for (int i = 0; i < LOCAL_VAR_SIZE; ++i)
35*71db0c75SAndroid Build Coastguard Worker var[i] = i;
36*71db0c75SAndroid Build Coastguard Worker // Verify that array is completely on the alt_stack.
37*71db0c75SAndroid Build Coastguard Worker for (int i = 0; i < LOCAL_VAR_SIZE; ++i) {
38*71db0c75SAndroid Build Coastguard Worker if (!(uintptr_t(var + i) < uintptr_t(alt_stack + ALT_STACK_SIZE) &&
39*71db0c75SAndroid Build Coastguard Worker uintptr_t(alt_stack) <= uintptr_t(var + i))) {
40*71db0c75SAndroid Build Coastguard Worker good_stack = false;
41*71db0c75SAndroid Build Coastguard Worker return;
42*71db0c75SAndroid Build Coastguard Worker }
43*71db0c75SAndroid Build Coastguard Worker }
44*71db0c75SAndroid Build Coastguard Worker good_stack = true;
45*71db0c75SAndroid Build Coastguard Worker }
46*71db0c75SAndroid Build Coastguard Worker
TEST(LlvmLibcSignalTest,SigaltstackRunOnAltStack)47*71db0c75SAndroid Build Coastguard Worker TEST(LlvmLibcSignalTest, SigaltstackRunOnAltStack) {
48*71db0c75SAndroid Build Coastguard Worker struct sigaction action;
49*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::libc_errno = 0;
50*71db0c75SAndroid Build Coastguard Worker ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGUSR1, nullptr, &action),
51*71db0c75SAndroid Build Coastguard Worker Succeeds(0));
52*71db0c75SAndroid Build Coastguard Worker action.sa_handler = handler;
53*71db0c75SAndroid Build Coastguard Worker // Indicate that the signal should be delivered on an alternate stack.
54*71db0c75SAndroid Build Coastguard Worker action.sa_flags = SA_ONSTACK;
55*71db0c75SAndroid Build Coastguard Worker ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGUSR1, &action, nullptr),
56*71db0c75SAndroid Build Coastguard Worker Succeeds(0));
57*71db0c75SAndroid Build Coastguard Worker
58*71db0c75SAndroid Build Coastguard Worker stack_t ss;
59*71db0c75SAndroid Build Coastguard Worker ss.ss_sp = alt_stack;
60*71db0c75SAndroid Build Coastguard Worker ss.ss_size = ALT_STACK_SIZE;
61*71db0c75SAndroid Build Coastguard Worker ss.ss_flags = 0;
62*71db0c75SAndroid Build Coastguard Worker // Setup the alternate stack.
63*71db0c75SAndroid Build Coastguard Worker ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Succeeds(0));
64*71db0c75SAndroid Build Coastguard Worker
65*71db0c75SAndroid Build Coastguard Worker good_stack = false;
66*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::raise(SIGUSR1);
67*71db0c75SAndroid Build Coastguard Worker EXPECT_TRUE(good_stack);
68*71db0c75SAndroid Build Coastguard Worker }
69*71db0c75SAndroid Build Coastguard Worker
70*71db0c75SAndroid Build Coastguard Worker // This tests for invalid input.
TEST(LlvmLibcSignalTest,SigaltstackInvalidStack)71*71db0c75SAndroid Build Coastguard Worker TEST(LlvmLibcSignalTest, SigaltstackInvalidStack) {
72*71db0c75SAndroid Build Coastguard Worker stack_t ss;
73*71db0c75SAndroid Build Coastguard Worker ss.ss_sp = alt_stack;
74*71db0c75SAndroid Build Coastguard Worker ss.ss_size = 0;
75*71db0c75SAndroid Build Coastguard Worker ss.ss_flags = SS_ONSTACK;
76*71db0c75SAndroid Build Coastguard Worker ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Fails(EINVAL));
77*71db0c75SAndroid Build Coastguard Worker
78*71db0c75SAndroid Build Coastguard Worker ss.ss_flags = 0;
79*71db0c75SAndroid Build Coastguard Worker ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Fails(ENOMEM));
80*71db0c75SAndroid Build Coastguard Worker }
81