| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 | 74 |
| 75 void ProbeProcess(void) { | 75 void ProbeProcess(void) { |
| 76 if (syscall(__NR_getpid) < 0 && errno == EPERM) { | 76 if (syscall(__NR_getpid) < 0 && errno == EPERM) { |
| 77 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); | 77 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 | 80 |
| 81 ErrorCode AllowAllEvaluator(SandboxBPF*, int sysnum, void*) { | 81 ErrorCode AllowAllEvaluator(SandboxBPF*, int sysnum, void*) { |
| 82 if (!SandboxBPF::IsValidSyscallNumber(sysnum)) { | 82 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum)); |
| 83 return ErrorCode(ENOSYS); | |
| 84 } | |
| 85 return ErrorCode(ErrorCode::ERR_ALLOWED); | 83 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 86 } | 84 } |
| 87 | 85 |
| 88 void TryVsyscallProcess(void) { | 86 void TryVsyscallProcess(void) { |
| 89 time_t current_time; | 87 time_t current_time; |
| 90 // time() is implemented as a vsyscall. With an older glibc, with | 88 // time() is implemented as a vsyscall. With an older glibc, with |
| 91 // vsyscall=emulate and some versions of the seccomp BPF patch | 89 // vsyscall=emulate and some versions of the seccomp BPF patch |
| 92 // we may get SIGKILL-ed. Detect this! | 90 // we may get SIGKILL-ed. Detect this! |
| 93 if (time(¤t_time) != static_cast<time_t>(-1)) { | 91 if (time(¤t_time) != static_cast<time_t>(-1)) { |
| 94 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); | 92 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 const SandboxBPFPolicy* wrapped_policy) | 179 const SandboxBPFPolicy* wrapped_policy) |
| 182 : wrapped_policy_(wrapped_policy) { | 180 : wrapped_policy_(wrapped_policy) { |
| 183 DCHECK(wrapped_policy_); | 181 DCHECK(wrapped_policy_); |
| 184 } | 182 } |
| 185 | 183 |
| 186 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, | 184 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, |
| 187 int system_call_number) const OVERRIDE { | 185 int system_call_number) const OVERRIDE { |
| 188 ErrorCode err = | 186 ErrorCode err = |
| 189 wrapped_policy_->EvaluateSyscall(sandbox_compiler, system_call_number); | 187 wrapped_policy_->EvaluateSyscall(sandbox_compiler, system_call_number); |
| 190 if ((err.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { | 188 if ((err.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { |
| 191 return sandbox_compiler->Trap( | 189 return ReturnErrnoViaTrap(sandbox_compiler, err.err() & SECCOMP_RET_DATA); |
| 192 ReturnErrno, reinterpret_cast<void*>(err.err() & SECCOMP_RET_DATA)); | |
| 193 } | 190 } |
| 194 return err; | 191 return err; |
| 195 } | 192 } |
| 196 | 193 |
| 194 virtual ErrorCode InvalidSyscall( |
| 195 SandboxBPF* sandbox_compiler) const OVERRIDE { |
| 196 return ReturnErrnoViaTrap(sandbox_compiler, ENOSYS); |
| 197 } |
| 198 |
| 197 private: | 199 private: |
| 200 ErrorCode ReturnErrnoViaTrap(SandboxBPF* sandbox_compiler, int err) const { |
| 201 return sandbox_compiler->Trap(ReturnErrno, reinterpret_cast<void*>(err)); |
| 202 } |
| 203 |
| 198 const SandboxBPFPolicy* wrapped_policy_; | 204 const SandboxBPFPolicy* wrapped_policy_; |
| 199 DISALLOW_COPY_AND_ASSIGN(RedirectToUserSpacePolicyWrapper); | 205 DISALLOW_COPY_AND_ASSIGN(RedirectToUserSpacePolicyWrapper); |
| 200 }; | 206 }; |
| 201 | 207 |
| 202 intptr_t BPFFailure(const struct arch_seccomp_data&, void* aux) { | 208 intptr_t BPFFailure(const struct arch_seccomp_data&, void* aux) { |
| 203 SANDBOX_DIE(static_cast<char*>(aux)); | 209 SANDBOX_DIE(static_cast<char*>(aux)); |
| 204 } | 210 } |
| 205 | 211 |
| 206 } // namespace | 212 } // namespace |
| 207 | 213 |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 // Install the filters. | 462 // Install the filters. |
| 457 InstallFilter(thread_state); | 463 InstallFilter(thread_state); |
| 458 | 464 |
| 459 // We are now inside the sandbox. | 465 // We are now inside the sandbox. |
| 460 status_ = STATUS_ENABLED; | 466 status_ = STATUS_ENABLED; |
| 461 | 467 |
| 462 return true; | 468 return true; |
| 463 } | 469 } |
| 464 | 470 |
| 465 void SandboxBPF::PolicySanityChecks(SandboxBPFPolicy* policy) { | 471 void SandboxBPF::PolicySanityChecks(SandboxBPFPolicy* policy) { |
| 466 for (SyscallIterator iter(true); !iter.Done();) { | 472 if (!IsDenied(policy->InvalidSyscall(this))) { |
| 467 uint32_t sysnum = iter.Next(); | 473 SANDBOX_DIE("Policies should deny invalid system calls."); |
| 468 if (!IsDenied(policy->EvaluateSyscall(this, sysnum))) { | |
| 469 SANDBOX_DIE( | |
| 470 "Policies should deny system calls that are outside the " | |
| 471 "expected range (typically MIN_SYSCALL..MAX_SYSCALL)"); | |
| 472 } | |
| 473 } | 474 } |
| 474 return; | 475 return; |
| 475 } | 476 } |
| 476 | 477 |
| 477 // Deprecated API, supported with a wrapper to the new API. | 478 // Deprecated API, supported with a wrapper to the new API. |
| 478 void SandboxBPF::SetSandboxPolicyDeprecated(EvaluateSyscall syscall_evaluator, | 479 void SandboxBPF::SetSandboxPolicyDeprecated(EvaluateSyscall syscall_evaluator, |
| 479 void* aux) { | 480 void* aux) { |
| 480 if (sandbox_has_started_ || !conds_) { | 481 if (sandbox_has_started_ || !conds_) { |
| 481 SANDBOX_DIE("Cannot change policy after sandbox has started"); | 482 SANDBOX_DIE("Cannot change policy after sandbox has started"); |
| 482 } | 483 } |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 SANDBOX_DIE(err); | 739 SANDBOX_DIE(err); |
| 739 } | 740 } |
| 740 } | 741 } |
| 741 | 742 |
| 742 void SandboxBPF::FindRanges(Ranges* ranges) { | 743 void SandboxBPF::FindRanges(Ranges* ranges) { |
| 743 // Please note that "struct seccomp_data" defines system calls as a signed | 744 // Please note that "struct seccomp_data" defines system calls as a signed |
| 744 // int32_t, but BPF instructions always operate on unsigned quantities. We | 745 // int32_t, but BPF instructions always operate on unsigned quantities. We |
| 745 // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL, | 746 // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL, |
| 746 // and then verifying that the rest of the number range (both positive and | 747 // and then verifying that the rest of the number range (both positive and |
| 747 // negative) all return the same ErrorCode. | 748 // negative) all return the same ErrorCode. |
| 749 const ErrorCode invalid_err = policy_->InvalidSyscall(this); |
| 748 uint32_t old_sysnum = 0; | 750 uint32_t old_sysnum = 0; |
| 749 ErrorCode old_err = policy_->EvaluateSyscall(this, old_sysnum); | 751 ErrorCode old_err = IsValidSyscallNumber(old_sysnum) |
| 750 ErrorCode invalid_err = policy_->EvaluateSyscall(this, MIN_SYSCALL - 1); | 752 ? policy_->EvaluateSyscall(this, old_sysnum) |
| 753 : invalid_err; |
| 751 | 754 |
| 752 for (SyscallIterator iter(false); !iter.Done();) { | 755 for (SyscallIterator iter(false); !iter.Done();) { |
| 753 uint32_t sysnum = iter.Next(); | 756 uint32_t sysnum = iter.Next(); |
| 754 ErrorCode err = policy_->EvaluateSyscall(this, static_cast<int>(sysnum)); | 757 ErrorCode err = |
| 755 if (!iter.IsValid(sysnum) && !invalid_err.Equals(err)) { | 758 IsValidSyscallNumber(sysnum) |
| 756 // A proper sandbox policy should always treat system calls outside of | 759 ? policy_->EvaluateSyscall(this, static_cast<int>(sysnum)) |
| 757 // the range MIN_SYSCALL..MAX_SYSCALL (i.e. anything that returns | 760 : invalid_err; |
| 758 // "false" for SyscallIterator::IsValid()) identically. Typically, all | |
| 759 // of these system calls would be denied with the same ErrorCode. | |
| 760 SANDBOX_DIE("Invalid seccomp policy"); | |
| 761 } | |
| 762 if (!err.Equals(old_err) || iter.Done()) { | 761 if (!err.Equals(old_err) || iter.Done()) { |
| 763 ranges->push_back(Range(old_sysnum, sysnum - 1, old_err)); | 762 ranges->push_back(Range(old_sysnum, sysnum - 1, old_err)); |
| 764 old_sysnum = sysnum; | 763 old_sysnum = sysnum; |
| 765 old_err = err; | 764 old_err = err; |
| 766 } | 765 } |
| 767 } | 766 } |
| 768 } | 767 } |
| 769 | 768 |
| 770 Instruction* SandboxBPF::AssembleJumpTable(CodeGen* gen, | 769 Instruction* SandboxBPF::AssembleJumpTable(CodeGen* gen, |
| 771 Ranges::const_iterator start, | 770 Ranges::const_iterator start, |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 &*conds_->insert(failed).first); | 1020 &*conds_->insert(failed).first); |
| 1022 } | 1021 } |
| 1023 | 1022 |
| 1024 ErrorCode SandboxBPF::Kill(const char* msg) { | 1023 ErrorCode SandboxBPF::Kill(const char* msg) { |
| 1025 return Trap(BPFFailure, const_cast<char*>(msg)); | 1024 return Trap(BPFFailure, const_cast<char*>(msg)); |
| 1026 } | 1025 } |
| 1027 | 1026 |
| 1028 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; | 1027 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; |
| 1029 | 1028 |
| 1030 } // namespace sandbox | 1029 } // namespace sandbox |
| OLD | NEW |