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

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

Issue 299743002: Add domain-specific language for BPF policies (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleanup CHECK statements a little bit Created 6 years, 6 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
6 #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
7
8 #include <stdint.h>
9
10 #include "base/macros.h"
11 #include "base/memory/ref_counted.h"
12 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
13 #include "sandbox/linux/seccomp-bpf/trap.h"
14 #include "sandbox/sandbox_export.h"
15
16 namespace sandbox {
17 class ErrorCode;
18 class SandboxBPF;
19 }
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 SandboxBPFDSLPolicy {
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 // }
jln (very slow on Chromium) 2014/06/24 00:03:52 nit: else {} so that the compiler checks that the
mdempsky 2014/06/24 00:55:40 Done.
51 // return Allow();
52 // }
53 // private:
54 // DISALLOW_COPY_AND_ASSIGN(SillyPolicy);
55 // };
56 //
57 // More generally, the DSL currently supports the following grammar:
58 //
59 // result = Allow() | Error(errno) | Trap(trap_func, arg)
60 // | If(bool).Then(result)[.ElseIf(bool).Then(result)].Else(result)
61 // bool = arg == val | (arg & mask) == mask | (arg & mask) == 0
62 // | !bool | bool && bool | bool || bool
63 //
64 // The semantics of each function and operator are intended to be
65 // intuitive, but are described in more detail below.
66 //
67 // (Credit to Sean Parent's "Inheritance is the Base Class of Evil"
68 // talk at Going Native 2013 for promoting value semantics via shared
69 // pointers to immutable state.)
70
71 namespace sandbox {
72
73 namespace bpf_dsl {
74
75 // Forward declarations of classes; see below for proper documentation.
76 class Thener;
77 class Elser;
78 namespace internal {
79 class ResultExprImpl;
80 class BoolExprImpl;
81 struct IfThen;
82 typedef scoped_refptr<const IfThen> IfThenList;
83 }
84
85 // ResultExpr is an opaque reference to an immutable result expression tree.
86 typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr;
87
88 // Allow specifies a result that the system call should be allowed to
89 // execute normally.
90 SANDBOX_EXPORT ResultExpr Allow();
91
92 // Error specifies a result that the system call should fail with
93 // error number |err|. As a special case, Error(0) will result in the
94 // system call appearing to have succeeded, but without having any
95 // side effects.
96 SANDBOX_EXPORT ResultExpr Error(int err);
97
98 // Trap specifies a result that the system call should be handled by
99 // trapping back into userspace and invoking |trap_func|, passing
100 // |aux| as the second parameter.
101 SANDBOX_EXPORT ResultExpr Trap(::sandbox::Trap::TrapFnc trap_func, void* aux);
102
103 // BoolExpr is an opaque reference to an immutable boolean expression tree.
104 typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr;
105
106 template <typename T>
107 class SANDBOX_EXPORT Arg {
108 public:
109 // Initializes the Arg to represent the |num|th system call
110 // argument, which is of type |T|.
111 explicit Arg(int num) : num_(num), mask_(-1) {}
112
113 Arg(const Arg& arg) : num_(arg.num_), mask_(arg.mask_) {}
114
115 // Returns an Arg representing the current argument, but after
116 // bitwise-and'ing it with |rhs|.
117 Arg operator&(uint64_t rhs) const { return Arg(num_, mask_ & rhs); }
118
119 // Returns a boolean expression comparing whether the system call
120 // argument (after applying any bitmasks, if appropriate) equals |rhs|.
121 BoolExpr operator==(T rhs) const;
122
123 private:
124 Arg(int num, uint64_t mask) : num_(num), mask_(mask) {}
125 int num_;
126 uint64_t mask_;
127 DISALLOW_ASSIGN(Arg);
128 };
129
130 // Various ways to combine boolean expressions into more complex expressions.
131 // They follow standard boolean algebra laws.
132 SANDBOX_EXPORT BoolExpr operator!(BoolExpr cond);
133 SANDBOX_EXPORT BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs);
134 SANDBOX_EXPORT BoolExpr operator||(BoolExpr lhs, BoolExpr rhs);
135
136 // If begins a conditional result expression predicated on the
137 // specified boolean expression.
138 SANDBOX_EXPORT Thener If(BoolExpr cond);
139
140 class SANDBOX_EXPORT Thener {
141 public:
142 Thener(const Thener& thener);
143 ~Thener();
144
145 // Then associates the result expression |then_result| with the most recent
146 // If or ElseIf clause's boolean expression.
147 Elser Then(ResultExpr then_result) const;
148
149 private:
150 Thener(internal::IfThenList if_then_list, BoolExpr cond);
151 internal::IfThenList if_then_list_;
152 BoolExpr cond_;
153 friend Thener If(BoolExpr);
154 friend class Elser;
155 DISALLOW_ASSIGN(Thener);
156 };
157
158 class SANDBOX_EXPORT Elser {
159 public:
160 Elser(const Elser& elser);
161 ~Elser();
162
163 // Else terminates a conditional result expression using |else_result| as
164 // the default fallback result expression.
165 ResultExpr Else(ResultExpr else_result) const;
166
167 // ElseIf extends the conditional result expression with another
168 // clause, predicated on the specified boolean expression.
169 Thener ElseIf(BoolExpr cond) const;
170
171 private:
172 Elser(internal::IfThenList if_then_list);
173 internal::IfThenList if_then_list_;
174 friend class Thener;
175 DISALLOW_ASSIGN(Elser);
176 };
177
178 // Helper class to make writing policies easier.
jln (very slow on Chromium) 2014/06/24 00:03:52 Let's have this earlier in the file as it is one o
mdempsky 2014/06/24 00:55:40 Done.
179 class SANDBOX_EXPORT SandboxBPFDSLPolicy : public SandboxBPFPolicy {
180 public:
181 SandboxBPFDSLPolicy() : SandboxBPFPolicy() {}
182
183 // User extension point for writing custom sandbox policies.
184 virtual ResultExpr EvaluateSyscall(int sysno) const = 0;
185
186 // Optional overload for specifying alternate behavior for invalid
187 // system calls. The default is to return ENOSYS.
188 virtual ResultExpr InvalidSyscall() const;
189
190 // Override implementations from SandboxBPFPolicy. Marked as FINAL
191 // to prevent mixups with child classes accidentally overloading
192 // these instead of the above methods.
193 virtual ErrorCode EvaluateSyscall(SandboxBPF* sb,
194 int sysno) const OVERRIDE FINAL;
195 virtual ErrorCode InvalidSyscall(SandboxBPF* sb) const OVERRIDE FINAL;
196
197 // Helper method so policies can just write Trap(func, aux).
198 static ResultExpr Trap(::sandbox::Trap::TrapFnc trap_func, void* aux) {
199 return bpf_dsl::Trap(trap_func, aux);
200 }
201
202 private:
203 DISALLOW_COPY_AND_ASSIGN(SandboxBPFDSLPolicy);
204 };
205
206 namespace internal {
207
208 // Returns a boolean expression that represents whether system call
209 // argument |num| of size |size| is equal to |val|, when masked
210 // according to |mask|. Users should use the Arg template class below
211 // instead of using this API directly.
212 SANDBOX_EXPORT BoolExpr
213 ArgEq(int num, size_t size, uint64_t mask, uint64_t val);
214
215 // Internal interface implemented by BoolExpr implementations.
216 class SANDBOX_EXPORT BoolExprImpl : public base::RefCounted<BoolExprImpl> {
217 public:
218 BoolExprImpl() {}
219 virtual ErrorCode Compile(SandboxBPF* sb,
220 ErrorCode true_ec,
221 ErrorCode false_ec) const = 0;
222
223 protected:
224 virtual ~BoolExprImpl() {}
225
226 private:
227 friend class base::RefCounted<BoolExprImpl>;
228 DISALLOW_COPY_AND_ASSIGN(BoolExprImpl);
229 };
230
231 // Internal interface implemented by ResultExpr implementations.
232 class SANDBOX_EXPORT ResultExprImpl : public base::RefCounted<ResultExprImpl> {
233 public:
234 ResultExprImpl() {}
235 virtual ErrorCode Compile(SandboxBPF* sb) const = 0;
236
237 protected:
238 virtual ~ResultExprImpl() {}
239
240 private:
241 friend class base::RefCounted<ResultExprImpl>;
242 DISALLOW_COPY_AND_ASSIGN(ResultExprImpl);
243 };
244
245 } // namespace internal
246
247 // Definition requires ArgEq to have been declared. Moved out-of-line
248 // to minimize how much internal clutter users have to ignore while
249 // reading the header documentation.
250 template <typename T>
251 BoolExpr Arg<T>::operator==(T rhs) const {
252 return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint64_t>(rhs));
253 }
254
255 } // namespace bpf_dsl
256
257 } // namespace sandbox
258
259 #endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_BPF_DSL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698