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 |