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 |