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