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 {
TestFailedMessage(const std::string & msg)22 std::string TestFailedMessage(const std::string& msg) {
23 return msg.empty() ? std::string() : "Actual test failure: " + msg;
24 }
25
GetSubProcessTimeoutTimeInSeconds()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.
CountThreads()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
IsAndroid()47 bool IsAndroid() {
48 #if defined(OS_ANDROID)
49 return true;
50 #else
51 return false;
52 #endif
53 }
54
IsArchitectureArm()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.
IsRunningOnValgrind()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
SigAlrmHandler(int)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.
SetProcessTimeout(int time_in_seconds)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.
RunTestInProcess(SandboxTestRunner * test_runner,DeathCheck death,const void * death_aux)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
DeathSuccess(int status,const std::string & msg,const void *)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
DeathSuccessAllowNoise(int status,const std::string & msg,const void *)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
DeathMessage(int status,const std::string & msg,const void * aux)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
DeathSEGVMessage(int status,const std::string & msg,const void * aux)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
DeathExitCode(int status,const std::string & msg,const void * aux)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
DeathBySignal(int status,const std::string & msg,const void * aux)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
AssertionFailure(const char * expr,const char * file,int line)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
IgnoreThisTest()321 void UnitTests::IgnoreThisTest() {
322 fflush(stderr);
323 _exit(kIgnoreThisTest);
324 }
325
326 } // namespace
327