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

Side by Side Diff: sandbox/linux/bpf_dsl/bpf_dsl.cc

Issue 299743002: Add domain-specific language for BPF policies (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Move bpf_dsl into its own top-level directory Created 6 years, 5 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
« no previous file with comments | « sandbox/linux/bpf_dsl/bpf_dsl.h ('k') | sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/bpf_dsl/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 namespace bpf_dsl {
19 namespace {
20
21 class AllowResultExprImpl : public ResultExprImpl {
22 public:
23 AllowResultExprImpl() {}
24 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
25 return ErrorCode(ErrorCode::ERR_ALLOWED);
26 }
27
28 private:
29 virtual ~AllowResultExprImpl() {}
30 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl);
31 };
32
33 class ErrorResultExprImpl : public ResultExprImpl {
34 public:
35 explicit ErrorResultExprImpl(int err) : err_(err) {
36 CHECK(err_ >= ErrorCode::ERR_MIN_ERRNO && err_ <= ErrorCode::ERR_MAX_ERRNO);
37 }
38 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
39 return ErrorCode(err_);
40 }
41
42 private:
43 virtual ~ErrorResultExprImpl() {}
44 int err_;
45 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl);
46 };
47
48 class TrapResultExprImpl : public ResultExprImpl {
49 public:
50 TrapResultExprImpl(TrapFnc func, void* arg) : func_(func), arg_(arg) {
51 DCHECK(func_);
52 }
53 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
54 return sb->Trap(func_, arg_);
55 }
56
57 private:
58 virtual ~TrapResultExprImpl() {}
59 TrapFnc func_;
60 void* arg_;
61 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
62 };
63
64 class IfThenResultExprImpl : public ResultExprImpl {
65 public:
66 IfThenResultExprImpl(BoolExpr cond,
67 ResultExpr then_result,
68 ResultExpr else_result)
69 : cond_(cond), then_result_(then_result), else_result_(else_result) {}
70 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
71 return cond_->Compile(
72 sb, then_result_->Compile(sb), else_result_->Compile(sb));
73 }
74
75 private:
76 virtual ~IfThenResultExprImpl() {}
77 BoolExpr cond_;
78 ResultExpr then_result_;
79 ResultExpr else_result_;
80 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl);
81 };
82
83 class PrimitiveBoolExprImpl : public BoolExprImpl {
84 public:
85 PrimitiveBoolExprImpl(int argno,
86 ErrorCode::ArgType is_32bit,
87 ErrorCode::Operation op,
88 uint64_t value)
89 : argno_(argno), is_32bit_(is_32bit), op_(op), value_(value) {}
90 virtual ErrorCode Compile(SandboxBPF* sb,
91 ErrorCode true_ec,
92 ErrorCode false_ec) const OVERRIDE {
93 return sb->Cond(argno_, is_32bit_, op_, value_, true_ec, false_ec);
94 }
95
96 private:
97 virtual ~PrimitiveBoolExprImpl() {}
98 int argno_;
99 ErrorCode::ArgType is_32bit_;
100 ErrorCode::Operation op_;
101 uint64_t value_;
102 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl);
103 };
104
105 class NegateBoolExprImpl : public BoolExprImpl {
106 public:
107 explicit NegateBoolExprImpl(BoolExpr cond) : cond_(cond) {}
108 virtual ErrorCode Compile(SandboxBPF* sb,
109 ErrorCode true_ec,
110 ErrorCode false_ec) const OVERRIDE {
111 return cond_->Compile(sb, false_ec, true_ec);
112 }
113
114 private:
115 virtual ~NegateBoolExprImpl() {}
116 BoolExpr cond_;
117 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl);
118 };
119
120 class AndBoolExprImpl : public BoolExprImpl {
121 public:
122 AndBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {}
123 virtual ErrorCode Compile(SandboxBPF* sb,
124 ErrorCode true_ec,
125 ErrorCode false_ec) const OVERRIDE {
126 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec);
127 }
128
129 private:
130 virtual ~AndBoolExprImpl() {}
131 BoolExpr lhs_, rhs_;
132 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl);
133 };
134
135 class OrBoolExprImpl : public BoolExprImpl {
136 public:
137 OrBoolExprImpl(BoolExpr lhs, BoolExpr rhs) : lhs_(lhs), rhs_(rhs) {}
138 virtual ErrorCode Compile(SandboxBPF* sb,
139 ErrorCode true_ec,
140 ErrorCode false_ec) const OVERRIDE {
141 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec));
142 }
143
144 private:
145 virtual ~OrBoolExprImpl() {}
146 BoolExpr lhs_, rhs_;
147 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl);
148 };
149
150 } // namespace
151
152 namespace internal {
153
154 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) {
155 CHECK(num >= 0 && num < 6);
156 CHECK(size >= 1 && size <= 8);
157 CHECK_NE(0U, mask) << "zero mask doesn't make sense";
158 CHECK_EQ(val, val & mask) << "val contains masked out bits";
159
160 // TODO(mdempsky): Should we just always use TP_64BIT?
161 const ErrorCode::ArgType arg_type =
162 (size <= 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT;
163
164 if (mask == static_cast<uint64_t>(-1)) {
165 // Arg == Val
166 return BoolExpr(new const PrimitiveBoolExprImpl(
167 num, arg_type, ErrorCode::OP_EQUAL, val));
168 } else if (mask == val) {
169 // (Arg & Mask) == Mask
170 return BoolExpr(new const PrimitiveBoolExprImpl(
171 num, arg_type, ErrorCode::OP_HAS_ALL_BITS, mask));
172 } else if (val == 0) {
173 // (Arg & Mask) == 0, which is semantically equivalent to !((arg & mask) !=
174 // 0).
175 return !BoolExpr(new const PrimitiveBoolExprImpl(
176 num, arg_type, ErrorCode::OP_HAS_ANY_BITS, mask));
177 } else {
178 CHECK(false) << "Unimplemented ArgEq case";
179 return BoolExpr();
180 }
181 }
182
183 } // namespace internal
184
185 ResultExpr Allow() {
186 return ResultExpr(new const AllowResultExprImpl());
187 }
188
189 ResultExpr Error(int err) {
190 return ResultExpr(new const ErrorResultExprImpl(err));
191 }
192
193 ResultExpr Trap(TrapFnc trap_func, void* aux) {
194 return ResultExpr(new const TrapResultExprImpl(trap_func, aux));
195 }
196
197 BoolExpr operator!(BoolExpr cond) {
198 return BoolExpr(new const NegateBoolExprImpl(cond));
199 }
200
201 BoolExpr operator&&(BoolExpr lhs, BoolExpr rhs) {
202 return BoolExpr(new const AndBoolExprImpl(lhs, rhs));
203 }
204
205 BoolExpr operator||(BoolExpr lhs, BoolExpr rhs) {
206 return BoolExpr(new const OrBoolExprImpl(lhs, rhs));
207 }
208
209 Elser If(BoolExpr cond, ResultExpr then_result) {
210 return Elser(Cons<Elser::Clause>::List()).ElseIf(cond, then_result);
211 }
212
213 Elser::Elser(Cons<Clause>::List clause_list) : clause_list_(clause_list) {
214 }
215
216 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) {
217 }
218
219 Elser::~Elser() {
220 }
221
222 Elser Elser::ElseIf(BoolExpr cond, ResultExpr then_result) const {
223 return Elser(
224 Cons<Clause>::Make(std::make_pair(cond, then_result), clause_list_));
225 }
226
227 ResultExpr Elser::Else(ResultExpr else_result) const {
228 // We finally have the default result expression for this
229 // if/then/else sequence. Also, we've already accumulated all
230 // if/then pairs into a list of reverse order (i.e., lower priority
231 // conditions are listed before higher priority ones). E.g., an
232 // expression like
233 //
234 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
235 //
236 // will have built up a list like
237 //
238 // [(b3, e3), (b2, e2), (b1, e1)].
239 //
240 // Now that we have e4, we can walk the list and create a ResultExpr
241 // tree like:
242 //
243 // expr = e4
244 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
245 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
246 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
247 //
248 // and end up with an appropriately chained tree.
249
250 ResultExpr expr = else_result;
251 for (Cons<Clause>::List it = clause_list_; it; it = it->tail()) {
252 Clause clause = it->head();
253 expr = ResultExpr(
254 new const IfThenResultExprImpl(clause.first, clause.second, expr));
255 }
256 return expr;
257 }
258
259 ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const {
260 return Error(ENOSYS);
261 }
262
263 ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb,
264 int sysno) const {
265 return EvaluateSyscall(sysno)->Compile(sb);
266 }
267
268 ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const {
269 return InvalidSyscall()->Compile(sb);
270 }
271
272 ResultExpr SandboxBPFDSLPolicy::Trap(::sandbox::Trap::TrapFnc trap_func,
273 void* aux) {
274 return bpf_dsl::Trap(trap_func, aux);
275 }
276
277 } // namespace bpf_dsl
278 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/bpf_dsl/bpf_dsl.h ('k') | sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698