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"
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>
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
43 void DoPipe(base::ScopedFD
* fds
) {
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
) {
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
,
69 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
70 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
74 const int kExpectedValue
= 123;
76 void* SetValueInThread(void* test_val_ptr
) {
77 *reinterpret_cast<int*>(test_val_ptr
) = kExpectedValue
;
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.
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
);
95 // Call clone() to do a fork().
96 const int pid
= syscall(__NR_clone
, SIGCHLD
, NULL
);
102 // The sanity check for DoFork without the sandbox.
103 TEST(NaClNonSfiSandboxTest
, DoFork
) {
104 const int pid
= DoFork();
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
,
115 DEATH_MESSAGE(sandbox::GetCloneErrorMessageContentForTests()),
116 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
120 BPF_TEST_C(NaClNonSfiSandboxTest
,
122 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
124 BPF_ASSERT_EQ(-1, syscall(__NR_prctl
, PR_SET_NAME
, "foo"));
125 BPF_ASSERT_EQ(EPERM
, errno
);
128 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
130 DEATH_MESSAGE(sandbox::GetPrctlErrorMessageContentForTests()),
131 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
132 syscall(__NR_prctl
, PR_SET_DUMPABLE
, 1UL);
135 BPF_TEST_C(NaClNonSfiSandboxTest
,
137 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
138 base::ScopedFD fds
[2];
139 struct msghdr msg
= {};
141 std::string
payload("foo");
142 iov
.iov_base
= &payload
[0];
143 iov
.iov_len
= payload
.size();
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
,
156 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
157 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
158 accept(0, NULL
, NULL
);
161 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
163 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
164 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
168 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
170 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
171 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
175 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
177 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
178 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
179 getpeername(0, NULL
, NULL
);
182 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
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
,
193 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
194 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
195 getsockopt(0, 0, 0, NULL
, NULL
);
198 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
200 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
201 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
205 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
207 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
208 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
212 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
214 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
215 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
216 recvfrom(0, NULL
, 0, 0, NULL
, NULL
);
219 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
221 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
222 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
226 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
228 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
229 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
230 sendto(0, NULL
, 0, 0, NULL
, 0);
233 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
235 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
236 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
237 setsockopt(0, 0, 0, NULL
, 0);
240 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
242 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
243 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
247 #if defined(__x86_64__) || defined(__arm__)
248 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
250 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
251 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
253 socketpair(AF_INET
, SOCK_STREAM
, 0, fds
);
257 BPF_TEST_C(NaClNonSfiSandboxTest
,
259 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
260 base::ScopedFD fds
[2];
262 BPF_ASSERT_EQ(0, fcntl(fds
[0].get(), F_SETFD
, FD_CLOEXEC
));
265 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
267 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
268 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
269 base::ScopedFD fds
[2];
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];
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
,
287 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
288 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
289 base::ScopedFD fds
[2];
291 fcntl(fds
[0].get(), F_SETFL
, O_APPEND
);
294 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
296 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
297 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
301 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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.
395 BPF_ASSERT_EQ(-1, brk(next_brk
));
396 BPF_ASSERT_EQ(ENOMEM
, errno
);
399 void CheckClock(clockid_t clockid
) {
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
) {
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
429 class ClockSystemTesterDelegate
: public sandbox::BPFTesterDelegate
{
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
);
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
);
453 const bool is_running_on_chromeos_
;
454 DISALLOW_COPY_AND_ASSIGN(ClockSystemTesterDelegate
);
457 BPF_TEST_D(BPFTest
, BPFTestWithDelegateClass
, ClockSystemTesterDelegate
);
461 BPF_DEATH_TEST_C(NaClNonSfiSandboxTest
,
462 clock_gettime_crash_system_trace
,
463 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
464 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy
) {
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
);
482 clock_gettime(kInitCPUClockID
, &ts
);
485 // The following test cases check if syscalls return EPERM regardless
487 #define RESTRICT_SYSCALL_EPERM_TEST(name) \
488 BPF_TEST_C(NaClNonSfiSandboxTest, \
490 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { \
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
);
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
);
517 #endif // !ADDRESS_SANITIZER && !THREAD_SANITIZER