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

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

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/baseline_policy.cc ('k') | sandbox/linux/seccomp-bpf-helpers/bpf_dsl.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.h
diff --git a/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h b/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h
index 36ec0e11879ce1c6f0645957275aef33cd9f4c9d..37505e333cfcc20f331ffce032fc401cc42fcd15 100644
--- a/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h
+++ b/sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h
@@ -5,100 +5,270 @@
#ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
#define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
+#include <stdint.h>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "sandbox/linux/seccomp-bpf/errorcode.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
+struct arch_seccomp_data;
+class ErrorCode;
class SandboxBPF;
}
+// The sandbox::bpf_dsl namespace provides a domain-specific language
+// to make writing BPF policies more expressive. In general, the
+// object types all have value semantics (i.e., they can be copied
+// around, returned from or passed to function calls, etc. without any
+// surprising side effects), though not all support assignment.
+//
+// An idiomatic and demonstrative (albeit silly) example of this API
+// would be:
+//
+// #include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h"
+//
+// using namespace sandbox::bpf_dsl;
+//
+// class SillyPolicy : public SandboxBPFPolicy {
+// public:
+// SillyPolicy() {}
+// virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
+// if (sysno == __NR_fcntl) {
+// Arg<int> fd(0), cmd(1);
+// Arg<unsigned long> flags(2);
+// const unsigned long kBadFlags = ~(O_ACCMODE|O_NONBLOCK);
+// return If(fd == 0 && cmd == F_SETFL &&
+// (flags & kBadFlags) == 0).Then(
+// Allow()
+// ).ElseIf(cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC).Then(
+// Error(EMFILE)
+// ).Else(
+// Trap(SetFlagHandler, NULL)
+// );
+// }
+// }
+// private:
+// DISALLOW_COPY_AND_ASSIGN(SillyPolicy);
+// };
+//
+// More generally, the DSL currently supports the following grammar:
+//
+// result = Allow() | Error(errno) | Trap(trap_func, arg)
+// | If(bool).Then(result)[.ElseIf(bool).Then(result)].Else(result)
+// bool = arg == val | (arg & mask) == mask | (arg & mask) == 0
+// | !bool | bool && bool | bool || bool
+//
+// The semantics of each function and operator are intended to be
+// intuitive, but are described in more detail below.
+//
+// (Credit to Sean Parent's "Inheritance is the Base Class of Evil"
+// talk at Going Native 2013 for promoting value semantics via shared
+// pointers to immutable state.)
+
namespace sandbox {
-namespace bpfdsl {
+namespace bpf_dsl {
-class CondImpl : public base::RefCounted<CondImpl> {
- public:
- CondImpl() {}
- virtual ErrorCode Compile(SandboxBPF* sb,
- ErrorCode true_ec,
- ErrorCode false_ec) const = 0;
+// Forward declarations of classes; see below for proper documentation.
+class Thener;
+class Elser;
+namespace internal {
+class ResultExprImpl;
+class BoolExprImpl;
+struct IfThen;
+typedef scoped_refptr<const IfThen> IfThenList;
+}
- protected:
- friend class base::RefCounted<CondImpl>;
- virtual ~CondImpl() {}
+// ResultExpr is an opaque reference to an immutable result expression tree.
+typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr;
- private:
- DISALLOW_COPY_AND_ASSIGN(CondImpl);
-};
+// BoolExpr is an opaque reference to an immutable boolean expression tree.
+typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr;
-typedef scoped_refptr<const CondImpl> Cond;
+// Various ways to combine boolean expressions into more complex expressions.
+// They follow standard boolean algebra laws.
+SANDBOX_EXPORT BoolExpr operator!(BoolExpr expr);
+SANDBOX_EXPORT BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs);
+SANDBOX_EXPORT BoolExpr operator||(BoolExpr lhs, BoolExpr rhs);
-SANDBOX_EXPORT Cond operator&&(Cond lhs, Cond rhs);
-SANDBOX_EXPORT Cond operator||(Cond lhs, Cond rhs);
+// Allow specifies a result that the system call should be allowed to
+// execute normally.
+SANDBOX_EXPORT ResultExpr Allow();
-class Iffer;
-class Thener;
-class Elser;
+// Error specifies a result that the system call should fail with
+// error number |err|. As a special case, Error(0) will result in the
+// system call appearing to have succeeded, but without having any
+// side effects.
+SANDBOX_EXPORT ResultExpr Error(int err);
-class SANDBOX_EXPORT Iffer {
- public:
- // TODO(mdempsky): Make private?
- explicit Iffer(SandboxBPF* sb);
- Iffer(const Iffer& iffer);
- Thener If(Cond cond) const;
+// TODO(mdempsky): Move elsewhere.
+typedef intptr_t (*TrapFunc)(const arch_seccomp_data&, void*);
- private:
- SandboxBPF* sb_;
- DISALLOW_ASSIGN(Iffer);
-};
+// Trap specifies a result that the system call should trap and invoke
+// the specified callback function.
+SANDBOX_EXPORT ResultExpr Trap(TrapFunc func, void* arg);
+
+// If begins a conditional result expression predicated on the
+// specified boolean expression.
+SANDBOX_EXPORT Thener If(BoolExpr cond);
class SANDBOX_EXPORT Thener {
public:
+ Thener(const Thener& thener);
~Thener();
- Elser Then(ErrorCode ec) const;
+
+ // Then associates the result expression |expr| with the most recent
+ // If or ElseIf clause's boolean expression.
+ Elser Then(ResultExpr expr) const;
private:
- Thener(SandboxBPF* sb, Cond cond);
- SandboxBPF* sb_;
- Cond cond_;
- friend class Iffer;
+ Thener(internal::IfThenList if_then_list, BoolExpr cond);
+ internal::IfThenList if_then_list_;
+ BoolExpr cond_;
+ friend Thener If(BoolExpr cond);
friend class Elser;
- DISALLOW_COPY_AND_ASSIGN(Thener);
+ DISALLOW_ASSIGN(Thener);
};
class SANDBOX_EXPORT Elser {
public:
+ Elser(const Elser& elser);
~Elser();
- ErrorCode Else(ErrorCode ec) const;
+
+ // Else terminates a conditional result expression using |expr| as
+ // the default fallback result expression.
+ ResultExpr Else(ResultExpr expr) const;
+
+ // ElseIf extends the conditional result expression with another
+ // clause, predicated on the specified boolean expression.
+ Thener ElseIf(BoolExpr cond) const;
private:
- Elser(SandboxBPF* sb, Cond cond, ErrorCode true_ec);
- SandboxBPF* sb_;
- Cond cond_;
- ErrorCode true_ec_;
- friend class Iffer;
+ Elser(internal::IfThenList if_then_list);
+ internal::IfThenList if_then_list_;
friend class Thener;
- DISALLOW_COPY_AND_ASSIGN(Elser);
+ DISALLOW_ASSIGN(Elser);
};
-} // namespace bpfdsl
-
-SANDBOX_EXPORT bpfdsl::Iffer DSL(SandboxBPF* sb);
-
template <typename T>
class SANDBOX_EXPORT Arg {
public:
- explicit Arg(int num);
- bpfdsl::Cond operator==(const T& rhs) const;
+ // Initializes the Arg to represent the |num|th system call
+ // argument, which is of type |T|.
+ Arg(int num) : num_(num), mask_(-1) {}
+
+ Arg(const Arg& arg) : num_(arg.num_), mask_(arg.mask_) {}
+
+ // Returns an Arg representing the current argument, but after
+ // bitwise-and'ing it with |rhs|.
+ Arg operator&(uint64_t rhs) const { return Arg(num_, mask_ & rhs); }
+
+ // Returns a boolean expression comparing whether the system call
+ // argument (after applying a bitmask, if appropriate) equals |rhs|.
+ BoolExpr operator==(T rhs) const;
private:
+ Arg(int num, uint64_t mask) : num_(num), mask_(mask) {}
int num_;
- DISALLOW_COPY_AND_ASSIGN(Arg);
+ uint64_t mask_;
+ DISALLOW_ASSIGN(Arg);
+};
+
+// Helper class to make writing policies easier.
+class SANDBOX_EXPORT SandboxBPFPolicyDSL : public SandboxBPFPolicy {
+ public:
+ SandboxBPFPolicyDSL() : SandboxBPFPolicy() {}
+
+ // User extension point for writing custom sandbox policies.
+ virtual ResultExpr EvaluateSyscall(int sysno) const = 0;
+
+ // Optional overload for specifying alternate behavior for invalid
+ // system calls. The default is to return ENOSYS.
+ virtual ResultExpr InvalidSyscall() const;
+
+ // Override implementations from SandboxBPFPolicy. Marked as FINAL
+ // to prevent mixups with child classes accidentally overloading
+ // these instead of the above methods.
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sb,
+ int sysno) const OVERRIDE FINAL;
+ virtual ErrorCode InvalidSyscall(SandboxBPF* sb) const OVERRIDE FINAL;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SandboxBPFPolicyDSL);
+};
+
+namespace internal {
+
+// Returns a boolean expression that represents whether system call
+// argument |num| of size |size| is equal to |val|, when masked
+// according to |mask|. Users should use the Arg template class below
+// instead of using this API directly.
+SANDBOX_EXPORT BoolExpr
+ ArgEq(int num, size_t size, uint64_t mask, uint64_t val);
+
+// Internal interface implemented by BoolExpr implementations.
+class BoolExprImpl : public base::RefCounted<BoolExprImpl> {
+ public:
+ BoolExprImpl() {}
+ virtual ErrorCode Compile(SandboxBPF* sb,
+ ErrorCode true_ec,
+ ErrorCode false_ec) const = 0;
+
+ protected:
+ virtual ~BoolExprImpl() {}
+
+ private:
+ friend class base::RefCounted<BoolExprImpl>;
+ DISALLOW_COPY_AND_ASSIGN(BoolExprImpl);
};
-extern template class Arg<int>;
+// Internal interface implemented by ResultExpr implementations.
+class ResultExprImpl : public base::RefCounted<ResultExprImpl> {
+ public:
+ ResultExprImpl() {}
+ virtual ErrorCode Compile(SandboxBPF* sb) const = 0;
+
+ protected:
+ virtual ~ResultExprImpl() {}
+
+ private:
+ friend class base::RefCounted<ResultExprImpl>;
+ DISALLOW_COPY_AND_ASSIGN(ResultExprImpl);
+};
+
+// Internal helper class. Represents a (BoolExpr, ResultExpr)-pair
+// node in a linked list.
+struct IfThen : public base::RefCounted<IfThen> {
+ BoolExpr cond;
+ ResultExpr then;
+ IfThenList rest;
+
+ // Returns a new IfThenList with a node for (cond, then) prepended
+ // before rest.
+ static IfThenList Cons(BoolExpr cond, ResultExpr then, IfThenList rest) {
+ return IfThenList(new const IfThen(cond, then, rest));
+ }
+
+ private:
+ IfThen(BoolExpr cond, ResultExpr then, IfThenList rest);
+ virtual ~IfThen();
+ friend class base::RefCounted<IfThen>;
+ DISALLOW_COPY_AND_ASSIGN(IfThen);
+};
+
+} // namespace internal
+
+// Definition requires ArgEq to have been declared. Moved out-of-line
+// to minimize how much internal clutter users have to ignore while
+// reading the header documentation.
+template <typename T>
+BoolExpr Arg<T>::operator==(T rhs) const {
+ return internal::ArgEq(num_, sizeof(T), mask_, rhs);
+}
+
+} // namespace bpf_dsl
} // namespace sandbox
« no previous file with comments | « sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc ('k') | sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698