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

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

Issue 293993006: Revert of Remove SandboxBPF's dependency on CompatibilityPolicy (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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"
26 #include "base/memory/scoped_ptr.h" 25 #include "base/memory/scoped_ptr.h"
27 #include "base/posix/eintr_wrapper.h" 26 #include "base/posix/eintr_wrapper.h"
28 #include "sandbox/linux/seccomp-bpf/codegen.h" 27 #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 class ProbePolicy : public SandboxBPFPolicy { 60 ErrorCode ProbeEvaluator(SandboxBPF*, int sysnum, void*) __attribute__((const));
61 public: 61 ErrorCode ProbeEvaluator(SandboxBPF*, int sysnum, void*) {
62 ProbePolicy() {} 62 switch (sysnum) {
63 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysnum) const OVERRIDE { 63 case __NR_getpid:
64 switch (sysnum) { 64 // Return EPERM so that we can check that the filter actually ran.
65 case __NR_getpid: 65 return ErrorCode(EPERM);
66 // Return EPERM so that we can check that the filter actually ran. 66 case __NR_exit_group:
67 return ErrorCode(EPERM); 67 // Allow exit() with a non-default return code.
68 case __NR_exit_group: 68 return ErrorCode(ErrorCode::ERR_ALLOWED);
69 // Allow exit() with a non-default return code. 69 default:
70 return ErrorCode(ErrorCode::ERR_ALLOWED); 70 // Make everything else fail in an easily recognizable way.
71 default: 71 return ErrorCode(EINVAL);
72 // Make everything else fail in an easily recognizable way.
73 return ErrorCode(EINVAL);
74 }
75 } 72 }
76 73 }
77 private:
78 DISALLOW_COPY_AND_ASSIGN(ProbePolicy);
79 };
80 74
81 void ProbeProcess(void) { 75 void ProbeProcess(void) {
82 if (syscall(__NR_getpid) < 0 && errno == EPERM) { 76 if (syscall(__NR_getpid) < 0 && errno == EPERM) {
83 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); 77 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode));
84 } 78 }
85 } 79 }
86 80
87 class AllowAllPolicy : public SandboxBPFPolicy { 81 ErrorCode AllowAllEvaluator(SandboxBPF*, int sysnum, void*) {
88 public: 82 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum));
89 AllowAllPolicy() {} 83 return ErrorCode(ErrorCode::ERR_ALLOWED);
90 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysnum) const OVERRIDE { 84 }
91 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum));
92 return ErrorCode(ErrorCode::ERR_ALLOWED);
93 }
94
95 private:
96 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy);
97 };
98 85
99 void TryVsyscallProcess(void) { 86 void TryVsyscallProcess(void) {
100 time_t current_time; 87 time_t current_time;
101 // time() is implemented as a vsyscall. With an older glibc, with 88 // time() is implemented as a vsyscall. With an older glibc, with
102 // vsyscall=emulate and some versions of the seccomp BPF patch 89 // vsyscall=emulate and some versions of the seccomp BPF patch
103 // we may get SIGKILL-ed. Detect this! 90 // we may get SIGKILL-ed. Detect this!
104 if (time(&current_time) != static_cast<time_t>(-1)) { 91 if (time(&current_time) != static_cast<time_t>(-1)) {
105 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); 92 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode));
106 } 93 }
107 } 94 }
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 if (conds_) { 232 if (conds_) {
246 delete conds_; 233 delete conds_;
247 } 234 }
248 } 235 }
249 236
250 bool SandboxBPF::IsValidSyscallNumber(int sysnum) { 237 bool SandboxBPF::IsValidSyscallNumber(int sysnum) {
251 return SyscallIterator::IsValid(sysnum); 238 return SyscallIterator::IsValid(sysnum);
252 } 239 }
253 240
254 bool SandboxBPF::RunFunctionInPolicy(void (*code_in_sandbox)(), 241 bool SandboxBPF::RunFunctionInPolicy(void (*code_in_sandbox)(),
255 scoped_ptr<SandboxBPFPolicy> policy) { 242 EvaluateSyscall syscall_evaluator,
243 void* aux) {
256 // Block all signals before forking a child process. This prevents an 244 // Block all signals before forking a child process. This prevents an
257 // attacker from manipulating our test by sending us an unexpected signal. 245 // attacker from manipulating our test by sending us an unexpected signal.
258 sigset_t old_mask, new_mask; 246 sigset_t old_mask, new_mask;
259 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) { 247 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) {
260 SANDBOX_DIE("sigprocmask() failed"); 248 SANDBOX_DIE("sigprocmask() failed");
261 } 249 }
262 int fds[2]; 250 int fds[2];
263 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) { 251 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) {
264 SANDBOX_DIE("pipe() failed"); 252 SANDBOX_DIE("pipe() failed");
265 } 253 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 } 303 }
316 if (IGNORE_EINTR(close(fds[1]))) { 304 if (IGNORE_EINTR(close(fds[1]))) {
317 // This call to close() has been failing in strange ways. See 305 // This call to close() has been failing in strange ways. See
318 // crbug.com/152530. So we only fail in debug mode now. 306 // crbug.com/152530. So we only fail in debug mode now.
319 #if !defined(NDEBUG) 307 #if !defined(NDEBUG)
320 WriteFailedStderrSetupMessage(fds[1]); 308 WriteFailedStderrSetupMessage(fds[1]);
321 SANDBOX_DIE(NULL); 309 SANDBOX_DIE(NULL);
322 #endif 310 #endif
323 } 311 }
324 312
325 SetSandboxPolicy(policy.release()); 313 SetSandboxPolicyDeprecated(syscall_evaluator, aux);
326 if (!StartSandbox(PROCESS_SINGLE_THREADED)) { 314 if (!StartSandbox(PROCESS_SINGLE_THREADED)) {
327 SANDBOX_DIE(NULL); 315 SANDBOX_DIE(NULL);
328 } 316 }
329 317
330 // Run our code in the sandbox. 318 // Run our code in the sandbox.
331 code_in_sandbox(); 319 code_in_sandbox();
332 320
333 // code_in_sandbox() is not supposed to return here. 321 // code_in_sandbox() is not supposed to return here.
334 SANDBOX_DIE(NULL); 322 SANDBOX_DIE(NULL);
335 } 323 }
(...skipping 28 matching lines...) Expand all
364 } 352 }
365 } 353 }
366 if (IGNORE_EINTR(close(fds[0]))) { 354 if (IGNORE_EINTR(close(fds[0]))) {
367 SANDBOX_DIE("close() failed"); 355 SANDBOX_DIE("close() failed");
368 } 356 }
369 357
370 return rc; 358 return rc;
371 } 359 }
372 360
373 bool SandboxBPF::KernelSupportSeccompBPF() { 361 bool SandboxBPF::KernelSupportSeccompBPF() {
374 return RunFunctionInPolicy(ProbeProcess, 362 return RunFunctionInPolicy(ProbeProcess, ProbeEvaluator, 0) &&
375 scoped_ptr<SandboxBPFPolicy>(new ProbePolicy())) && 363 RunFunctionInPolicy(TryVsyscallProcess, AllowAllEvaluator, 0);
376 RunFunctionInPolicy(
377 TryVsyscallProcess,
378 scoped_ptr<SandboxBPFPolicy>(new AllowAllPolicy()));
379 } 364 }
380 365
381 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { 366 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) {
382 // It the sandbox is currently active, we clearly must have support for 367 // It the sandbox is currently active, we clearly must have support for
383 // sandboxing. 368 // sandboxing.
384 if (status_ == STATUS_ENABLED) { 369 if (status_ == STATUS_ENABLED) {
385 return status_; 370 return status_;
386 } 371 }
387 372
388 // Even if the sandbox was previously available, something might have 373 // Even if the sandbox was previously available, something might have
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 return true; 468 return true;
484 } 469 }
485 470
486 void SandboxBPF::PolicySanityChecks(SandboxBPFPolicy* policy) { 471 void SandboxBPF::PolicySanityChecks(SandboxBPFPolicy* policy) {
487 if (!IsDenied(policy->InvalidSyscall(this))) { 472 if (!IsDenied(policy->InvalidSyscall(this))) {
488 SANDBOX_DIE("Policies should deny invalid system calls."); 473 SANDBOX_DIE("Policies should deny invalid system calls.");
489 } 474 }
490 return; 475 return;
491 } 476 }
492 477
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
493 // Don't take a scoped_ptr here, polymorphism make their use awkward. 487 // Don't take a scoped_ptr here, polymorphism make their use awkward.
494 void SandboxBPF::SetSandboxPolicy(SandboxBPFPolicy* policy) { 488 void SandboxBPF::SetSandboxPolicy(SandboxBPFPolicy* policy) {
495 DCHECK(!policy_); 489 DCHECK(!policy_);
496 if (sandbox_has_started_ || !conds_) { 490 if (sandbox_has_started_ || !conds_) {
497 SANDBOX_DIE("Cannot change policy after sandbox has started"); 491 SANDBOX_DIE("Cannot change policy after sandbox has started");
498 } 492 }
499 PolicySanityChecks(policy); 493 PolicySanityChecks(policy);
500 policy_.reset(policy); 494 policy_.reset(policy);
501 } 495 }
502 496
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 &*conds_->insert(failed).first); 1020 &*conds_->insert(failed).first);
1027 } 1021 }
1028 1022
1029 ErrorCode SandboxBPF::Kill(const char* msg) { 1023 ErrorCode SandboxBPF::Kill(const char* msg) {
1030 return Trap(BPFFailure, const_cast<char*>(msg)); 1024 return Trap(BPFFailure, const_cast<char*>(msg));
1031 } 1025 }
1032 1026
1033 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; 1027 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN;
1034 1028
1035 } // namespace sandbox 1029 } // 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