Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" | 5 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <linux/net.h> | 9 #include <linux/net.h> |
| 10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
| 11 #include <sys/prctl.h> | 11 #include <sys/prctl.h> |
| 12 #include <sys/socket.h> | 12 #include <sys/socket.h> |
| 13 #include <sys/syscall.h> | 13 #include <sys/syscall.h> |
| 14 #include <sys/time.h> | 14 #include <sys/time.h> |
| 15 | 15 |
| 16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 20 #include "content/public/common/sandbox_init.h" | 20 #include "content/public/common/sandbox_init.h" |
| 21 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" | 21 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" |
| 22 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" | 22 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" |
| 23 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" | 23 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" |
| 24 #include "sandbox/linux/system_headers/linux_futex.h" | 24 #include "sandbox/linux/system_headers/linux_futex.h" |
| 25 #include "sandbox/linux/system_headers/linux_signal.h" | |
| 25 #include "sandbox/linux/system_headers/linux_syscalls.h" | 26 #include "sandbox/linux/system_headers/linux_syscalls.h" |
| 26 | 27 |
| 27 // Chrome OS Daisy (ARM) build environment and PNaCl toolchain do not define | 28 // Chrome OS Daisy (ARM) build environment and PNaCl toolchain do not define |
| 28 // MAP_STACK. | 29 // MAP_STACK. |
| 29 #if !defined(MAP_STACK) | 30 #if !defined(MAP_STACK) |
| 30 # if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) | 31 # if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) |
| 31 # define MAP_STACK 0x20000 | 32 # define MAP_STACK 0x20000 |
| 32 # else | 33 # else |
| 33 // Note that, on other architecture, MAP_STACK has different value (e.g. mips' | 34 // Note that, on other architecture, MAP_STACK has different value (e.g. mips' |
| 34 // MAP_STACK is 0x40000), though Non-SFI is not supported on such | 35 // MAP_STACK is 0x40000), though Non-SFI is not supported on such |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 | 77 |
| 77 ResultExpr RestrictClone() { | 78 ResultExpr RestrictClone() { |
| 78 // We allow clone only for new thread creation. | 79 // We allow clone only for new thread creation. |
| 79 int clone_flags = | 80 int clone_flags = |
| 80 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | | 81 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | |
| 81 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS; | 82 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS; |
| 82 #if !defined(OS_NACL_NONSFI) | 83 #if !defined(OS_NACL_NONSFI) |
| 83 clone_flags |= CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID; | 84 clone_flags |= CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID; |
| 84 #endif | 85 #endif |
| 85 const Arg<int> flags(0); | 86 const Arg<int> flags(0); |
| 86 return If(flags == clone_flags, Allow()).Else(CrashSIGSYSClone()); | 87 return If(flags == clone_flags || |
|
Mark Seaborn
2015/08/13 23:38:10
How about adding a TODO to remove the variant with
Luis Héctor Chávez
2015/08/14 00:29:32
Done.
| |
| 88 flags == (clone_flags | CLONE_PARENT_SETTID), | |
| 89 Allow()).Else(CrashSIGSYSClone()); | |
| 87 } | 90 } |
| 88 | 91 |
| 89 ResultExpr RestrictFutexOperation() { | 92 ResultExpr RestrictFutexOperation() { |
| 90 // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes. | 93 // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes. |
| 91 const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; | 94 const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; |
| 92 const Arg<int> op(1); | 95 const Arg<int> op(1); |
| 93 return Switch(op & ~kAllowedFutexFlags) | 96 return Switch(op & ~kAllowedFutexFlags) |
| 94 .CASES((FUTEX_WAIT, | 97 .CASES((FUTEX_WAIT, |
| 95 FUTEX_WAKE, | 98 FUTEX_WAKE, |
| 96 FUTEX_REQUEUE, | 99 FUTEX_REQUEUE, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_FIXED; | 142 MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_FIXED; |
| 140 // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper | 143 // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper |
| 141 // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect, | 144 // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect, |
| 142 // so we do not need to allow PROT_EXEC in mmap. | 145 // so we do not need to allow PROT_EXEC in mmap. |
| 143 const uint64_t kAllowedProtMask = PROT_READ | PROT_WRITE; | 146 const uint64_t kAllowedProtMask = PROT_READ | PROT_WRITE; |
| 144 const Arg<int> prot(2), flags(3); | 147 const Arg<int> prot(2), flags(3); |
| 145 return If((prot & ~kAllowedProtMask) == 0 && (flags & ~kAllowedFlagMask) == 0, | 148 return If((prot & ~kAllowedProtMask) == 0 && (flags & ~kAllowedFlagMask) == 0, |
| 146 Allow()).Else(CrashSIGSYS()); | 149 Allow()).Else(CrashSIGSYS()); |
| 147 } | 150 } |
| 148 | 151 |
| 152 ResultExpr RestrictTgkill() { | |
| 153 const Arg<int> tgid(0), signum(2); | |
| 154 // Only sending SIGUSR1 to a thread in the same process is allowed. | |
| 155 return If(tgid == getpid() && signum == LINUX_SIGUSR1, | |
|
Mark Seaborn
2015/08/13 23:38:10
Should we check that the thread ID is positive too
Luis Héctor Chávez
2015/08/14 00:29:32
Arg<int> does not support greater-than comparison
Mark Seaborn
2015/08/14 20:12:41
I suppose you can check that:
* arg != 0
* (arg
| |
| 156 Allow()).Else(CrashSIGSYS()); | |
| 157 } | |
| 158 | |
| 149 #if !defined(OS_NACL_NONSFI) && (defined(__x86_64__) || defined(__arm__)) | 159 #if !defined(OS_NACL_NONSFI) && (defined(__x86_64__) || defined(__arm__)) |
| 150 ResultExpr RestrictSocketpair() { | 160 ResultExpr RestrictSocketpair() { |
| 151 // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen. | 161 // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen. |
| 152 static_assert(AF_UNIX == PF_UNIX, "AF_UNIX must equal PF_UNIX."); | 162 static_assert(AF_UNIX == PF_UNIX, "AF_UNIX must equal PF_UNIX."); |
| 153 const Arg<int> domain(0); | 163 const Arg<int> domain(0); |
| 154 return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS()); | 164 return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS()); |
| 155 } | 165 } |
| 156 #endif | 166 #endif |
| 157 | 167 |
| 158 bool IsGracefullyDenied(int sysno) { | 168 bool IsGracefullyDenied(int sysno) { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 #if !defined(OS_NACL_NONSFI) | 307 #if !defined(OS_NACL_NONSFI) |
| 298 // nacl_helper in Non-SFI mode still uses socketpair() internally | 308 // nacl_helper in Non-SFI mode still uses socketpair() internally |
| 299 // via libevent. | 309 // via libevent. |
| 300 // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi | 310 // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi |
| 301 // is completed. | 311 // is completed. |
| 302 case __NR_socketpair: | 312 case __NR_socketpair: |
| 303 return RestrictSocketpair(); | 313 return RestrictSocketpair(); |
| 304 #endif | 314 #endif |
| 305 #endif | 315 #endif |
| 306 | 316 |
| 317 case __NR_tgkill: | |
| 318 return RestrictTgkill(); | |
| 319 | |
| 307 case __NR_brk: | 320 case __NR_brk: |
| 308 // The behavior of brk on Linux is different from other system | 321 // The behavior of brk on Linux is different from other system |
| 309 // calls. It does not return errno but the current break on | 322 // calls. It does not return errno but the current break on |
| 310 // failure. glibc thinks brk failed if the return value of brk | 323 // failure. glibc thinks brk failed if the return value of brk |
| 311 // is less than the requested address (i.e., brk(addr) < addr). | 324 // is less than the requested address (i.e., brk(addr) < addr). |
| 312 // So, glibc thinks brk succeeded if we return -EPERM and we | 325 // So, glibc thinks brk succeeded if we return -EPERM and we |
| 313 // need to return zero instead. | 326 // need to return zero instead. |
| 314 return Error(0); | 327 return Error(0); |
| 315 | 328 |
| 316 default: | 329 default: |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 330 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy()), | 343 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy()), |
| 331 proc_fd.Pass()); | 344 proc_fd.Pass()); |
| 332 if (!sandbox_is_initialized) | 345 if (!sandbox_is_initialized) |
| 333 return false; | 346 return false; |
| 334 RunSandboxSanityChecks(); | 347 RunSandboxSanityChecks(); |
| 335 return true; | 348 return true; |
| 336 } | 349 } |
| 337 | 350 |
| 338 } // namespace nonsfi | 351 } // namespace nonsfi |
| 339 } // namespace nacl | 352 } // namespace nacl |
| OLD | NEW |