• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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 
SigAlrmHandler(int)72 static 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.
SetProcessTimeout(int time_in_seconds)83 static 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.
RunTestInProcess(SandboxTestRunner * test_runner,DeathCheck death,const void * death_aux)108 void UnitTests::RunTestInProcess(SandboxTestRunner* test_runner,
109                                  DeathCheck death,
110                                  const void* death_aux) {
111   CHECK(test_runner);
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   for (unsigned int iteration = 0; iteration < 30; iteration++) {
132     struct timespec ts = {0, 1L << iteration /* nanoseconds */};
133     PCHECK(0 == HANDLE_EINTR(nanosleep(&ts, &ts)));
134     num_threads = CountThreads();
135     if (kNumExpectedThreads == num_threads)
136       break;
137   }
138 
139   ASSERT_EQ(kNumExpectedThreads, num_threads)
140       << "Running sandbox tests with multiple threads "
141       << "is not supported and will make the tests flaky.";
142   int fds[2];
143   ASSERT_EQ(0, pipe(fds));
144   // Check that our pipe is not on one of the standard file descriptor.
145   SANDBOX_ASSERT(fds[0] > 2 && fds[1] > 2);
146 
147   pid_t pid;
148   ASSERT_LE(0, (pid = fork()));
149   if (!pid) {
150     // In child process
151     // Redirect stderr to our pipe. This way, we can capture all error
152     // messages, if we decide we want to do so in our tests.
153     SANDBOX_ASSERT(dup2(fds[1], 2) == 2);
154     SANDBOX_ASSERT(!close(fds[0]));
155     SANDBOX_ASSERT(!close(fds[1]));
156 
157     // Don't set a timeout if running on Valgrind, since it's generally much
158     // slower.
159     if (!IsRunningOnValgrind()) {
160       SetProcessTimeout(GetSubProcessTimeoutTimeInSeconds());
161     }
162 
163     // Disable core files. They are not very useful for our individual test
164     // cases.
165     struct rlimit no_core = {0};
166     setrlimit(RLIMIT_CORE, &no_core);
167 
168     test_runner->Run();
169     if (test_runner->ShouldCheckForLeaks()) {
170 #if defined(LEAK_SANITIZER)
171       __lsan_do_leak_check();
172 #endif
173     }
174     _exit(kExpectedValue);
175   }
176 
177   close(fds[1]);
178   std::vector<char> msg_buf;
179   ssize_t rc;
180 
181   // Make sure read() will never block as we'll use poll() to
182   // block with a timeout instead.
183   const int fcntl_ret = fcntl(fds[0], F_SETFL, O_NONBLOCK);
184   ASSERT_EQ(0, fcntl_ret);
185   struct pollfd poll_fd = {fds[0], POLLIN | POLLRDHUP, 0};
186 
187   int poll_ret;
188   // We prefer the SIGALRM timeout to trigger in the child than this timeout
189   // so we double the common value here.
190   int poll_timeout = GetSubProcessTimeoutTimeInSeconds() * 2 * 1000;
191   while ((poll_ret = poll(&poll_fd, 1, poll_timeout) > 0)) {
192     const size_t kCapacity = 256;
193     const size_t len = msg_buf.size();
194     msg_buf.resize(len + kCapacity);
195     rc = HANDLE_EINTR(read(fds[0], &msg_buf[len], kCapacity));
196     msg_buf.resize(len + std::max(rc, static_cast<ssize_t>(0)));
197     if (rc <= 0)
198       break;
199   }
200   ASSERT_NE(poll_ret, -1) << "poll() failed";
201   ASSERT_NE(poll_ret, 0) << "Timeout while reading child state";
202   close(fds[0]);
203   std::string msg(msg_buf.begin(), msg_buf.end());
204 
205   int status = 0;
206   int waitpid_returned = HANDLE_EINTR(waitpid(pid, &status, 0));
207   ASSERT_EQ(pid, waitpid_returned) << TestFailedMessage(msg);
208 
209   // At run-time, we sometimes decide that a test shouldn't actually
210   // run (e.g. when testing sandbox features on a kernel that doesn't
211   // have sandboxing support). When that happens, don't attempt to
212   // call the "death" function, as it might be looking for a
213   // death-test condition that would never have triggered.
214   if (!WIFEXITED(status) || WEXITSTATUS(status) != kIgnoreThisTest ||
215       !msg.empty()) {
216     // We use gtest's ASSERT_XXX() macros instead of the DeathCheck
217     // functions.  This means, on failure, "return" is called. This
218     // only works correctly, if the call of the "death" callback is
219     // the very last thing in our function.
220     death(status, msg, death_aux);
221   }
222 }
223 
DeathSuccess(int status,const std::string & msg,const void *)224 void UnitTests::DeathSuccess(int status, const std::string& msg, const void*) {
225   std::string details(TestFailedMessage(msg));
226 
227   bool subprocess_terminated_normally = WIFEXITED(status);
228   ASSERT_TRUE(subprocess_terminated_normally) << details;
229   int subprocess_exit_status = WEXITSTATUS(status);
230   ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details;
231   bool subprocess_exited_but_printed_messages = !msg.empty();
232   EXPECT_FALSE(subprocess_exited_but_printed_messages) << details;
233 }
234 
DeathSuccessAllowNoise(int status,const std::string & msg,const void *)235 void UnitTests::DeathSuccessAllowNoise(int status,
236                                        const std::string& msg,
237                                        const void*) {
238   std::string details(TestFailedMessage(msg));
239 
240   bool subprocess_terminated_normally = WIFEXITED(status);
241   ASSERT_TRUE(subprocess_terminated_normally) << details;
242   int subprocess_exit_status = WEXITSTATUS(status);
243   ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details;
244 }
245 
DeathMessage(int status,const std::string & msg,const void * aux)246 void UnitTests::DeathMessage(int status,
247                              const std::string& msg,
248                              const void* aux) {
249   std::string details(TestFailedMessage(msg));
250   const char* expected_msg = static_cast<const char*>(aux);
251 
252   bool subprocess_terminated_normally = WIFEXITED(status);
253   ASSERT_TRUE(subprocess_terminated_normally) << details;
254   int subprocess_exit_status = WEXITSTATUS(status);
255   ASSERT_EQ(kExitWithAssertionFailure, subprocess_exit_status) << details;
256   bool subprocess_exited_without_matching_message =
257       msg.find(expected_msg) == std::string::npos;
258   EXPECT_FALSE(subprocess_exited_without_matching_message) << details;
259 }
260 
DeathExitCode(int status,const std::string & msg,const void * aux)261 void UnitTests::DeathExitCode(int status,
262                               const std::string& msg,
263                               const void* aux) {
264   int expected_exit_code = static_cast<int>(reinterpret_cast<intptr_t>(aux));
265   std::string details(TestFailedMessage(msg));
266 
267   bool subprocess_terminated_normally = WIFEXITED(status);
268   ASSERT_TRUE(subprocess_terminated_normally) << details;
269   int subprocess_exit_status = WEXITSTATUS(status);
270   ASSERT_EQ(expected_exit_code, subprocess_exit_status) << details;
271 }
272 
DeathBySignal(int status,const std::string & msg,const void * aux)273 void UnitTests::DeathBySignal(int status,
274                               const std::string& msg,
275                               const void* aux) {
276   int expected_signo = static_cast<int>(reinterpret_cast<intptr_t>(aux));
277   std::string details(TestFailedMessage(msg));
278 
279   bool subprocess_terminated_by_signal = WIFSIGNALED(status);
280   ASSERT_TRUE(subprocess_terminated_by_signal) << details;
281   int subprocess_signal_number = WTERMSIG(status);
282   ASSERT_EQ(expected_signo, subprocess_signal_number) << details;
283 }
284 
AssertionFailure(const char * expr,const char * file,int line)285 void UnitTests::AssertionFailure(const char* expr, const char* file, int line) {
286   fprintf(stderr, "%s:%d:%s", file, line, expr);
287   fflush(stderr);
288   _exit(kExitWithAssertionFailure);
289 }
290 
IgnoreThisTest()291 void UnitTests::IgnoreThisTest() {
292   fflush(stderr);
293   _exit(kIgnoreThisTest);
294 }
295 
296 }  // namespace
297