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

Side by Side Diff: sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h

Issue 299683004: Rewrite all BPF policies to use DSL API Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Overhaul of DSL and implementation Created 6 years, 7 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
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_SECCOMP_BPF_HELPERS_BPF_DSL_H_ 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
6 #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_ 6 #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
7 7
8 #include <stdint.h>
9
8 #include "base/macros.h" 10 #include "base/macros.h"
9 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
10 #include "sandbox/linux/seccomp-bpf/errorcode.h" 12 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
11 #include "sandbox/sandbox_export.h" 13 #include "sandbox/sandbox_export.h"
12 14
13 namespace sandbox { 15 namespace sandbox {
16 struct arch_seccomp_data;
17 class ErrorCode;
14 class SandboxBPF; 18 class SandboxBPF;
15 } 19 }
16 20
21 // The sandbox::bpf_dsl namespace provides a domain-specific language
22 // to make writing BPF policies more expressive. In general, the
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
25 // surprising side effects), though not all support assignment.
26 //
27 // An idiomatic and demonstrative (albeit silly) example of this API
28 // would be:
29 //
30 // #include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h"
31 //
32 // using namespace sandbox::bpf_dsl;
33 //
34 // class SillyPolicy : public SandboxBPFPolicy {
35 // public:
36 // SillyPolicy() {}
37 // virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
38 // if (sysno == __NR_fcntl) {
39 // Arg<int> fd(0), cmd(1);
40 // Arg<unsigned long> flags(2);
41 // const unsigned long kBadFlags = ~(O_ACCMODE|O_NONBLOCK);
42 // return If(fd == 0 && cmd == F_SETFL &&
43 // (flags & kBadFlags) == 0).Then(
44 // Allow()
45 // ).ElseIf(cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC).Then(
46 // Error(EMFILE)
47 // ).Else(
48 // Trap(SetFlagHandler, NULL)
49 // );
50 // }
51 // }
52 // private:
53 // DISALLOW_COPY_AND_ASSIGN(SillyPolicy);
54 // };
55 //
56 // More generally, the DSL currently supports the following grammar:
57 //
58 // result = Allow() | Error(errno) | Trap(trap_func, arg)
59 // | If(bool).Then(result)[.ElseIf(bool).Then(result)].Else(result)
60 // bool = arg == val | (arg & mask) == mask | (arg & mask) == 0
61 // | !bool | bool && bool | bool || bool
62 //
63 // The semantics of each function and operator are intended to be
64 // intuitive, but are described in more detail below.
65 //
66 // (Credit to Sean Parent's "Inheritance is the Base Class of Evil"
67 // talk at Going Native 2013 for promoting value semantics via shared
68 // pointers to immutable state.)
69
17 namespace sandbox { 70 namespace sandbox {
18 71
19 namespace bpfdsl { 72 namespace bpf_dsl {
20 73
21 class CondImpl : public base::RefCounted<CondImpl> { 74 // Forward declarations of classes; see below for proper documentation.
22 public: 75 class Thener;
23 CondImpl() {} 76 class Elser;
77 namespace internal {
78 class ResultExprImpl;
79 class BoolExprImpl;
80 struct IfThen;
81 typedef scoped_refptr<const IfThen> IfThenList;
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 // Various ways to combine boolean expressions into more complex expressions.
91 // They follow standard boolean algebra laws.
92 SANDBOX_EXPORT BoolExpr operator!(BoolExpr expr);
93 SANDBOX_EXPORT BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs);
94 SANDBOX_EXPORT BoolExpr operator||(BoolExpr lhs, BoolExpr rhs);
95
96 // Allow specifies a result that the system call should be allowed to
97 // execute normally.
98 SANDBOX_EXPORT ResultExpr Allow();
99
100 // Error specifies a result that the system call should fail with
101 // error number |err|. As a special case, Error(0) will result in the
102 // system call appearing to have succeeded, but without having any
103 // side effects.
104 SANDBOX_EXPORT ResultExpr Error(int err);
105
106 // TODO(mdempsky): Move elsewhere.
107 typedef intptr_t (*TrapFunc)(const arch_seccomp_data&, void*);
108
109 // Trap specifies a result that the system call should trap and invoke
110 // the specified callback function.
111 SANDBOX_EXPORT ResultExpr Trap(TrapFunc func, void* arg);
112
113 // If begins a conditional result expression predicated on the
114 // specified boolean expression.
115 SANDBOX_EXPORT Thener If(BoolExpr cond);
116
117 class SANDBOX_EXPORT Thener {
118 public:
119 Thener(const Thener& thener);
120 ~Thener();
121
122 // Then associates the result expression |expr| with the most recent
123 // If or ElseIf clause's boolean expression.
124 Elser Then(ResultExpr expr) const;
125
126 private:
127 Thener(internal::IfThenList if_then_list, BoolExpr cond);
128 internal::IfThenList if_then_list_;
129 BoolExpr cond_;
130 friend Thener If(BoolExpr cond);
131 friend class Elser;
132 DISALLOW_ASSIGN(Thener);
133 };
134
135 class SANDBOX_EXPORT Elser {
136 public:
137 Elser(const Elser& elser);
138 ~Elser();
139
140 // Else terminates a conditional result expression using |expr| as
141 // the default fallback result expression.
142 ResultExpr Else(ResultExpr expr) const;
143
144 // ElseIf extends the conditional result expression with another
145 // clause, predicated on the specified boolean expression.
146 Thener ElseIf(BoolExpr cond) const;
147
148 private:
149 Elser(internal::IfThenList if_then_list);
150 internal::IfThenList if_then_list_;
151 friend class Thener;
152 DISALLOW_ASSIGN(Elser);
153 };
154
155 template <typename T>
156 class SANDBOX_EXPORT Arg {
157 public:
158 // Initializes the Arg to represent the |num|th system call
159 // argument, which is of type |T|.
160 Arg(int num) : num_(num), mask_(-1) {}
161
162 Arg(const Arg& arg) : num_(arg.num_), mask_(arg.mask_) {}
163
164 // Returns an Arg representing the current argument, but after
165 // bitwise-and'ing it with |rhs|.
166 Arg operator&(uint64_t rhs) const { return Arg(num_, mask_ & rhs); }
167
168 // Returns a boolean expression comparing whether the system call
169 // argument (after applying a bitmask, if appropriate) equals |rhs|.
170 BoolExpr operator==(T rhs) const;
171
172 private:
173 Arg(int num, uint64_t mask) : num_(num), mask_(mask) {}
174 int num_;
175 uint64_t mask_;
176 DISALLOW_ASSIGN(Arg);
177 };
178
179 // Helper class to make writing policies easier.
180 class SANDBOX_EXPORT SandboxBPFPolicyDSL : public SandboxBPFPolicy {
181 public:
182 SandboxBPFPolicyDSL() : SandboxBPFPolicy() {}
183
184 // User extension point for writing custom sandbox policies.
185 virtual ResultExpr EvaluateSyscall(int sysno) const = 0;
186
187 // Optional overload for specifying alternate behavior for invalid
188 // system calls. The default is to return ENOSYS.
189 virtual ResultExpr InvalidSyscall() const;
190
191 // Override implementations from SandboxBPFPolicy. Marked as FINAL
192 // to prevent mixups with child classes accidentally overloading
193 // these instead of the above methods.
194 virtual ErrorCode EvaluateSyscall(SandboxBPF* sb,
195 int sysno) const OVERRIDE FINAL;
196 virtual ErrorCode InvalidSyscall(SandboxBPF* sb) const OVERRIDE FINAL;
197
198 private:
199 DISALLOW_COPY_AND_ASSIGN(SandboxBPFPolicyDSL);
200 };
201
202 namespace internal {
203
204 // Returns a boolean expression that represents whether system call
205 // argument |num| of size |size| is equal to |val|, when masked
206 // according to |mask|. Users should use the Arg template class below
207 // instead of using this API directly.
208 SANDBOX_EXPORT BoolExpr
209 ArgEq(int num, size_t size, uint64_t mask, uint64_t val);
210
211 // Internal interface implemented by BoolExpr implementations.
212 class BoolExprImpl : public base::RefCounted<BoolExprImpl> {
213 public:
214 BoolExprImpl() {}
24 virtual ErrorCode Compile(SandboxBPF* sb, 215 virtual ErrorCode Compile(SandboxBPF* sb,
25 ErrorCode true_ec, 216 ErrorCode true_ec,
26 ErrorCode false_ec) const = 0; 217 ErrorCode false_ec) const = 0;
27 218
28 protected: 219 protected:
29 friend class base::RefCounted<CondImpl>; 220 virtual ~BoolExprImpl() {}
30 virtual ~CondImpl() {} 221
31 222 private:
32 private: 223 friend class base::RefCounted<BoolExprImpl>;
33 DISALLOW_COPY_AND_ASSIGN(CondImpl); 224 DISALLOW_COPY_AND_ASSIGN(BoolExprImpl);
34 }; 225 };
35 226
36 typedef scoped_refptr<const CondImpl> Cond; 227 // Internal interface implemented by ResultExpr implementations.
37 228 class ResultExprImpl : public base::RefCounted<ResultExprImpl> {
38 SANDBOX_EXPORT Cond operator&&(Cond lhs, Cond rhs); 229 public:
39 SANDBOX_EXPORT Cond operator||(Cond lhs, Cond rhs); 230 ResultExprImpl() {}
40 231 virtual ErrorCode Compile(SandboxBPF* sb) const = 0;
41 class Iffer; 232
42 class Thener; 233 protected:
43 class Elser; 234 virtual ~ResultExprImpl() {}
44 235
45 class SANDBOX_EXPORT Iffer { 236 private:
46 public: 237 friend class base::RefCounted<ResultExprImpl>;
47 // TODO(mdempsky): Make private? 238 DISALLOW_COPY_AND_ASSIGN(ResultExprImpl);
48 explicit Iffer(SandboxBPF* sb); 239 };
49 Iffer(const Iffer& iffer); 240
50 Thener If(Cond cond) const; 241 // Internal helper class. Represents a (BoolExpr, ResultExpr)-pair
51 242 // node in a linked list.
52 private: 243 struct IfThen : public base::RefCounted<IfThen> {
53 SandboxBPF* sb_; 244 BoolExpr cond;
54 DISALLOW_ASSIGN(Iffer); 245 ResultExpr then;
55 }; 246 IfThenList rest;
56 247
57 class SANDBOX_EXPORT Thener { 248 // Returns a new IfThenList with a node for (cond, then) prepended
58 public: 249 // before rest.
59 ~Thener(); 250 static IfThenList Cons(BoolExpr cond, ResultExpr then, IfThenList rest) {
60 Elser Then(ErrorCode ec) const; 251 return IfThenList(new const IfThen(cond, then, rest));
61 252 }
62 private: 253
63 Thener(SandboxBPF* sb, Cond cond); 254 private:
64 SandboxBPF* sb_; 255 IfThen(BoolExpr cond, ResultExpr then, IfThenList rest);
65 Cond cond_; 256 virtual ~IfThen();
66 friend class Iffer; 257 friend class base::RefCounted<IfThen>;
67 friend class Elser; 258 DISALLOW_COPY_AND_ASSIGN(IfThen);
68 DISALLOW_COPY_AND_ASSIGN(Thener); 259 };
69 }; 260
70 261 } // namespace internal
71 class SANDBOX_EXPORT Elser { 262
72 public: 263 // Definition requires ArgEq to have been declared. Moved out-of-line
73 ~Elser(); 264 // to minimize how much internal clutter users have to ignore while
74 ErrorCode Else(ErrorCode ec) const; 265 // reading the header documentation.
75
76 private:
77 Elser(SandboxBPF* sb, Cond cond, ErrorCode true_ec);
78 SandboxBPF* sb_;
79 Cond cond_;
80 ErrorCode true_ec_;
81 friend class Iffer;
82 friend class Thener;
83 DISALLOW_COPY_AND_ASSIGN(Elser);
84 };
85
86 } // namespace bpfdsl
87
88 SANDBOX_EXPORT bpfdsl::Iffer DSL(SandboxBPF* sb);
89
90 template <typename T> 266 template <typename T>
91 class SANDBOX_EXPORT Arg { 267 BoolExpr Arg<T>::operator==(T rhs) const {
92 public: 268 return internal::ArgEq(num_, sizeof(T), mask_, rhs);
93 explicit Arg(int num); 269 }
94 bpfdsl::Cond operator==(const T& rhs) const; 270
95 271 } // namespace bpf_dsl
96 private:
97 int num_;
98 DISALLOW_COPY_AND_ASSIGN(Arg);
99 };
100
101 extern template class Arg<int>;
102 272
103 } // namespace sandbox 273 } // namespace sandbox
104 274
105 #endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_ 275 #endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc ('k') | sandbox/linux/seccomp-bpf-helpers/bpf_dsl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698