Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <fcntl.h>
      6 #include <poll.h>
      7 #include <signal.h>
      8 #include <stdio.h>
      9 #include <sys/resource.h>
     10 #include <sys/time.h>
     11 #include <time.h>
     12 #include <unistd.h>
     13 
     14 #include "base/debug/leak_annotations.h"
     15 #include "base/files/file_util.h"
     16 #include "base/posix/eintr_wrapper.h"
     17 #include "base/third_party/valgrind/valgrind.h"
     18 #include "build/build_config.h"
     19 #include "sandbox/linux/tests/unit_tests.h"
     20 
     21 namespace {
     22 std::string TestFailedMessage(const std::string& msg) {
     23   return msg.empty() ? std::string() : "Actual test failure: " + msg;
     24 }
     25 
     26 int GetSubProcessTimeoutTimeInSeconds() {
     27   // 10s ought to be enough for anybody.
     28   return 10;
     29 }
     30 
     31 // Returns the number of threads of the current process or -1.
     32 int CountThreads() {
     33   struct stat task_stat;
     34   int task_d = stat("/proc/self/task", &task_stat);
     35   // task_stat.st_nlink should be the number of tasks + 2 (accounting for
     36   // "." and "..".
     37   if (task_d != 0 || task_stat.st_nlink < 3)
     38     return -1;
     39   const int num_threads = task_stat.st_nlink - 2;
     40   return num_threads;
     41 }
     42 
     43 }  // namespace
     44 
     45 namespace sandbox {
     46 
     47 bool IsAndroid() {
     48 #if defined(OS_ANDROID)
     49   return true;
     50 #else
     51   return false;
     52 #endif
     53 }
     54 
     55 bool IsArchitectureArm() {
     56 #if defined(ARCH_CPU_ARM_FAMILY)
     57   return true;
     58 #else
     59   return false;
     60 #endif
     61 }
     62 
     63 // TODO(jln): figure out why base/.../dynamic_annotations.h's
     64 // RunningOnValgrind() cannot link.
     65 bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; }
     66 
     67 static const int kExpectedValue = 42;
     68 static const int kIgnoreThisTest = 43;
     69 static const int kExitWithAssertionFailure = 1;
     70 static const int kExitForTimeout = 2;
     71 
     72 #if !defined(OS_ANDROID)
     73 // This is due to StackDumpSignalHandler() performing _exit(1).
     74 // TODO(jln): get rid of the collision with kExitWithAssertionFailure.
     75 const int kExitAfterSIGSEGV = 1;
     76 #endif
     77 
     78 static void SigAlrmHandler(int) {
     79   const char failure_message[] = "Timeout reached!\n";
     80   // Make sure that we never block here.
     81   if (!fcntl(2, F_SETFL, O_NONBLOCK)) {
     82     ignore_result(write(2, failure_message, sizeof(failure_message) - 1));
     83   }
     84   _exit(kExitForTimeout);
     85 }
     86 
     87 // Set a timeout with a handler that will automatically fail the
     88 // test.
     89 static void SetProcessTimeout(int time_in_seconds) {
     90   struct sigaction act = {};
     91   act.sa_handler = SigAlrmHandler;
     92   SANDBOX_ASSERT(sigemptyset(&act.sa_mask) == 0);
     93   act.sa_flags = 0;
     94 
     95   struct sigaction old_act;
     96   SANDBOX_ASSERT(sigaction(SIGALRM, &act, &old_act) == 0);
     97 
     98   // We don't implemenet signal chaining, so make sure that nothing else
     99   // is expecting to handle SIGALRM.
    100   SANDBOX_ASSERT((old_act.sa_flags & SA_SIGINFO) == 0);
    101   SANDBOX_ASSERT(old_act.sa_handler == SIG_DFL);
    102   sigset_t sigalrm_set;
    103   SANDBOX_ASSERT(sigemptyset(&sigalrm_set) == 0);
    104   SANDBOX_ASSERT(sigaddset(&sigalrm_set, SIGALRM) == 0);
    105   SANDBOX_ASSERT(sigprocmask(SIG_UNBLOCK, &sigalrm_set, NULL) == 0);
    106   SANDBOX_ASSERT(alarm(time_in_seconds) == 0);  // There should be no previous
    107                                                 // alarm.
    108 }
    109 
    110 // Runs a test in a sub-process. This is necessary for most of the code
    111 // in the BPF sandbox, as it potentially makes global state changes and as
    112 // it also tends to raise fatal errors, if the code has been used in an
    113 // insecure manner.
    114 void UnitTests::RunTestInProcess(SandboxTestRunner* test_runner,
    115                                  DeathCheck death,
    116                                  const void* death_aux) {
    117   CHECK(test_runner);
    118   // We need to fork(), so we can't be multi-threaded, as threads could hold
    119   // locks.
    120   int num_threads = CountThreads();
    121 #if !defined(THREAD_SANITIZER)
    122   const int kNumExpectedThreads = 1;
    123 #else
    124   // Under TSAN, there is a special helper thread. It should be completely
    125   // invisible to our testing, so we ignore it. It should be ok to fork()
    126   // with this thread. It's currently buggy, but it's the best we can do until
    127   // there is a way to delay the start of the thread
    128   // (https://code.google.com/p/thread-sanitizer/issues/detail?id=19).
    129   const int kNumExpectedThreads = 2;
    130 #endif
    131 
    132   // The kernel is at liberty to wake a thread id futex before updating /proc.
    133   // If another test running in the same process has stopped a thread, it may
    134   // appear as still running in /proc.
    135   // We poll /proc, with an exponential back-off. At most, we'll sleep around
    136   // 2^iterations nanoseconds in nanosleep().
    137   for (unsigned int iteration = 0; iteration < 30; iteration++) {
    138     struct timespec ts = {0, 1L << iteration /* nanoseconds */};
    139     PCHECK(0 == HANDLE_EINTR(nanosleep(&ts, &ts)));
    140     num_threads = CountThreads();
    141     if (kNumExpectedThreads == num_threads)
    142       break;
    143   }
    144 
    145   ASSERT_EQ(kNumExpectedThreads, num_threads)
    146       << "Running sandbox tests with multiple threads "
    147       << "is not supported and will make the tests flaky.";
    148   int fds[2];
    149   ASSERT_EQ(0, pipe(fds));
    150   // Check that our pipe is not on one of the standard file descriptor.
    151   SANDBOX_ASSERT(fds[0] > 2 && fds[1] > 2);
    152 
    153   pid_t pid;
    154   ASSERT_LE(0, (pid = fork()));
    155   if (!pid) {
    156     // In child process
    157     // Redirect stderr to our pipe. This way, we can capture all error
    158     // messages, if we decide we want to do so in our tests.
    159     SANDBOX_ASSERT(dup2(fds[1], 2) == 2);
    160     SANDBOX_ASSERT(!close(fds[0]));
    161     SANDBOX_ASSERT(!close(fds[1]));
    162 
    163     // Don't set a timeout if running on Valgrind, since it's generally much
    164     // slower.
    165     if (!IsRunningOnValgrind()) {
    166       SetProcessTimeout(GetSubProcessTimeoutTimeInSeconds());
    167     }
    168 
    169     // Disable core files. They are not very useful for our individual test
    170     // cases.
    171     struct rlimit no_core = {0};
    172     setrlimit(RLIMIT_CORE, &no_core);
    173 
    174     test_runner->Run();
    175     if (test_runner->ShouldCheckForLeaks()) {
    176 #if defined(LEAK_SANITIZER)
    177       __lsan_do_leak_check();
    178 #endif
    179     }
    180     _exit(kExpectedValue);
    181   }
    182 
    183   close(fds[1]);
    184   std::vector<char> msg_buf;
    185   ssize_t rc;
    186 
    187   // Make sure read() will never block as we'll use poll() to
    188   // block with a timeout instead.
    189   const int fcntl_ret = fcntl(fds[0], F_SETFL, O_NONBLOCK);
    190   ASSERT_EQ(0, fcntl_ret);
    191   struct pollfd poll_fd = {fds[0], POLLIN | POLLRDHUP, 0};
    192 
    193   int poll_ret;
    194   // We prefer the SIGALRM timeout to trigger in the child than this timeout
    195   // so we double the common value here.
    196   int poll_timeout = GetSubProcessTimeoutTimeInSeconds() * 2 * 1000;
    197   while ((poll_ret = poll(&poll_fd, 1, poll_timeout) > 0)) {
    198     const size_t kCapacity = 256;
    199     const size_t len = msg_buf.size();
    200     msg_buf.resize(len + kCapacity);
    201     rc = HANDLE_EINTR(read(fds[0], &msg_buf[len], kCapacity));
    202     msg_buf.resize(len + std::max(rc, static_cast<ssize_t>(0)));
    203     if (rc <= 0)
    204       break;
    205   }
    206   ASSERT_NE(poll_ret, -1) << "poll() failed";
    207   ASSERT_NE(poll_ret, 0) << "Timeout while reading child state";
    208   close(fds[0]);
    209   std::string msg(msg_buf.begin(), msg_buf.end());
    210 
    211   int status = 0;
    212   int waitpid_returned = HANDLE_EINTR(waitpid(pid, &status, 0));
    213   ASSERT_EQ(pid, waitpid_returned) << TestFailedMessage(msg);
    214 
    215   // At run-time, we sometimes decide that a test shouldn't actually
    216   // run (e.g. when testing sandbox features on a kernel that doesn't
    217   // have sandboxing support). When that happens, don't attempt to
    218   // call the "death" function, as it might be looking for a
    219   // death-test condition that would never have triggered.
    220   if (!WIFEXITED(status) || WEXITSTATUS(status) != kIgnoreThisTest ||
    221       !msg.empty()) {
    222     // We use gtest's ASSERT_XXX() macros instead of the DeathCheck
    223     // functions.  This means, on failure, "return" is called. This
    224     // only works correctly, if the call of the "death" callback is
    225     // the very last thing in our function.
    226     death(status, msg, death_aux);
    227   }
    228 }
    229 
    230 void UnitTests::DeathSuccess(int status, const std::string& msg, const void*) {
    231   std::string details(TestFailedMessage(msg));
    232 
    233   bool subprocess_terminated_normally = WIFEXITED(status);
    234   ASSERT_TRUE(subprocess_terminated_normally) << details;
    235   int subprocess_exit_status = WEXITSTATUS(status);
    236   ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details;
    237   bool subprocess_exited_but_printed_messages = !msg.empty();
    238   EXPECT_FALSE(subprocess_exited_but_printed_messages) << details;
    239 }
    240 
    241 void UnitTests::DeathSuccessAllowNoise(int status,
    242                                        const std::string& msg,
    243                                        const void*) {
    244   std::string details(TestFailedMessage(msg));
    245 
    246   bool subprocess_terminated_normally = WIFEXITED(status);
    247   ASSERT_TRUE(subprocess_terminated_normally) << details;
    248   int subprocess_exit_status = WEXITSTATUS(status);
    249   ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details;
    250 }
    251 
    252 void UnitTests::DeathMessage(int status,
    253                              const std::string& msg,
    254                              const void* aux) {
    255   std::string details(TestFailedMessage(msg));
    256   const char* expected_msg = static_cast<const char*>(aux);
    257 
    258   bool subprocess_terminated_normally = WIFEXITED(status);
    259   ASSERT_TRUE(subprocess_terminated_normally) << "Exit status: " << status
    260                                               << " " << details;
    261   int subprocess_exit_status = WEXITSTATUS(status);
    262   ASSERT_EQ(1, subprocess_exit_status) << details;
    263 
    264   bool subprocess_exited_without_matching_message =
    265       msg.find(expected_msg) == std::string::npos;
    266   EXPECT_FALSE(subprocess_exited_without_matching_message) << details;
    267 }
    268 
    269 void UnitTests::DeathSEGVMessage(int status,
    270                                  const std::string& msg,
    271                                  const void* aux) {
    272   std::string details(TestFailedMessage(msg));
    273   const char* expected_msg = static_cast<const char*>(aux);
    274 
    275 #if defined(OS_ANDROID)
    276   const bool subprocess_got_sigsegv =
    277       WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status));
    278 #else
    279   const bool subprocess_got_sigsegv =
    280       WIFEXITED(status) && (kExitAfterSIGSEGV == WEXITSTATUS(status));
    281 #endif
    282 
    283   ASSERT_TRUE(subprocess_got_sigsegv) << "Exit status: " << status
    284                                       << " " << details;
    285 
    286   bool subprocess_exited_without_matching_message =
    287       msg.find(expected_msg) == std::string::npos;
    288   EXPECT_FALSE(subprocess_exited_without_matching_message) << details;
    289 }
    290 
    291 void UnitTests::DeathExitCode(int status,
    292                               const std::string& msg,
    293                               const void* aux) {
    294   int expected_exit_code = static_cast<int>(reinterpret_cast<intptr_t>(aux));
    295   std::string details(TestFailedMessage(msg));
    296 
    297   bool subprocess_terminated_normally = WIFEXITED(status);
    298   ASSERT_TRUE(subprocess_terminated_normally) << details;
    299   int subprocess_exit_status = WEXITSTATUS(status);
    300   ASSERT_EQ(expected_exit_code, subprocess_exit_status) << details;
    301 }
    302 
    303 void UnitTests::DeathBySignal(int status,
    304                               const std::string& msg,
    305                               const void* aux) {
    306   int expected_signo = static_cast<int>(reinterpret_cast<intptr_t>(aux));
    307   std::string details(TestFailedMessage(msg));
    308 
    309   bool subprocess_terminated_by_signal = WIFSIGNALED(status);
    310   ASSERT_TRUE(subprocess_terminated_by_signal) << details;
    311   int subprocess_signal_number = WTERMSIG(status);
    312   ASSERT_EQ(expected_signo, subprocess_signal_number) << details;
    313 }
    314 
    315 void UnitTests::AssertionFailure(const char* expr, const char* file, int line) {
    316   fprintf(stderr, "%s:%d:%s", file, line, expr);
    317   fflush(stderr);
    318   _exit(kExitWithAssertionFailure);
    319 }
    320 
    321 void UnitTests::IgnoreThisTest() {
    322   fflush(stderr);
    323   _exit(kIgnoreThisTest);
    324 }
    325 
    326 }  // namespace
    327