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. 4 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) 8 9#include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" 10 11#include <errno.h> 12#include <fcntl.h> 13#include <linux/futex.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/ptrace.h> 22#include <sys/socket.h> 23#include <sys/syscall.h> 24#include <sys/types.h> 25#include <sys/wait.h> 26#include <time.h> 27#include <unistd.h> 28 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/services/linux_syscalls.h" 43#include "third_party/lss/linux_syscall_support.h" // for MAKE_PROCESS_CPUCLOCK 44 45namespace { 46 47void DoPipe(base::ScopedFD* fds) { 48 int tmp_fds[2]; 49 BPF_ASSERT_EQ(0, pipe(tmp_fds)); 50 fds[0].reset(tmp_fds[0]); 51 fds[1].reset(tmp_fds[1]); 52} 53 54void DoSocketpair(base::ScopedFD* fds) { 55 int tmp_fds[2]; 56 BPF_ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, tmp_fds)); 57 fds[0].reset(tmp_fds[0]); 58 fds[1].reset(tmp_fds[1]); 59} 60 61TEST(NaClNonSfiSandboxTest, BPFIsSupported) { 62 bool seccomp_bpf_supported = ( 63 sandbox::SandboxBPF::SupportsSeccompSandbox(-1) == 64 sandbox::SandboxBPF::STATUS_AVAILABLE); 65 if (!seccomp_bpf_supported) { 66 LOG(ERROR) << "Seccomp BPF is not supported, these tests " 67 << "will pass without running"; 68 } 69} 70 71BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 72 invalid_sysno, 73 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 74 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 75 syscall(999); 76} 77 78const int kExpectedValue = 123; 79 80void* SetValueInThread(void* test_val_ptr) { 81 *reinterpret_cast<int*>(test_val_ptr) = kExpectedValue; 82 return NULL; 83} 84 85// To make this test pass, we need to allow sched_getaffinity and 86// mmap. We just disable this test not to complicate the sandbox. 87BPF_TEST_C(NaClNonSfiSandboxTest, 88 clone_by_pthread_create, 89 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 90 // clone call for thread creation is allowed. 91 pthread_t th; 92 int test_val = 42; 93 BPF_ASSERT_EQ(0, pthread_create(&th, NULL, &SetValueInThread, &test_val)); 94 BPF_ASSERT_EQ(0, pthread_join(th, NULL)); 95 BPF_ASSERT_EQ(kExpectedValue, test_val); 96} 97 98int DoFork() { 99 // Call clone() to do a fork(). 100 const int pid = syscall(__NR_clone, SIGCHLD, NULL); 101 if (pid == 0) 102 _exit(0); 103 return pid; 104} 105 106// The sanity check for DoFork without the sandbox. 107TEST(NaClNonSfiSandboxTest, DoFork) { 108 const int pid = DoFork(); 109 ASSERT_LT(0, pid); 110 int status; 111 ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0))); 112 ASSERT_TRUE(WIFEXITED(status)); 113 ASSERT_EQ(0, WEXITSTATUS(status)); 114} 115 116// Then, try this in the sandbox. 117BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 118 clone_for_fork, 119 DEATH_MESSAGE(sandbox::GetCloneErrorMessageContentForTests()), 120 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 121 DoFork(); 122} 123 124BPF_TEST_C(NaClNonSfiSandboxTest, 125 prctl_SET_NAME, 126 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 127 errno = 0; 128 BPF_ASSERT_EQ(-1, syscall(__NR_prctl, PR_SET_NAME, "foo")); 129 BPF_ASSERT_EQ(EPERM, errno); 130} 131 132BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 133 prctl_SET_DUMPABLE, 134 DEATH_MESSAGE(sandbox::GetPrctlErrorMessageContentForTests()), 135 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 136 syscall(__NR_prctl, PR_SET_DUMPABLE, 1UL); 137} 138 139BPF_TEST_C(NaClNonSfiSandboxTest, 140 socketcall_allowed, 141 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 142 base::ScopedFD fds[2]; 143 struct msghdr msg = {}; 144 struct iovec iov; 145 std::string payload("foo"); 146 iov.iov_base = &payload[0]; 147 iov.iov_len = payload.size(); 148 msg.msg_iov = &iov; 149 msg.msg_iovlen = 1; 150 DoSocketpair(fds); 151 BPF_ASSERT_EQ(static_cast<int>(payload.size()), 152 HANDLE_EINTR(sendmsg(fds[1].get(), &msg, 0))); 153 BPF_ASSERT_EQ(static_cast<int>(payload.size()), 154 HANDLE_EINTR(recvmsg(fds[0].get(), &msg, 0))); 155 BPF_ASSERT_EQ(0, shutdown(fds[0].get(), SHUT_RDWR)); 156} 157 158BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 159 accept, 160 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 161 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 162 accept(0, NULL, NULL); 163} 164 165BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 166 bind, 167 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 168 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 169 bind(0, NULL, 0); 170} 171 172BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 173 connect, 174 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 175 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 176 connect(0, NULL, 0); 177} 178 179BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 180 getpeername, 181 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 182 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 183 getpeername(0, NULL, NULL); 184} 185 186BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 187 getsockname, 188 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 189 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 190 struct sockaddr addr; 191 socklen_t addrlen = 0; 192 getsockname(0, &addr, &addrlen); 193} 194 195BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 196 getsockopt, 197 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 198 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 199 getsockopt(0, 0, 0, NULL, NULL); 200} 201 202BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 203 listen, 204 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 205 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 206 listen(0, 0); 207} 208 209BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 210 recv, 211 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 212 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 213 recv(0, NULL, 0, 0); 214} 215 216BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 217 recvfrom, 218 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 219 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 220 recvfrom(0, NULL, 0, 0, NULL, NULL); 221} 222 223BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 224 send, 225 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 226 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 227 send(0, NULL, 0, 0); 228} 229 230BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 231 sendto, 232 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 233 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 234 sendto(0, NULL, 0, 0, NULL, 0); 235} 236 237BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 238 setsockopt, 239 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 240 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 241 setsockopt(0, 0, 0, NULL, 0); 242} 243 244BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 245 socket, 246 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 247 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 248 socket(0, 0, 0); 249} 250 251#if defined(__x86_64__) || defined(__arm__) 252BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 253 socketpair, 254 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 255 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 256 int fds[2]; 257 socketpair(AF_INET, SOCK_STREAM, 0, fds); 258} 259#endif 260 261BPF_TEST_C(NaClNonSfiSandboxTest, 262 fcntl_SETFD_allowed, 263 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 264 base::ScopedFD fds[2]; 265 DoSocketpair(fds); 266 BPF_ASSERT_EQ(0, fcntl(fds[0].get(), F_SETFD, FD_CLOEXEC)); 267} 268 269BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 270 fcntl_SETFD, 271 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 272 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 273 base::ScopedFD fds[2]; 274 DoSocketpair(fds); 275 fcntl(fds[0].get(), F_SETFD, 99); 276} 277 278BPF_TEST_C(NaClNonSfiSandboxTest, 279 fcntl_GETFL_SETFL_allowed, 280 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 281 base::ScopedFD fds[2]; 282 DoPipe(fds); 283 const int fd = fds[0].get(); 284 BPF_ASSERT_EQ(0, fcntl(fd, F_GETFL)); 285 BPF_ASSERT_EQ(0, fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK)); 286 BPF_ASSERT_EQ(O_NONBLOCK, fcntl(fd, F_GETFL)); 287} 288 289BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 290 fcntl_GETFL_SETFL, 291 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 292 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 293 base::ScopedFD fds[2]; 294 DoSocketpair(fds); 295 fcntl(fds[0].get(), F_SETFL, O_APPEND); 296} 297 298BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 299 fcntl_DUPFD, 300 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 301 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 302 fcntl(0, F_DUPFD); 303} 304 305BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 306 fcntl_DUPFD_CLOEXEC, 307 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 308 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 309 fcntl(0, F_DUPFD_CLOEXEC); 310} 311 312BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 313 FutexWithRequeuePriorityInheritence, 314 DEATH_MESSAGE(sandbox::GetFutexErrorMessageContentForTests()), 315 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 316 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0); 317 _exit(1); 318} 319 320BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 321 FutexWithRequeuePriorityInheritencePrivate, 322 DEATH_MESSAGE(sandbox::GetFutexErrorMessageContentForTests()), 323 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 324 syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0); 325 _exit(1); 326} 327 328BPF_TEST_C(NaClNonSfiSandboxTest, 329 StartingAndJoiningThreadWorks, 330 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 331 base::Thread thread("sandbox_tests"); 332 BPF_ASSERT(thread.Start()); 333 // |thread|'s destructor will join the thread. 334} 335 336BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 337 FutexWithUnlockPIPrivate, 338 DEATH_MESSAGE(sandbox::GetFutexErrorMessageContentForTests()), 339 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 340 syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); 341 _exit(1); 342} 343 344void* DoAllowedAnonymousMmap() { 345 return mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, 346 MAP_ANONYMOUS | MAP_SHARED, -1, 0); 347} 348 349BPF_TEST_C(NaClNonSfiSandboxTest, 350 mmap_allowed, 351 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 352 void* ptr = DoAllowedAnonymousMmap(); 353 BPF_ASSERT_NE(MAP_FAILED, ptr); 354 BPF_ASSERT_EQ(0, munmap(ptr, getpagesize())); 355} 356 357BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 358 mmap_unallowed_flag, 359 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 360 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 361 mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, 362 MAP_ANONYMOUS | MAP_POPULATE, -1, 0); 363} 364 365BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 366 mmap_unallowed_prot, 367 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 368 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 369 mmap(NULL, getpagesize(), PROT_READ | PROT_GROWSDOWN, 370 MAP_ANONYMOUS, -1, 0); 371} 372 373BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 374 mmap_exec, 375 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 376 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 377 mmap(NULL, getpagesize(), PROT_EXEC, MAP_ANONYMOUS, -1, 0); 378} 379 380BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 381 mmap_read_exec, 382 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 383 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 384 mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_ANONYMOUS, -1, 0); 385} 386 387BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 388 mmap_write_exec, 389 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 390 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 391 mmap(NULL, getpagesize(), PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS, -1, 0); 392} 393 394BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 395 mmap_read_write_exec, 396 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 397 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 398 mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, 399 MAP_ANONYMOUS, -1, 0); 400} 401 402BPF_TEST_C(NaClNonSfiSandboxTest, 403 mprotect_allowed, 404 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 405 void* ptr = DoAllowedAnonymousMmap(); 406 BPF_ASSERT_NE(MAP_FAILED, ptr); 407 BPF_ASSERT_EQ(0, mprotect(ptr, getpagesize(), PROT_READ)); 408 BPF_ASSERT_EQ(0, munmap(ptr, getpagesize())); 409} 410 411BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 412 mprotect_unallowed_prot, 413 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 414 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 415 // We have tested DoAllowedAnonymousMmap is allowed in 416 // mmap_allowed, so we can make sure the following mprotect call 417 // kills the process. 418 void* ptr = DoAllowedAnonymousMmap(); 419 BPF_ASSERT_NE(MAP_FAILED, ptr); 420 mprotect(ptr, getpagesize(), PROT_READ | PROT_GROWSDOWN); 421} 422 423BPF_TEST_C(NaClNonSfiSandboxTest, 424 brk, 425 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 426 char* next_brk = static_cast<char*>(sbrk(0)) + getpagesize(); 427 // The kernel interface must return zero for brk. 428 BPF_ASSERT_EQ(0, syscall(__NR_brk, next_brk)); 429 // The libc wrapper translates it to ENOMEM. 430 errno = 0; 431 BPF_ASSERT_EQ(-1, brk(next_brk)); 432 BPF_ASSERT_EQ(ENOMEM, errno); 433} 434 435// clockid restrictions are mostly tested in sandbox/ with the 436// RestrictClockID() unittests. Some basic tests are duplicated here as 437// a precaution. 438 439void CheckClock(clockid_t clockid) { 440 struct timespec ts; 441 ts.tv_sec = ts.tv_nsec = -1; 442 BPF_ASSERT_EQ(0, clock_gettime(clockid, &ts)); 443 BPF_ASSERT_LE(0, ts.tv_sec); 444 BPF_ASSERT_LE(0, ts.tv_nsec); 445} 446 447BPF_TEST_C(NaClNonSfiSandboxTest, 448 clock_gettime_allowed, 449 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 450 CheckClock(CLOCK_MONOTONIC); 451 CheckClock(CLOCK_PROCESS_CPUTIME_ID); 452 CheckClock(CLOCK_REALTIME); 453 CheckClock(CLOCK_THREAD_CPUTIME_ID); 454} 455 456BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 457 clock_gettime_crash_monotonic_raw, 458 DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), 459 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 460 struct timespec ts; 461 clock_gettime(CLOCK_MONOTONIC_RAW, &ts); 462} 463 464BPF_DEATH_TEST_C(NaClNonSfiSandboxTest, 465 invalid_syscall_crash, 466 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()), 467 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { 468 sandbox::Syscall::InvalidCall(); 469} 470 471// The following test cases check if syscalls return EPERM regardless 472// of arguments. 473#define RESTRICT_SYSCALL_EPERM_TEST(name) \ 474 BPF_TEST_C(NaClNonSfiSandboxTest, \ 475 name##_EPERM, \ 476 nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) { \ 477 errno = 0; \ 478 BPF_ASSERT_EQ(-1, syscall(__NR_##name, 0, 0, 0, 0, 0, 0)); \ 479 BPF_ASSERT_EQ(EPERM, errno); \ 480 } 481 482RESTRICT_SYSCALL_EPERM_TEST(epoll_create); 483#if defined(__i386__) || defined(__arm__) 484RESTRICT_SYSCALL_EPERM_TEST(getegid32); 485RESTRICT_SYSCALL_EPERM_TEST(geteuid32); 486RESTRICT_SYSCALL_EPERM_TEST(getgid32); 487RESTRICT_SYSCALL_EPERM_TEST(getuid32); 488#endif 489RESTRICT_SYSCALL_EPERM_TEST(getegid); 490RESTRICT_SYSCALL_EPERM_TEST(geteuid); 491RESTRICT_SYSCALL_EPERM_TEST(getgid); 492RESTRICT_SYSCALL_EPERM_TEST(getuid); 493RESTRICT_SYSCALL_EPERM_TEST(madvise); 494RESTRICT_SYSCALL_EPERM_TEST(open); 495RESTRICT_SYSCALL_EPERM_TEST(openat); 496RESTRICT_SYSCALL_EPERM_TEST(ptrace); 497RESTRICT_SYSCALL_EPERM_TEST(set_robust_list); 498#if defined(__i386__) || defined(__x86_64__) 499RESTRICT_SYSCALL_EPERM_TEST(time); 500#endif 501 502} // namespace 503 504#endif // !ADDRESS_SANITIZER && !THREAD_SANITIZER && 505 // !MEMORY_SANITIZER && !LEAK_SANITIZER 506