OLD | NEW |
| (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 | |
OLD | NEW |