OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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_ |
OLD | NEW |