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

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

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 #include "sandbox/linux/seccomp-bpf-helpers/bpf_dsl.h"
6
7 #include <errno.h>
8
9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
11 #include "sandbox/linux/seccomp-bpf/errorcode.h"
12 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
13
14 using namespace sandbox::bpf_dsl::internal;
15 typedef ::sandbox::Trap::TrapFnc TrapFnc;
16
17 namespace sandbox {
18
19 namespace bpf_dsl {
20
21 namespace {
22
23 class AllowResultExprImpl : public ResultExprImpl {
24 public:
25 AllowResultExprImpl() {}
26 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
27 return ErrorCode(ErrorCode::ERR_ALLOWED);
28 }
29
30 private:
31 virtual ~AllowResultExprImpl() {}
32 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl);
33 };
34
35 class ErrorResultExprImpl : public ResultExprImpl {
36 public:
37 ErrorResultExprImpl(int err) : err_(err) {
jln (very slow on Chromium) 2014/06/24 00:03:52 Nit: explicit
mdempsky 2014/06/24 00:55:40 Done.
38 CHECK(err_ >= ErrorCode::ERR_MIN_ERRNO && err_ <= ErrorCode::ERR_MAX_ERRNO);
39 }
40 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
41 return ErrorCode(err_);
42 }
43
44 private:
45 virtual ~ErrorResultExprImpl() {}
46 int err_;
47 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl);
48 };
49
50 class TrapResultExprImpl : public ResultExprImpl {
51 public:
52 TrapResultExprImpl(TrapFnc func, void* arg) : func_(func), arg_(arg) {
53 DCHECK(func_);
54 }
55 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
56 return sb->Trap(func_, arg_);
57 }
58
59 private:
60 virtual ~TrapResultExprImpl() {}
61 TrapFnc func_;
62 void* arg_;
63 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
64 };
65
66 class IfThenResultExprImpl : public ResultExprImpl {
67 public:
68 IfThenResultExprImpl(BoolExpr cond,
69 ResultExpr then_result,
70 ResultExpr else_result)
71 : cond_(cond), then_result_(then_result), else_result_(else_result) {}
72 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
73 return cond_->Compile(
74 sb, then_result_->Compile(sb), else_result_->Compile(sb));
75 }
76
77 private:
78 virtual ~IfThenResultExprImpl() {}
79 BoolExpr cond_;
80 ResultExpr then_result_;
81 ResultExpr else_result_;
82 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl);
83 };
84
85 class PrimitiveBoolExprImpl : public BoolExprImpl {
86 public:
87 PrimitiveBoolExprImpl(int argno,
88 ErrorCode::ArgType is_32bit,
89 ErrorCode::Operation op,
90 uint64_t value)
91 : argno_(argno), is_32bit_(is_32bit), op_(op), value_(value) {}
92 virtual ErrorCode Compile(SandboxBPF* sb,
93 ErrorCode true_ec,
94 ErrorCode false_ec) const OVERRIDE {
95 return sb->Cond(argno_, is_32bit_, op_, value_, true_ec, false_ec);
96 }
97
98 private:
99 virtual ~PrimitiveBoolExprImpl() {}
100 int argno_;
101 ErrorCode::ArgType is_32bit_;
102 ErrorCode::Operation op_;
103 uint64_t value_;
104 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl);
105 };
106
107 class NegateBoolExprImpl : public BoolExprImpl {
108 public:
109 NegateBoolExprImpl(BoolExpr cond) : cond_(cond) {}
110 virtual ErrorCode Compile(SandboxBPF* sb,
111 ErrorCode true_ec,
112 ErrorCode false_ec) const OVERRIDE {
113 return cond_->Compile(sb, false_ec, true_ec);
114 }
115
116 private:
117 virtual ~NegateBoolExprImpl() {}
118 BoolExpr cond_;
119 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl);
120 };
121
122 class AndBoolExprImpl : public BoolExprImpl {
123 public:
124 AndBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {}
125 virtual ErrorCode Compile(SandboxBPF* sb,
126 ErrorCode true_ec,
127 ErrorCode false_ec) const OVERRIDE {
128 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec);
129 }
130
131 private:
132 virtual ~AndBoolExprImpl() {}
133 BoolExpr lhs_, rhs_;
134 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl);
135 };
136
137 class OrBoolExprImpl : public BoolExprImpl {
138 public:
139 OrBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {}
140 virtual ErrorCode Compile(SandboxBPF* sb,
141 ErrorCode true_ec,
142 ErrorCode false_ec) const OVERRIDE {
143 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec));
144 }
145
146 private:
147 virtual ~OrBoolExprImpl() {}
148 BoolExpr lhs_, rhs_;
149 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl);
150 };
151
152 } // namespace
153
154 namespace internal {
155
156 // Internal helper class. Represents a (BoolExpr, ResultExpr)-pair
157 // node in an immutable linked list.
158 struct IfThen : public base::RefCounted<IfThen> {
159 BoolExpr cond;
160 ResultExpr then;
161 IfThenList rest;
162
163 // Returns a new IfThenList with a node for (cond, then) prepended
164 // before rest.
165 static IfThenList Cons(BoolExpr cond, ResultExpr then, IfThenList rest) {
166 return IfThenList(new const IfThen(cond, then, rest));
167 }
168
169 private:
170 IfThen(BoolExpr cond_, ResultExpr then_, IfThenList rest_)
171 : cond(cond_), then(then_), rest(rest_) {}
172 virtual ~IfThen() {}
173 friend class base::RefCounted<IfThen>;
174 DISALLOW_COPY_AND_ASSIGN(IfThen);
175 };
176
177 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) {
178 CHECK(num >= 0 && num < 6);
179 CHECK(size >= 1 && size <= 8);
180 CHECK_NE(0, mask) << "zero mask doesn't make sense";
181 CHECK_EQ(val, val & mask) << "val contains masked out bits";
182
183 const ErrorCode::ArgType arg_type =
184 (size <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT;
185 if (mask == static_cast<uint64_t>(-1)) {
186 // Arg == Val
187 return BoolExpr(new const PrimitiveBoolExprImpl(
188 num, arg_type, ErrorCode::OP_EQUAL, val));
189 } else if (mask == val) {
190 // (Arg & Mask) == Mask
191 return BoolExpr(new const PrimitiveBoolExprImpl(
192 num, arg_type, ErrorCode::OP_HAS_ALL_BITS, mask));
193 } else if (val == 0) {
194 // (Arg & Mask) == 0, which is semantically equivalent to !((arg & mask) !=
195 // 0).
196 return !BoolExpr(new const PrimitiveBoolExprImpl(
197 num, arg_type, ErrorCode::OP_HAS_ANY_BITS, mask));
198 } else {
199 NOTREACHED() << "Unimplemented ArgEq case";
200 return BoolExpr();
201 }
202 }
203
204 } // namespace internal
205
206 ResultExpr Allow() {
207 return ResultExpr(new const AllowResultExprImpl());
208 }
209
210 ResultExpr Error(int err) {
211 return ResultExpr(new const ErrorResultExprImpl(err));
212 }
213
214 ResultExpr Trap(TrapFnc trap_func, void* aux) {
215 return ResultExpr(new const TrapResultExprImpl(trap_func, aux));
216 }
217
218 BoolExpr operator!(BoolExpr cond) {
219 return BoolExpr(new const NegateBoolExprImpl(cond));
220 }
221
222 BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs) {
223 return BoolExpr(new const AndBoolExprImpl(lhs, rhs));
224 }
225
226 BoolExpr operator||(BoolExpr lhs, BoolExpr rhs) {
227 return BoolExpr(new const OrBoolExprImpl(lhs, rhs));
228 }
229
230 Thener If(BoolExpr cond) {
231 return Thener(IfThenList(), cond);
232 }
233
234 Thener::Thener(IfThenList if_then_list, BoolExpr cond)
235 : if_then_list_(if_then_list), cond_(cond) {
236 }
237
238 Thener::Thener(const Thener& thener)
239 : if_then_list_(thener.if_then_list_), cond_(thener.cond_) {
240 }
241
242 Thener::~Thener() {
243 }
244
245 Elser Thener::Then(ResultExpr then_result) const {
246 return Elser(IfThen::Cons(cond_, then_result, if_then_list_));
247 }
248
249 Elser::Elser(IfThenList if_then_list) : if_then_list_(if_then_list) {
250 }
251
252 Elser::Elser(const Elser& elser) : if_then_list_(elser.if_then_list_) {
253 }
254
255 Elser::~Elser() {
256 }
257
258 ResultExpr Elser::Else(ResultExpr else_result) const {
259 // We finally have the default result expression for this
260 // if/then/else sequence. Also, we've already accumulated all
261 // if/then pairs into a list of reverse order (i.e., lower priority
262 // conditions are listed before higher priority ones). E.g., an
263 // expression like
264 //
265 // If(b1).Then(e1).ElseIf(b2).Then(e2).ElseIf(b3).Then(e3).Else(e4)
266 //
267 // will have built up a list like
268 //
269 // [(b3, e3), (b2, e2), (b1, e1)].
270 //
271 // Now that we have e4, we can walk the list and create a ResultExpr
272 // tree like:
273 //
274 // expr = e4
275 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
276 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
277 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
278 //
279 // and end up with an appropriately chained tree.
280
281 ResultExpr expr = else_result;
282 for (IfThenList it = if_then_list_; it; it = it->rest) {
283 expr = ResultExpr(new const IfThenResultExprImpl(it->cond, it->then, expr));
284 }
285 return expr;
286 }
287
288 Thener Elser::ElseIf(BoolExpr cond) const {
289 return Thener(if_then_list_, cond);
290 }
291
292 ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const {
293 return Error(ENOSYS);
294 }
295
296 ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb,
297 int sysno) const {
298 return EvaluateSyscall(sysno)->Compile(sb);
299 }
300
301 ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const {
302 return InvalidSyscall()->Compile(sb);
303 }
304
305 } // namespace bpf_dsl
306
307 } // namespace sandbox
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698