Index: sandbox/linux/bpf_dsl/policy_compiler.cc |
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc |
index ad9ccbab61170df5e54733e096297844b5d5e7fa..cb6f00c114587b5e366bd2341ec4c3e5d4a64b41 100644 |
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc |
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc |
@@ -14,7 +14,6 @@ |
#include "sandbox/linux/bpf_dsl/bpf_dsl.h" |
#include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" |
#include "sandbox/linux/bpf_dsl/codegen.h" |
-#include "sandbox/linux/bpf_dsl/errorcode.h" |
#include "sandbox/linux/bpf_dsl/policy.h" |
#include "sandbox/linux/bpf_dsl/seccomp_macros.h" |
#include "sandbox/linux/bpf_dsl/syscall_set.h" |
@@ -91,7 +90,6 @@ PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry) |
registry_(registry), |
escapepc_(0), |
panic_func_(DefaultPanic), |
- conds_(), |
gen_(), |
has_unsafe_traps_(HasUnsafeTraps(policy_)) { |
DCHECK(policy); |
@@ -185,7 +183,7 @@ CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) { |
} |
CodeGen::Node PolicyCompiler::DispatchSyscall() { |
- // Evaluate all possible system calls and group their ErrorCodes into |
+ // Evaluate all possible system calls and group their Nodes into |
// ranges of identical codes. |
Ranges ranges; |
FindRanges(&ranges); |
@@ -225,7 +223,7 @@ void PolicyCompiler::FindRanges(Ranges* ranges) { |
// int32_t, but BPF instructions always operate on unsigned quantities. We |
// deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL, |
// and then verifying that the rest of the number range (both positive and |
- // negative) all return the same ErrorCode. |
+ // negative) all return the same Node. |
const CodeGen::Node invalid_node = CompileResult(policy_->InvalidSyscall()); |
uint32_t old_sysnum = 0; |
CodeGen::Node old_node = |
@@ -277,68 +275,54 @@ CodeGen::Node PolicyCompiler::AssembleJumpTable(Ranges::const_iterator start, |
} |
CodeGen::Node PolicyCompiler::CompileResult(const ResultExpr& res) { |
- return RetExpression(res->Compile(this)); |
+ return res->Compile(this); |
} |
-CodeGen::Node PolicyCompiler::RetExpression(const ErrorCode& err) { |
- switch (err.error_type()) { |
- case ErrorCode::ET_COND: |
- return CondExpression(err); |
- case ErrorCode::ET_SIMPLE: |
- case ErrorCode::ET_TRAP: |
- return gen_.MakeInstruction(BPF_RET + BPF_K, err.err()); |
- default: |
- LOG(FATAL) |
- << "ErrorCode is not suitable for returning from a BPF program"; |
- return CodeGen::kNullNode; |
- } |
-} |
- |
-CodeGen::Node PolicyCompiler::CondExpression(const ErrorCode& cond) { |
- // Sanity check that |cond| makes sense. |
- CHECK(cond.argno_ >= 0 && cond.argno_ < 6) << "Invalid argument number " |
- << cond.argno_; |
- CHECK(cond.width_ == ErrorCode::TP_32BIT || |
- cond.width_ == ErrorCode::TP_64BIT) |
- << "Invalid argument width " << cond.width_; |
- CHECK_NE(0U, cond.mask_) << "Zero mask is invalid"; |
- CHECK_EQ(cond.value_, cond.value_ & cond.mask_) |
- << "Value contains masked out bits"; |
+CodeGen::Node PolicyCompiler::MaskedEqual(int argno, |
+ size_t width, |
+ uint64_t mask, |
+ uint64_t value, |
+ CodeGen::Node passed, |
+ CodeGen::Node failed) { |
+ // Sanity check that arguments make sense. |
+ CHECK(argno >= 0 && argno < 6) << "Invalid argument number " << argno; |
+ CHECK(width == 4 || width == 8) << "Invalid argument width " << width; |
+ CHECK_NE(0U, mask) << "Zero mask is invalid"; |
+ CHECK_EQ(value, value & mask) << "Value contains masked out bits"; |
if (sizeof(void*) == 4) { |
rickyz (no longer on Chrome)
2015/09/03 23:34:11
(Question unrelated to your change): Is there ever
mdempsky
2015/09/04 18:32:09
Agreed that Clang's cross-compiler model is nicer,
|
- CHECK_EQ(ErrorCode::TP_32BIT, cond.width_) |
- << "Invalid width on 32-bit platform"; |
+ CHECK_EQ(4U, width) << "Invalid width on 32-bit platform"; |
} |
- if (cond.width_ == ErrorCode::TP_32BIT) { |
- CHECK_EQ(0U, cond.mask_ >> 32) << "Mask exceeds argument size"; |
- CHECK_EQ(0U, cond.value_ >> 32) << "Value exceeds argument size"; |
+ if (width == 4) { |
+ CHECK_EQ(0U, mask >> 32) << "Mask exceeds argument size"; |
+ CHECK_EQ(0U, value >> 32) << "Value exceeds argument size"; |
} |
- CodeGen::Node passed = RetExpression(*cond.passed_); |
- CodeGen::Node failed = RetExpression(*cond.failed_); |
- |
// We want to emit code to check "(arg & mask) == value" where arg, mask, and |
// value are 64-bit values, but the BPF machine is only 32-bit. We implement |
// this by independently testing the upper and lower 32-bits and continuing to |
// |passed| if both evaluate true, or to |failed| if either evaluate false. |
- return CondExpressionHalf(cond, |
- UpperHalf, |
- CondExpressionHalf(cond, LowerHalf, passed, failed), |
- failed); |
+ return MaskedEqualHalf(argno, width, mask, value, ArgHalf::UPPER, |
+ MaskedEqualHalf(argno, width, mask, value, |
+ ArgHalf::LOWER, passed, failed), |
+ failed); |
} |
-CodeGen::Node PolicyCompiler::CondExpressionHalf(const ErrorCode& cond, |
- ArgHalf half, |
- CodeGen::Node passed, |
- CodeGen::Node failed) { |
- if (cond.width_ == ErrorCode::TP_32BIT && half == UpperHalf) { |
+CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, |
+ size_t width, |
+ uint64_t full_mask, |
+ uint64_t full_value, |
+ ArgHalf half, |
+ CodeGen::Node passed, |
+ CodeGen::Node failed) { |
+ if (width == 4 && half == ArgHalf::UPPER) { |
// Special logic for sanity checking the upper 32-bits of 32-bit system |
// call arguments. |
// TODO(mdempsky): Compile Unexpected64bitArgument() just per program. |
- CodeGen::Node invalid_64bit = RetExpression(Unexpected64bitArgument()); |
+ CodeGen::Node invalid_64bit = Unexpected64bitArgument(); |
- const uint32_t upper = SECCOMP_ARG_MSB_IDX(cond.argno_); |
- const uint32_t lower = SECCOMP_ARG_LSB_IDX(cond.argno_); |
+ const uint32_t upper = SECCOMP_ARG_MSB_IDX(argno); |
+ const uint32_t lower = SECCOMP_ARG_LSB_IDX(argno); |
if (sizeof(void*) == 4) { |
// On 32-bit platforms, the upper 32-bits should always be 0: |
@@ -381,10 +365,11 @@ CodeGen::Node PolicyCompiler::CondExpressionHalf(const ErrorCode& cond, |
invalid_64bit))); |
} |
- const uint32_t idx = (half == UpperHalf) ? SECCOMP_ARG_MSB_IDX(cond.argno_) |
- : SECCOMP_ARG_LSB_IDX(cond.argno_); |
- const uint32_t mask = (half == UpperHalf) ? cond.mask_ >> 32 : cond.mask_; |
- const uint32_t value = (half == UpperHalf) ? cond.value_ >> 32 : cond.value_; |
+ const uint32_t idx = (half == ArgHalf::UPPER) ? SECCOMP_ARG_MSB_IDX(argno) |
+ : SECCOMP_ARG_LSB_IDX(argno); |
+ const uint32_t mask = (half == ArgHalf::UPPER) ? full_mask >> 32 : full_mask; |
+ const uint32_t value = |
+ (half == ArgHalf::UPPER) ? full_value >> 32 : full_value; |
// Emit a suitable instruction sequence for (arg & mask) == value. |
@@ -439,12 +424,12 @@ CodeGen::Node PolicyCompiler::CondExpressionHalf(const ErrorCode& cond, |
BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed))); |
} |
-ErrorCode PolicyCompiler::Unexpected64bitArgument() { |
- return panic_func_("Unexpected 64bit argument detected")->Compile(this); |
+CodeGen::Node PolicyCompiler::Unexpected64bitArgument() { |
+ return CompileResult(panic_func_("Unexpected 64bit argument detected")); |
} |
-ErrorCode PolicyCompiler::Error(int err) { |
- if (has_unsafe_traps_) { |
+CodeGen::Node PolicyCompiler::Return(uint32_t ret) { |
+ if (has_unsafe_traps_ && (ret & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { |
// When inside an UnsafeTrap() callback, we want to allow all system calls. |
// This means, we must conditionally disable the sandbox -- and that's not |
// something that kernel-side BPF filters can do, as they cannot inspect |
@@ -454,17 +439,18 @@ ErrorCode PolicyCompiler::Error(int err) { |
// The performance penalty for this extra round-trip to user-space is not |
// actually that bad, as we only ever pay it for denied system calls; and a |
// typical program has very few of these. |
- return Trap(ReturnErrno, reinterpret_cast<void*>(err), true); |
+ return Trap(ReturnErrno, reinterpret_cast<void*>(ret & SECCOMP_RET_DATA), |
+ true); |
} |
- return ErrorCode(err); |
+ return gen_.MakeInstruction(BPF_RET + BPF_K, ret); |
} |
-ErrorCode PolicyCompiler::Trap(TrapRegistry::TrapFnc fnc, |
- const void* aux, |
- bool safe) { |
+CodeGen::Node PolicyCompiler::Trap(TrapRegistry::TrapFnc fnc, |
+ const void* aux, |
+ bool safe) { |
uint16_t trap_id = registry_->Add(fnc, aux, safe); |
- return ErrorCode(trap_id, fnc, aux, safe); |
+ return gen_.MakeInstruction(BPF_RET + BPF_K, SECCOMP_RET_TRAP + trap_id); |
} |
bool PolicyCompiler::IsRequiredForUnsafeTrap(int sysno) { |
@@ -476,19 +462,5 @@ bool PolicyCompiler::IsRequiredForUnsafeTrap(int sysno) { |
return false; |
} |
-ErrorCode PolicyCompiler::CondMaskedEqual(int argno, |
- ErrorCode::ArgType width, |
- uint64_t mask, |
- uint64_t value, |
- const ErrorCode& passed, |
- const ErrorCode& failed) { |
- return ErrorCode(argno, |
- width, |
- mask, |
- value, |
- &*conds_.insert(passed).first, |
- &*conds_.insert(failed).first); |
-} |
- |
} // namespace bpf_dsl |
} // namespace sandbox |