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 // TODO(lhchavez): Add CLONE_PARENT_SETTID unconditionally to the allowed |
88 // flags after the NaCl roll. | |
89 return If(flags == clone_flags || | |
90 flags == (clone_flags | CLONE_PARENT_SETTID), | |
91 Allow()).Else(CrashSIGSYSClone()); | |
87 } | 92 } |
88 | 93 |
89 ResultExpr RestrictFutexOperation() { | 94 ResultExpr RestrictFutexOperation() { |
90 // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes. | 95 // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes. |
91 const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; | 96 const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; |
92 const Arg<int> op(1); | 97 const Arg<int> op(1); |
93 return Switch(op & ~kAllowedFutexFlags) | 98 return Switch(op & ~kAllowedFutexFlags) |
94 .CASES((FUTEX_WAIT, | 99 .CASES((FUTEX_WAIT, |
95 FUTEX_WAKE, | 100 FUTEX_WAKE, |
96 FUTEX_REQUEUE, | 101 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; | 144 MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_FIXED; |
140 // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper | 145 // 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, | 146 // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect, |
142 // so we do not need to allow PROT_EXEC in mmap. | 147 // so we do not need to allow PROT_EXEC in mmap. |
143 const uint64_t kAllowedProtMask = PROT_READ | PROT_WRITE; | 148 const uint64_t kAllowedProtMask = PROT_READ | PROT_WRITE; |
144 const Arg<int> prot(2), flags(3); | 149 const Arg<int> prot(2), flags(3); |
145 return If((prot & ~kAllowedProtMask) == 0 && (flags & ~kAllowedFlagMask) == 0, | 150 return If((prot & ~kAllowedProtMask) == 0 && (flags & ~kAllowedFlagMask) == 0, |
146 Allow()).Else(CrashSIGSYS()); | 151 Allow()).Else(CrashSIGSYS()); |
147 } | 152 } |
148 | 153 |
154 ResultExpr RestrictTgkill() { | |
155 const Arg<int> tgid(0), tid(1), signum(2); | |
156 // Only sending SIGUSR1 to a thread in the same process is allowed. | |
157 return If(tgid == getpid() && | |
jln (very slow on Chromium)
2015/08/17 21:21:11
Don't use getpid() in policies. This should be a p
Luis Héctor Chávez
2015/08/17 22:13:07
Done.
| |
158 // Arg does not support a greater-than operator, so two separate | |
159 // checks are needed to ensure tid is positive. | |
160 tid != 0 && | |
jln (very slow on Chromium)
2015/08/17 21:21:11
FYI, this check isn't strictly necessary, Linux do
Luis Héctor Chávez
2015/08/17 22:13:07
Acknowledged.
| |
161 (tid & (1u << 31)) == 0 && // tid is non-negative. | |
162 signum == LINUX_SIGUSR1, | |
163 Allow()).Else(CrashSIGSYS()); | |
164 } | |
165 | |
149 #if !defined(OS_NACL_NONSFI) && (defined(__x86_64__) || defined(__arm__)) | 166 #if !defined(OS_NACL_NONSFI) && (defined(__x86_64__) || defined(__arm__)) |
150 ResultExpr RestrictSocketpair() { | 167 ResultExpr RestrictSocketpair() { |
151 // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen. | 168 // 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."); | 169 static_assert(AF_UNIX == PF_UNIX, "AF_UNIX must equal PF_UNIX."); |
153 const Arg<int> domain(0); | 170 const Arg<int> domain(0); |
154 return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS()); | 171 return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS()); |
155 } | 172 } |
156 #endif | 173 #endif |
157 | 174 |
158 bool IsGracefullyDenied(int sysno) { | 175 bool IsGracefullyDenied(int sysno) { |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
297 #if !defined(OS_NACL_NONSFI) | 314 #if !defined(OS_NACL_NONSFI) |
298 // nacl_helper in Non-SFI mode still uses socketpair() internally | 315 // nacl_helper in Non-SFI mode still uses socketpair() internally |
299 // via libevent. | 316 // via libevent. |
300 // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi | 317 // TODO(hidehiko): Remove this when the switching to nacl_helper_nonsfi |
301 // is completed. | 318 // is completed. |
302 case __NR_socketpair: | 319 case __NR_socketpair: |
303 return RestrictSocketpair(); | 320 return RestrictSocketpair(); |
304 #endif | 321 #endif |
305 #endif | 322 #endif |
306 | 323 |
324 case __NR_tgkill: | |
325 return RestrictTgkill(); | |
326 | |
307 case __NR_brk: | 327 case __NR_brk: |
308 // The behavior of brk on Linux is different from other system | 328 // The behavior of brk on Linux is different from other system |
309 // calls. It does not return errno but the current break on | 329 // calls. It does not return errno but the current break on |
310 // failure. glibc thinks brk failed if the return value of brk | 330 // failure. glibc thinks brk failed if the return value of brk |
311 // is less than the requested address (i.e., brk(addr) < addr). | 331 // is less than the requested address (i.e., brk(addr) < addr). |
312 // So, glibc thinks brk succeeded if we return -EPERM and we | 332 // So, glibc thinks brk succeeded if we return -EPERM and we |
313 // need to return zero instead. | 333 // need to return zero instead. |
314 return Error(0); | 334 return Error(0); |
315 | 335 |
316 default: | 336 default: |
(...skipping 13 matching lines...) Expand all Loading... | |
330 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy()), | 350 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy()), |
331 proc_fd.Pass()); | 351 proc_fd.Pass()); |
332 if (!sandbox_is_initialized) | 352 if (!sandbox_is_initialized) |
333 return false; | 353 return false; |
334 RunSandboxSanityChecks(); | 354 RunSandboxSanityChecks(); |
335 return true; | 355 return true; |
336 } | 356 } |
337 | 357 |
338 } // namespace nonsfi | 358 } // namespace nonsfi |
339 } // namespace nacl | 359 } // namespace nacl |
OLD | NEW |