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

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

Issue 293463002: Add SandboxBPFPolicy::InvalidSyscall() to simplify writing policies (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>
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
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(&current_time) != static_cast<time_t>(-1)) { 91 if (time(&current_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
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
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
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
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
OLDNEW
« no previous file with comments | « sandbox/linux/sandbox_linux.gypi ('k') | sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698