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

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

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

Powered by Google App Engine
This is Rietveld 408576698