| 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
|
|
|