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