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

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: Add explicit virtual destructors to test policies 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 explicit ErrorResultExprImpl(int err) : err_(err) {
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 explicit 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 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) {
157 CHECK(num >= 0 && num < 6);
158 CHECK(size >= 1 && size <= 8);
159 CHECK_NE(0U, mask) << "zero mask doesn't make sense";
160 CHECK_EQ(val, val & mask) << "val contains masked out bits";
161
162 // TODO(mdempsky): Should we just always use TP_64BIT?
163 const ErrorCode::ArgType arg_type =
164 (size <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT;
165
166 if (mask == static_cast<uint64_t>(-1)) {
167 // Arg == Val
168 return BoolExpr(new const PrimitiveBoolExprImpl(
169 num, arg_type, ErrorCode::OP_EQUAL, val));
170 } else if (mask == val) {
171 // (Arg & Mask) == Mask
172 return BoolExpr(new const PrimitiveBoolExprImpl(
173 num, arg_type, ErrorCode::OP_HAS_ALL_BITS, mask));
174 } else if (val == 0) {
175 // (Arg & Mask) == 0, which is semantically equivalent to !((arg & mask) !=
176 // 0).
177 return !BoolExpr(new const PrimitiveBoolExprImpl(
178 num, arg_type, ErrorCode::OP_HAS_ANY_BITS, mask));
179 } else {
180 CHECK(false) << "Unimplemented ArgEq case";
181 return BoolExpr();
182 }
183 }
184
185 } // namespace internal
186
187 ResultExpr Allow() {
188 return ResultExpr(new const AllowResultExprImpl());
189 }
190
191 ResultExpr Error(int err) {
192 return ResultExpr(new const ErrorResultExprImpl(err));
193 }
194
195 ResultExpr Trap(TrapFnc trap_func, void* aux) {
196 return ResultExpr(new const TrapResultExprImpl(trap_func, aux));
197 }
198
199 BoolExpr operator!(BoolExpr cond) {
200 return BoolExpr(new const NegateBoolExprImpl(cond));
201 }
202
203 BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs) {
204 return BoolExpr(new const AndBoolExprImpl(lhs, rhs));
205 }
206
207 BoolExpr operator||(BoolExpr lhs, BoolExpr rhs) {
208 return BoolExpr(new const OrBoolExprImpl(lhs, rhs));
209 }
210
211 Elser If(BoolExpr cond, ResultExpr then_result) {
212 return Elser(Cons<Elser::Clause>::List()).ElseIf(cond, then_result);
213 }
214
215 Elser::Elser(Cons<Clause>::List clause_list) : clause_list_(clause_list) {
216 }
217
218 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) {
219 }
220
221 Elser::~Elser() {
222 }
223
224 Elser Elser::ElseIf(BoolExpr cond, ResultExpr then_result) const {
225 return Elser(
226 Cons<Clause>::Make(std::make_pair(cond, then_result), clause_list_));
227 }
228
229 ResultExpr Elser::Else(ResultExpr else_result) const {
230 // We finally have the default result expression for this
231 // if/then/else sequence. Also, we've already accumulated all
232 // if/then pairs into a list of reverse order (i.e., lower priority
233 // conditions are listed before higher priority ones). E.g., an
234 // expression like
235 //
236 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
237 //
238 // will have built up a list like
239 //
240 // [(b3, e3), (b2, e2), (b1, e1)].
241 //
242 // Now that we have e4, we can walk the list and create a ResultExpr
243 // tree like:
244 //
245 // expr = e4
246 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
247 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
248 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
249 //
250 // and end up with an appropriately chained tree.
251
252 ResultExpr expr = else_result;
253 for (Cons<Clause>::List it = clause_list_; it; it = it->tail()) {
254 Clause clause = it->head();
255 expr = ResultExpr(
256 new const IfThenResultExprImpl(clause.first, clause.second, expr));
257 }
258 return expr;
259 }
260
261 ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const {
262 return Error(ENOSYS);
263 }
264
265 ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb,
266 int sysno) const {
267 return EvaluateSyscall(sysno)->Compile(sb);
268 }
269
270 ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const {
271 return InvalidSyscall()->Compile(sb);
272 }
273
274 ResultExpr SandboxBPFDSLPolicy::Trap(::sandbox::Trap::TrapFnc trap_func,
275 void* aux) {
276 return bpf_dsl::Trap(trap_func, aux);
277 }
278
279 } // namespace bpf_dsl
280
281 } // namespace sandbox
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698