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