| OLD | NEW |
| 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> |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include <sys/wait.h> | 22 #include <sys/wait.h> |
| 23 #include <time.h> | 23 #include <time.h> |
| 24 #include <unistd.h> | 24 #include <unistd.h> |
| 25 | 25 |
| 26 #include "base/compiler_specific.h" | 26 #include "base/compiler_specific.h" |
| 27 #include "base/logging.h" | 27 #include "base/logging.h" |
| 28 #include "base/macros.h" | 28 #include "base/macros.h" |
| 29 #include "base/memory/scoped_ptr.h" | 29 #include "base/memory/scoped_ptr.h" |
| 30 #include "base/posix/eintr_wrapper.h" | 30 #include "base/posix/eintr_wrapper.h" |
| 31 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" | 31 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" |
| 32 #include "sandbox/linux/bpf_dsl/policy.h" |
| 32 #include "sandbox/linux/bpf_dsl/policy_compiler.h" | 33 #include "sandbox/linux/bpf_dsl/policy_compiler.h" |
| 33 #include "sandbox/linux/seccomp-bpf/codegen.h" | 34 #include "sandbox/linux/seccomp-bpf/codegen.h" |
| 34 #include "sandbox/linux/seccomp-bpf/die.h" | 35 #include "sandbox/linux/seccomp-bpf/die.h" |
| 35 #include "sandbox/linux/seccomp-bpf/errorcode.h" | 36 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
| 36 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" | 37 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" |
| 37 #include "sandbox/linux/seccomp-bpf/syscall.h" | 38 #include "sandbox/linux/seccomp-bpf/syscall.h" |
| 38 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" | 39 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" |
| 39 #include "sandbox/linux/seccomp-bpf/trap.h" | 40 #include "sandbox/linux/seccomp-bpf/trap.h" |
| 40 #include "sandbox/linux/seccomp-bpf/verifier.h" | 41 #include "sandbox/linux/seccomp-bpf/verifier.h" |
| 41 #include "sandbox/linux/services/linux_syscalls.h" | 42 #include "sandbox/linux/services/linux_syscalls.h" |
| 42 | 43 |
| 43 using sandbox::bpf_dsl::Allow; | 44 using sandbox::bpf_dsl::Allow; |
| 44 using sandbox::bpf_dsl::Error; | 45 using sandbox::bpf_dsl::Error; |
| 45 using sandbox::bpf_dsl::ResultExpr; | 46 using sandbox::bpf_dsl::ResultExpr; |
| 46 using sandbox::bpf_dsl::SandboxBPFDSLPolicy; | |
| 47 | 47 |
| 48 namespace sandbox { | 48 namespace sandbox { |
| 49 | 49 |
| 50 namespace { | 50 namespace { |
| 51 | 51 |
| 52 const int kExpectedExitCode = 100; | 52 const int kExpectedExitCode = 100; |
| 53 | 53 |
| 54 #if !defined(NDEBUG) | 54 #if !defined(NDEBUG) |
| 55 void WriteFailedStderrSetupMessage(int out_fd) { | 55 void WriteFailedStderrSetupMessage(int out_fd) { |
| 56 const char* error_string = strerror(errno); | 56 const char* error_string = strerror(errno); |
| 57 static const char msg[] = | 57 static const char msg[] = |
| 58 "You have reproduced a puzzling issue.\n" | 58 "You have reproduced a puzzling issue.\n" |
| 59 "Please, report to crbug.com/152530!\n" | 59 "Please, report to crbug.com/152530!\n" |
| 60 "Failed to set up stderr: "; | 60 "Failed to set up stderr: "; |
| 61 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string && | 61 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string && |
| 62 HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 && | 62 HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 && |
| 63 HANDLE_EINTR(write(out_fd, "\n", 1))) { | 63 HANDLE_EINTR(write(out_fd, "\n", 1))) { |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 #endif // !defined(NDEBUG) | 66 #endif // !defined(NDEBUG) |
| 67 | 67 |
| 68 // We define a really simple sandbox policy. It is just good enough for us | 68 // We define a really simple sandbox policy. It is just good enough for us |
| 69 // to tell that the sandbox has actually been activated. | 69 // to tell that the sandbox has actually been activated. |
| 70 class ProbePolicy : public SandboxBPFDSLPolicy { | 70 class ProbePolicy : public bpf_dsl::Policy { |
| 71 public: | 71 public: |
| 72 ProbePolicy() {} | 72 ProbePolicy() {} |
| 73 virtual ~ProbePolicy() {} | 73 virtual ~ProbePolicy() {} |
| 74 | 74 |
| 75 virtual ResultExpr EvaluateSyscall(int sysnum) const override { | 75 virtual ResultExpr EvaluateSyscall(int sysnum) const override { |
| 76 switch (sysnum) { | 76 switch (sysnum) { |
| 77 case __NR_getpid: | 77 case __NR_getpid: |
| 78 // Return EPERM so that we can check that the filter actually ran. | 78 // Return EPERM so that we can check that the filter actually ran. |
| 79 return Error(EPERM); | 79 return Error(EPERM); |
| 80 case __NR_exit_group: | 80 case __NR_exit_group: |
| 81 // Allow exit() with a non-default return code. | 81 // Allow exit() with a non-default return code. |
| 82 return Allow(); | 82 return Allow(); |
| 83 default: | 83 default: |
| 84 // Make everything else fail in an easily recognizable way. | 84 // Make everything else fail in an easily recognizable way. |
| 85 return Error(EINVAL); | 85 return Error(EINVAL); |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 | 88 |
| 89 private: | 89 private: |
| 90 DISALLOW_COPY_AND_ASSIGN(ProbePolicy); | 90 DISALLOW_COPY_AND_ASSIGN(ProbePolicy); |
| 91 }; | 91 }; |
| 92 | 92 |
| 93 void ProbeProcess(void) { | 93 void ProbeProcess(void) { |
| 94 if (syscall(__NR_getpid) < 0 && errno == EPERM) { | 94 if (syscall(__NR_getpid) < 0 && errno == EPERM) { |
| 95 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); | 95 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 | 98 |
| 99 class AllowAllPolicy : public SandboxBPFDSLPolicy { | 99 class AllowAllPolicy : public bpf_dsl::Policy { |
| 100 public: | 100 public: |
| 101 AllowAllPolicy() {} | 101 AllowAllPolicy() {} |
| 102 virtual ~AllowAllPolicy() {} | 102 virtual ~AllowAllPolicy() {} |
| 103 | 103 |
| 104 virtual ResultExpr EvaluateSyscall(int sysnum) const override { | 104 virtual ResultExpr EvaluateSyscall(int sysnum) const override { |
| 105 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum)); | 105 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum)); |
| 106 return Allow(); | 106 return Allow(); |
| 107 } | 107 } |
| 108 | 108 |
| 109 private: | 109 private: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 : quiet_(false), proc_fd_(-1), sandbox_has_started_(false), policy_() { | 146 : quiet_(false), proc_fd_(-1), sandbox_has_started_(false), policy_() { |
| 147 } | 147 } |
| 148 | 148 |
| 149 SandboxBPF::~SandboxBPF() { | 149 SandboxBPF::~SandboxBPF() { |
| 150 } | 150 } |
| 151 | 151 |
| 152 bool SandboxBPF::IsValidSyscallNumber(int sysnum) { | 152 bool SandboxBPF::IsValidSyscallNumber(int sysnum) { |
| 153 return SyscallSet::IsValid(sysnum); | 153 return SyscallSet::IsValid(sysnum); |
| 154 } | 154 } |
| 155 | 155 |
| 156 bool SandboxBPF::RunFunctionInPolicy( | 156 bool SandboxBPF::RunFunctionInPolicy(void (*code_in_sandbox)(), |
| 157 void (*code_in_sandbox)(), | 157 scoped_ptr<bpf_dsl::Policy> policy) { |
| 158 scoped_ptr<bpf_dsl::SandboxBPFDSLPolicy> policy) { | |
| 159 // Block all signals before forking a child process. This prevents an | 158 // Block all signals before forking a child process. This prevents an |
| 160 // attacker from manipulating our test by sending us an unexpected signal. | 159 // attacker from manipulating our test by sending us an unexpected signal. |
| 161 sigset_t old_mask, new_mask; | 160 sigset_t old_mask, new_mask; |
| 162 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) { | 161 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) { |
| 163 SANDBOX_DIE("sigprocmask() failed"); | 162 SANDBOX_DIE("sigprocmask() failed"); |
| 164 } | 163 } |
| 165 int fds[2]; | 164 int fds[2]; |
| 166 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) { | 165 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) { |
| 167 SANDBOX_DIE("pipe() failed"); | 166 SANDBOX_DIE("pipe() failed"); |
| 168 } | 167 } |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 } | 266 } |
| 268 } | 267 } |
| 269 if (IGNORE_EINTR(close(fds[0]))) { | 268 if (IGNORE_EINTR(close(fds[0]))) { |
| 270 SANDBOX_DIE("close() failed"); | 269 SANDBOX_DIE("close() failed"); |
| 271 } | 270 } |
| 272 | 271 |
| 273 return rc; | 272 return rc; |
| 274 } | 273 } |
| 275 | 274 |
| 276 bool SandboxBPF::KernelSupportSeccompBPF() { | 275 bool SandboxBPF::KernelSupportSeccompBPF() { |
| 277 return RunFunctionInPolicy( | 276 return RunFunctionInPolicy(ProbeProcess, |
| 278 ProbeProcess, | 277 scoped_ptr<bpf_dsl::Policy>(new ProbePolicy())) && |
| 279 scoped_ptr<bpf_dsl::SandboxBPFDSLPolicy>(new ProbePolicy())) && | 278 RunFunctionInPolicy(TryVsyscallProcess, |
| 280 RunFunctionInPolicy( | 279 scoped_ptr<bpf_dsl::Policy>(new AllowAllPolicy())); |
| 281 TryVsyscallProcess, | |
| 282 scoped_ptr<bpf_dsl::SandboxBPFDSLPolicy>(new AllowAllPolicy())); | |
| 283 } | 280 } |
| 284 | 281 |
| 285 // static | 282 // static |
| 286 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { | 283 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { |
| 287 // It the sandbox is currently active, we clearly must have support for | 284 // It the sandbox is currently active, we clearly must have support for |
| 288 // sandboxing. | 285 // sandboxing. |
| 289 if (status_ == STATUS_ENABLED) { | 286 if (status_ == STATUS_ENABLED) { |
| 290 return status_; | 287 return status_; |
| 291 } | 288 } |
| 292 | 289 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 // Install the filters. | 413 // Install the filters. |
| 417 InstallFilter(supports_tsync || thread_state == PROCESS_MULTI_THREADED); | 414 InstallFilter(supports_tsync || thread_state == PROCESS_MULTI_THREADED); |
| 418 | 415 |
| 419 // We are now inside the sandbox. | 416 // We are now inside the sandbox. |
| 420 status_ = STATUS_ENABLED; | 417 status_ = STATUS_ENABLED; |
| 421 | 418 |
| 422 return true; | 419 return true; |
| 423 } | 420 } |
| 424 | 421 |
| 425 // Don't take a scoped_ptr here, polymorphism make their use awkward. | 422 // Don't take a scoped_ptr here, polymorphism make their use awkward. |
| 426 void SandboxBPF::SetSandboxPolicy(bpf_dsl::SandboxBPFDSLPolicy* policy) { | 423 void SandboxBPF::SetSandboxPolicy(bpf_dsl::Policy* policy) { |
| 427 DCHECK(!policy_); | 424 DCHECK(!policy_); |
| 428 if (sandbox_has_started_) { | 425 if (sandbox_has_started_) { |
| 429 SANDBOX_DIE("Cannot change policy after sandbox has started"); | 426 SANDBOX_DIE("Cannot change policy after sandbox has started"); |
| 430 } | 427 } |
| 431 policy_.reset(policy); | 428 policy_.reset(policy); |
| 432 } | 429 } |
| 433 | 430 |
| 434 void SandboxBPF::InstallFilter(bool must_sync_threads) { | 431 void SandboxBPF::InstallFilter(bool must_sync_threads) { |
| 435 // We want to be very careful in not imposing any requirements on the | 432 // We want to be very careful in not imposing any requirements on the |
| 436 // policies that are set with SetSandboxPolicy(). This means, as soon as | 433 // policies that are set with SetSandboxPolicy(). This means, as soon as |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 static_cast<intptr_t>(args.args[1]), | 513 static_cast<intptr_t>(args.args[1]), |
| 517 static_cast<intptr_t>(args.args[2]), | 514 static_cast<intptr_t>(args.args[2]), |
| 518 static_cast<intptr_t>(args.args[3]), | 515 static_cast<intptr_t>(args.args[3]), |
| 519 static_cast<intptr_t>(args.args[4]), | 516 static_cast<intptr_t>(args.args[4]), |
| 520 static_cast<intptr_t>(args.args[5])); | 517 static_cast<intptr_t>(args.args[5])); |
| 521 } | 518 } |
| 522 | 519 |
| 523 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; | 520 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; |
| 524 | 521 |
| 525 } // namespace sandbox | 522 } // namespace sandbox |
| OLD | NEW |