gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/exec_state_workload.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 <signal.h> 16 #include <stdint.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <sys/auxv.h> 20 #include <sys/prctl.h> 21 #include <sys/time.h> 22 23 #include <iostream> 24 #include <ostream> 25 #include <string> 26 27 #include "absl/strings/numbers.h" 28 29 // Pretty-print a sigset_t when it is a struct type. 30 // This is disabled for targets such as Android x86_64, which define sigset_t as 31 // an integral type, to prevent conflicts with the std library. 32 template <typename = std::enable_if<std::is_class<sigset_t>::value>> 33 std::ostream& operator<<(std::ostream& out, const sigset_t& s) { 34 out << "{ "; 35 36 for (int i = 0; i < NSIG; i++) { 37 if (sigismember(&s, i)) { 38 out << i << " "; 39 } 40 } 41 42 out << "}"; 43 return out; 44 } 45 46 // Verify that the signo handler is handler. 47 int CheckSigHandler(uint32_t signo, uintptr_t handler) { 48 struct sigaction sa; 49 int ret = sigaction(signo, nullptr, &sa); 50 if (ret < 0) { 51 perror("sigaction"); 52 return 1; 53 } 54 55 if (reinterpret_cast<void (*)(int)>(handler) != sa.sa_handler) { 56 std::cerr << "signo " << signo << " handler got: " << sa.sa_handler 57 << " expected: " << std::hex << handler; 58 return 1; 59 } 60 return 0; 61 } 62 63 // Verify that the signo is blocked. 64 int CheckSigBlocked(uint32_t signo) { 65 sigset_t s; 66 int ret = sigprocmask(SIG_SETMASK, nullptr, &s); 67 if (ret < 0) { 68 perror("sigprocmask"); 69 return 1; 70 } 71 72 if (!sigismember(&s, signo)) { 73 std::cerr << "signal " << signo << " not blocked in signal mask: " << s 74 << std::endl; 75 return 1; 76 } 77 return 0; 78 } 79 80 // Verify that the itimer is enabled. 81 int CheckItimerEnabled(uint32_t timer) { 82 struct itimerval itv; 83 int ret = getitimer(timer, &itv); 84 if (ret < 0) { 85 perror("getitimer"); 86 return 1; 87 } 88 89 if (!itv.it_value.tv_sec && !itv.it_value.tv_usec && 90 !itv.it_interval.tv_sec && !itv.it_interval.tv_usec) { 91 std::cerr << "timer " << timer 92 << " not enabled. value sec: " << itv.it_value.tv_sec 93 << " usec: " << itv.it_value.tv_usec 94 << " interval sec: " << itv.it_interval.tv_sec 95 << " usec: " << itv.it_interval.tv_usec << std::endl; 96 return 1; 97 } 98 return 0; 99 } 100 101 int PrintExecFn() { 102 unsigned long execfn = getauxval(AT_EXECFN); 103 if (!execfn) { 104 std::cerr << "AT_EXECFN missing" << std::endl; 105 return 1; 106 } 107 108 std::cerr << reinterpret_cast<const char*>(execfn) << std::endl; 109 return 0; 110 } 111 112 int PrintExecName() { 113 const size_t name_length = 20; 114 char name[name_length] = {0}; 115 if (prctl(PR_GET_NAME, name) < 0) { 116 std::cerr << "prctl(PR_GET_NAME) failed" << std::endl; 117 return 1; 118 } 119 120 std::cerr << name << std::endl; 121 return 0; 122 } 123 124 void usage(const std::string& prog) { 125 std::cerr << "usage:\n" 126 << "\t" << prog << " CheckSigHandler <signo> <handler addr (hex)>\n" 127 << "\t" << prog << " CheckSigBlocked <signo>\n" 128 << "\t" << prog << " CheckTimerDisabled <timer>\n" 129 << "\t" << prog << " PrintExecFn\n" 130 << "\t" << prog << " PrintExecName" << std::endl; 131 } 132 133 int main(int argc, char** argv) { 134 if (argc < 2) { 135 usage(argv[0]); 136 return 1; 137 } 138 139 std::string func(argv[1]); 140 141 if (func == "CheckSigHandler") { 142 if (argc != 4) { 143 usage(argv[0]); 144 return 1; 145 } 146 147 uint32_t signo; 148 if (!absl::SimpleAtoi(argv[2], &signo)) { 149 std::cerr << "invalid signo: " << argv[2] << std::endl; 150 return 1; 151 } 152 153 uintptr_t handler; 154 if (!absl::numbers_internal::safe_strtoi_base(argv[3], &handler, 16)) { 155 std::cerr << "invalid handler: " << std::hex << argv[3] << std::endl; 156 return 1; 157 } 158 159 return CheckSigHandler(signo, handler); 160 } 161 162 if (func == "CheckSigBlocked") { 163 if (argc != 3) { 164 usage(argv[0]); 165 return 1; 166 } 167 168 uint32_t signo; 169 if (!absl::SimpleAtoi(argv[2], &signo)) { 170 std::cerr << "invalid signo: " << argv[2] << std::endl; 171 return 1; 172 } 173 174 return CheckSigBlocked(signo); 175 } 176 177 if (func == "CheckItimerEnabled") { 178 if (argc != 3) { 179 usage(argv[0]); 180 return 1; 181 } 182 183 uint32_t timer; 184 if (!absl::SimpleAtoi(argv[2], &timer)) { 185 std::cerr << "invalid signo: " << argv[2] << std::endl; 186 return 1; 187 } 188 189 return CheckItimerEnabled(timer); 190 } 191 192 if (func == "PrintExecFn") { 193 // N.B. This will be called as an interpreter script, with the script passed 194 // as the third argument. We don't care about that script. 195 return PrintExecFn(); 196 } 197 198 if (func == "PrintExecName") { 199 // N.B. This may be called as an interpreter script like PrintExecFn. 200 return PrintExecName(); 201 } 202 203 std::cerr << "Invalid function: " << func << std::endl; 204 return 1; 205 }