| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <fcntl.h> | 5 #include <fcntl.h> |
| 6 #include <poll.h> | 6 #include <poll.h> |
| 7 #include <signal.h> | 7 #include <signal.h> |
| 8 #include <stdio.h> | 8 #include <stdio.h> |
| 9 #include <sys/resource.h> | 9 #include <sys/resource.h> |
| 10 #include <sys/time.h> | 10 #include <sys/time.h> |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 bool IsArchitectureArm() { | 52 bool IsArchitectureArm() { |
| 53 #if defined(ARCH_CPU_ARM_FAMILY) | 53 #if defined(ARCH_CPU_ARM_FAMILY) |
| 54 return true; | 54 return true; |
| 55 #else | 55 #else |
| 56 return false; | 56 return false; |
| 57 #endif | 57 #endif |
| 58 } | 58 } |
| 59 | 59 |
| 60 // TODO(jln): figure out why base/.../dynamic_annotations.h's | 60 // TODO(jln): figure out why base/.../dynamic_annotations.h's |
| 61 // RunningOnValgrind() cannot link. | 61 // RunningOnValgrind() cannot link. |
| 62 bool IsRunningOnValgrind() { | 62 bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; } |
| 63 return RUNNING_ON_VALGRIND; | |
| 64 } | |
| 65 | 63 |
| 66 static const int kExpectedValue = 42; | 64 static const int kExpectedValue = 42; |
| 67 static const int kIgnoreThisTest = 43; | 65 static const int kIgnoreThisTest = 43; |
| 68 static const int kExitWithAssertionFailure = 1; | 66 static const int kExitWithAssertionFailure = 1; |
| 69 static const int kExitForTimeout = 2; | 67 static const int kExitForTimeout = 2; |
| 70 | 68 |
| 71 static void SigAlrmHandler(int) { | 69 static void SigAlrmHandler(int) { |
| 72 const char failure_message[] = "Timeout reached!\n"; | 70 const char failure_message[] = "Timeout reached!\n"; |
| 73 // Make sure that we never block here. | 71 // Make sure that we never block here. |
| 74 if (!fcntl(2, F_SETFL, O_NONBLOCK)) { | 72 if (!fcntl(2, F_SETFL, O_NONBLOCK)) { |
| 75 if (write(2, failure_message, sizeof(failure_message) - 1) < 0) { | 73 if (write(2, failure_message, sizeof(failure_message) - 1) < 0) { |
| 76 } | |
| 77 } | 74 } |
| 78 _exit(kExitForTimeout); | 75 } |
| 76 _exit(kExitForTimeout); |
| 79 } | 77 } |
| 80 | 78 |
| 81 // Set a timeout with a handler that will automatically fail the | 79 // Set a timeout with a handler that will automatically fail the |
| 82 // test. | 80 // test. |
| 83 static void SetProcessTimeout(int time_in_seconds) { | 81 static void SetProcessTimeout(int time_in_seconds) { |
| 84 struct sigaction act = {}; | 82 struct sigaction act = {}; |
| 85 act.sa_handler = SigAlrmHandler; | 83 act.sa_handler = SigAlrmHandler; |
| 86 SANDBOX_ASSERT(sigemptyset(&act.sa_mask) == 0); | 84 SANDBOX_ASSERT(sigemptyset(&act.sa_mask) == 0); |
| 87 act.sa_flags = 0; | 85 act.sa_flags = 0; |
| 88 | 86 |
| 89 struct sigaction old_act; | 87 struct sigaction old_act; |
| 90 SANDBOX_ASSERT(sigaction(SIGALRM, &act, &old_act) == 0); | 88 SANDBOX_ASSERT(sigaction(SIGALRM, &act, &old_act) == 0); |
| 91 | 89 |
| 92 // We don't implemenet signal chaining, so make sure that nothing else | 90 // We don't implemenet signal chaining, so make sure that nothing else |
| 93 // is expecting to handle SIGALRM. | 91 // is expecting to handle SIGALRM. |
| 94 SANDBOX_ASSERT((old_act.sa_flags & SA_SIGINFO) == 0); | 92 SANDBOX_ASSERT((old_act.sa_flags & SA_SIGINFO) == 0); |
| 95 SANDBOX_ASSERT(old_act.sa_handler == SIG_DFL); | 93 SANDBOX_ASSERT(old_act.sa_handler == SIG_DFL); |
| 96 sigset_t sigalrm_set; | 94 sigset_t sigalrm_set; |
| 97 SANDBOX_ASSERT(sigemptyset(&sigalrm_set) == 0); | 95 SANDBOX_ASSERT(sigemptyset(&sigalrm_set) == 0); |
| 98 SANDBOX_ASSERT(sigaddset(&sigalrm_set, SIGALRM) == 0); | 96 SANDBOX_ASSERT(sigaddset(&sigalrm_set, SIGALRM) == 0); |
| 99 SANDBOX_ASSERT(sigprocmask(SIG_UNBLOCK, &sigalrm_set, NULL) == 0); | 97 SANDBOX_ASSERT(sigprocmask(SIG_UNBLOCK, &sigalrm_set, NULL) == 0); |
| 100 SANDBOX_ASSERT(alarm(time_in_seconds) == 0); // There should be no previous | 98 SANDBOX_ASSERT(alarm(time_in_seconds) == 0); // There should be no previous |
| 101 // alarm. | 99 // alarm. |
| 102 } | 100 } |
| 103 | 101 |
| 104 // Runs a test in a sub-process. This is necessary for most of the code | 102 // 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 | 103 // 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 | 104 // it also tends to raise fatal errors, if the code has been used in an |
| 107 // insecure manner. | 105 // insecure manner. |
| 108 void UnitTests::RunTestInProcess(UnitTests::Test test, void *arg, | 106 void UnitTests::RunTestInProcess(UnitTests::Test test, |
| 109 DeathCheck death, const void *death_aux) { | 107 void* arg, |
| 108 DeathCheck death, |
| 109 const void* death_aux) { |
| 110 // We need to fork(), so we can't be multi-threaded, as threads could hold | 110 // We need to fork(), so we can't be multi-threaded, as threads could hold |
| 111 // locks. | 111 // locks. |
| 112 int num_threads = CountThreads(); | 112 int num_threads = CountThreads(); |
| 113 #if defined(THREAD_SANITIZER) | 113 #if defined(THREAD_SANITIZER) |
| 114 // Under TSAN, there is a special helper thread. It should be completely | 114 // Under TSAN, there is a special helper thread. It should be completely |
| 115 // invisible to our testing, so we ignore it. It should be ok to fork() | 115 // invisible to our testing, so we ignore it. It should be ok to fork() |
| 116 // with this thread. It's currently buggy, but it's the best we can do until | 116 // with this thread. It's currently buggy, but it's the best we can do until |
| 117 // there is a way to delay the start of the thread | 117 // there is a way to delay the start of the thread |
| 118 // (https://code.google.com/p/thread-sanitizer/issues/detail?id=19). | 118 // (https://code.google.com/p/thread-sanitizer/issues/detail?id=19). |
| 119 num_threads--; | 119 num_threads--; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 137 SANDBOX_ASSERT(!close(fds[1])); | 137 SANDBOX_ASSERT(!close(fds[1])); |
| 138 | 138 |
| 139 // Don't set a timeout if running on Valgrind, since it's generally much | 139 // Don't set a timeout if running on Valgrind, since it's generally much |
| 140 // slower. | 140 // slower. |
| 141 if (!IsRunningOnValgrind()) { | 141 if (!IsRunningOnValgrind()) { |
| 142 SetProcessTimeout(GetSubProcessTimeoutTimeInSeconds()); | 142 SetProcessTimeout(GetSubProcessTimeoutTimeInSeconds()); |
| 143 } | 143 } |
| 144 | 144 |
| 145 // Disable core files. They are not very useful for our individual test | 145 // Disable core files. They are not very useful for our individual test |
| 146 // cases. | 146 // cases. |
| 147 struct rlimit no_core = { 0 }; | 147 struct rlimit no_core = {0}; |
| 148 setrlimit(RLIMIT_CORE, &no_core); | 148 setrlimit(RLIMIT_CORE, &no_core); |
| 149 | 149 |
| 150 test(arg); | 150 test(arg); |
| 151 _exit(kExpectedValue); | 151 _exit(kExpectedValue); |
| 152 } | 152 } |
| 153 | 153 |
| 154 (void)HANDLE_EINTR(close(fds[1])); | 154 (void)HANDLE_EINTR(close(fds[1])); |
| 155 std::vector<char> msg_buf; | 155 std::vector<char> msg_buf; |
| 156 ssize_t rc; | 156 ssize_t rc; |
| 157 | 157 |
| 158 // Make sure read() will never block as we'll use poll() to | 158 // Make sure read() will never block as we'll use poll() to |
| 159 // block with a timeout instead. | 159 // block with a timeout instead. |
| 160 const int fcntl_ret = fcntl(fds[0], F_SETFL, O_NONBLOCK); | 160 const int fcntl_ret = fcntl(fds[0], F_SETFL, O_NONBLOCK); |
| 161 ASSERT_EQ(fcntl_ret, 0); | 161 ASSERT_EQ(fcntl_ret, 0); |
| 162 struct pollfd poll_fd = { fds[0], POLLIN | POLLRDHUP, 0 }; | 162 struct pollfd poll_fd = {fds[0], POLLIN | POLLRDHUP, 0}; |
| 163 | 163 |
| 164 int poll_ret; | 164 int poll_ret; |
| 165 // We prefer the SIGALRM timeout to trigger in the child than this timeout | 165 // We prefer the SIGALRM timeout to trigger in the child than this timeout |
| 166 // so we double the common value here. | 166 // so we double the common value here. |
| 167 int poll_timeout = GetSubProcessTimeoutTimeInSeconds() * 2 * 1000; | 167 int poll_timeout = GetSubProcessTimeoutTimeInSeconds() * 2 * 1000; |
| 168 while ((poll_ret = poll(&poll_fd, 1, poll_timeout) > 0)) { | 168 while ((poll_ret = poll(&poll_fd, 1, poll_timeout) > 0)) { |
| 169 const size_t kCapacity = 256; | 169 const size_t kCapacity = 256; |
| 170 const size_t len = msg_buf.size(); | 170 const size_t len = msg_buf.size(); |
| 171 msg_buf.resize(len + kCapacity); | 171 msg_buf.resize(len + kCapacity); |
| 172 rc = HANDLE_EINTR(read(fds[0], &msg_buf[len], kCapacity)); | 172 rc = HANDLE_EINTR(read(fds[0], &msg_buf[len], kCapacity)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 191 if (!WIFEXITED(status) || WEXITSTATUS(status) != kIgnoreThisTest || | 191 if (!WIFEXITED(status) || WEXITSTATUS(status) != kIgnoreThisTest || |
| 192 !msg.empty()) { | 192 !msg.empty()) { |
| 193 // We use gtest's ASSERT_XXX() macros instead of the DeathCheck | 193 // We use gtest's ASSERT_XXX() macros instead of the DeathCheck |
| 194 // functions. This means, on failure, "return" is called. This | 194 // functions. This means, on failure, "return" is called. This |
| 195 // only works correctly, if the call of the "death" callback is | 195 // only works correctly, if the call of the "death" callback is |
| 196 // the very last thing in our function. | 196 // the very last thing in our function. |
| 197 death(status, msg, death_aux); | 197 death(status, msg, death_aux); |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 | 200 |
| 201 void UnitTests::DeathSuccess(int status, const std::string& msg, | 201 void UnitTests::DeathSuccess(int status, const std::string& msg, const void*) { |
| 202 const void *) { | |
| 203 std::string details(TestFailedMessage(msg)); | 202 std::string details(TestFailedMessage(msg)); |
| 204 | 203 |
| 205 bool subprocess_terminated_normally = WIFEXITED(status); | 204 bool subprocess_terminated_normally = WIFEXITED(status); |
| 206 ASSERT_TRUE(subprocess_terminated_normally) << details; | 205 ASSERT_TRUE(subprocess_terminated_normally) << details; |
| 207 int subprocess_exit_status = WEXITSTATUS(status); | 206 int subprocess_exit_status = WEXITSTATUS(status); |
| 208 ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details; | 207 ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details; |
| 209 bool subprocess_exited_but_printed_messages = !msg.empty(); | 208 bool subprocess_exited_but_printed_messages = !msg.empty(); |
| 210 EXPECT_FALSE(subprocess_exited_but_printed_messages) << details; | 209 EXPECT_FALSE(subprocess_exited_but_printed_messages) << details; |
| 211 } | 210 } |
| 212 | 211 |
| 213 void UnitTests::DeathMessage(int status, const std::string& msg, | 212 void UnitTests::DeathMessage(int status, |
| 214 const void *aux) { | 213 const std::string& msg, |
| 214 const void* aux) { |
| 215 std::string details(TestFailedMessage(msg)); | 215 std::string details(TestFailedMessage(msg)); |
| 216 const char *expected_msg = static_cast<const char *>(aux); | 216 const char* expected_msg = static_cast<const char*>(aux); |
| 217 | 217 |
| 218 bool subprocess_terminated_normally = WIFEXITED(status); | 218 bool subprocess_terminated_normally = WIFEXITED(status); |
| 219 ASSERT_TRUE(subprocess_terminated_normally) << details; | 219 ASSERT_TRUE(subprocess_terminated_normally) << details; |
| 220 int subprocess_exit_status = WEXITSTATUS(status); | 220 int subprocess_exit_status = WEXITSTATUS(status); |
| 221 ASSERT_EQ(kExitWithAssertionFailure, subprocess_exit_status) << details; | 221 ASSERT_EQ(kExitWithAssertionFailure, subprocess_exit_status) << details; |
| 222 bool subprocess_exited_without_matching_message = | 222 bool subprocess_exited_without_matching_message = |
| 223 msg.find(expected_msg) == std::string::npos; | 223 msg.find(expected_msg) == std::string::npos; |
| 224 EXPECT_FALSE(subprocess_exited_without_matching_message) << details; | 224 EXPECT_FALSE(subprocess_exited_without_matching_message) << details; |
| 225 } | 225 } |
| 226 | 226 |
| 227 void UnitTests::DeathExitCode(int status, const std::string& msg, | 227 void UnitTests::DeathExitCode(int status, |
| 228 const void *aux) { | 228 const std::string& msg, |
| 229 const void* aux) { |
| 229 int expected_exit_code = static_cast<int>(reinterpret_cast<intptr_t>(aux)); | 230 int expected_exit_code = static_cast<int>(reinterpret_cast<intptr_t>(aux)); |
| 230 std::string details(TestFailedMessage(msg)); | 231 std::string details(TestFailedMessage(msg)); |
| 231 | 232 |
| 232 bool subprocess_terminated_normally = WIFEXITED(status); | 233 bool subprocess_terminated_normally = WIFEXITED(status); |
| 233 ASSERT_TRUE(subprocess_terminated_normally) << details; | 234 ASSERT_TRUE(subprocess_terminated_normally) << details; |
| 234 int subprocess_exit_status = WEXITSTATUS(status); | 235 int subprocess_exit_status = WEXITSTATUS(status); |
| 235 ASSERT_EQ(subprocess_exit_status, expected_exit_code) << details; | 236 ASSERT_EQ(subprocess_exit_status, expected_exit_code) << details; |
| 236 } | 237 } |
| 237 | 238 |
| 238 void UnitTests::DeathBySignal(int status, const std::string& msg, | 239 void UnitTests::DeathBySignal(int status, |
| 239 const void *aux) { | 240 const std::string& msg, |
| 241 const void* aux) { |
| 240 int expected_signo = static_cast<int>(reinterpret_cast<intptr_t>(aux)); | 242 int expected_signo = static_cast<int>(reinterpret_cast<intptr_t>(aux)); |
| 241 std::string details(TestFailedMessage(msg)); | 243 std::string details(TestFailedMessage(msg)); |
| 242 | 244 |
| 243 bool subprocess_terminated_by_signal = WIFSIGNALED(status); | 245 bool subprocess_terminated_by_signal = WIFSIGNALED(status); |
| 244 ASSERT_TRUE(subprocess_terminated_by_signal) << details; | 246 ASSERT_TRUE(subprocess_terminated_by_signal) << details; |
| 245 int subprocess_signal_number = WTERMSIG(status); | 247 int subprocess_signal_number = WTERMSIG(status); |
| 246 ASSERT_EQ(subprocess_signal_number, expected_signo) << details; | 248 ASSERT_EQ(subprocess_signal_number, expected_signo) << details; |
| 247 } | 249 } |
| 248 | 250 |
| 249 void UnitTests::AssertionFailure(const char *expr, const char *file, | 251 void UnitTests::AssertionFailure(const char* expr, const char* file, int line) { |
| 250 int line) { | |
| 251 fprintf(stderr, "%s:%d:%s", file, line, expr); | 252 fprintf(stderr, "%s:%d:%s", file, line, expr); |
| 252 fflush(stderr); | 253 fflush(stderr); |
| 253 _exit(kExitWithAssertionFailure); | 254 _exit(kExitWithAssertionFailure); |
| 254 } | 255 } |
| 255 | 256 |
| 256 void UnitTests::IgnoreThisTest() { | 257 void UnitTests::IgnoreThisTest() { |
| 257 fflush(stderr); | 258 fflush(stderr); |
| 258 _exit(kIgnoreThisTest); | 259 _exit(kIgnoreThisTest); |
| 259 } | 260 } |
| 260 | 261 |
| 261 } // namespace | 262 } // namespace |
| OLD | NEW |