Support for unpacked ARM packed relocations.
[chromium-blink-merge.git] / components / nacl / loader / nonsfi / nonsfi_sandbox_unittest.cc
blob4b3da8581836ce2c76cce9bb8846513780815319
1 // Copyright 2014 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.
5 // ASan internally uses some syscalls which non-SFI NaCl disallows.
6 // Seccomp-BPF tests die under TSan v2. See http://crbug.com/356588
7 #if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
9 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <pthread.h>
14 #include <sched.h>
15 #include <signal.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/mman.h>
19 #include <sys/prctl.h>
20 #include <sys/ptrace.h>
21 #include <sys/socket.h>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <time.h>
26 #include <unistd.h>
28 #include "base/bind.h"
29 #include "base/callback.h"
30 #include "base/compiler_specific.h"
31 #include "base/files/scoped_file.h"
32 #include "base/logging.h"
33 #include "base/posix/eintr_wrapper.h"
34 #include "base/sys_info.h"
35 #include "base/time/time.h"
36 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
37 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
38 #include "sandbox/linux/services/linux_syscalls.h"
39 #include "third_party/lss/linux_syscall_support.h" // for MAKE_PROCESS_CPUCLOCK
41 namespace {
43 void DoPipe(base::ScopedFD* fds) {
44 int tmp_fds[2];
45 BPF_ASSERT_EQ(0, pipe(tmp_fds));
46 fds[0].reset(tmp_fds[0]);
47 fds[1].reset(tmp_fds[1]);
50 void DoSocketpair(base::ScopedFD* fds) {
51 int tmp_fds[2];
52 BPF_ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, tmp_fds));
53 fds[0].reset(tmp_fds[0]);
54 fds[1].reset(tmp_fds[1]);
57 TEST(NaClNonSfiSandboxTest, BPFIsSupported) {
58 bool seccomp_bpf_supported = (
59 sandbox::SandboxBPF::SupportsSeccompSandbox(-1) ==
60 sandbox::SandboxBPF::STATUS_AVAILABLE);
61 if (!seccomp_bpf_supported) {
62 LOG(ERROR) << "Seccomp BPF is not supported, these tests "
63 << "will pass without running";
67 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
68 invalid_sysno,
69 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
70 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
71 syscall(999);
74 const int kExpectedValue = 123;
76 void* SetValueInThread(void* test_val_ptr) {
77 *reinterpret_cast<int*>(test_val_ptr) = kExpectedValue;
78 return NULL;
81 // To make this test pass, we need to allow sched_getaffinity and
82 // mmap. We just disable this test not to complicate the sandbox.
83 BPF_TEST_C(NaClNonSfiSandboxTest,
84 clone_by_pthread_create,
85 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
86 // clone call for thread creation is allowed.
87 pthread_t th;
88 int test_val = 42;
89 BPF_ASSERT_EQ(0, pthread_create(&th, NULL, &SetValueInThread, &test_val));
90 BPF_ASSERT_EQ(0, pthread_join(th, NULL));
91 BPF_ASSERT_EQ(kExpectedValue, test_val);
94 int DoFork() {
95 // Call clone() to do a fork().
96 const int pid = syscall(__NR_clone, SIGCHLD, NULL);
97 if (pid == 0)
98 _exit(0);
99 return pid;
102 // The sanity check for DoFork without the sandbox.
103 TEST(NaClNonSfiSandboxTest, DoFork) {
104 const int pid = DoFork();
105 ASSERT_LT(0, pid);
106 int status;
107 ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
108 ASSERT_TRUE(WIFEXITED(status));
109 ASSERT_EQ(0, WEXITSTATUS(status));
112 // Then, try this in the sandbox.
113 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
114 clone_for_fork,
115 DEATH_MESSAGE(sandbox::GetCloneErrorMessageContentForTests()),
116 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
117 DoFork();
120 BPF_TEST_C(NaClNonSfiSandboxTest,
121 prctl_SET_NAME,
122 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
123 errno = 0;
124 BPF_ASSERT_EQ(-1, syscall(__NR_prctl, PR_SET_NAME, "foo"));
125 BPF_ASSERT_EQ(EPERM, errno);
128 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
129 prctl_SET_DUMPABLE,
130 DEATH_MESSAGE(sandbox::GetPrctlErrorMessageContentForTests()),
131 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
132 syscall(__NR_prctl, PR_SET_DUMPABLE, 1UL);
135 BPF_TEST_C(NaClNonSfiSandboxTest,
136 socketcall_allowed,
137 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
138 base::ScopedFD fds[2];
139 struct msghdr msg = {};
140 struct iovec iov;
141 std::string payload("foo");
142 iov.iov_base = &payload[0];
143 iov.iov_len = payload.size();
144 msg.msg_iov = &iov;
145 msg.msg_iovlen = 1;
146 DoSocketpair(fds);
147 BPF_ASSERT_EQ(static_cast<int>(payload.size()),
148 HANDLE_EINTR(sendmsg(fds[1].get(), &msg, 0)));
149 BPF_ASSERT_EQ(static_cast<int>(payload.size()),
150 HANDLE_EINTR(recvmsg(fds[0].get(), &msg, 0)));
151 BPF_ASSERT_EQ(0, shutdown(fds[0].get(), SHUT_RDWR));
154 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
155 accept,
156 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
157 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
158 accept(0, NULL, NULL);
161 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
162 bind,
163 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
164 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
165 bind(0, NULL, 0);
168 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
169 connect,
170 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
171 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
172 connect(0, NULL, 0);
175 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
176 getpeername,
177 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
178 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
179 getpeername(0, NULL, NULL);
182 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
183 getsockname,
184 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
185 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
186 struct sockaddr addr;
187 socklen_t addrlen = 0;
188 getsockname(0, &addr, &addrlen);
191 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
192 getsockopt,
193 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
194 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
195 getsockopt(0, 0, 0, NULL, NULL);
198 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
199 listen,
200 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
201 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
202 listen(0, 0);
205 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
206 recv,
207 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
208 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
209 recv(0, NULL, 0, 0);
212 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
213 recvfrom,
214 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
215 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
216 recvfrom(0, NULL, 0, 0, NULL, NULL);
219 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
220 send,
221 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
222 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
223 send(0, NULL, 0, 0);
226 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
227 sendto,
228 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
229 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
230 sendto(0, NULL, 0, 0, NULL, 0);
233 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
234 setsockopt,
235 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
236 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
237 setsockopt(0, 0, 0, NULL, 0);
240 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
241 socket,
242 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
243 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
244 socket(0, 0, 0);
247 #if defined(__x86_64__) || defined(__arm__)
248 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
249 socketpair,
250 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
251 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
252 int fds[2];
253 socketpair(AF_INET, SOCK_STREAM, 0, fds);
255 #endif
257 BPF_TEST_C(NaClNonSfiSandboxTest,
258 fcntl_SETFD_allowed,
259 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
260 base::ScopedFD fds[2];
261 DoSocketpair(fds);
262 BPF_ASSERT_EQ(0, fcntl(fds[0].get(), F_SETFD, FD_CLOEXEC));
265 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
266 fcntl_SETFD,
267 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
268 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
269 base::ScopedFD fds[2];
270 DoSocketpair(fds);
271 fcntl(fds[0].get(), F_SETFD, 99);
274 BPF_TEST_C(NaClNonSfiSandboxTest,
275 fcntl_GETFL_SETFL_allowed,
276 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
277 base::ScopedFD fds[2];
278 DoPipe(fds);
279 const int fd = fds[0].get();
280 BPF_ASSERT_EQ(0, fcntl(fd, F_GETFL));
281 BPF_ASSERT_EQ(0, fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK));
282 BPF_ASSERT_EQ(O_NONBLOCK, fcntl(fd, F_GETFL));
285 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
286 fcntl_GETFL_SETFL,
287 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
288 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
289 base::ScopedFD fds[2];
290 DoSocketpair(fds);
291 fcntl(fds[0].get(), F_SETFL, O_APPEND);
294 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
295 fcntl_DUPFD,
296 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
297 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
298 fcntl(0, F_DUPFD);
301 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
302 fcntl_DUPFD_CLOEXEC,
303 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
304 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
305 fcntl(0, F_DUPFD_CLOEXEC);
308 void* DoAllowedAnonymousMmap() {
309 return mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
310 MAP_ANONYMOUS | MAP_SHARED, -1, 0);
313 BPF_TEST_C(NaClNonSfiSandboxTest,
314 mmap_allowed,
315 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
316 void* ptr = DoAllowedAnonymousMmap();
317 BPF_ASSERT_NE(MAP_FAILED, ptr);
318 BPF_ASSERT_EQ(0, munmap(ptr, getpagesize()));
321 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
322 mmap_unallowed_flag,
323 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
324 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
325 mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
326 MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
329 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
330 mmap_unallowed_prot,
331 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
332 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
333 mmap(NULL, getpagesize(), PROT_READ | PROT_GROWSDOWN,
334 MAP_ANONYMOUS, -1, 0);
337 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
338 mmap_exec,
339 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
340 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
341 mmap(NULL, getpagesize(), PROT_EXEC, MAP_ANONYMOUS, -1, 0);
344 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
345 mmap_read_exec,
346 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
347 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
348 mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_ANONYMOUS, -1, 0);
351 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
352 mmap_write_exec,
353 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
354 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
355 mmap(NULL, getpagesize(), PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS, -1, 0);
358 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
359 mmap_read_write_exec,
360 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
361 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
362 mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
363 MAP_ANONYMOUS, -1, 0);
366 BPF_TEST_C(NaClNonSfiSandboxTest,
367 mprotect_allowed,
368 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
369 void* ptr = DoAllowedAnonymousMmap();
370 BPF_ASSERT_NE(MAP_FAILED, ptr);
371 BPF_ASSERT_EQ(0, mprotect(ptr, getpagesize(), PROT_READ));
372 BPF_ASSERT_EQ(0, munmap(ptr, getpagesize()));
375 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
376 mprotect_unallowed_prot,
377 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
378 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
379 // We have tested DoAllowedAnonymousMmap is allowed in
380 // mmap_allowed, so we can make sure the following mprotect call
381 // kills the process.
382 void* ptr = DoAllowedAnonymousMmap();
383 BPF_ASSERT_NE(MAP_FAILED, ptr);
384 mprotect(ptr, getpagesize(), PROT_READ | PROT_GROWSDOWN);
387 BPF_TEST_C(NaClNonSfiSandboxTest,
388 brk,
389 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
390 char* next_brk = static_cast<char*>(sbrk(0)) + getpagesize();
391 // The kernel interface must return zero for brk.
392 BPF_ASSERT_EQ(0, syscall(__NR_brk, next_brk));
393 // The libc wrapper translates it to ENOMEM.
394 errno = 0;
395 BPF_ASSERT_EQ(-1, brk(next_brk));
396 BPF_ASSERT_EQ(ENOMEM, errno);
399 void CheckClock(clockid_t clockid) {
400 struct timespec ts;
401 ts.tv_sec = ts.tv_nsec = -1;
402 BPF_ASSERT_EQ(0, clock_gettime(clockid, &ts));
403 BPF_ASSERT_LE(0, ts.tv_sec);
404 BPF_ASSERT_LE(0, ts.tv_nsec);
407 BPF_TEST_C(NaClNonSfiSandboxTest,
408 clock_gettime_allowed,
409 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
410 CheckClock(CLOCK_MONOTONIC);
411 CheckClock(CLOCK_PROCESS_CPUTIME_ID);
412 CheckClock(CLOCK_REALTIME);
413 CheckClock(CLOCK_THREAD_CPUTIME_ID);
416 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
417 clock_gettime_crash_monotonic_raw,
418 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
419 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
420 struct timespec ts;
421 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
424 #if defined(OS_CHROMEOS)
426 // A custom BPF tester delegate to run IsRunningOnChromeOS() before
427 // the sandbox is enabled because we cannot run it with non-SFI BPF
428 // sandbox enabled.
429 class ClockSystemTesterDelegate : public sandbox::BPFTesterDelegate {
430 public:
431 ClockSystemTesterDelegate()
432 : is_running_on_chromeos_(base::SysInfo::IsRunningOnChromeOS()) {}
433 virtual ~ClockSystemTesterDelegate() {}
435 virtual scoped_ptr<sandbox::SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
436 return scoped_ptr<sandbox::SandboxBPFPolicy>(
437 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy());
439 virtual void RunTestFunction() OVERRIDE {
440 if (is_running_on_chromeos_) {
441 CheckClock(base::TimeTicks::kClockSystemTrace);
442 } else {
443 struct timespec ts;
444 // kClockSystemTrace is 11, which is CLOCK_THREAD_CPUTIME_ID of
445 // the init process (pid=1). If kernel supports this feature,
446 // this may succeed even if this is not running on Chrome OS. We
447 // just check this clock_gettime call does not crash.
448 clock_gettime(base::TimeTicks::kClockSystemTrace, &ts);
452 private:
453 const bool is_running_on_chromeos_;
454 DISALLOW_COPY_AND_ASSIGN(ClockSystemTesterDelegate);
457 BPF_TEST_D(BPFTest, BPFTestWithDelegateClass, ClockSystemTesterDelegate);
459 #else
461 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
462 clock_gettime_crash_system_trace,
463 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
464 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
465 struct timespec ts;
466 clock_gettime(base::TimeTicks::kClockSystemTrace, &ts);
469 #endif // defined(OS_CHROMEOS)
471 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
472 clock_gettime_crash_cpu_clock,
473 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
474 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
475 // We can't use clock_getcpuclockid() because it's not implemented in newlib,
476 // and it might not work inside the sandbox anyway.
477 const pid_t kInitPID = 1;
478 const clockid_t kInitCPUClockID =
479 MAKE_PROCESS_CPUCLOCK(kInitPID, CPUCLOCK_SCHED);
481 struct timespec ts;
482 clock_gettime(kInitCPUClockID, &ts);
485 // The following test cases check if syscalls return EPERM regardless
486 // of arguments.
487 #define RESTRICT_SYSCALL_EPERM_TEST(name) \
488 BPF_TEST_C(NaClNonSfiSandboxTest, \
489 name##_EPERM, \
490 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { \
491 errno = 0; \
492 BPF_ASSERT_EQ(-1, syscall(__NR_##name, 0, 0, 0, 0, 0, 0)); \
493 BPF_ASSERT_EQ(EPERM, errno); \
496 RESTRICT_SYSCALL_EPERM_TEST(epoll_create);
497 #if defined(__i386__) || defined(__arm__)
498 RESTRICT_SYSCALL_EPERM_TEST(getegid32);
499 RESTRICT_SYSCALL_EPERM_TEST(geteuid32);
500 RESTRICT_SYSCALL_EPERM_TEST(getgid32);
501 RESTRICT_SYSCALL_EPERM_TEST(getuid32);
502 #endif
503 RESTRICT_SYSCALL_EPERM_TEST(getegid);
504 RESTRICT_SYSCALL_EPERM_TEST(geteuid);
505 RESTRICT_SYSCALL_EPERM_TEST(getgid);
506 RESTRICT_SYSCALL_EPERM_TEST(getuid);
507 RESTRICT_SYSCALL_EPERM_TEST(madvise);
508 RESTRICT_SYSCALL_EPERM_TEST(open);
509 RESTRICT_SYSCALL_EPERM_TEST(ptrace);
510 RESTRICT_SYSCALL_EPERM_TEST(set_robust_list);
511 #if defined(__i386__) || defined(__x86_64__)
512 RESTRICT_SYSCALL_EPERM_TEST(time);
513 #endif
515 } // namespace
517 #endif // !ADDRESS_SANITIZER && !THREAD_SANITIZER