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