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

Side by Side Diff: sandbox/linux/bpf_dsl/bpf_dsl.h

Issue 299743002: Add domain-specific language for BPF policies (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Move bpf_dsl into its own top-level directory Created 6 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/bpf_dsl/DEPS ('k') | sandbox/linux/bpf_dsl/bpf_dsl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_
6 #define SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_
7
8 #include <stdint.h>
9
10 #include <utility>
11
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "sandbox/linux/bpf_dsl/cons.h"
15 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
16 #include "sandbox/linux/seccomp-bpf/trap.h"
17 #include "sandbox/sandbox_export.h"
18
19 namespace sandbox {
20 class ErrorCode;
21 class SandboxBPF;
22 }
23
24 // The sandbox::bpf_dsl namespace provides a domain-specific language
25 // to make writing BPF policies more expressive. In general, the
26 // object types all have value semantics (i.e., they can be copied
27 // around, returned from or passed to function calls, etc. without any
28 // surprising side effects), though not all support assignment.
29 //
30 // An idiomatic and demonstrative (albeit silly) example of this API
31 // would be:
32 //
33 // #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
34 //
35 // using namespace sandbox::bpf_dsl;
36 //
37 // class SillyPolicy : public SandboxBPFDSLPolicy {
38 // public:
39 // SillyPolicy() {}
40 // virtual ~SillyPolicy() {}
41 // virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
42 // if (sysno == __NR_fcntl) {
43 // Arg<int> fd(0), cmd(1);
44 // Arg<unsigned long> flags(2);
45 // const unsigned long kBadFlags = ~(O_ACCMODE | O_NONBLOCK);
46 // return If(fd == 0 && cmd == F_SETFL && (flags & kBadFlags) == 0,
47 // Allow())
48 // .ElseIf(cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC,
49 // Error(EMFILE))
50 // .Else(Trap(SetFlagHandler, NULL));
51 // } else {
52 // return Allow();
53 // }
54 // }
55 //
56 // private:
57 // DISALLOW_COPY_AND_ASSIGN(SillyPolicy);
58 // };
59 //
60 // More generally, the DSL currently supports the following grammar:
61 //
62 // result = Allow() | Error(errno) | Trap(trap_func, arg)
63 // | If(bool, result)[.ElseIf(bool, result)].Else(result)
64 // bool = arg == val | (arg & mask) == mask | (arg & mask) == 0
65 // | !bool | bool && bool | bool || bool
66 //
67 // The semantics of each function and operator are intended to be
68 // intuitive, but are described in more detail below.
69 //
70 // (Credit to Sean Parent's "Inheritance is the Base Class of Evil"
71 // talk at Going Native 2013 for promoting value semantics via shared
72 // pointers to immutable state.)
73
74 namespace sandbox {
75 namespace bpf_dsl {
76
77 // Forward declarations of classes; see below for proper documentation.
78 class Elser;
79 namespace internal {
80 class ResultExprImpl;
81 class BoolExprImpl;
82 }
83
84 // ResultExpr is an opaque reference to an immutable result expression tree.
85 typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr;
86
87 // BoolExpr is an opaque reference to an immutable boolean expression tree.
88 typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr;
89
90 // Helper class to make writing policies easier.
91 class SANDBOX_EXPORT SandboxBPFDSLPolicy : public SandboxBPFPolicy {
92 public:
93 SandboxBPFDSLPolicy() : SandboxBPFPolicy() {}
94 virtual ~SandboxBPFDSLPolicy() {}
95
96 // User extension point for writing custom sandbox policies.
97 virtual ResultExpr EvaluateSyscall(int sysno) const = 0;
98
99 // Optional overload for specifying alternate behavior for invalid
100 // system calls. The default is to return ENOSYS.
101 virtual ResultExpr InvalidSyscall() const;
102
103 // Override implementations from SandboxBPFPolicy. Marked as FINAL
104 // to prevent mixups with child classes accidentally overloading
105 // these instead of the above methods.
106 virtual ErrorCode EvaluateSyscall(SandboxBPF* sb,
107 int sysno) const OVERRIDE FINAL;
108 virtual ErrorCode InvalidSyscall(SandboxBPF* sb) const OVERRIDE FINAL;
109
110 // Helper method so policies can just write Trap(func, aux).
111 static ResultExpr Trap(::sandbox::Trap::TrapFnc trap_func, void* aux);
112
113 private:
114 DISALLOW_COPY_AND_ASSIGN(SandboxBPFDSLPolicy);
115 };
116
117 // Allow specifies a result that the system call should be allowed to
118 // execute normally.
119 SANDBOX_EXPORT ResultExpr Allow();
120
121 // Error specifies a result that the system call should fail with
122 // error number |err|. As a special case, Error(0) will result in the
123 // system call appearing to have succeeded, but without having any
124 // side effects.
125 SANDBOX_EXPORT ResultExpr Error(int err);
126
127 // Trap specifies a result that the system call should be handled by
128 // trapping back into userspace and invoking |trap_func|, passing
129 // |aux| as the second parameter.
130 SANDBOX_EXPORT ResultExpr Trap(::sandbox::Trap::TrapFnc trap_func, void* aux);
131
132 template <typename T>
133 class SANDBOX_EXPORT Arg {
134 public:
135 // Initializes the Arg to represent the |num|th system call
136 // argument (indexed from 0), which is of type |T|.
137 explicit Arg(int num) : num_(num), mask_(-1) {}
138
139 Arg(const Arg& arg) : num_(arg.num_), mask_(arg.mask_) {}
140
141 // Returns an Arg representing the current argument, but after
142 // bitwise-and'ing it with |rhs|.
143 Arg operator&(uint64_t rhs) const { return Arg(num_, mask_ & rhs); }
144
145 // Returns a boolean expression comparing whether the system call
146 // argument (after applying any bitmasks, if appropriate) equals |rhs|.
147 BoolExpr operator==(T rhs) const;
148
149 private:
150 Arg(int num, uint64_t mask) : num_(num), mask_(mask) {}
151 int num_;
152 uint64_t mask_;
153 DISALLOW_ASSIGN(Arg);
154 };
155
156 // Various ways to combine boolean expressions into more complex expressions.
157 // They follow standard boolean algebra laws.
158 SANDBOX_EXPORT BoolExpr operator!(BoolExpr cond);
159 SANDBOX_EXPORT BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs);
160 SANDBOX_EXPORT BoolExpr operator||(BoolExpr lhs, BoolExpr rhs);
161
162 // If begins a conditional result expression predicated on the
163 // specified boolean expression.
164 SANDBOX_EXPORT Elser If(BoolExpr cond, ResultExpr then_result);
165
166 class SANDBOX_EXPORT Elser {
167 public:
168 Elser(const Elser& elser);
169 ~Elser();
170
171 // ElseIf extends the conditional result expression with another
172 // "if then" clause, predicated on the specified boolean expression.
173 Elser ElseIf(BoolExpr cond, ResultExpr then_result) const;
174
175 // Else terminates a conditional result expression using |else_result| as
176 // the default fallback result expression.
177 ResultExpr Else(ResultExpr else_result) const;
178
179 private:
180 typedef std::pair<BoolExpr, ResultExpr> Clause;
181 explicit Elser(Cons<Clause>::List clause_list);
182 Cons<Clause>::List clause_list_;
183 friend Elser If(BoolExpr, ResultExpr);
184 DISALLOW_ASSIGN(Elser);
185 };
186
187 // =====================================================================
188 // Official API ends here.
189 // =====================================================================
190
191 // Definitions below are necessary here only for C++03 compatibility.
192 // Once C++11 is available, they should be moved into bpf_dsl.cc via extern
193 // templates.
194 namespace internal {
195
196 // Returns a boolean expression that represents whether system call
197 // argument |num| of size |size| is equal to |val|, when masked
198 // according to |mask|. Users should use the Arg template class below
199 // instead of using this API directly.
200 SANDBOX_EXPORT BoolExpr
201 ArgEq(int num, size_t size, uint64_t mask, uint64_t val);
202
203 // Internal interface implemented by BoolExpr implementations.
204 class SANDBOX_EXPORT BoolExprImpl : public base::RefCounted<BoolExprImpl> {
205 public:
206 BoolExprImpl() {}
207 virtual ErrorCode Compile(SandboxBPF* sb,
208 ErrorCode true_ec,
209 ErrorCode false_ec) const = 0;
210
211 protected:
212 virtual ~BoolExprImpl() {}
213
214 private:
215 friend class base::RefCounted<BoolExprImpl>;
216 DISALLOW_COPY_AND_ASSIGN(BoolExprImpl);
217 };
218
219 // Internal interface implemented by ResultExpr implementations.
220 class SANDBOX_EXPORT ResultExprImpl : public base::RefCounted<ResultExprImpl> {
221 public:
222 ResultExprImpl() {}
223 virtual ErrorCode Compile(SandboxBPF* sb) const = 0;
224
225 protected:
226 virtual ~ResultExprImpl() {}
227
228 private:
229 friend class base::RefCounted<ResultExprImpl>;
230 DISALLOW_COPY_AND_ASSIGN(ResultExprImpl);
231 };
232
233 } // namespace internal
234
235 // Definition requires ArgEq to have been declared. Moved out-of-line
236 // to minimize how much internal clutter users have to ignore while
237 // reading the header documentation.
238 template <typename T>
239 BoolExpr Arg<T>::operator==(T rhs) const {
240 return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint64_t>(rhs));
241 }
242
243 } // namespace bpf_dsl
244 } // namespace sandbox
245
246 #endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_
OLDNEW
« no previous file with comments | « sandbox/linux/bpf_dsl/DEPS ('k') | sandbox/linux/bpf_dsl/bpf_dsl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698