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  }