| 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 <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include <memory> |
| 11 #include <utility> | 12 #include <utility> |
| 12 #include <vector> | 13 #include <vector> |
| 13 | 14 |
| 14 #include "base/macros.h" | 15 #include "base/macros.h" |
| 15 #include "base/memory/ref_counted.h" | |
| 16 #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h" | 16 #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h" |
| 17 #include "sandbox/linux/bpf_dsl/cons.h" | 17 #include "sandbox/linux/bpf_dsl/cons.h" |
| 18 #include "sandbox/linux/bpf_dsl/trap_registry.h" | 18 #include "sandbox/linux/bpf_dsl/trap_registry.h" |
| 19 #include "sandbox/sandbox_export.h" | 19 #include "sandbox/sandbox_export.h" |
| 20 | 20 |
| 21 // The sandbox::bpf_dsl namespace provides a domain-specific language | 21 // The sandbox::bpf_dsl namespace provides a domain-specific language |
| 22 // to make writing BPF policies more expressive. In general, the | 22 // to make writing BPF policies more expressive. In general, the |
| 23 // object types all have value semantics (i.e., they can be copied | 23 // object types all have value semantics (i.e., they can be copied |
| 24 // around, returned from or passed to function calls, etc. without any | 24 // around, returned from or passed to function calls, etc. without any |
| 25 // surprising side effects), though not all support assignment. | 25 // surprising side effects), though not all support assignment. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 // intuitive, but are described in more detail below. | 70 // intuitive, but are described in more detail below. |
| 71 // | 71 // |
| 72 // (Credit to Sean Parent's "Inheritance is the Base Class of Evil" | 72 // (Credit to Sean Parent's "Inheritance is the Base Class of Evil" |
| 73 // talk at Going Native 2013 for promoting value semantics via shared | 73 // talk at Going Native 2013 for promoting value semantics via shared |
| 74 // pointers to immutable state.) | 74 // pointers to immutable state.) |
| 75 | 75 |
| 76 namespace sandbox { | 76 namespace sandbox { |
| 77 namespace bpf_dsl { | 77 namespace bpf_dsl { |
| 78 | 78 |
| 79 // ResultExpr is an opaque reference to an immutable result expression tree. | 79 // ResultExpr is an opaque reference to an immutable result expression tree. |
| 80 typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr; | 80 using ResultExpr = std::shared_ptr<const internal::ResultExprImpl>; |
| 81 | 81 |
| 82 // BoolExpr is an opaque reference to an immutable boolean expression tree. | 82 // BoolExpr is an opaque reference to an immutable boolean expression tree. |
| 83 typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr; | 83 using BoolExpr = std::shared_ptr<const internal::BoolExprImpl>; |
| 84 | 84 |
| 85 // Allow specifies a result that the system call should be allowed to | 85 // Allow specifies a result that the system call should be allowed to |
| 86 // execute normally. | 86 // execute normally. |
| 87 SANDBOX_EXPORT ResultExpr Allow(); | 87 SANDBOX_EXPORT ResultExpr Allow(); |
| 88 | 88 |
| 89 // Error specifies a result that the system call should fail with | 89 // Error specifies a result that the system call should fail with |
| 90 // error number |err|. As a special case, Error(0) will result in the | 90 // error number |err|. As a special case, Error(0) will result in the |
| 91 // system call appearing to have succeeded, but without having any | 91 // system call appearing to have succeeded, but without having any |
| 92 // side effects. | 92 // side effects. |
| 93 SANDBOX_EXPORT ResultExpr Error(int err); | 93 SANDBOX_EXPORT ResultExpr Error(int err); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 114 // very useful to diagnose code that is incompatible with the sandbox. | 114 // very useful to diagnose code that is incompatible with the sandbox. |
| 115 // If even a single system call returns "UnsafeTrap", the security of | 115 // If even a single system call returns "UnsafeTrap", the security of |
| 116 // entire sandbox should be considered compromised. | 116 // entire sandbox should be considered compromised. |
| 117 SANDBOX_EXPORT ResultExpr | 117 SANDBOX_EXPORT ResultExpr |
| 118 UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux); | 118 UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux); |
| 119 | 119 |
| 120 // BoolConst converts a bool value into a BoolExpr. | 120 // BoolConst converts a bool value into a BoolExpr. |
| 121 SANDBOX_EXPORT BoolExpr BoolConst(bool value); | 121 SANDBOX_EXPORT BoolExpr BoolConst(bool value); |
| 122 | 122 |
| 123 // Not returns a BoolExpr representing the logical negation of |cond|. | 123 // Not returns a BoolExpr representing the logical negation of |cond|. |
| 124 SANDBOX_EXPORT BoolExpr Not(const BoolExpr& cond); | 124 SANDBOX_EXPORT BoolExpr Not(BoolExpr cond); |
| 125 | 125 |
| 126 // AllOf returns a BoolExpr representing the logical conjunction ("and") | 126 // AllOf returns a BoolExpr representing the logical conjunction ("and") |
| 127 // of zero or more BoolExprs. | 127 // of zero or more BoolExprs. |
| 128 SANDBOX_EXPORT BoolExpr AllOf(); | 128 SANDBOX_EXPORT BoolExpr AllOf(); |
| 129 SANDBOX_EXPORT BoolExpr AllOf(const BoolExpr& lhs, const BoolExpr& rhs); | 129 SANDBOX_EXPORT BoolExpr AllOf(BoolExpr lhs, BoolExpr rhs); |
| 130 template <typename... Rest> | 130 template <typename... Rest> |
| 131 SANDBOX_EXPORT BoolExpr AllOf(const BoolExpr& first, const Rest&... rest); | 131 SANDBOX_EXPORT BoolExpr AllOf(BoolExpr first, Rest&&... rest); |
| 132 | 132 |
| 133 // AnyOf returns a BoolExpr representing the logical disjunction ("or") | 133 // AnyOf returns a BoolExpr representing the logical disjunction ("or") |
| 134 // of zero or more BoolExprs. | 134 // of zero or more BoolExprs. |
| 135 SANDBOX_EXPORT BoolExpr AnyOf(); | 135 SANDBOX_EXPORT BoolExpr AnyOf(); |
| 136 SANDBOX_EXPORT BoolExpr AnyOf(const BoolExpr& lhs, const BoolExpr& rhs); | 136 SANDBOX_EXPORT BoolExpr AnyOf(BoolExpr lhs, BoolExpr rhs); |
| 137 template <typename... Rest> | 137 template <typename... Rest> |
| 138 SANDBOX_EXPORT BoolExpr AnyOf(const BoolExpr& first, const Rest&... rest); | 138 SANDBOX_EXPORT BoolExpr AnyOf(BoolExpr first, Rest&&... rest); |
| 139 | 139 |
| 140 template <typename T> | 140 template <typename T> |
| 141 class SANDBOX_EXPORT Arg { | 141 class SANDBOX_EXPORT Arg { |
| 142 public: | 142 public: |
| 143 // Initializes the Arg to represent the |num|th system call | 143 // Initializes the Arg to represent the |num|th system call |
| 144 // argument (indexed from 0), which is of type |T|. | 144 // argument (indexed from 0), which is of type |T|. |
| 145 explicit Arg(int num); | 145 explicit Arg(int num); |
| 146 | 146 |
| 147 Arg(const Arg& arg) : num_(arg.num_), mask_(arg.mask_) {} | 147 Arg(const Arg& arg) : num_(arg.num_), mask_(arg.mask_) {} |
| 148 | 148 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 166 BoolExpr EqualTo(T val) const; | 166 BoolExpr EqualTo(T val) const; |
| 167 | 167 |
| 168 int num_; | 168 int num_; |
| 169 uint64_t mask_; | 169 uint64_t mask_; |
| 170 | 170 |
| 171 DISALLOW_ASSIGN(Arg); | 171 DISALLOW_ASSIGN(Arg); |
| 172 }; | 172 }; |
| 173 | 173 |
| 174 // If begins a conditional result expression predicated on the | 174 // If begins a conditional result expression predicated on the |
| 175 // specified boolean expression. | 175 // specified boolean expression. |
| 176 SANDBOX_EXPORT Elser If(const BoolExpr& cond, const ResultExpr& then_result); | 176 SANDBOX_EXPORT Elser If(BoolExpr cond, ResultExpr then_result); |
| 177 | 177 |
| 178 class SANDBOX_EXPORT Elser { | 178 class SANDBOX_EXPORT Elser { |
| 179 public: | 179 public: |
| 180 Elser(const Elser& elser); | 180 Elser(const Elser& elser); |
| 181 ~Elser(); | 181 ~Elser(); |
| 182 | 182 |
| 183 // ElseIf extends the conditional result expression with another | 183 // ElseIf extends the conditional result expression with another |
| 184 // "if then" clause, predicated on the specified boolean expression. | 184 // "if then" clause, predicated on the specified boolean expression. |
| 185 Elser ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const; | 185 Elser ElseIf(BoolExpr cond, ResultExpr then_result) const; |
| 186 | 186 |
| 187 // Else terminates a conditional result expression using |else_result| as | 187 // Else terminates a conditional result expression using |else_result| as |
| 188 // the default fallback result expression. | 188 // the default fallback result expression. |
| 189 ResultExpr Else(const ResultExpr& else_result) const; | 189 ResultExpr Else(ResultExpr else_result) const; |
| 190 | 190 |
| 191 private: | 191 private: |
| 192 typedef std::pair<BoolExpr, ResultExpr> Clause; | 192 using Clause = std::pair<BoolExpr, ResultExpr>; |
| 193 | 193 |
| 194 explicit Elser(cons::List<Clause> clause_list); | 194 explicit Elser(cons::List<Clause> clause_list); |
| 195 | 195 |
| 196 cons::List<Clause> clause_list_; | 196 cons::List<Clause> clause_list_; |
| 197 | 197 |
| 198 friend Elser If(const BoolExpr&, const ResultExpr&); | 198 friend Elser If(BoolExpr, ResultExpr); |
| 199 template <typename T> | 199 template <typename T> |
| 200 friend Caser<T> Switch(const Arg<T>&); | 200 friend Caser<T> Switch(const Arg<T>&); |
| 201 DISALLOW_ASSIGN(Elser); | 201 DISALLOW_ASSIGN(Elser); |
| 202 }; | 202 }; |
| 203 | 203 |
| 204 // Switch begins a switch expression dispatched according to the | 204 // Switch begins a switch expression dispatched according to the |
| 205 // specified argument value. | 205 // specified argument value. |
| 206 template <typename T> | 206 template <typename T> |
| 207 SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg); | 207 SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg); |
| 208 | 208 |
| 209 template <typename T> | 209 template <typename T> |
| 210 class SANDBOX_EXPORT Caser { | 210 class SANDBOX_EXPORT Caser { |
| 211 public: | 211 public: |
| 212 Caser(const Caser<T>& caser) : arg_(caser.arg_), elser_(caser.elser_) {} | 212 Caser(const Caser<T>& caser) : arg_(caser.arg_), elser_(caser.elser_) {} |
| 213 ~Caser() {} | 213 ~Caser() {} |
| 214 | 214 |
| 215 // Case adds a single-value "case" clause to the switch. | 215 // Case adds a single-value "case" clause to the switch. |
| 216 Caser<T> Case(T value, const ResultExpr& result) const; | 216 Caser<T> Case(T value, ResultExpr result) const; |
| 217 | 217 |
| 218 // Cases adds a multiple-value "case" clause to the switch. | 218 // Cases adds a multiple-value "case" clause to the switch. |
| 219 // See also the SANDBOX_BPF_DSL_CASES macro below for a more idiomatic way | 219 // See also the SANDBOX_BPF_DSL_CASES macro below for a more idiomatic way |
| 220 // of using this function. | 220 // of using this function. |
| 221 template <typename... Values> | 221 template <typename... Values> |
| 222 Caser<T> CasesImpl(const ResultExpr& result, const Values&... values) const; | 222 Caser<T> CasesImpl(ResultExpr result, const Values&... values) const; |
| 223 | 223 |
| 224 // Terminate the switch with a "default" clause. | 224 // Terminate the switch with a "default" clause. |
| 225 ResultExpr Default(const ResultExpr& result) const; | 225 ResultExpr Default(ResultExpr result) const; |
| 226 | 226 |
| 227 private: | 227 private: |
| 228 Caser(const Arg<T>& arg, Elser elser) : arg_(arg), elser_(elser) {} | 228 Caser(const Arg<T>& arg, Elser elser) : arg_(arg), elser_(elser) {} |
| 229 | 229 |
| 230 Arg<T> arg_; | 230 Arg<T> arg_; |
| 231 Elser elser_; | 231 Elser elser_; |
| 232 | 232 |
| 233 template <typename U> | 233 template <typename U> |
| 234 friend Caser<U> Switch(const Arg<U>&); | 234 friend Caser<U> Switch(const Arg<U>&); |
| 235 DISALLOW_ASSIGN(Caser); | 235 DISALLOW_ASSIGN(Caser); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 } | 292 } |
| 293 return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint64_t>(val)); | 293 return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint64_t>(val)); |
| 294 } | 294 } |
| 295 | 295 |
| 296 template <typename T> | 296 template <typename T> |
| 297 SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg) { | 297 SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg) { |
| 298 return Caser<T>(arg, Elser(nullptr)); | 298 return Caser<T>(arg, Elser(nullptr)); |
| 299 } | 299 } |
| 300 | 300 |
| 301 template <typename T> | 301 template <typename T> |
| 302 Caser<T> Caser<T>::Case(T value, const ResultExpr& result) const { | 302 Caser<T> Caser<T>::Case(T value, ResultExpr result) const { |
| 303 return SANDBOX_BPF_DSL_CASES((value), result); | 303 return SANDBOX_BPF_DSL_CASES((value), std::move(result)); |
| 304 } | 304 } |
| 305 | 305 |
| 306 template <typename T> | 306 template <typename T> |
| 307 template <typename... Values> | 307 template <typename... Values> |
| 308 Caser<T> Caser<T>::CasesImpl(const ResultExpr& result, | 308 Caser<T> Caser<T>::CasesImpl(ResultExpr result, const Values&... values) const { |
| 309 const Values&... values) const { | |
| 310 // Theoretically we could evaluate arg_ just once and emit a more efficient | 309 // Theoretically we could evaluate arg_ just once and emit a more efficient |
| 311 // dispatch table, but for now we simply translate into an equivalent | 310 // dispatch table, but for now we simply translate into an equivalent |
| 312 // If/ElseIf/Else chain. | 311 // If/ElseIf/Else chain. |
| 313 | 312 |
| 314 return Caser<T>(arg_, elser_.ElseIf(AnyOf((arg_ == values)...), result)); | 313 return Caser<T>(arg_, |
| 314 elser_.ElseIf(AnyOf((arg_ == values)...), std::move(result))); |
| 315 } | 315 } |
| 316 | 316 |
| 317 template <typename T> | 317 template <typename T> |
| 318 ResultExpr Caser<T>::Default(const ResultExpr& result) const { | 318 ResultExpr Caser<T>::Default(ResultExpr result) const { |
| 319 return elser_.Else(result); | 319 return elser_.Else(std::move(result)); |
| 320 } | 320 } |
| 321 | 321 |
| 322 template <typename... Rest> | 322 template <typename... Rest> |
| 323 BoolExpr AllOf(const BoolExpr& first, const Rest&... rest) { | 323 BoolExpr AllOf(BoolExpr first, Rest&&... rest) { |
| 324 return AllOf(first, AllOf(rest...)); | 324 return AllOf(std::move(first), AllOf(std::forward<Rest>(rest)...)); |
| 325 } | 325 } |
| 326 | 326 |
| 327 template <typename... Rest> | 327 template <typename... Rest> |
| 328 BoolExpr AnyOf(const BoolExpr& first, const Rest&... rest) { | 328 BoolExpr AnyOf(BoolExpr first, Rest&&... rest) { |
| 329 return AnyOf(first, AnyOf(rest...)); | 329 return AnyOf(std::move(first), AnyOf(std::forward<Rest>(rest)...)); |
| 330 } | 330 } |
| 331 | 331 |
| 332 } // namespace bpf_dsl | 332 } // namespace bpf_dsl |
| 333 } // namespace sandbox | 333 } // namespace sandbox |
| 334 | 334 |
| 335 #endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ | 335 #endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ |
| OLD | NEW |