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

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

Issue 438683004: bpf_dsl: support Switch/Case expressions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync and resolve conflicts Created 6 years, 3 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 | « no previous file | 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ 5 #ifndef SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_
6 #define SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ 6 #define SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <utility> 10 #include <utility>
11 #include <vector>
11 12
12 #include "base/macros.h" 13 #include "base/macros.h"
13 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
14 #include "sandbox/linux/bpf_dsl/cons.h" 15 #include "sandbox/linux/bpf_dsl/cons.h"
15 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" 16 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
16 #include "sandbox/linux/seccomp-bpf/trap.h" 17 #include "sandbox/linux/seccomp-bpf/trap.h"
17 #include "sandbox/sandbox_export.h" 18 #include "sandbox/sandbox_export.h"
18 19
19 namespace sandbox { 20 namespace sandbox {
20 class ErrorCode; 21 class ErrorCode;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 // return Allow(); 53 // return Allow();
53 // } 54 // }
54 // } 55 // }
55 // 56 //
56 // private: 57 // private:
57 // DISALLOW_COPY_AND_ASSIGN(SillyPolicy); 58 // DISALLOW_COPY_AND_ASSIGN(SillyPolicy);
58 // }; 59 // };
59 // 60 //
60 // More generally, the DSL currently supports the following grammar: 61 // More generally, the DSL currently supports the following grammar:
61 // 62 //
62 // result = Allow() | Error(errno) | Trap(trap_func, arg) 63 // result = Allow() | Error(errno) | Trap(trap_func, aux)
63 // | If(bool, result)[.ElseIf(bool, result)].Else(result) 64 // | If(bool, result)[.ElseIf(bool, result)].Else(result)
64 // bool = arg == val | (arg & mask) == val 65 // | Switch(arg)[.Case(val, result)].Default(result)
65 // | !bool | bool && bool | bool || bool 66 // bool = BoolConst(boolean) | !bool | bool && bool | bool || bool
67 // | arg == val
68 // arg = Arg<T>(num) | arg & mask
66 // 69 //
67 // The semantics of each function and operator are intended to be 70 // The semantics of each function and operator are intended to be
68 // intuitive, but are described in more detail below. 71 // intuitive, but are described in more detail below.
69 // 72 //
70 // (Credit to Sean Parent's "Inheritance is the Base Class of Evil" 73 // (Credit to Sean Parent's "Inheritance is the Base Class of Evil"
71 // talk at Going Native 2013 for promoting value semantics via shared 74 // talk at Going Native 2013 for promoting value semantics via shared
72 // pointers to immutable state.) 75 // pointers to immutable state.)
73 76
74 namespace sandbox { 77 namespace sandbox {
75 namespace bpf_dsl { 78 namespace bpf_dsl {
76 79
77 // Forward declarations of classes; see below for proper documentation. 80 // Forward declarations of classes; see below for proper documentation.
78 class Elser; 81 class Elser;
82 template <typename T>
83 class Caser;
79 namespace internal { 84 namespace internal {
80 class ResultExprImpl; 85 class ResultExprImpl;
81 class BoolExprImpl; 86 class BoolExprImpl;
82 } 87 }
83 88
84 // ResultExpr is an opaque reference to an immutable result expression tree. 89 // ResultExpr is an opaque reference to an immutable result expression tree.
85 typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr; 90 typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr;
86 91
87 // BoolExpr is an opaque reference to an immutable boolean expression tree. 92 // BoolExpr is an opaque reference to an immutable boolean expression tree.
88 typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr; 93 typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 Arg(int num, uint64_t mask) : num_(num), mask_(mask) {} 157 Arg(int num, uint64_t mask) : num_(num), mask_(mask) {}
153 158
154 BoolExpr EqualTo(T val) const; 159 BoolExpr EqualTo(T val) const;
155 160
156 int num_; 161 int num_;
157 uint64_t mask_; 162 uint64_t mask_;
158 163
159 DISALLOW_ASSIGN(Arg); 164 DISALLOW_ASSIGN(Arg);
160 }; 165 };
161 166
167 // Convert a bool value into a BoolExpr.
168 SANDBOX_EXPORT BoolExpr BoolConst(bool value);
169
162 // Various ways to combine boolean expressions into more complex expressions. 170 // Various ways to combine boolean expressions into more complex expressions.
163 // They follow standard boolean algebra laws. 171 // They follow standard boolean algebra laws.
164 SANDBOX_EXPORT BoolExpr operator!(const BoolExpr& cond); 172 SANDBOX_EXPORT BoolExpr operator!(const BoolExpr& cond);
165 SANDBOX_EXPORT BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs); 173 SANDBOX_EXPORT BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs);
166 SANDBOX_EXPORT BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs); 174 SANDBOX_EXPORT BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs);
167 175
168 // If begins a conditional result expression predicated on the 176 // If begins a conditional result expression predicated on the
169 // specified boolean expression. 177 // specified boolean expression.
170 SANDBOX_EXPORT Elser If(const BoolExpr& cond, const ResultExpr& then_result); 178 SANDBOX_EXPORT Elser If(const BoolExpr& cond, const ResultExpr& then_result);
171 179
(...skipping 11 matching lines...) Expand all
183 ResultExpr Else(const ResultExpr& else_result) const; 191 ResultExpr Else(const ResultExpr& else_result) const;
184 192
185 private: 193 private:
186 typedef std::pair<BoolExpr, ResultExpr> Clause; 194 typedef std::pair<BoolExpr, ResultExpr> Clause;
187 195
188 explicit Elser(Cons<Clause>::List clause_list); 196 explicit Elser(Cons<Clause>::List clause_list);
189 197
190 Cons<Clause>::List clause_list_; 198 Cons<Clause>::List clause_list_;
191 199
192 friend Elser If(const BoolExpr&, const ResultExpr&); 200 friend Elser If(const BoolExpr&, const ResultExpr&);
201 template <typename T>
202 friend Caser<T> Switch(const Arg<T>&);
193 DISALLOW_ASSIGN(Elser); 203 DISALLOW_ASSIGN(Elser);
194 }; 204 };
195 205
206 // Switch begins a switch expression dispatched according to the
207 // specified argument value.
208 template <typename T>
209 SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg);
210
211 template <typename T>
212 class SANDBOX_EXPORT Caser {
213 public:
214 Caser(const Caser<T>& caser) : arg_(caser.arg_), elser_(caser.elser_) {}
215 ~Caser() {}
216
217 // Case adds a single-value "case" clause to the switch.
218 Caser<T> Case(T value, ResultExpr result) const;
219
220 // Cases adds a multiple-value "case" clause to the switch.
221 // See also the SANDBOX_BPF_DSL_CASES macro below for a more idiomatic way
222 // of using this function.
223 Caser<T> Cases(const std::vector<T>& values, ResultExpr result) const;
224
225 // Terminate the switch with a "default" clause.
226 ResultExpr Default(ResultExpr result) const;
227
228 private:
229 Caser(const Arg<T>& arg, Elser elser) : arg_(arg), elser_(elser) {}
230
231 Arg<T> arg_;
232 Elser elser_;
233
234 template <typename U>
235 friend Caser<U> Switch(const Arg<U>&);
236 DISALLOW_ASSIGN(Caser);
237 };
238
239 // Recommended usage is to put
240 // #define CASES SANDBOX_BPF_DSL_CASES
241 // near the top of the .cc file (e.g., nearby any "using" statements), then
242 // use like:
243 // Switch(arg).CASES((3, 5, 7), result)...;
244 #define SANDBOX_BPF_DSL_CASES(values, result) \
245 Cases(SANDBOX_BPF_DSL_CASES_HELPER values, result)
246
247 // Helper macro to construct a std::vector from an initializer list.
248 // TODO(mdempsky): Convert to use C++11 initializer lists instead.
249 #define SANDBOX_BPF_DSL_CASES_HELPER(value, ...) \
250 ({ \
251 const __typeof__(value) bpf_dsl_cases_values[] = {value, __VA_ARGS__}; \
252 std::vector<__typeof__(value)>( \
253 bpf_dsl_cases_values, \
254 bpf_dsl_cases_values + arraysize(bpf_dsl_cases_values)); \
255 })
256
196 // ===================================================================== 257 // =====================================================================
197 // Official API ends here. 258 // Official API ends here.
198 // ===================================================================== 259 // =====================================================================
199 260
200 // Definitions below are necessary here only for C++03 compatibility. 261 // Definitions below are necessary here only for C++03 compatibility.
201 // Once C++11 is available, they should be moved into bpf_dsl.cc via extern 262 // Once C++11 is available, they should be moved into bpf_dsl.cc via extern
202 // templates. 263 // templates.
203 namespace internal { 264 namespace internal {
204 265
205 // Returns a boolean expression that represents whether system call 266 // Returns a boolean expression that represents whether system call
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 // reading the header documentation. 315 // reading the header documentation.
255 // 316 //
256 // Additionally, we use this helper member function to avoid linker errors 317 // Additionally, we use this helper member function to avoid linker errors
257 // caused by defining operator== out-of-line. For a more detailed explanation, 318 // caused by defining operator== out-of-line. For a more detailed explanation,
258 // see http://www.parashift.com/c++-faq-lite/template-friends.html. 319 // see http://www.parashift.com/c++-faq-lite/template-friends.html.
259 template <typename T> 320 template <typename T>
260 BoolExpr Arg<T>::EqualTo(T val) const { 321 BoolExpr Arg<T>::EqualTo(T val) const {
261 return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint64_t>(val)); 322 return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint64_t>(val));
262 } 323 }
263 324
325 template <typename T>
326 SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg) {
327 return Caser<T>(arg, Elser(Cons<Elser::Clause>::List()));
328 }
329
330 template <typename T>
331 Caser<T> Caser<T>::Case(T value, ResultExpr result) const {
332 return SANDBOX_BPF_DSL_CASES((value), result);
333 }
334
335 template <typename T>
336 Caser<T> Caser<T>::Cases(const std::vector<T>& values,
337 ResultExpr result) const {
338 // Theoretically we could evaluate arg_ just once and emit a more efficient
339 // dispatch table, but for now we simply translate into an equivalent
340 // If/ElseIf/Else chain.
341
342 typedef typename std::vector<T>::const_iterator Iter;
343 BoolExpr test = BoolConst(false);
344 for (Iter i = values.begin(), end = values.end(); i != end; i++) {
jln (very slow on Chromium) 2014/09/05 22:48:39 Nit: I find ++i more idiomatic (because there is n
mdempsky 2014/09/05 23:08:31 Done. (Oops, yeah, I usually use preincrement too
345 test = test || (arg_ == *i);
346 }
347 return Caser<T>(arg_, elser_.ElseIf(test, result));
348 }
349
350 template <typename T>
351 ResultExpr Caser<T>::Default(ResultExpr result) const {
352 return elser_.Else(result);
353 }
354
264 } // namespace bpf_dsl 355 } // namespace bpf_dsl
265 } // namespace sandbox 356 } // namespace sandbox
266 357
267 #endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ 358 #endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_
OLDNEW
« no previous file with comments | « no previous file | sandbox/linux/bpf_dsl/bpf_dsl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698