Rename GetIconID to GetIconId
[chromium-blink-merge.git] / components / nacl / loader / nonsfi / nonsfi_sandbox_unittest.cc
blob102f5faa1416243af9200d4ab1284e13a70ac002
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 // Sanitizers internally use some syscalls which non-SFI NaCl disallows.
6 #if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \
7 !defined(MEMORY_SANITIZER) && !defined(LEAK_SANITIZER)
9 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <linux/net.h>
14 #include <pthread.h>
15 #include <sched.h>
16 #include <signal.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/mman.h>
20 #include <sys/prctl.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/at_exit.h"
29 #include "base/bind.h"
30 #include "base/callback.h"
31 #include "base/compiler_specific.h"
32 #include "base/files/scoped_file.h"
33 #include "base/logging.h"
34 #include "base/posix/eintr_wrapper.h"
35 #include "base/sys_info.h"
36 #include "base/threading/thread.h"
37 #include "base/time/time.h"
38 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
39 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
40 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
41 #include "sandbox/linux/seccomp-bpf/syscall.h"
42 #include "sandbox/linux/system_headers/linux_futex.h"
43 #include "sandbox/linux/system_headers/linux_signal.h"
44 #include "sandbox/linux/system_headers/linux_syscalls.h"
46 // These defines are for PNaCl toolchain build.
47 #if !defined(F_DUPFD_CLOEXEC)
48 #define F_DUPFD_CLOEXEC 1030
49 #endif
51 #if !defined(MAP_POPULATE)
52 #define MAP_POPULATE 0x8000
53 #endif
55 #if !defined(PROT_GROWSDOWN)
56 #define PROT_GROWSDOWN 0x01000000
57 #endif
59 #if !defined(CLOCK_MONOTONIC_RAW)
60 #define CLOCK_MONOTONIC_RAW 4
61 #endif
63 #if !defined(AF_INET)
64 #define AF_INET 2
65 #endif
67 #if defined(__i386__)
69 #if !defined(SYS_SOCKET)
70 #define SYS_SOCKET 1
71 #endif
73 #if !defined(SYS_BIND)
74 #define SYS_BIND 2
75 #endif
77 #if !defined(SYS_CONNECT)
78 #define SYS_CONNECT 3
79 #endif
81 #if !defined(SYS_LISTEN)
82 #define SYS_LISTEN 4
83 #endif
85 #if !defined(SYS_ACCEPT)
86 #define SYS_ACCEPT 5
87 #endif
89 #if !defined(SYS_GETSOCKNAME)
90 #define SYS_GETSOCKNAME 6
91 #endif
93 #if !defined(SYS_GETPEERNAME)
94 #define SYS_GETPEERNAME 7
95 #endif
97 #if !defined(SYS_SETSOCKOPT)
98 #define SYS_SETSOCKOPT 14
99 #endif
101 #if !defined(SYS_GETSOCKOPT)
102 #define SYS_GETSOCKOPT 15
103 #endif
105 #endif // defined(__i386__)
107 namespace {
109 void DoPipe(base::ScopedFD* fds) {
110 int tmp_fds[2];
111 BPF_ASSERT_EQ(0, pipe(tmp_fds));
112 fds[0].reset(tmp_fds[0]);
113 fds[1].reset(tmp_fds[1]);
116 void DoSocketpair(base::ScopedFD* fds) {
117 int tmp_fds[2];
118 BPF_ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, tmp_fds));
119 fds[0].reset(tmp_fds[0]);
120 fds[1].reset(tmp_fds[1]);
123 TEST(NaClNonSfiSandboxTest, BPFIsSupported) {
124 bool seccomp_bpf_supported = sandbox::SandboxBPF::SupportsSeccompSandbox(
125 sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED);
127 if (!seccomp_bpf_supported) {
128 LOG(ERROR) << "Seccomp BPF is not supported, these tests "
129 << "will pass without running";
133 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
134 invalid_sysno,
135 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
136 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
137 syscall(999);
140 const int kExpectedValue = 123;
142 void* SetValueInThread(void* test_val_ptr) {
143 *reinterpret_cast<int*>(test_val_ptr) = kExpectedValue;
144 return NULL;
147 // To make this test pass, we need to allow sched_getaffinity and
148 // mmap. We just disable this test not to complicate the sandbox.
149 BPF_TEST_C(NaClNonSfiSandboxTest,
150 clone_by_pthread_create,
151 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
152 // clone call for thread creation is allowed.
153 pthread_t th;
154 int test_val = 42;
155 BPF_ASSERT_EQ(0, pthread_create(&th, NULL, &SetValueInThread, &test_val));
156 BPF_ASSERT_EQ(0, pthread_join(th, NULL));
157 BPF_ASSERT_EQ(kExpectedValue, test_val);
160 int DoFork() {
161 // Call clone() to do a fork().
162 const int pid = syscall(__NR_clone, LINUX_SIGCHLD, NULL);
163 if (pid == 0)
164 _exit(0);
165 return pid;
168 // The sanity check for DoFork without the sandbox.
169 TEST(NaClNonSfiSandboxTest, DoFork) {
170 const int pid = DoFork();
171 ASSERT_LT(0, pid);
172 int status;
173 ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
174 ASSERT_TRUE(WIFEXITED(status));
175 ASSERT_EQ(0, WEXITSTATUS(status));
178 // Then, try this in the sandbox.
179 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
180 clone_for_fork,
181 DEATH_SEGV_MESSAGE(
182 sandbox::GetCloneErrorMessageContentForTests()),
183 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
184 DoFork();
187 BPF_TEST_C(NaClNonSfiSandboxTest,
188 prctl_SET_NAME,
189 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
190 errno = 0;
191 BPF_ASSERT_EQ(-1, syscall(__NR_prctl, PR_SET_NAME, "foo"));
192 BPF_ASSERT_EQ(EPERM, errno);
195 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
196 prctl_SET_DUMPABLE,
197 DEATH_SEGV_MESSAGE(
198 sandbox::GetPrctlErrorMessageContentForTests()),
199 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
200 syscall(__NR_prctl, PR_SET_DUMPABLE, 1UL);
203 #if defined(OS_NACL_NONSFI)
204 BPF_DEATH_TEST_C(NaClNonsfiSandboxTest,
205 socketpair_af_unix_disallowed,
206 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
207 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
208 int tmp_fds[2];
209 socketpair(AF_UNIX, SOCK_STREAM, 0, tmp_fds);
211 #else
212 BPF_TEST_C(NaClNonSfiSandboxTest,
213 socketcall_allowed,
214 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
215 base::ScopedFD fds[2];
216 struct msghdr msg = {};
217 struct iovec iov;
218 std::string payload("foo");
219 iov.iov_base = &payload[0];
220 iov.iov_len = payload.size();
221 msg.msg_iov = &iov;
222 msg.msg_iovlen = 1;
223 DoSocketpair(fds);
224 BPF_ASSERT_EQ(static_cast<int>(payload.size()),
225 HANDLE_EINTR(sendmsg(fds[1].get(), &msg, 0)));
226 BPF_ASSERT_EQ(static_cast<int>(payload.size()),
227 HANDLE_EINTR(recvmsg(fds[0].get(), &msg, 0)));
228 BPF_ASSERT_EQ(0, shutdown(fds[0].get(), SHUT_RDWR));
230 #endif
232 // On arm and x86_64 the arguments to socketpair are passed in registers,
233 // so they can be filtered by seccomp-bpf. This filter cannot be applied
234 // on x86_32 as the arguments are passed in memory.
235 #if defined(__x86_64__) || defined(__arm__)
236 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
237 socketpair_af_inet_disallowed,
238 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
239 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
240 int fds[2];
241 socketpair(AF_INET, SOCK_STREAM, 0, fds);
243 #endif
245 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
246 accept,
247 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
248 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
249 #if defined(__i386__)
250 uintptr_t args[] = {0, 0, 0};
251 syscall(__NR_socketcall, SYS_ACCEPT, args);
252 #else
253 syscall(__NR_accept, 0, 0, 0);
254 #endif
257 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
258 bind,
259 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
260 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
261 #if defined(__i386__)
262 uintptr_t args[] = {0, 0, 0};
263 syscall(__NR_socketcall, SYS_BIND, args);
264 #else
265 syscall(__NR_bind, 0, 0, 0);
266 #endif
269 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
270 connect,
271 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
272 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
273 #if defined(__i386__)
274 uintptr_t args[] = {0, 0, 0};
275 syscall(__NR_socketcall, SYS_CONNECT, args);
276 #else
277 syscall(__NR_connect, 0, 0, 0);
278 #endif
281 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
282 getpeername,
283 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
284 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
285 #if defined(__i386__)
286 uintptr_t args[] = {0, 0, 0};
287 syscall(__NR_socketcall, SYS_GETPEERNAME, args);
288 #else
289 syscall(__NR_getpeername, 0, 0, 0);
290 #endif
293 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
294 getsockname,
295 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
296 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
297 #if defined(__i386__)
298 uintptr_t args[] = {0, 0, 0};
299 syscall(__NR_socketcall, SYS_GETSOCKNAME, args);
300 #else
301 syscall(__NR_getsockname, 0, 0, 0);
302 #endif
305 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
306 getsockopt,
307 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
308 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
309 #if defined(__i386__)
310 uintptr_t args[] = {0, 0, 0, 0, 0};
311 syscall(__NR_socketcall, SYS_GETSOCKOPT, args);
312 #else
313 syscall(__NR_getsockname, 0, 0, 0, 0, 0);
314 #endif
317 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
318 listen,
319 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
320 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
321 #if defined(__i386__)
322 uintptr_t args[] = {0, 0};
323 syscall(__NR_socketcall, SYS_LISTEN, args);
324 #else
325 syscall(__NR_listen, 0, 0);
326 #endif
329 // On x86_64 architecture, there is no __NR_recv system call. Note: recv()
330 // syscall wrapper usually uses __NR_recvfrom, instead, (like in glibc).
331 #if defined(__i386__) || defined(__arm__)
332 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
333 recv,
334 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
335 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
336 #if defined(__i386__)
337 uintptr_t args[] = {0, 0, 0, 0};
338 syscall(__NR_socketcall, SYS_RECV, args);
339 #else
340 syscall(__NR_recv, 0, 0, 0, 0);
341 #endif
343 #endif
345 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
346 recvfrom,
347 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
348 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
349 #if defined(__i386__)
350 uintptr_t args[] = {0, 0, 0, 0, 0, 0};
351 syscall(__NR_socketcall, SYS_RECVFROM, args);
352 #else
353 syscall(__NR_recvfrom, 0, 0, 0, 0, 0, 0);
354 #endif
357 // On x86_64 architecture, there is no __NR_send system call. Note: send()
358 // syscall wrapper usually uses __NR_sendto, instead, (like in glibc).
359 #if defined(__i386__) || defined(__arm__)
360 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
361 send,
362 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
363 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
364 #if defined(__i386__)
365 uintptr_t args[] = {0, 0, 0, 0};
366 syscall(__NR_socketcall, SYS_SEND, args);
367 #else
368 syscall(__NR_send, 0, 0, 0, 0);
369 #endif
371 #endif
373 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
374 sendto,
375 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
376 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
377 #if defined(__i386__)
378 uintptr_t args[] = {0, 0, 0, 0, 0, 0};
379 syscall(__NR_socketcall, SYS_SENDTO, args);
380 #else
381 syscall(__NR_sendto, 0, 0, 0, 0, 0, 0);
382 #endif
385 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
386 setsockopt,
387 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
388 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
389 #if defined(__i386__)
390 uintptr_t args[] = {0, 0, 0, 0, 0};
391 syscall(__NR_socketcall, SYS_SETSOCKOPT, args);
392 #else
393 syscall(__NR_setsockopt, 0, 0, 0, 0, 0);
394 #endif
397 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
398 socket,
399 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
400 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
401 #if defined(__i386__)
402 uintptr_t args[] = {0, 0, 0};
403 syscall(__NR_socketcall, SYS_SOCKET, args);
404 #else
405 syscall(__NR_socket, 0, 0, 0);
406 #endif
409 BPF_TEST_C(NaClNonSfiSandboxTest,
410 fcntl_SETFD_allowed,
411 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
412 base::ScopedFD fds[2];
413 DoPipe(fds);
414 BPF_ASSERT_EQ(0, fcntl(fds[0].get(), F_SETFD, FD_CLOEXEC));
417 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
418 fcntl_SETFD,
419 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
420 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
421 base::ScopedFD fds[2];
422 DoPipe(fds);
423 fcntl(fds[0].get(), F_SETFD, 99);
426 BPF_TEST_C(NaClNonSfiSandboxTest,
427 fcntl_GETFL_SETFL_allowed,
428 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
429 base::ScopedFD fds[2];
430 DoPipe(fds);
431 const int fd = fds[0].get();
432 BPF_ASSERT_EQ(0, fcntl(fd, F_GETFL));
433 BPF_ASSERT_EQ(0, fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK));
434 BPF_ASSERT_EQ(O_NONBLOCK, fcntl(fd, F_GETFL));
437 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
438 fcntl_GETFL_SETFL,
439 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
440 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
441 base::ScopedFD fds[2];
442 DoPipe(fds);
443 fcntl(fds[0].get(), F_SETFL, O_APPEND);
446 void DoFcntl(int fd, int cmd) {
447 // fcntl in PNaCl toolchain returns an error without calling actual system
448 // call for unknown |cmd|. So, instead, here we use syscall().
449 #if defined(OS_NACL_NONSFI)
450 syscall(__NR_fcntl64, fd, cmd);
451 #else
452 fcntl(fd, cmd);
453 #endif
456 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
457 fcntl_DUPFD,
458 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
459 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
460 DoFcntl(0, F_DUPFD);
463 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
464 fcntl_DUPFD_CLOEXEC,
465 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
466 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
467 DoFcntl(0, F_DUPFD_CLOEXEC);
470 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
471 FutexWithRequeuePriorityInheritence,
472 DEATH_SEGV_MESSAGE(
473 sandbox::GetFutexErrorMessageContentForTests()),
474 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
475 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
476 _exit(1);
479 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
480 FutexWithRequeuePriorityInheritencePrivate,
481 DEATH_SEGV_MESSAGE(
482 sandbox::GetFutexErrorMessageContentForTests()),
483 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
484 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
485 _exit(1);
488 BPF_TEST_C(NaClNonSfiSandboxTest,
489 StartingAndJoiningThreadWorks,
490 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
491 base::Thread thread("sandbox_tests");
492 BPF_ASSERT(thread.Start());
493 // |thread|'s destructor will join the thread.
496 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
497 FutexWithUnlockPIPrivate,
498 DEATH_SEGV_MESSAGE(
499 sandbox::GetFutexErrorMessageContentForTests()),
500 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
501 syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
502 _exit(1);
505 void* DoMmap(int prot, int flags) {
506 #if defined(OS_NACL_NONSFI)
507 // When PROT_EXEC is set, PNaCl toolchain's mmap() system call wrapper uses
508 // two system calls mmap2(2) and mprotect(2), so that we cannot test
509 // sandbox with the wrapper. Instead, here we use syscall().
510 return reinterpret_cast<void*>(
511 syscall(__NR_mmap2, NULL, getpagesize(), prot, flags, -1, 0));
512 #else
513 return mmap(NULL, getpagesize(), prot, flags, -1, 0);
514 #endif
517 void* DoAllowedAnonymousMmap() {
518 return DoMmap(PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED);
521 BPF_TEST_C(NaClNonSfiSandboxTest,
522 mmap_allowed,
523 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
524 void* ptr = DoAllowedAnonymousMmap();
525 BPF_ASSERT_NE(MAP_FAILED, ptr);
526 BPF_ASSERT_EQ(0, munmap(ptr, getpagesize()));
529 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
530 mmap_unallowed_flag,
531 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
532 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
533 DoMmap(PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_POPULATE);
536 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
537 mmap_unallowed_prot,
538 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
539 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
540 DoMmap(PROT_READ | PROT_GROWSDOWN, MAP_ANONYMOUS);
543 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
544 mmap_exec,
545 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
546 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
547 DoMmap(PROT_EXEC, MAP_ANONYMOUS);
550 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
551 mmap_read_exec,
552 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
553 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
554 DoMmap(PROT_READ | PROT_EXEC, MAP_ANONYMOUS);
557 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
558 mmap_write_exec,
559 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
560 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
561 DoMmap(PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS);
564 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
565 mmap_read_write_exec,
566 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
567 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
568 DoMmap(PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS);
571 BPF_TEST_C(NaClNonSfiSandboxTest,
572 mprotect_allowed,
573 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
574 void* ptr = DoAllowedAnonymousMmap();
575 BPF_ASSERT_NE(MAP_FAILED, ptr);
576 BPF_ASSERT_EQ(0, mprotect(ptr, getpagesize(), PROT_READ));
577 BPF_ASSERT_EQ(0, munmap(ptr, getpagesize()));
580 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
581 mprotect_unallowed_prot,
582 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
583 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
584 // We have tested DoAllowedAnonymousMmap is allowed in
585 // mmap_allowed, so we can make sure the following mprotect call
586 // kills the process.
587 void* ptr = DoAllowedAnonymousMmap();
588 BPF_ASSERT_NE(MAP_FAILED, ptr);
589 mprotect(ptr, getpagesize(), PROT_READ | PROT_GROWSDOWN);
592 BPF_TEST_C(NaClNonSfiSandboxTest,
593 brk,
594 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
595 char* next_brk = static_cast<char*>(sbrk(0)) + getpagesize();
596 // The kernel interface must return zero for brk.
597 BPF_ASSERT_EQ(0, syscall(__NR_brk, next_brk));
598 // The libc wrapper translates it to ENOMEM.
600 // Note: PNaCl toolchain does not provide brk() system call wrapper.
601 #if !defined(OS_NACL_NONSFI)
602 errno = 0;
603 BPF_ASSERT_EQ(-1, brk(next_brk));
604 BPF_ASSERT_EQ(ENOMEM, errno);
605 #endif
608 // clockid restrictions are mostly tested in sandbox/ with the
609 // RestrictClockID() unittests. Some basic tests are duplicated here as
610 // a precaution.
612 void CheckClock(clockid_t clockid) {
613 struct timespec ts;
614 ts.tv_sec = ts.tv_nsec = -1;
615 BPF_ASSERT_EQ(0, clock_gettime(clockid, &ts));
616 BPF_ASSERT_LE(0, ts.tv_sec);
617 BPF_ASSERT_LE(0, ts.tv_nsec);
620 BPF_TEST_C(NaClNonSfiSandboxTest,
621 clock_gettime_allowed,
622 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
623 CheckClock(CLOCK_MONOTONIC);
624 CheckClock(CLOCK_PROCESS_CPUTIME_ID);
625 CheckClock(CLOCK_REALTIME);
626 CheckClock(CLOCK_THREAD_CPUTIME_ID);
629 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
630 clock_gettime_crash_monotonic_raw,
631 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
632 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
633 struct timespec ts;
634 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
637 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
638 invalid_syscall_crash,
639 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
640 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
641 sandbox::Syscall::InvalidCall();
644 // The following tests check for several restrictions in tgkill(). A delegate is
645 // needed to be able to call getpid() from inside the process that will be
646 // sandboxed, but before the sandbox is installed.
647 template<void(*callback)(int pid, int tid)>
648 class TgkillDelegate : public sandbox::BPFTesterDelegate {
649 public:
650 TgkillDelegate() {}
651 ~TgkillDelegate() override {}
653 scoped_ptr<sandbox::bpf_dsl::Policy> GetSandboxBPFPolicy() override {
654 // These two values must be obtained when running in the sandboxed process.
655 // They cannot be set in the constructor and are also not available from
656 // within |RunTestFunction|.
657 pid_ = getpid();
658 tid_ = syscall(__NR_gettid);
660 return scoped_ptr<sandbox::bpf_dsl::Policy>(
661 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy());
664 void RunTestFunction() override {
665 callback(pid_, tid_);
668 int pid_;
669 int tid_;
671 private:
672 DISALLOW_COPY_AND_ASSIGN(TgkillDelegate);
675 void BPF_TEST_D_tgkill_with_invalid_signal(int pid, int tid) {
676 syscall(__NR_tgkill, pid, tid, SIGKILL);
679 BPF_DEATH_TEST_D(NaClNonSfiSandboxTest,
680 tgkill_with_invalid_signal,
681 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
682 TgkillDelegate<BPF_TEST_D_tgkill_with_invalid_signal>);
684 void BPF_TEST_D_tgkill_with_invalid_tgid(int pid, int tid) {
685 syscall(__NR_tgkill, 1, tid, LINUX_SIGUSR1);
688 BPF_DEATH_TEST_D(NaClNonSfiSandboxTest,
689 tgkill_with_invalid_tgid,
690 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
691 TgkillDelegate<BPF_TEST_D_tgkill_with_invalid_tgid>);
693 void BPF_TEST_D_tgkill_with_negative_tgid(int pid, int tid) {
694 syscall(__NR_tgkill, pid, -1, LINUX_SIGUSR1);
697 BPF_DEATH_TEST_D(NaClNonSfiSandboxTest,
698 tgkill_with_negative_tgid,
699 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
700 TgkillDelegate<BPF_TEST_D_tgkill_with_negative_tgid>);
702 void BPF_TEST_D_tgkill_with_invalid_tid(int pid, int tid) {
703 BPF_ASSERT_EQ(-1, syscall(__NR_tgkill, pid, 1, LINUX_SIGUSR1));
704 BPF_ASSERT_EQ(ESRCH, errno);
707 BPF_TEST_D(NaClNonSfiSandboxTest,
708 tgkill_with_invalid_tid,
709 TgkillDelegate<BPF_TEST_D_tgkill_with_invalid_tid>);
711 // The following test cases check if syscalls return EPERM regardless
712 // of arguments.
713 #define RESTRICT_SYSCALL_EPERM_TEST(name) \
714 BPF_TEST_C(NaClNonSfiSandboxTest, \
715 name##_EPERM, \
716 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { \
717 errno = 0; \
718 BPF_ASSERT_EQ(-1, syscall(__NR_##name, 0, 0, 0, 0, 0, 0)); \
719 BPF_ASSERT_EQ(EPERM, errno); \
722 RESTRICT_SYSCALL_EPERM_TEST(epoll_create);
723 #if defined(__i386__) || defined(__arm__)
724 RESTRICT_SYSCALL_EPERM_TEST(getegid32);
725 RESTRICT_SYSCALL_EPERM_TEST(geteuid32);
726 RESTRICT_SYSCALL_EPERM_TEST(getgid32);
727 RESTRICT_SYSCALL_EPERM_TEST(getuid32);
728 #endif
729 RESTRICT_SYSCALL_EPERM_TEST(getegid);
730 RESTRICT_SYSCALL_EPERM_TEST(geteuid);
731 RESTRICT_SYSCALL_EPERM_TEST(getgid);
732 RESTRICT_SYSCALL_EPERM_TEST(getuid);
733 RESTRICT_SYSCALL_EPERM_TEST(madvise);
734 RESTRICT_SYSCALL_EPERM_TEST(open);
735 RESTRICT_SYSCALL_EPERM_TEST(openat);
736 RESTRICT_SYSCALL_EPERM_TEST(ptrace);
737 RESTRICT_SYSCALL_EPERM_TEST(set_robust_list);
738 #if defined(__i386__) || defined(__x86_64__)
739 RESTRICT_SYSCALL_EPERM_TEST(time);
740 #endif
742 } // namespace
744 #endif // !ADDRESS_SANITIZER && !THREAD_SANITIZER &&
745 // !MEMORY_SANITIZER && !LEAK_SANITIZER