gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/kill.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 <errno.h>
    16  #include <sys/syscall.h>
    17  #include <sys/types.h>
    18  #include <unistd.h>
    19  
    20  #include <cerrno>
    21  #include <csignal>
    22  
    23  #include "gtest/gtest.h"
    24  #include "absl/flags/flag.h"
    25  #include "absl/synchronization/mutex.h"
    26  #include "absl/time/clock.h"
    27  #include "absl/time/time.h"
    28  #include "test/util/capability_util.h"
    29  #include "test/util/file_descriptor.h"
    30  #include "test/util/logging.h"
    31  #include "test/util/signal_util.h"
    32  #include "test/util/test_util.h"
    33  #include "test/util/thread_util.h"
    34  
    35  ABSL_FLAG(int32_t, scratch_uid, 65534, "scratch UID");
    36  ABSL_FLAG(int32_t, scratch_gid, 65534, "scratch GID");
    37  
    38  using ::testing::Ge;
    39  
    40  namespace gvisor {
    41  namespace testing {
    42  
    43  namespace {
    44  
    45  TEST(KillTest, CanKillValidPid) {
    46    // If pid is positive, then signal sig is sent to the process with the ID
    47    // specified by pid.
    48    EXPECT_THAT(kill(getpid(), 0), SyscallSucceeds());
    49    // If pid equals 0, then sig is sent to every process in the process group of
    50    // the calling process.
    51    EXPECT_THAT(kill(0, 0), SyscallSucceeds());
    52  
    53    ScopedThread([] { EXPECT_THAT(kill(gettid(), 0), SyscallSucceeds()); });
    54  }
    55  
    56  void SigHandler(int sig, siginfo_t* info, void* context) { _exit(0); }
    57  
    58  // If pid equals -1, then sig is sent to every process for which the calling
    59  // process has permission to send signals, except for process 1 (init).
    60  TEST(KillTest, CanKillAllPIDs) {
    61    // If we're not running inside the sandbox, then we skip this test
    62    // as our namespace may contain may more processes that cannot tolerate
    63    // the signal below. We also cannot reliably create a new pid namespace
    64    // for ourselves and test the same functionality.
    65    SKIP_IF(!IsRunningOnGvisor());
    66  
    67    int pipe_fds[2];
    68    ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
    69    FileDescriptor read_fd(pipe_fds[0]);
    70    FileDescriptor write_fd(pipe_fds[1]);
    71  
    72    pid_t pid = fork();
    73    if (pid == 0) {
    74      read_fd.reset();
    75  
    76      struct sigaction sa;
    77      sa.sa_sigaction = SigHandler;
    78      sigfillset(&sa.sa_mask);
    79      sa.sa_flags = SA_SIGINFO;
    80      TEST_PCHECK(sigaction(SIGWINCH, &sa, nullptr) == 0);
    81      MaybeSave();
    82  
    83      // Indicate to the parent that we're ready.
    84      write_fd.reset();
    85  
    86      // Wait until we get the signal from the parent.
    87      while (true) {
    88        pause();
    89      }
    90    }
    91  
    92    ASSERT_THAT(pid, SyscallSucceeds());
    93  
    94    write_fd.reset();
    95  
    96    // Wait for the child to indicate that it's unmasked the signal by closing
    97    // the write end.
    98    char buf;
    99    ASSERT_THAT(ReadFd(read_fd.get(), &buf, 1), SyscallSucceedsWithValue(0));
   100  
   101    // Signal the child and wait for it to die with status 0, indicating that
   102    // it got the expected signal.
   103    EXPECT_THAT(kill(-1, SIGWINCH), SyscallSucceeds());
   104  
   105    int status;
   106    ASSERT_THAT(RetryEINTR(waitpid)(pid, &status, 0),
   107                SyscallSucceedsWithValue(pid));
   108    EXPECT_TRUE(WIFEXITED(status));
   109    EXPECT_EQ(0, WEXITSTATUS(status));
   110  }
   111  
   112  TEST(KillTest, CannotKillInvalidPID) {
   113    // We need an unused pid to verify that kill fails when given one.
   114    //
   115    // There is no way to guarantee that a PID is unused, but the PID of a
   116    // recently exited process likely won't be reused soon.
   117    pid_t fake_pid = fork();
   118    if (fake_pid == 0) {
   119      _exit(0);
   120    }
   121  
   122    ASSERT_THAT(fake_pid, SyscallSucceeds());
   123  
   124    int status;
   125    ASSERT_THAT(RetryEINTR(waitpid)(fake_pid, &status, 0),
   126                SyscallSucceedsWithValue(fake_pid));
   127    EXPECT_TRUE(WIFEXITED(status));
   128    EXPECT_EQ(0, WEXITSTATUS(status));
   129  
   130    EXPECT_THAT(kill(fake_pid, 0), SyscallFailsWithErrno(ESRCH));
   131  }
   132  
   133  TEST(KillTest, CannotUseInvalidSignal) {
   134    EXPECT_THAT(kill(getpid(), 200), SyscallFailsWithErrno(EINVAL));
   135  }
   136  
   137  TEST(KillTest, CanKillRemoteProcess) {
   138    pid_t pid = fork();
   139    if (pid == 0) {
   140      while (true) {
   141        pause();
   142      }
   143    }
   144  
   145    ASSERT_THAT(pid, SyscallSucceeds());
   146  
   147    EXPECT_THAT(kill(pid, SIGKILL), SyscallSucceeds());
   148  
   149    int status;
   150    ASSERT_THAT(RetryEINTR(waitpid)(pid, &status, 0),
   151                SyscallSucceedsWithValue(pid));
   152    EXPECT_TRUE(WIFSIGNALED(status));
   153    EXPECT_EQ(SIGKILL, WTERMSIG(status));
   154  }
   155  
   156  TEST(KillTest, CanKillOwnProcess) {
   157    EXPECT_THAT(kill(getpid(), 0), SyscallSucceeds());
   158  }
   159  
   160  // Verify that you can kill a process even using a tid from a thread other than
   161  // the group leader.
   162  TEST(KillTest, CannotKillTid) {
   163    pid_t tid;
   164    bool tid_available = false;
   165    bool finished = false;
   166    absl::Mutex mu;
   167    ScopedThread t([&] {
   168      mu.Lock();
   169      tid = gettid();
   170      tid_available = true;
   171      mu.Await(absl::Condition(&finished));
   172      mu.Unlock();
   173    });
   174    mu.LockWhen(absl::Condition(&tid_available));
   175    EXPECT_THAT(kill(tid, 0), SyscallSucceeds());
   176    finished = true;
   177    mu.Unlock();
   178  }
   179  
   180  TEST(KillTest, SetPgid) {
   181    for (int i = 0; i < 10; i++) {
   182      // The following in the normal pattern for creating a new process group.
   183      // Both the parent and child process will call setpgid in order to avoid any
   184      // race conditions. We do this ten times to catch races.
   185      pid_t pid = fork();
   186      if (pid == 0) {
   187        setpgid(0, 0);
   188        while (true) {
   189          pause();
   190        }
   191      }
   192  
   193      ASSERT_THAT(pid, SyscallSucceeds());
   194  
   195      // Set the child's group and exit.
   196      ASSERT_THAT(setpgid(pid, pid), SyscallSucceeds());
   197      EXPECT_THAT(kill(pid, SIGKILL), SyscallSucceeds());
   198  
   199      int status;
   200      EXPECT_THAT(RetryEINTR(waitpid)(-pid, &status, 0),
   201                  SyscallSucceedsWithValue(pid));
   202      EXPECT_TRUE(WIFSIGNALED(status));
   203      EXPECT_EQ(SIGKILL, WTERMSIG(status));
   204    }
   205  }
   206  
   207  TEST(KillTest, ProcessGroups) {
   208    // Fork a new child.
   209    //
   210    // other_child is used as a placeholder process. We use this PID as our "does
   211    // not exist" process group to ensure some amount of safety. (It is still
   212    // possible to violate this assumption, but extremely unlikely.)
   213    pid_t child = fork();
   214    if (child == 0) {
   215      while (true) {
   216        pause();
   217      }
   218    }
   219    ASSERT_THAT(child, SyscallSucceeds());
   220  
   221    pid_t other_child = fork();
   222    if (other_child == 0) {
   223      while (true) {
   224        pause();
   225      }
   226    }
   227    ASSERT_THAT(other_child, SyscallSucceeds());
   228  
   229    // Ensure the kill does not succeed without the new group.
   230    EXPECT_THAT(kill(-child, SIGKILL), SyscallFailsWithErrno(ESRCH));
   231  
   232    // Put the child in its own process group.
   233    ASSERT_THAT(setpgid(child, child), SyscallSucceeds());
   234  
   235    // This should be not allowed: you can only create a new group with the same
   236    // id or join an existing one. The other_child group should not exist.
   237    ASSERT_THAT(setpgid(child, other_child), SyscallFailsWithErrno(EPERM));
   238  
   239    // Done with other_child; kill it.
   240    EXPECT_THAT(kill(other_child, SIGKILL), SyscallSucceeds());
   241    int status;
   242    EXPECT_THAT(RetryEINTR(waitpid)(other_child, &status, 0), SyscallSucceeds());
   243  
   244    // Linux returns success for the no-op call.
   245    ASSERT_THAT(setpgid(child, child), SyscallSucceeds());
   246  
   247    // Kill the child's process group.
   248    ASSERT_THAT(kill(-child, SIGKILL), SyscallSucceeds());
   249  
   250    // Wait on the process group; ensure that the signal was as expected.
   251    EXPECT_THAT(RetryEINTR(waitpid)(-child, &status, 0),
   252                SyscallSucceedsWithValue(child));
   253    EXPECT_TRUE(WIFSIGNALED(status));
   254    EXPECT_EQ(SIGKILL, WTERMSIG(status));
   255  
   256    // Try to kill the process group again; ensure that the wait fails.
   257    EXPECT_THAT(kill(-child, SIGKILL), SyscallFailsWithErrno(ESRCH));
   258    EXPECT_THAT(RetryEINTR(waitpid)(-child, &status, 0),
   259                SyscallFailsWithErrno(ECHILD));
   260  }
   261  
   262  TEST(KillTest, ChildDropsPrivsCannotKill) {
   263    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SETUID)));
   264  
   265    const int uid = absl::GetFlag(FLAGS_scratch_uid);
   266    const int gid = absl::GetFlag(FLAGS_scratch_gid);
   267  
   268    // Create the child that drops privileges and tries to kill the parent.
   269    pid_t pid = fork();
   270    if (pid == 0) {
   271      TEST_PCHECK(setresgid(gid, gid, gid) == 0);
   272      MaybeSave();
   273  
   274      TEST_PCHECK(setresuid(uid, uid, uid) == 0);
   275      MaybeSave();
   276  
   277      // setresuid should have dropped CAP_KILL. Make sure.
   278      TEST_CHECK(!HaveCapability(CAP_KILL).ValueOrDie());
   279  
   280      // Try to kill parent with every signal-sending syscall possible.
   281      pid_t parent = getppid();
   282  
   283      TEST_CHECK(kill(parent, SIGKILL) < 0);
   284      TEST_PCHECK_MSG(errno == EPERM, "kill failed with wrong errno");
   285      MaybeSave();
   286  
   287      TEST_CHECK(tgkill(parent, parent, SIGKILL) < 0);
   288      TEST_PCHECK_MSG(errno == EPERM, "tgkill failed with wrong errno");
   289      MaybeSave();
   290  
   291      TEST_CHECK(syscall(SYS_tkill, parent, SIGKILL) < 0);
   292      TEST_PCHECK_MSG(errno == EPERM, "tkill failed with wrong errno");
   293      MaybeSave();
   294  
   295      siginfo_t uinfo;
   296      uinfo.si_code = -1;  // SI_QUEUE (allowed).
   297  
   298      TEST_CHECK(syscall(SYS_rt_sigqueueinfo, parent, SIGKILL, &uinfo) < 0);
   299      TEST_PCHECK_MSG(errno == EPERM, "rt_sigqueueinfo failed with wrong errno");
   300      MaybeSave();
   301  
   302      TEST_CHECK(syscall(SYS_rt_tgsigqueueinfo, parent, parent, SIGKILL, &uinfo) <
   303                 0);
   304      TEST_PCHECK_MSG(errno == EPERM, "rt_sigqueueinfo failed with wrong errno");
   305      MaybeSave();
   306  
   307      _exit(0);
   308    }
   309  
   310    ASSERT_THAT(pid, SyscallSucceeds());
   311  
   312    int status;
   313    EXPECT_THAT(RetryEINTR(waitpid)(pid, &status, 0),
   314                SyscallSucceedsWithValue(pid));
   315    EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0)
   316        << "status = " << status;
   317  }
   318  
   319  TEST(KillTest, CanSIGCONTSameSession) {
   320    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SETUID)));
   321  
   322    pid_t stopped_child = fork();
   323    if (stopped_child == 0) {
   324      raise(SIGSTOP);
   325      _exit(0);
   326    }
   327  
   328    ASSERT_THAT(stopped_child, SyscallSucceeds());
   329  
   330    // Put the child in its own process group. The child and parent process
   331    // groups also share a session.
   332    ASSERT_THAT(setpgid(stopped_child, stopped_child), SyscallSucceeds());
   333  
   334    // Make sure child stopped.
   335    int status;
   336    EXPECT_THAT(RetryEINTR(waitpid)(stopped_child, &status, WUNTRACED),
   337                SyscallSucceedsWithValue(stopped_child));
   338    EXPECT_TRUE(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)
   339        << "status " << status;
   340  
   341    const int uid = absl::GetFlag(FLAGS_scratch_uid);
   342    const int gid = absl::GetFlag(FLAGS_scratch_gid);
   343  
   344    // Drop privileges only in child process, or else this parent process won't be
   345    // able to open some log files after the test ends.
   346    pid_t other_child = fork();
   347    if (other_child == 0) {
   348      // Drop privileges.
   349      TEST_PCHECK(setresgid(gid, gid, gid) == 0);
   350      MaybeSave();
   351  
   352      TEST_PCHECK(setresuid(uid, uid, uid) == 0);
   353      MaybeSave();
   354  
   355      // setresuid should have dropped CAP_KILL.
   356      TEST_CHECK(!HaveCapability(CAP_KILL).ValueOrDie());
   357  
   358      // Child 2 and child should now not share a thread group and any UIDs.
   359      // Child 2 should have no privileges. That means any signal other than
   360      // SIGCONT should fail.
   361      TEST_CHECK(kill(stopped_child, SIGKILL) < 0);
   362      TEST_PCHECK_MSG(errno == EPERM, "kill failed with wrong errno");
   363      MaybeSave();
   364  
   365      TEST_PCHECK(kill(stopped_child, SIGCONT) == 0);
   366      MaybeSave();
   367  
   368      _exit(0);
   369    }
   370  
   371    ASSERT_THAT(stopped_child, SyscallSucceeds());
   372  
   373    // Make sure child exited normally.
   374    EXPECT_THAT(RetryEINTR(waitpid)(stopped_child, &status, 0),
   375                SyscallSucceedsWithValue(stopped_child));
   376    EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0)
   377        << "status " << status;
   378  
   379    // Make sure other_child exited normally.
   380    EXPECT_THAT(RetryEINTR(waitpid)(other_child, &status, 0),
   381                SyscallSucceedsWithValue(other_child));
   382    EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0)
   383        << "status " << status;
   384  }
   385  
   386  }  // namespace
   387  
   388  }  // namespace testing
   389  }  // namespace gvisor