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

Unified Diff: sandbox/linux/seccomp-bpf/sandbox_bpf.cc

Issue 10833044: Refactored ErrorCode into it's own class (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased, and removed "protected" as requested by jln Created 8 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: sandbox/linux/seccomp-bpf/sandbox_bpf.cc
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index 959954480bad83f82b16e95fba3efd446fbd6fd9..3964b1e7c89f10577a4e67122889c61169e65c6a 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -14,7 +14,7 @@ namespace playground2 {
// We define a really simple sandbox policy. It is just good enough for us
// to tell that the sandbox has actually been activated.
-Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) {
+ErrorCode Sandbox::probeEvaluator(int signo) {
switch (signo) {
case __NR_getpid:
// Return EPERM so that we can check that the filter actually ran.
@@ -34,7 +34,7 @@ void Sandbox::probeProcess(void) {
}
}
-Sandbox::ErrorCode Sandbox::allowAllEvaluator(int signo) {
+ErrorCode Sandbox::allowAllEvaluator(int signo) {
if (signo < static_cast<int>(MIN_SYSCALL) ||
signo > static_cast<int>(MAX_SYSCALL)) {
return ENOSYS;
@@ -138,6 +138,15 @@ bool Sandbox::RunFunctionInPolicy(void (*CodeInSandbox)(),
}
bool Sandbox::kernelSupportSeccompBPF(int proc_fd) {
+#ifdef SECCOMP_BPF_VALGRIND_HACKS
+ if (RUNNING_ON_VALGRIND) {
+ // Valgrind doesn't like our run-time test. Disable testing and assume we
+ // always support sandboxing. This feature should only ever be enabled when
+ // debugging.
+ return true;
+ }
+#endif
+
return RunFunctionInPolicy(probeProcess, Sandbox::probeEvaluator, proc_fd) &&
RunFunctionInPolicy(tryVsyscallProcess, Sandbox::allowAllEvaluator,
proc_fd);
@@ -249,10 +258,10 @@ bool Sandbox::isSingleThreaded(int proc_fd) {
return true;
}
-static bool isDenied(const Sandbox::ErrorCode& code) {
- return (code & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP ||
- (code >= (SECCOMP_RET_ERRNO + 1) &&
- code <= (SECCOMP_RET_ERRNO + 4095));
+bool Sandbox::isDenied(ErrorCode code) {
jln (very slow on Chromium) 2012/07/27 19:46:30 Shouldn't this be a const reference ?
+ return (code.err_ & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP ||
+ (code.err_ >= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MIN_ERRNO) &&
+ code.err_ <= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MAX_ERRNO));
jln (very slow on Chromium) 2012/07/27 19:46:30 Please create an accessor err() in the ErrorCode c
}
void Sandbox::policySanityChecks(EvaluateSyscall syscallEvaluator,
@@ -353,8 +362,7 @@ void Sandbox::installFilter() {
program->push_back((struct sock_filter)
BPF_STMT(BPF_RET+BPF_K,
- ErrorCode(bpfFailure,
- "Invalid audit architecture in BPF filter")));
+ Kill("Invalid audit architecture in BPF filter").err_));
// Grab the system call number, so that we can implement jump tables.
program->push_back((struct sock_filter)
@@ -373,8 +381,7 @@ void Sandbox::installFilter() {
#endif
program->push_back((struct sock_filter)
BPF_STMT(BPF_RET+BPF_K,
- ErrorCode(bpfFailure,
- "Illegal mixing of system call ABIs")));
+ Kill("Illegal mixing of system call ABIs").err_));
#endif
@@ -419,13 +426,22 @@ void Sandbox::installFilter() {
// Release memory that is no longer needed
evaluators_.clear();
+ errMap_.clear();
- // Install BPF filter program
- if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
- die(dryRun_ ? NULL : "Kernel refuses to enable no-new-privs");
- } else {
- if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
- die(dryRun_ ? NULL : "Kernel refuses to turn on BPF filters");
+#ifdef SECCOMP_BPF_VALGRIND_HACKS
+ // Valgrind is really not happy about our sandbox. Disable it when running
+ // in Valgrind. This feature is dangerous and should never be enabled by
+ // default. We protect it behind a pre-processor option.
+ if (!RUNNING_ON_VALGRIND)
+#endif
+ {
+ // Install BPF filter program
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+ die(dryRun_ ? NULL : "Kernel refuses to enable no-new-privs");
+ } else {
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
+ die(dryRun_ ? NULL : "Kernel refuses to turn on BPF filters");
+ }
}
}
@@ -445,7 +461,7 @@ void Sandbox::findRanges(Ranges *ranges) {
sysnum <= MAX_SYSCALL + 1;
++sysnum) {
ErrorCode err = evaluateSyscall(static_cast<int>(sysnum));
- if (err != oldErr) {
+ if (!err.isEqual(oldErr)) {
ranges->push_back(Range(oldSysnum, sysnum-1, oldErr));
oldSysnum = sysnum;
oldErr = err;
@@ -460,9 +476,9 @@ void Sandbox::findRanges(Ranges *ranges) {
// We don't actually iterate over all possible 2^32 values, though. We just
// perform spot checks at the boundaries.
// The cases that we test are: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF.
- if (oldErr != evaluateSyscall(std::numeric_limits<int>::max()) ||
- oldErr != evaluateSyscall(std::numeric_limits<int>::min()) ||
- oldErr != evaluateSyscall(-1)) {
+ if (!oldErr.isEqual(evaluateSyscall(std::numeric_limits<int>::max())) ||
+ !oldErr.isEqual(evaluateSyscall(std::numeric_limits<int>::min())) ||
+ !oldErr.isEqual(evaluateSyscall(-1))) {
die("Invalid seccomp policy");
}
ranges->push_back(
@@ -506,7 +522,7 @@ void Sandbox::emitJumpStatements(Program *program, RetInsns *rets,
// Since all branches in BPF programs have to be forward branches, we
// keep track of our current instruction pointer and then fix up the
// branch when we emit the BPF_RET statement in emitReturnStatements().
- (*rets)[start->err].push_back(FixUp(jmp, false));
+ (*rets)[start->err.err_].push_back(FixUp(jmp, false));
} else {
// Sub-divide the list of ranges and continue recursively.
emitJumpStatements(program, rets, start, mid);
@@ -518,7 +534,7 @@ void Sandbox::emitJumpStatements(Program *program, RetInsns *rets,
// We narrowed things down to a single range object. Remember instruction
// pointer and exit code, so that we can patch up the target of the jump
// instruction in emitReturnStatements().
- (*rets)[mid->err].push_back(FixUp(jmp, true));
+ (*rets)[mid->err.err_].push_back(FixUp(jmp, true));
} else {
// We now know where the block of instructions for the "true" comparison
// starts. Patch up the jump target of the BPF_JMP instruction that we
@@ -639,19 +655,16 @@ void Sandbox::sigSys(int nr, siginfo_t *info, void *void_context) {
return;
}
-intptr_t Sandbox::bpfFailure(const struct arch_seccomp_data&, void *aux) {
- die(static_cast<char *>(aux));
-}
-
-int Sandbox::getTrapId(Sandbox::TrapFnc fnc, const void *aux) {
+ErrorCode Sandbox::Trap(ErrorCode::TrapFnc fnc, const void *aux) {
// Each unique pair of TrapFnc and auxiliary data make up a distinct instance
// of a SECCOMP_RET_TRAP.
- std::pair<TrapFnc, const void *> key(fnc, aux);
+ std::pair<ErrorCode::TrapFnc, const void *> key(fnc, aux);
TrapIds::const_iterator iter = trapIds_.find(key);
+ uint16_t id;
if (iter != trapIds_.end()) {
// We have seen this pair before. Return the same id that we assigned
// earlier.
- return iter->second;
+ id = iter->second;
} else {
// This is a new pair. Remember it and assign a new id.
// Please note that we have to store traps in memory that doesn't get
@@ -661,12 +674,12 @@ int Sandbox::getTrapId(Sandbox::TrapFnc fnc, const void *aux) {
if (!traps_) {
traps_ = new Traps();
}
- Traps::size_type id = traps_->size() + 1;
- if (id > SECCOMP_RET_DATA) {
+ if (traps_->size() >= SECCOMP_RET_DATA) {
// In practice, this is pretty much impossible to trigger, as there
// are other kernel limitations that restrict overall BPF program sizes.
die("Too many SECCOMP_RET_TRAP callback instances");
}
+ id = traps_->size() + 1;
traps_->push_back(ErrorCode(fnc, aux, id));
trapIds_[key] = id;
@@ -679,17 +692,28 @@ int Sandbox::getTrapId(Sandbox::TrapFnc fnc, const void *aux) {
// signal handler, where we can safely do so.
trapArray_ = &(*traps_)[0];
trapArraySize_ = id;
- return id;
}
+
+ ErrorCode err = ErrorCode(fnc, aux, id);
+ return errMap_[err.err_] = err;
+}
+
+intptr_t Sandbox::bpfFailure(const struct arch_seccomp_data&, void *aux) {
+ die(static_cast<char *>(aux));
+}
+
+ErrorCode Sandbox::Kill(const char *msg) {
+ return Trap(bpfFailure, const_cast<char *>(msg));
}
bool Sandbox::dryRun_ = false;
Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
int Sandbox::proc_fd_ = -1;
Sandbox::Evaluators Sandbox::evaluators_;
+Sandbox::ErrMap Sandbox::errMap_;
Sandbox::Traps *Sandbox::traps_ = NULL;
Sandbox::TrapIds Sandbox::trapIds_;
-Sandbox::ErrorCode *Sandbox::trapArray_ = NULL;
+ErrorCode *Sandbox::trapArray_ = NULL;
size_t Sandbox::trapArraySize_ = 0;
} // namespace

Powered by Google App Engine
This is Rietveld 408576698