github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/util/signal_util.h (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 #ifndef GVISOR_TEST_UTIL_SIGNAL_UTIL_H_ 16 #define GVISOR_TEST_UTIL_SIGNAL_UTIL_H_ 17 18 #include <signal.h> 19 #include <sys/syscall.h> 20 #include <unistd.h> 21 22 #include <ostream> 23 24 #include "gmock/gmock.h" 25 #include "test/util/cleanup.h" 26 #include "test/util/posix_error.h" 27 28 // Format a sigset_t as a comma separated list of numeric ranges. 29 ::std::ostream& operator<<(::std::ostream& os, const sigset_t& sigset); 30 31 namespace gvisor { 32 namespace testing { 33 34 // The maximum signal number. 35 static constexpr int kMaxSignal = 64; 36 37 // Wrapper for the tgkill(2) syscall, which glibc does not provide. 38 inline int tgkill(pid_t tgid, pid_t tid, int sig) { 39 return syscall(__NR_tgkill, tgid, tid, sig); 40 } 41 42 // Installs the passed sigaction and returns a cleanup function to restore the 43 // previous handler when it goes out of scope. 44 PosixErrorOr<Cleanup> ScopedSigaction(int sig, struct sigaction const& sa); 45 46 // Updates the signal mask as per sigprocmask(2) and returns a cleanup function 47 // to restore the previous signal mask when it goes out of scope. 48 PosixErrorOr<Cleanup> ScopedSignalMask(int how, sigset_t const& set); 49 50 // ScopedSignalMask variant that creates a mask of the single signal 'sig'. 51 inline PosixErrorOr<Cleanup> ScopedSignalMask(int how, int sig) { 52 sigset_t set; 53 sigemptyset(&set); 54 sigaddset(&set, sig); 55 return ScopedSignalMask(how, set); 56 } 57 58 // Asserts equality of two sigset_t values. 59 MATCHER_P(EqualsSigset, value, "equals " + ::testing::PrintToString(value)) { 60 for (int sig = 1; sig <= kMaxSignal; ++sig) { 61 if (sigismember(&arg, sig) != sigismember(&value, sig)) { 62 return false; 63 } 64 } 65 return true; 66 } 67 68 #ifdef __x86_64__ 69 // Fault can be used to generate a synchronous SIGSEGV. 70 // 71 // This fault can be fixed up in a handler via fixup, below. 72 inline void Fault() { 73 // Zero and dereference %ax. 74 asm("movabs $0, %%rax\r\n" 75 "mov 0(%%rax), %%rax\r\n" 76 : 77 : 78 : "ax"); 79 } 80 81 // FixupFault fixes up a fault generated by fault, above. 82 inline void FixupFault(ucontext_t* ctx) { 83 // Skip the bad instruction above. 84 // 85 // The encoding is 0x48 0xab 0x00. 86 ctx->uc_mcontext.gregs[REG_RIP] += 3; 87 } 88 #elif __aarch64__ 89 inline void Fault() { 90 // Zero and dereference x0. 91 asm("mov x0, xzr\r\n" 92 "str xzr, [x0]\r\n" 93 : 94 : 95 : "x0"); 96 } 97 98 inline void FixupFault(ucontext_t* ctx) { 99 // Skip the bad instruction above. 100 ctx->uc_mcontext.pc += 4; 101 } 102 #endif 103 104 } // namespace testing 105 } // namespace gvisor 106 107 #endif // GVISOR_TEST_UTIL_SIGNAL_UTIL_H_