Index: sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc |
diff --git a/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc b/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc |
index 95b6f34c51a9e6864c99cf12a5c3f31535f2f101..abecf83d962e09e1ac5f91c2b2334ff27acc1453 100644 |
--- a/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc |
+++ b/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc |
@@ -9,18 +9,83 @@ |
#include "sandbox/linux/seccomp-bpf/errorcode.h" |
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
+using namespace sandbox::bpf_dsl::internal; |
+ |
namespace sandbox { |
-namespace bpfdsl { |
+namespace bpf_dsl { |
namespace { |
-class BasicCondImpl : public CondImpl { |
+class AllowResultExprImpl : public ResultExprImpl { |
+ public: |
+ AllowResultExprImpl() {} |
+ virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ } |
+ |
+ private: |
+ virtual ~AllowResultExprImpl() {} |
+ DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl); |
+}; |
+ |
+class ErrorResultExprImpl : public ResultExprImpl { |
public: |
- BasicCondImpl(int argno, |
- ErrorCode::ArgType is_32bit, |
- ErrorCode::Operation op, |
- uint64_t value) |
+ ErrorResultExprImpl(int err) : err_(err) { |
+ // TODO(mdempsky): Symbolic constants; tighter bounds check? |
+ CHECK(err_ >= 0 && err_ < 4096); |
+ } |
+ virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
+ return ErrorCode(err_); |
+ } |
+ |
+ private: |
+ virtual ~ErrorResultExprImpl() {} |
+ int err_; |
+ DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl); |
+}; |
+ |
+class TrapResultExprImpl : public ResultExprImpl { |
+ public: |
+ TrapResultExprImpl(TrapFunc func, void* arg) : func_(func), arg_(arg) { |
+ DCHECK(func_); |
+ } |
+ virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
+ return sb->Trap(func_, arg_); |
+ } |
+ |
+ private: |
+ virtual ~TrapResultExprImpl() {} |
+ TrapFunc func_; |
+ void* arg_; |
+ DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl); |
+}; |
+ |
+class IfThenResultExprImpl : public ResultExprImpl { |
+ public: |
+ IfThenResultExprImpl(BoolExpr cond, |
+ ResultExpr then_result, |
+ ResultExpr else_result) |
+ : cond_(cond), then_result_(then_result), else_result_(else_result) {} |
+ virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE { |
+ return cond_->Compile( |
+ sb, then_result_->Compile(sb), else_result_->Compile(sb)); |
+ } |
+ |
+ private: |
+ virtual ~IfThenResultExprImpl() {} |
+ BoolExpr cond_; |
+ ResultExpr then_result_; |
+ ResultExpr else_result_; |
+ DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl); |
+}; |
+ |
+class PrimBoolExprImpl : public BoolExprImpl { |
+ public: |
+ PrimBoolExprImpl(int argno, |
+ ErrorCode::ArgType is_32bit, |
+ ErrorCode::Operation op, |
+ uint64_t value) |
: argno_(argno), is_32bit_(is_32bit), op_(op), value_(value) {} |
virtual ErrorCode Compile(SandboxBPF* sb, |
ErrorCode true_ec, |
@@ -29,17 +94,32 @@ class BasicCondImpl : public CondImpl { |
} |
private: |
- virtual ~BasicCondImpl() {} |
+ virtual ~PrimBoolExprImpl() {} |
int argno_; |
ErrorCode::ArgType is_32bit_; |
ErrorCode::Operation op_; |
uint64_t value_; |
- DISALLOW_COPY_AND_ASSIGN(BasicCondImpl); |
+ DISALLOW_COPY_AND_ASSIGN(PrimBoolExprImpl); |
+}; |
+ |
+class NegateBoolExprImpl : public BoolExprImpl { |
+ public: |
+ NegateBoolExprImpl(BoolExpr cond) : cond_(cond) {} |
+ virtual ErrorCode Compile(SandboxBPF* sb, |
+ ErrorCode true_ec, |
+ ErrorCode false_ec) const OVERRIDE { |
+ return cond_->Compile(sb, false_ec, true_ec); |
+ } |
+ |
+ private: |
+ virtual ~NegateBoolExprImpl() {} |
+ BoolExpr cond_; |
+ DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl); |
}; |
-class AndCondImpl : public CondImpl { |
+class AndBoolExprImpl : public BoolExprImpl { |
public: |
- AndCondImpl(Cond lhs, Cond rhs) : lhs_(lhs), rhs_(rhs) {} |
+ AndBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {} |
virtual ErrorCode Compile(SandboxBPF* sb, |
ErrorCode true_ec, |
ErrorCode false_ec) const OVERRIDE { |
@@ -47,14 +127,14 @@ class AndCondImpl : public CondImpl { |
} |
private: |
- virtual ~AndCondImpl() {} |
- Cond lhs_, rhs_; |
- DISALLOW_COPY_AND_ASSIGN(AndCondImpl); |
+ virtual ~AndBoolExprImpl() {} |
+ BoolExpr lhs_, rhs_; |
+ DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl); |
}; |
-class OrCondImpl : public CondImpl { |
+class OrBoolExprImpl : public BoolExprImpl { |
public: |
- OrCondImpl(Cond lhs, Cond rhs) : lhs_(lhs), rhs_(rhs) {} |
+ OrBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {} |
virtual ErrorCode Compile(SandboxBPF* sb, |
ErrorCode true_ec, |
ErrorCode false_ec) const OVERRIDE { |
@@ -62,73 +142,145 @@ class OrCondImpl : public CondImpl { |
} |
private: |
- virtual ~OrCondImpl() {} |
- Cond lhs_, rhs_; |
- DISALLOW_COPY_AND_ASSIGN(OrCondImpl); |
+ virtual ~OrBoolExprImpl() {} |
+ BoolExpr lhs_, rhs_; |
+ DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl); |
}; |
} // namespace |
-Cond operator&&(Cond lhs, Cond rhs) { |
- return Cond(new AndCondImpl(lhs, rhs)); |
+namespace internal { |
+ |
+BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) { |
+ CHECK(num >= 0 && num < 6); |
+ CHECK(size >= 1 && size <= 8); |
+ CHECK(mask != 0) << "zero mask doesn't make sense"; |
+ const ErrorCode::ArgType arg_type = |
+ (size <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT; |
+ if (mask == static_cast<uint64_t>(-1)) { |
+ return BoolExpr( |
+ new const PrimBoolExprImpl(num, arg_type, ErrorCode::OP_EQUAL, val)); |
+ } else if (mask == val) { |
+ return BoolExpr(new const PrimBoolExprImpl( |
+ num, arg_type, ErrorCode::OP_HAS_ALL_BITS, val)); |
+ } else if (val == 0) { |
+ // User asked for (arg & mask) == 0; we return !(arg & mask), |
+ // which is semantically equivalent. |
+ return !BoolExpr(new const PrimBoolExprImpl( |
+ num, arg_type, ErrorCode::OP_HAS_ANY_BITS, mask)); |
+ } else { |
+ NOTREACHED() << "Unsupported case"; |
+ return BoolExpr(); |
+ } |
+} |
+ |
+IfThen::IfThen(BoolExpr cond_, ResultExpr then_, IfThenList rest_) |
+ : cond(cond_), then(then_), rest(rest_) { |
} |
-Cond operator||(Cond lhs, Cond rhs) { |
- return Cond(new OrCondImpl(lhs, rhs)); |
+IfThen::~IfThen() { |
+} |
+ |
+} // namespace internal |
+ |
+ResultExpr Allow() { |
+ return ResultExpr(new const AllowResultExprImpl()); |
} |
-Iffer::Iffer(SandboxBPF* sb) : sb_(sb) { |
- DCHECK(sb); |
+ResultExpr Error(int err) { |
+ return ResultExpr(new const ErrorResultExprImpl(err)); |
} |
-Iffer::Iffer(const Iffer& iffer) : sb_(iffer.sb_) { |
+ResultExpr Trap(TrapFunc func, void* arg) { |
+ return ResultExpr(new const TrapResultExprImpl(func, arg)); |
} |
-Thener Iffer::If(Cond cond) const { |
- return Thener(sb_, cond); |
+BoolExpr operator!(BoolExpr cond) { |
+ return BoolExpr(new const NegateBoolExprImpl(cond)); |
} |
-Thener::Thener(SandboxBPF* sb, Cond cond) : sb_(sb), cond_(cond) { |
+BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs) { |
+ return BoolExpr(new const AndBoolExprImpl(lhs, rhs)); |
+} |
+ |
+BoolExpr operator||(BoolExpr lhs, BoolExpr rhs) { |
+ return BoolExpr(new const OrBoolExprImpl(lhs, rhs)); |
+} |
+ |
+Thener If(BoolExpr cond) { |
+ return Thener(IfThenList(), cond); |
+} |
+ |
+Thener::Thener(IfThenList if_then_list, BoolExpr cond) |
+ : if_then_list_(if_then_list), cond_(cond) { |
+} |
+ |
+Thener::Thener(const Thener& thener) |
+ : if_then_list_(thener.if_then_list_), cond_(thener.cond_) { |
} |
Thener::~Thener() { |
} |
-Elser Thener::Then(ErrorCode true_ec) const { |
- return Elser(sb_, cond_, true_ec); |
+Elser Thener::Then(ResultExpr expr) const { |
+ return Elser(IfThen::Cons(cond_, expr, if_then_list_)); |
+} |
+ |
+Elser::Elser(IfThenList if_then_list) : if_then_list_(if_then_list) { |
} |
-Elser::Elser(SandboxBPF* sb, Cond cond, ErrorCode true_ec) |
- : sb_(sb), cond_(cond), true_ec_(true_ec) { |
+Elser::Elser(const Elser& elser) : if_then_list_(elser.if_then_list_) { |
} |
Elser::~Elser() { |
} |
-ErrorCode Elser::Else(ErrorCode false_ec) const { |
- return cond_->Compile(sb_, true_ec_, false_ec); |
+ResultExpr Elser::Else(ResultExpr expr) const { |
+ // We finally have the default result expression for this |
+ // if/then/else sequence. Also, we've already accumulated all |
+ // if/then pairs into a list of reverse order (i.e., lower priority |
+ // conditions are listed before higher priority ones). E.g., an |
+ // expression like |
+ // |
+ // If(b1).Then(e1).ElseIf(b2).Then(e2).ElseIf(b3).Then(e3).Else(e4) |
+ // |
+ // will have built up a list like |
+ // |
+ // [(b3, e3), (b2, e2), (b1, e1)]. |
+ // |
+ // Now that we have e4, we can walk the list and create a ResultExpr |
+ // tree like: |
+ // |
+ // expr = e4 |
+ // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4) |
+ // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4)) |
+ // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4))) |
+ // |
+ // and end up with an appropriately chained tree. |
+ |
+ for (IfThenList it = if_then_list_; it; it = it->rest) { |
+ expr = ResultExpr(new const IfThenResultExprImpl(it->cond, it->then, expr)); |
+ } |
+ return expr; |
} |
-} // namespace bpfdsl |
+Thener Elser::ElseIf(BoolExpr expr) const { |
+ return Thener(if_then_list_, expr); |
+} |
-bpfdsl::Iffer DSL(SandboxBPF* sb) { |
- return bpfdsl::Iffer(sb); |
+ErrorCode SandboxBPFPolicyDSL::EvaluateSyscall(SandboxBPF* sb, |
+ int sysno) const { |
+ return EvaluateSyscall(sysno)->Compile(sb); |
} |
-template <typename T> |
-Arg<T>::Arg(int num) |
- : num_(num) { |
- DCHECK(num >= 0 && num < 6); |
+ErrorCode SandboxBPFPolicyDSL::InvalidSyscall(SandboxBPF* sb) const { |
+ return InvalidSyscall()->Compile(sb); |
} |
-template <typename T> |
-bpfdsl::Cond Arg<T>::operator==(const T& rhs) const { |
- const ErrorCode::ArgType arg_type = |
- (sizeof(T) <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT; |
- return bpfdsl::Cond( |
- new bpfdsl::BasicCondImpl(num_, arg_type, ErrorCode::OP_EQUAL, rhs)); |
+ResultExpr SandboxBPFPolicyDSL::InvalidSyscall() const { |
+ return Error(ENOSYS); |
} |
-template class Arg<int>; |
+} // namespace bpf_dsl |
} // sandbox |