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