gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/processes.cc (about)

     1  // Copyright 2021 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 <stdint.h>
    16  #include <sys/mman.h>
    17  #include <sys/syscall.h>
    18  #include <unistd.h>
    19  
    20  #include <algorithm>
    21  #include <cstring>
    22  #include <memory>
    23  
    24  #include "gmock/gmock.h"
    25  #include "gtest/gtest.h"
    26  #include "absl/flags/flag.h"
    27  #include "absl/strings/str_format.h"
    28  #include "absl/strings/string_view.h"
    29  #include "absl/time/clock.h"
    30  #include "absl/time/time.h"
    31  #include "test/util/capability_util.h"
    32  #include "test/util/multiprocess_util.h"
    33  #include "test/util/save_util.h"
    34  #include "test/util/test_util.h"
    35  #include "test/util/thread_util.h"
    36  
    37  ABSL_FLAG(bool, processes_test_exec_swap, false,
    38            "If true, run the ExecSwap function.");
    39  ABSL_FLAG(int, processes_test_exec_swap_pre_clone_pid, -1,
    40            "Process ID from before clone; required when using "
    41            "--processes_test_exec_swap.");
    42  ABSL_FLAG(int, processes_test_exec_swap_pre_clone_tid, -1,
    43            "Thread ID from before clone; required when using "
    44            "--processes_test_exec_swap.");
    45  ABSL_FLAG(int, processes_test_exec_swap_pre_exec_pid, -1,
    46            "Process ID from before exec; required when using "
    47            "--processes_test_exec_swap.");
    48  ABSL_FLAG(int, processes_test_exec_swap_pre_exec_tid, -1,
    49            "Thread ID from before exec; required when using "
    50            "--processes_test_exec_swap.");
    51  ABSL_FLAG(int, processes_test_exec_swap_pipe_fd, -1,
    52            "File descriptor to write data to; required when using "
    53            "--processes_test_exec_swap.");
    54  
    55  namespace gvisor {
    56  namespace testing {
    57  
    58  int testSetPGIDOfZombie(void* arg) {
    59    int p[2];
    60  
    61    TEST_PCHECK(pipe(p) == 0);
    62  
    63    pid_t pid = fork();
    64    if (pid == 0) {
    65      pid = fork();
    66      // Create a second child to repeat one of syzkaller reproducers.
    67      if (pid == 0) {
    68        pid = getpid();
    69        TEST_PCHECK(setpgid(pid, 0) == 0);
    70        TEST_PCHECK(WriteFd(p[1], &pid, sizeof(pid)) == sizeof(pid));
    71        _exit(0);
    72      }
    73      TEST_PCHECK(pid > 0);
    74      _exit(0);
    75    }
    76    close(p[1]);
    77    TEST_PCHECK(pid > 0);
    78  
    79    // Get PID of the second child.
    80    pid_t cpid;
    81    TEST_PCHECK(ReadFd(p[0], &cpid, sizeof(cpid)) == sizeof(cpid));
    82  
    83    // Wait when both child processes will die.
    84    int c;
    85    TEST_PCHECK(ReadFd(p[0], &c, sizeof(c)) == 0);
    86  
    87    // Wait the second child process to collect its zombie.
    88    int status;
    89    TEST_PCHECK(RetryEINTR(waitpid)(cpid, &status, 0) == cpid);
    90  
    91    // Set the child's group.
    92    TEST_PCHECK(setpgid(pid, pid) == 0);
    93  
    94    TEST_PCHECK(RetryEINTR(waitpid)(-pid, &status, 0) == pid);
    95  
    96    TEST_PCHECK(status == 0);
    97    _exit(0);
    98  }
    99  
   100  TEST(Processes, SetPGIDOfZombie) {
   101    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   102  
   103    // Fork a test process in a new PID namespace, because it needs to manipulate
   104    // with reparented processes.
   105    struct clone_arg {
   106      // Reserve some space for clone() to locate arguments and retcode in this
   107      // place.
   108      char stack[128] __attribute__((aligned(16)));
   109      char stack_ptr[0];
   110    } ca;
   111    pid_t pid;
   112    ASSERT_THAT(pid = clone(testSetPGIDOfZombie, ca.stack_ptr,
   113                            CLONE_NEWPID | SIGCHLD, &ca),
   114                SyscallSucceeds());
   115  
   116    int status;
   117    ASSERT_THAT(RetryEINTR(waitpid)(pid, &status, 0),
   118                SyscallSucceedsWithValue(pid));
   119    EXPECT_EQ(status, 0);
   120  }
   121  
   122  void WritePIDToPipe(int* pipe_fds) {
   123    pid_t child_pid;
   124    TEST_PCHECK(child_pid = getpid());
   125    TEST_PCHECK(child_pid != gettid());
   126    TEST_PCHECK(WriteFd(pipe_fds[1], &child_pid, sizeof(child_pid)) ==
   127                sizeof(child_pid));
   128  }
   129  
   130  TEST(Processes, TheadSharesSamePID) {
   131    int pipe_fds[2];
   132    ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
   133    pid_t test_pid;
   134    ASSERT_THAT(test_pid = getpid(), SyscallSucceeds());
   135    EXPECT_NE(test_pid, 0);
   136    ScopedThread([&pipe_fds]() { WritePIDToPipe(pipe_fds); }).Join();
   137    ASSERT_THAT(close(pipe_fds[1]), SyscallSucceeds());
   138    pid_t pid_from_child;
   139    TEST_PCHECK(ReadFd(pipe_fds[0], &pid_from_child, sizeof(pid_from_child)) ==
   140                sizeof(pid_from_child));
   141    int buf;
   142    TEST_PCHECK(ReadFd(pipe_fds[0], &buf, sizeof(buf)) ==
   143                0);  // Wait for cloned thread to exit
   144    ASSERT_THAT(close(pipe_fds[0]), SyscallSucceeds());
   145    EXPECT_EQ(test_pid, pid_from_child);
   146  }
   147  
   148  TEST(Processes, ThousandsOfThreads) {
   149    const DisableSave ds;  // Too many syscalls.
   150    const int kThreadCount = 1000;
   151    const int kSyscallsPerThread = 1000;
   152    std::unique_ptr<ScopedThread> threads[kThreadCount];
   153    int pipe_fds[2];
   154    ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
   155  
   156    for (int i = 0; i < kThreadCount; i++) {
   157      threads[i] = std::make_unique<ScopedThread>([&pipe_fds]() {
   158        char c;
   159        EXPECT_THAT(ReadFd(pipe_fds[0], &c, 1), SyscallSucceedsWithValue(0));
   160        for (int j = 0; j < kSyscallsPerThread; j++) {
   161          syscall(SYS_close, -1);
   162        }
   163      });
   164    }
   165    close(pipe_fds[1]);
   166    for (int i = 0; i < kThreadCount; i++) {
   167      threads[i]->Join();
   168    }
   169  }
   170  
   171  // ExecSwapResult is used to carry PIDs and TIDs in ExecSwapThreadGroupLeader.
   172  struct ExecSwapResult {
   173    int pipe_fd;  // FD to write result data to.
   174  
   175    // PID and TID before we call clone().
   176    pid_t pre_clone_pid;
   177    pid_t pre_clone_tid;
   178  
   179    // PID and TID before the clone calls execv().
   180    pid_t pre_exec_pid;
   181    pid_t pre_exec_tid;
   182  
   183    // PID and TID after the execv().
   184    pid_t post_exec_pid;
   185    pid_t post_exec_tid;
   186  };
   187  
   188  // The number of elements in ExecSwapArg.execve_array.
   189  constexpr int kExecveArraySize = 7;
   190  
   191  // The size of the preallocated elements of execve_array that are populated
   192  // in ExecSwapPreExec. Should be large enough to hold any flag string.
   193  constexpr int kExecveArrayComponentsSize = 256;
   194  
   195  // ExecSwapArg is passed as argument to ExecSwapPreExec.
   196  struct ExecSwapArg {
   197    // The pipe FD to write results to.
   198    int pipe_fd;
   199  
   200    // Data from prior to cloning.
   201    pid_t pre_clone_pid;
   202    pid_t pre_clone_tid;
   203  
   204    // Pre-allocated array to use in execve, so that we can use it without doing
   205    // allocations in ExecSwapPreExec.
   206    char* execve_array[kExecveArraySize];
   207  };
   208  
   209  // ExecSwapPostExec is the third part of the ExecSwapThreadGroupLeader test.
   210  // It is called after the test has fork()'d, clone()'d, and exec()'d into
   211  // this. It writes all the PIDs and TIDs from each part of the test to a pipe.
   212  int ExecSwapPostExec() {
   213    std::cerr << "Test exec'd." << std::endl;
   214    pid_t pid;
   215    TEST_PCHECK(pid = getpid());
   216    pid_t tid;
   217    TEST_PCHECK(tid = gettid());
   218    ExecSwapResult result;
   219    result.pipe_fd = absl::GetFlag(FLAGS_processes_test_exec_swap_pipe_fd);
   220    result.pre_clone_pid =
   221        absl::GetFlag(FLAGS_processes_test_exec_swap_pre_clone_pid);
   222    result.pre_clone_tid =
   223        absl::GetFlag(FLAGS_processes_test_exec_swap_pre_clone_tid);
   224    result.pre_exec_pid =
   225        absl::GetFlag(FLAGS_processes_test_exec_swap_pre_exec_pid);
   226    result.pre_exec_tid =
   227        absl::GetFlag(FLAGS_processes_test_exec_swap_pre_exec_tid);
   228    result.post_exec_pid = pid;
   229    result.post_exec_tid = tid;
   230    std::cerr << "Test writing results to pipe FD." << std::endl;
   231    TEST_PCHECK(WriteFd(result.pipe_fd, &result, sizeof(result)) ==
   232                sizeof(result));
   233    if (close(result.pipe_fd) != 0) {
   234      std::cerr << "Failed to close pipe FD: " << errno << std::endl;
   235    }
   236    std::cerr << "Test results written out." << std::endl;
   237    return 0;
   238  }
   239  
   240  // ExecSwapPreExec is the second part of the ExecSwapThreadGroupLeader test.
   241  // It is called after the test has fork()'d and clone()'d.
   242  // It calls exec() with flags that cause the test binary to run
   243  // ExecSwapPostExec.
   244  [[noreturn]] int ExecSwapPreExec(void* void_arg) {
   245    ExecSwapArg* arg = reinterpret_cast<ExecSwapArg*>(void_arg);
   246    pid_t pid = getpid();
   247    TEST_PCHECK(pid > 0);
   248    pid_t tid = gettid();
   249    TEST_PCHECK(tid > 0);
   250  
   251    strncpy(arg->execve_array[0], "/proc/self/exe", kExecveArrayComponentsSize);
   252    strncpy(arg->execve_array[1], "--processes_test_exec_swap",
   253            kExecveArrayComponentsSize);
   254    absl::SNPrintF(arg->execve_array[2], kExecveArrayComponentsSize,
   255                   "--processes_test_exec_swap_pre_clone_pid=%d",
   256                   arg->pre_clone_pid);
   257    absl::SNPrintF(arg->execve_array[3], kExecveArrayComponentsSize,
   258                   "--processes_test_exec_swap_pre_clone_tid=%d",
   259                   arg->pre_clone_tid);
   260    absl::SNPrintF(arg->execve_array[4], kExecveArrayComponentsSize,
   261                   "--processes_test_exec_swap_pre_exec_pid=%d", pid);
   262    absl::SNPrintF(arg->execve_array[5], kExecveArrayComponentsSize,
   263                   "--processes_test_exec_swap_pre_exec_tid=%d", tid);
   264    absl::SNPrintF(arg->execve_array[6], kExecveArrayComponentsSize,
   265                   "--processes_test_exec_swap_pipe_fd=%d", arg->pipe_fd);
   266    std::cerr << "Test exec'ing:" << std::endl;
   267    for (int i = 0; i < kExecveArraySize; ++i) {
   268      std::cerr << "  execve_array[" << i << "] = " << arg->execve_array[i]
   269                << std::endl;
   270    }
   271    TEST_PCHECK(execv("/proc/self/exe", arg->execve_array) == 0);
   272    _exit(1);  // Should be unreachable.
   273  }
   274  
   275  // ExecSwapPreClone is the first part of the ExecSwapThreadGroupLeader test.
   276  // It is called after the test has fork()'d.
   277  // It calls clone() to run ExecSwapPreExec.
   278  [[noreturn]] void ExecSwapPreClone(ExecSwapArg* exec_swap_arg) {
   279    pid_t pid = getpid();
   280    TEST_PCHECK(pid > 0);
   281    pid_t tid = gettid();
   282    TEST_PCHECK(tid > 0);
   283    struct clone_arg {
   284      char stack[4096] __attribute__((aligned(16)));
   285      char stack_ptr[0];
   286    } ca;
   287    exec_swap_arg->pre_clone_pid = pid;
   288    exec_swap_arg->pre_clone_tid = tid;
   289    std::cerr << "Test cloning." << std::endl;
   290    TEST_PCHECK(clone(ExecSwapPreExec, ca.stack_ptr,
   291                      CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_FS,
   292                      exec_swap_arg) > 0);
   293    // The clone thread will call exec, so just sit around here until it does.
   294    while (true) {
   295      absl::SleepFor(absl::Milliseconds(500));
   296    }
   297  }
   298  
   299  TEST(Processes, ExecSwapThreadGroupLeader) {
   300    // This test verifies that a non-leading thread calling exec() replaces the
   301    // former leader of its thread group and adopts its thread ID.
   302    // This is the zeroth part of this test, which calls fork() to run
   303    // ExecSwapPreClone in a separate thread group.
   304  
   305    int pipe_fds[2];
   306    ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
   307    pid_t test_pid;
   308    ASSERT_THAT(test_pid = getpid(), SyscallSucceeds());
   309    pid_t test_tid;
   310    ASSERT_THAT(test_tid = gettid(), SyscallSucceeds());
   311  
   312    // Preallocate ExecSwapArg ahead of fork().
   313    // This uses shared memory because we use it after fork()+clone().
   314    ExecSwapArg* exec_swap_arg =
   315        (ExecSwapArg*)mmap(NULL, sizeof(ExecSwapArg), PROT_READ | PROT_WRITE,
   316                           MAP_SHARED | MAP_ANONYMOUS, -1, 0);
   317    ASSERT_NE(exec_swap_arg, MAP_FAILED);
   318    exec_swap_arg->pipe_fd = pipe_fds[1];
   319    char* execve_array_component;
   320    for (int i = 0; i < kExecveArraySize; ++i) {
   321      execve_array_component =
   322          (char*)mmap(NULL, kExecveArrayComponentsSize * sizeof(char),
   323                      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
   324      ASSERT_NE(execve_array_component, MAP_FAILED);
   325      exec_swap_arg->execve_array[i] = execve_array_component;
   326    }
   327  
   328    std::cerr << "Test forking." << std::endl;
   329    pid_t fork_pid = fork();
   330    if (fork_pid == 0) {
   331      ExecSwapPreClone(exec_swap_arg);
   332    }
   333    ASSERT_THAT(close(pipe_fds[1]), SyscallSucceeds());
   334  
   335    std::cerr << "Waiting for test results." << std::endl;
   336    ExecSwapResult result;
   337    TEST_PCHECK(ReadFd(pipe_fds[0], &result, sizeof(result)) == sizeof(result));
   338  
   339    std::cerr << "ExecSwap results:" << std::endl;
   340    std::cerr << "  Parent test process PID / TID:" << test_pid << " / "
   341              << test_tid << std::endl;
   342    std::cerr << "  Parent test child PID, as seen by parent:" << fork_pid
   343              << std::endl;
   344    std::cerr << "  Pre-clone PID / TID: " << result.pre_clone_pid << " / "
   345              << result.pre_clone_tid << std::endl;
   346    std::cerr << "  Pre-exec  PID / TID: " << result.pre_exec_pid << " / "
   347              << result.pre_exec_tid << std::endl;
   348    std::cerr << "  Post-exec PID / TID: " << result.post_exec_pid << " / "
   349              << result.post_exec_tid << std::endl;
   350  
   351    ASSERT_THAT(close(pipe_fds[0]), SyscallSucceeds());
   352  
   353    // Test starts out as the thread group leader of itself.
   354    EXPECT_EQ(test_pid, test_tid);
   355  
   356    // The child is a different thread group altogether.
   357    EXPECT_NE(test_pid, fork_pid);
   358    EXPECT_EQ(fork_pid, result.pre_clone_pid);  // Sanity check.
   359  
   360    // Before cloning, PID == TID, the child thread is leader of its thread
   361    // group.
   362    EXPECT_EQ(result.pre_clone_pid, result.pre_clone_tid);
   363  
   364    // PID should not change with clone.
   365    EXPECT_EQ(result.pre_clone_pid, result.pre_exec_pid);
   366  
   367    // But TID should change with clone.
   368    EXPECT_NE(result.pre_clone_tid, result.pre_exec_tid);
   369  
   370    // So we now have PID != TID.
   371    EXPECT_NE(result.pre_exec_pid, result.pre_exec_tid);
   372  
   373    // exec'ing does not change the PID, even when done from non-leader thread.
   374    EXPECT_EQ(result.pre_exec_pid, result.post_exec_pid);
   375  
   376    // After exec, the PID is back to matching TID.
   377    EXPECT_EQ(result.post_exec_pid, result.post_exec_tid);
   378  
   379    // The TID matches the one from before clone.
   380    EXPECT_EQ(result.post_exec_tid, result.pre_clone_tid);
   381  }
   382  
   383  }  // namespace testing
   384  }  // namespace gvisor
   385  
   386  int main(int argc, char** argv) {
   387    gvisor::testing::TestInit(&argc, &argv);
   388  
   389    if (absl::GetFlag(FLAGS_processes_test_exec_swap)) {
   390      return gvisor::testing::ExecSwapPostExec();
   391    }
   392    return gvisor::testing::RunAllTests();
   393  }