github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/sigaltstack.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <errno.h> 16 #include <signal.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include <unistd.h> 20 21 #include <functional> 22 #include <vector> 23 24 #include "gtest/gtest.h" 25 #include "test/util/cleanup.h" 26 #include "test/util/fs_util.h" 27 #include "test/util/multiprocess_util.h" 28 #include "test/util/posix_error.h" 29 #include "test/util/signal_util.h" 30 #include "test/util/test_util.h" 31 #include "test/util/thread_util.h" 32 33 namespace gvisor { 34 namespace testing { 35 36 namespace { 37 38 PosixErrorOr<Cleanup> ScopedSigaltstack(stack_t const& stack) { 39 stack_t old_stack; 40 int rc = sigaltstack(&stack, &old_stack); 41 MaybeSave(); 42 if (rc < 0) { 43 return PosixError(errno, "sigaltstack failed"); 44 } 45 return Cleanup([old_stack] { 46 EXPECT_THAT(sigaltstack(&old_stack, nullptr), SyscallSucceeds()); 47 }); 48 } 49 50 volatile bool got_signal = false; 51 volatile int sigaltstack_errno = 0; 52 volatile int ss_flags = 0; 53 54 void sigaltstack_handler(int sig, siginfo_t* siginfo, void* arg) { 55 got_signal = true; 56 57 stack_t stack; 58 int ret = sigaltstack(nullptr, &stack); 59 MaybeSave(); 60 if (ret < 0) { 61 sigaltstack_errno = errno; 62 return; 63 } 64 ss_flags = stack.ss_flags; 65 } 66 67 TEST(SigaltstackTest, Success) { 68 std::vector<char> stack_mem(SIGSTKSZ); 69 stack_t stack = {}; 70 stack.ss_sp = stack_mem.data(); 71 stack.ss_size = stack_mem.size(); 72 auto const cleanup_sigstack = 73 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaltstack(stack)); 74 75 struct sigaction sa = {}; 76 sa.sa_sigaction = sigaltstack_handler; 77 sigfillset(&sa.sa_mask); 78 sa.sa_flags = SA_SIGINFO | SA_ONSTACK; 79 auto const cleanup_sa = 80 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGUSR1, sa)); 81 82 // Send signal to this thread, as sigaltstack is per-thread. 83 EXPECT_THAT(tgkill(getpid(), gettid(), SIGUSR1), SyscallSucceeds()); 84 85 EXPECT_TRUE(got_signal); 86 EXPECT_EQ(sigaltstack_errno, 0); 87 EXPECT_NE(0, ss_flags & SS_ONSTACK); 88 } 89 90 TEST(SigaltstackTest, ResetByExecve) { 91 std::vector<char> stack_mem(SIGSTKSZ); 92 stack_t stack = {}; 93 stack.ss_sp = stack_mem.data(); 94 stack.ss_size = stack_mem.size(); 95 auto const cleanup_sigstack = 96 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaltstack(stack)); 97 98 std::string full_path = RunfilePath("test/syscalls/linux/sigaltstack_check"); 99 100 pid_t child_pid = -1; 101 int execve_errno = 0; 102 auto cleanup = ASSERT_NO_ERRNO_AND_VALUE( 103 ForkAndExec(full_path, {"sigaltstack_check"}, {}, nullptr, &child_pid, 104 &execve_errno)); 105 106 ASSERT_GT(child_pid, 0); 107 ASSERT_EQ(execve_errno, 0); 108 109 int status = 0; 110 ASSERT_THAT(RetryEINTR(waitpid)(child_pid, &status, 0), SyscallSucceeds()); 111 ASSERT_TRUE(WIFEXITED(status)); 112 ASSERT_EQ(WEXITSTATUS(status), 0); 113 } 114 115 volatile bool badhandler_on_sigaltstack = true; // Set by the handler. 116 char* volatile badhandler_low_water_mark = nullptr; // Set by the handler. 117 volatile uint8_t badhandler_recursive_faults = 0; // Consumed by the handler. 118 119 void badhandler(int sig, siginfo_t* siginfo, void* arg) { 120 char stack_var = 0; 121 char* current_ss = &stack_var; 122 123 stack_t stack; 124 int ret = sigaltstack(nullptr, &stack); 125 if (ret < 0 || (stack.ss_flags & SS_ONSTACK) != SS_ONSTACK) { 126 // We should always be marked as being on the stack. Don't allow this to hit 127 // the bottom if this is ever not true (the main test will fail as a 128 // result, but we still need to unwind the recursive faults). 129 badhandler_on_sigaltstack = false; 130 } 131 if (current_ss < badhandler_low_water_mark) { 132 // Record the low point for the signal stack. We never expected this to be 133 // before stack bottom, but this is asserted in the actual test. 134 badhandler_low_water_mark = current_ss; 135 } 136 if (badhandler_recursive_faults > 0) { 137 badhandler_recursive_faults--; 138 Fault(); 139 } 140 FixupFault(reinterpret_cast<ucontext_t*>(arg)); 141 } 142 143 TEST(SigaltstackTest, WalksOffBottom) { 144 // This test marks the upper half of the stack_mem array as the signal stack. 145 // It asserts that when a fault occurs in the handler (already on the signal 146 // stack), we eventually continue to fault our way off the stack. We should 147 // not revert to the top of the signal stack when we fall off the bottom and 148 // the signal stack should remain "in use". When we fall off the signal stack, 149 // we should have an unconditional signal delivered and not start using the 150 // first part of the stack_mem array. 151 std::vector<char> stack_mem(SIGSTKSZ * 2); 152 stack_t stack = {}; 153 stack.ss_sp = stack_mem.data() + SIGSTKSZ; // See above: upper half. 154 stack.ss_size = SIGSTKSZ; // Only one half the array. 155 auto const cleanup_sigstack = 156 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaltstack(stack)); 157 158 // Setup the handler: this must be for SIGSEGV, and it must allow proper 159 // nesting (no signal mask, no defer) so that we can trigger multiple times. 160 // 161 // When we walk off the bottom of the signal stack and force signal delivery 162 // of a SIGSEGV, the handler will revert to the default behavior (kill). 163 struct sigaction sa = {}; 164 sa.sa_sigaction = badhandler; 165 sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER; 166 auto const cleanup_sa = 167 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGSEGV, sa)); 168 169 // Trigger a single fault. 170 badhandler_low_water_mark = 171 static_cast<char*>(stack.ss_sp) + SIGSTKSZ; // Expected top. 172 badhandler_recursive_faults = 0; // Disable refault. 173 Fault(); 174 EXPECT_TRUE(badhandler_on_sigaltstack); 175 EXPECT_THAT(sigaltstack(nullptr, &stack), SyscallSucceeds()); 176 EXPECT_EQ(stack.ss_flags & SS_ONSTACK, 0); 177 EXPECT_LT(badhandler_low_water_mark, 178 reinterpret_cast<char*>(stack.ss_sp) + 2 * SIGSTKSZ); 179 EXPECT_GT(badhandler_low_water_mark, reinterpret_cast<char*>(stack.ss_sp)); 180 181 // Trigger two faults. 182 char* prev_low_water_mark = badhandler_low_water_mark; // Previous top. 183 badhandler_recursive_faults = 1; // One refault. 184 Fault(); 185 ASSERT_TRUE(badhandler_on_sigaltstack); 186 EXPECT_THAT(sigaltstack(nullptr, &stack), SyscallSucceeds()); 187 EXPECT_EQ(stack.ss_flags & SS_ONSTACK, 0); 188 EXPECT_LT(badhandler_low_water_mark, prev_low_water_mark); 189 EXPECT_GT(badhandler_low_water_mark, reinterpret_cast<char*>(stack.ss_sp)); 190 191 // Calculate the stack growth for a fault, and set the recursive faults to 192 // ensure that the signal handler stack required exceeds our marked stack area 193 // by a minimal amount. It should remain in the valid stack_mem area so that 194 // we can test the signal is forced merely by going out of the signal stack 195 // bounds, not by a genuine fault. 196 uintptr_t frame_size = 197 static_cast<uintptr_t>(prev_low_water_mark - badhandler_low_water_mark); 198 badhandler_recursive_faults = (SIGSTKSZ + frame_size) / frame_size; 199 EXPECT_EXIT(Fault(), ::testing::KilledBySignal(SIGSEGV), ""); 200 } 201 202 volatile int setonstack_retval = 0; // Set by the handler. 203 volatile int setonstack_errno = 0; // Set by the handler. 204 205 void setonstack(int sig, siginfo_t* siginfo, void* arg) { 206 char stack_mem[SIGSTKSZ]; 207 stack_t stack = {}; 208 stack.ss_sp = &stack_mem[0]; 209 stack.ss_size = SIGSTKSZ; 210 setonstack_retval = sigaltstack(&stack, nullptr); 211 setonstack_errno = errno; 212 FixupFault(reinterpret_cast<ucontext_t*>(arg)); 213 } 214 215 TEST(SigaltstackTest, SetWhileOnStack) { 216 // Reserve twice as much stack here, since the handler will allocate a vector 217 // of size SIGTKSZ and attempt to set the sigaltstack to that value. 218 std::vector<char> stack_mem(2 * SIGSTKSZ); 219 stack_t stack = {}; 220 stack.ss_sp = stack_mem.data(); 221 stack.ss_size = stack_mem.size(); 222 auto const cleanup_sigstack = 223 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaltstack(stack)); 224 225 // See above. 226 struct sigaction sa = {}; 227 sa.sa_sigaction = setonstack; 228 sa.sa_flags = SA_SIGINFO | SA_ONSTACK; 229 auto const cleanup_sa = 230 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGSEGV, sa)); 231 232 // Trigger a fault. 233 Fault(); 234 235 // The set should have failed. 236 EXPECT_EQ(setonstack_retval, -1); 237 EXPECT_EQ(setonstack_errno, EPERM); 238 } 239 240 TEST(SigaltstackTest, SetCurrentStack) { 241 // This is executed as an exit test because once the signal stack is set to 242 // the local stack, there's no good way to unwind. We don't want to taint the 243 // test of any other tests that might run within this process. 244 EXPECT_EXIT( 245 { 246 char stack_value = 0; 247 stack_t stack = {}; 248 stack.ss_sp = &stack_value - kPageSize; // Lower than current level. 249 stack.ss_size = 2 * kPageSize; // => &stack_value +/- kPageSize. 250 TEST_CHECK(sigaltstack(&stack, nullptr) == 0); 251 TEST_CHECK(sigaltstack(nullptr, &stack) == 0); 252 TEST_CHECK((stack.ss_flags & SS_ONSTACK) != 0); 253 254 // Should not be able to change the stack (even no-op). 255 TEST_CHECK(sigaltstack(&stack, nullptr) == -1 && errno == EPERM); 256 257 // Should not be able to disable the stack. 258 stack.ss_flags = SS_DISABLE; 259 TEST_CHECK(sigaltstack(&stack, nullptr) == -1 && errno == EPERM); 260 exit(0); 261 }, 262 ::testing::ExitedWithCode(0), ""); 263 } 264 265 } // namespace 266 267 } // namespace testing 268 } // namespace gvisor