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

Unified Diff: sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc

Issue 299683004: Rewrite all BPF policies to use DSL API Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Overhaul of DSL and implementation 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h ('k') | sandbox/linux/seccomp-bpf-helpers/bpf_dsl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h ('k') | sandbox/linux/seccomp-bpf-helpers/bpf_dsl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698