Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf.cc

Issue 290223002: Remove SandboxBPF's dependency on CompatibilityPolicy (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Two more missing default constructors Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
6 6
7 // Some headers on Android are missing cdefs: crbug.com/172337. 7 // Some headers on Android are missing cdefs: crbug.com/172337.
8 // (We can't use OS_ANDROID here since build_config.h is not included). 8 // (We can't use OS_ANDROID here since build_config.h is not included).
9 #if defined(ANDROID) 9 #if defined(ANDROID)
10 #include <sys/cdefs.h> 10 #include <sys/cdefs.h>
11 #endif 11 #endif
12 12
13 #include <errno.h> 13 #include <errno.h>
14 #include <fcntl.h> 14 #include <fcntl.h>
15 #include <string.h> 15 #include <string.h>
16 #include <sys/prctl.h> 16 #include <sys/prctl.h>
17 #include <sys/stat.h> 17 #include <sys/stat.h>
18 #include <sys/syscall.h> 18 #include <sys/syscall.h>
19 #include <sys/types.h> 19 #include <sys/types.h>
20 #include <time.h> 20 #include <time.h>
21 #include <unistd.h> 21 #include <unistd.h>
22 22
23 #include "base/compiler_specific.h" 23 #include "base/compiler_specific.h"
24 #include "base/logging.h" 24 #include "base/logging.h"
25 #include "base/macros.h"
25 #include "base/memory/scoped_ptr.h" 26 #include "base/memory/scoped_ptr.h"
26 #include "base/posix/eintr_wrapper.h" 27 #include "base/posix/eintr_wrapper.h"
27 #include "sandbox/linux/seccomp-bpf/codegen.h" 28 #include "sandbox/linux/seccomp-bpf/codegen.h"
28 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h"
29 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" 29 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
30 #include "sandbox/linux/seccomp-bpf/syscall.h" 30 #include "sandbox/linux/seccomp-bpf/syscall.h"
31 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" 31 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
32 #include "sandbox/linux/seccomp-bpf/verifier.h" 32 #include "sandbox/linux/seccomp-bpf/verifier.h"
33 33
34 namespace sandbox { 34 namespace sandbox {
35 35
36 namespace { 36 namespace {
37 37
38 const int kExpectedExitCode = 100; 38 const int kExpectedExitCode = 100;
(...skipping 11 matching lines...) Expand all
50 "Failed to set up stderr: "; 50 "Failed to set up stderr: ";
51 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string && 51 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string &&
52 HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 && 52 HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 &&
53 HANDLE_EINTR(write(out_fd, "\n", 1))) { 53 HANDLE_EINTR(write(out_fd, "\n", 1))) {
54 } 54 }
55 } 55 }
56 #endif // !defined(NDEBUG) 56 #endif // !defined(NDEBUG)
57 57
58 // We define a really simple sandbox policy. It is just good enough for us 58 // We define a really simple sandbox policy. It is just good enough for us
59 // to tell that the sandbox has actually been activated. 59 // to tell that the sandbox has actually been activated.
60 ErrorCode ProbeEvaluator(SandboxBPF*, int sysnum, void*) __attribute__((const)); 60 class ProbePolicy : public SandboxBPFPolicy {
61 ErrorCode ProbeEvaluator(SandboxBPF*, int sysnum, void*) { 61 public:
62 switch (sysnum) { 62 ProbePolicy() {}
63 case __NR_getpid: 63 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysnum) const OVERRIDE {
64 // Return EPERM so that we can check that the filter actually ran. 64 switch (sysnum) {
65 return ErrorCode(EPERM); 65 case __NR_getpid:
66 case __NR_exit_group: 66 // Return EPERM so that we can check that the filter actually ran.
67 // Allow exit() with a non-default return code. 67 return ErrorCode(EPERM);
68 return ErrorCode(ErrorCode::ERR_ALLOWED); 68 case __NR_exit_group:
69 default: 69 // Allow exit() with a non-default return code.
70 // Make everything else fail in an easily recognizable way. 70 return ErrorCode(ErrorCode::ERR_ALLOWED);
71 return ErrorCode(EINVAL); 71 default:
72 // Make everything else fail in an easily recognizable way.
73 return ErrorCode(EINVAL);
74 }
72 } 75 }
73 } 76
77 private:
78 DISALLOW_COPY_AND_ASSIGN(ProbePolicy);
79 };
74 80
75 void ProbeProcess(void) { 81 void ProbeProcess(void) {
76 if (syscall(__NR_getpid) < 0 && errno == EPERM) { 82 if (syscall(__NR_getpid) < 0 && errno == EPERM) {
77 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); 83 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode));
78 } 84 }
79 } 85 }
80 86
81 ErrorCode AllowAllEvaluator(SandboxBPF*, int sysnum, void*) { 87 class AllowAllPolicy : public SandboxBPFPolicy {
82 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum)); 88 public:
83 return ErrorCode(ErrorCode::ERR_ALLOWED); 89 AllowAllPolicy() {}
84 } 90 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysnum) const OVERRIDE {
91 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum));
92 return ErrorCode(ErrorCode::ERR_ALLOWED);
93 }
94
95 private:
96 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy);
97 };
85 98
86 void TryVsyscallProcess(void) { 99 void TryVsyscallProcess(void) {
87 time_t current_time; 100 time_t current_time;
88 // time() is implemented as a vsyscall. With an older glibc, with 101 // time() is implemented as a vsyscall. With an older glibc, with
89 // vsyscall=emulate and some versions of the seccomp BPF patch 102 // vsyscall=emulate and some versions of the seccomp BPF patch
90 // we may get SIGKILL-ed. Detect this! 103 // we may get SIGKILL-ed. Detect this!
91 if (time(&current_time) != static_cast<time_t>(-1)) { 104 if (time(&current_time) != static_cast<time_t>(-1)) {
92 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); 105 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode));
93 } 106 }
94 } 107 }
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 if (conds_) { 245 if (conds_) {
233 delete conds_; 246 delete conds_;
234 } 247 }
235 } 248 }
236 249
237 bool SandboxBPF::IsValidSyscallNumber(int sysnum) { 250 bool SandboxBPF::IsValidSyscallNumber(int sysnum) {
238 return SyscallIterator::IsValid(sysnum); 251 return SyscallIterator::IsValid(sysnum);
239 } 252 }
240 253
241 bool SandboxBPF::RunFunctionInPolicy(void (*code_in_sandbox)(), 254 bool SandboxBPF::RunFunctionInPolicy(void (*code_in_sandbox)(),
242 EvaluateSyscall syscall_evaluator, 255 scoped_ptr<SandboxBPFPolicy> policy) {
243 void* aux) {
244 // Block all signals before forking a child process. This prevents an 256 // Block all signals before forking a child process. This prevents an
245 // attacker from manipulating our test by sending us an unexpected signal. 257 // attacker from manipulating our test by sending us an unexpected signal.
246 sigset_t old_mask, new_mask; 258 sigset_t old_mask, new_mask;
247 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) { 259 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) {
248 SANDBOX_DIE("sigprocmask() failed"); 260 SANDBOX_DIE("sigprocmask() failed");
249 } 261 }
250 int fds[2]; 262 int fds[2];
251 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) { 263 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) {
252 SANDBOX_DIE("pipe() failed"); 264 SANDBOX_DIE("pipe() failed");
253 } 265 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 } 315 }
304 if (IGNORE_EINTR(close(fds[1]))) { 316 if (IGNORE_EINTR(close(fds[1]))) {
305 // This call to close() has been failing in strange ways. See 317 // This call to close() has been failing in strange ways. See
306 // crbug.com/152530. So we only fail in debug mode now. 318 // crbug.com/152530. So we only fail in debug mode now.
307 #if !defined(NDEBUG) 319 #if !defined(NDEBUG)
308 WriteFailedStderrSetupMessage(fds[1]); 320 WriteFailedStderrSetupMessage(fds[1]);
309 SANDBOX_DIE(NULL); 321 SANDBOX_DIE(NULL);
310 #endif 322 #endif
311 } 323 }
312 324
313 SetSandboxPolicyDeprecated(syscall_evaluator, aux); 325 SetSandboxPolicy(policy.release());
314 if (!StartSandbox(PROCESS_SINGLE_THREADED)) { 326 if (!StartSandbox(PROCESS_SINGLE_THREADED)) {
315 SANDBOX_DIE(NULL); 327 SANDBOX_DIE(NULL);
316 } 328 }
317 329
318 // Run our code in the sandbox. 330 // Run our code in the sandbox.
319 code_in_sandbox(); 331 code_in_sandbox();
320 332
321 // code_in_sandbox() is not supposed to return here. 333 // code_in_sandbox() is not supposed to return here.
322 SANDBOX_DIE(NULL); 334 SANDBOX_DIE(NULL);
323 } 335 }
(...skipping 28 matching lines...) Expand all
352 } 364 }
353 } 365 }
354 if (IGNORE_EINTR(close(fds[0]))) { 366 if (IGNORE_EINTR(close(fds[0]))) {
355 SANDBOX_DIE("close() failed"); 367 SANDBOX_DIE("close() failed");
356 } 368 }
357 369
358 return rc; 370 return rc;
359 } 371 }
360 372
361 bool SandboxBPF::KernelSupportSeccompBPF() { 373 bool SandboxBPF::KernelSupportSeccompBPF() {
362 return RunFunctionInPolicy(ProbeProcess, ProbeEvaluator, 0) && 374 return RunFunctionInPolicy(ProbeProcess,
363 RunFunctionInPolicy(TryVsyscallProcess, AllowAllEvaluator, 0); 375 scoped_ptr<SandboxBPFPolicy>(new ProbePolicy())) &&
376 RunFunctionInPolicy(
377 TryVsyscallProcess,
378 scoped_ptr<SandboxBPFPolicy>(new AllowAllPolicy()));
364 } 379 }
365 380
366 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { 381 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) {
367 // It the sandbox is currently active, we clearly must have support for 382 // It the sandbox is currently active, we clearly must have support for
368 // sandboxing. 383 // sandboxing.
369 if (status_ == STATUS_ENABLED) { 384 if (status_ == STATUS_ENABLED) {
370 return status_; 385 return status_;
371 } 386 }
372 387
373 // Even if the sandbox was previously available, something might have 388 // Even if the sandbox was previously available, something might have
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 return true; 483 return true;
469 } 484 }
470 485
471 void SandboxBPF::PolicySanityChecks(SandboxBPFPolicy* policy) { 486 void SandboxBPF::PolicySanityChecks(SandboxBPFPolicy* policy) {
472 if (!IsDenied(policy->InvalidSyscall(this))) { 487 if (!IsDenied(policy->InvalidSyscall(this))) {
473 SANDBOX_DIE("Policies should deny invalid system calls."); 488 SANDBOX_DIE("Policies should deny invalid system calls.");
474 } 489 }
475 return; 490 return;
476 } 491 }
477 492
478 // Deprecated API, supported with a wrapper to the new API.
479 void SandboxBPF::SetSandboxPolicyDeprecated(EvaluateSyscall syscall_evaluator,
480 void* aux) {
481 if (sandbox_has_started_ || !conds_) {
482 SANDBOX_DIE("Cannot change policy after sandbox has started");
483 }
484 SetSandboxPolicy(new CompatibilityPolicy<void>(syscall_evaluator, aux));
485 }
486
487 // Don't take a scoped_ptr here, polymorphism make their use awkward. 493 // Don't take a scoped_ptr here, polymorphism make their use awkward.
488 void SandboxBPF::SetSandboxPolicy(SandboxBPFPolicy* policy) { 494 void SandboxBPF::SetSandboxPolicy(SandboxBPFPolicy* policy) {
489 DCHECK(!policy_); 495 DCHECK(!policy_);
490 if (sandbox_has_started_ || !conds_) { 496 if (sandbox_has_started_ || !conds_) {
491 SANDBOX_DIE("Cannot change policy after sandbox has started"); 497 SANDBOX_DIE("Cannot change policy after sandbox has started");
492 } 498 }
493 PolicySanityChecks(policy); 499 PolicySanityChecks(policy);
494 policy_.reset(policy); 500 policy_.reset(policy);
495 } 501 }
496 502
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 &*conds_->insert(failed).first); 1026 &*conds_->insert(failed).first);
1021 } 1027 }
1022 1028
1023 ErrorCode SandboxBPF::Kill(const char* msg) { 1029 ErrorCode SandboxBPF::Kill(const char* msg) {
1024 return Trap(BPFFailure, const_cast<char*>(msg)); 1030 return Trap(BPFFailure, const_cast<char*>(msg));
1025 } 1031 }
1026 1032
1027 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; 1033 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN;
1028 1034
1029 } // namespace sandbox 1035 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/sandbox_bpf.h ('k') | sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698