Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / sandbox / linux / bpf_dsl / bpf_dsl.cc
blob3a35903ec91a3a7f7690dce1471b81b41bffacef
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.
5 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
7 #include <limits>
9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
11 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
12 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
13 #include "sandbox/linux/seccomp-bpf/die.h"
14 #include "sandbox/linux/seccomp-bpf/errorcode.h"
16 namespace sandbox {
17 namespace bpf_dsl {
18 namespace {
20 intptr_t BPFFailure(const struct arch_seccomp_data&, void* aux) {
21 SANDBOX_DIE(static_cast<char*>(aux));
24 class AllowResultExprImpl : public internal::ResultExprImpl {
25 public:
26 AllowResultExprImpl() {}
28 ErrorCode Compile(PolicyCompiler* pc) const override {
29 return ErrorCode(ErrorCode::ERR_ALLOWED);
32 bool IsAllow() const override { return true; }
34 private:
35 ~AllowResultExprImpl() override {}
37 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl);
40 class ErrorResultExprImpl : public internal::ResultExprImpl {
41 public:
42 explicit ErrorResultExprImpl(int err) : err_(err) {
43 CHECK(err_ >= ErrorCode::ERR_MIN_ERRNO && err_ <= ErrorCode::ERR_MAX_ERRNO);
46 ErrorCode Compile(PolicyCompiler* pc) const override {
47 return pc->Error(err_);
50 bool IsDeny() const override { return true; }
52 private:
53 ~ErrorResultExprImpl() override {}
55 int err_;
57 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl);
60 class TraceResultExprImpl : public internal::ResultExprImpl {
61 public:
62 TraceResultExprImpl(uint16_t aux) : aux_(aux) {}
64 ErrorCode Compile(PolicyCompiler* pc) const override {
65 return ErrorCode(ErrorCode::ERR_TRACE + aux_);
68 private:
69 ~TraceResultExprImpl() override {}
71 uint16_t aux_;
73 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl);
76 class TrapResultExprImpl : public internal::ResultExprImpl {
77 public:
78 TrapResultExprImpl(TrapRegistry::TrapFnc func, const void* arg, bool safe)
79 : func_(func), arg_(arg), safe_(safe) {
80 DCHECK(func_);
83 ErrorCode Compile(PolicyCompiler* pc) const override {
84 return pc->Trap(func_, arg_, safe_);
87 bool HasUnsafeTraps() const override { return safe_ == false; }
89 bool IsDeny() const override { return true; }
91 private:
92 ~TrapResultExprImpl() override {}
94 TrapRegistry::TrapFnc func_;
95 const void* arg_;
96 bool safe_;
98 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
101 class IfThenResultExprImpl : public internal::ResultExprImpl {
102 public:
103 IfThenResultExprImpl(const BoolExpr& cond,
104 const ResultExpr& then_result,
105 const ResultExpr& else_result)
106 : cond_(cond), then_result_(then_result), else_result_(else_result) {}
108 ErrorCode Compile(PolicyCompiler* pc) const override {
109 return cond_->Compile(
110 pc, then_result_->Compile(pc), else_result_->Compile(pc));
113 bool HasUnsafeTraps() const override {
114 return then_result_->HasUnsafeTraps() || else_result_->HasUnsafeTraps();
117 private:
118 ~IfThenResultExprImpl() override {}
120 BoolExpr cond_;
121 ResultExpr then_result_;
122 ResultExpr else_result_;
124 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl);
127 class ConstBoolExprImpl : public internal::BoolExprImpl {
128 public:
129 ConstBoolExprImpl(bool value) : value_(value) {}
131 ErrorCode Compile(PolicyCompiler* pc,
132 ErrorCode true_ec,
133 ErrorCode false_ec) const override {
134 return value_ ? true_ec : false_ec;
137 private:
138 ~ConstBoolExprImpl() override {}
140 bool value_;
142 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl);
145 class PrimitiveBoolExprImpl : public internal::BoolExprImpl {
146 public:
147 PrimitiveBoolExprImpl(int argno,
148 ErrorCode::ArgType is_32bit,
149 uint64_t mask,
150 uint64_t value)
151 : argno_(argno), is_32bit_(is_32bit), mask_(mask), value_(value) {}
153 ErrorCode Compile(PolicyCompiler* pc,
154 ErrorCode true_ec,
155 ErrorCode false_ec) const override {
156 return pc->CondMaskedEqual(
157 argno_, is_32bit_, mask_, value_, true_ec, false_ec);
160 private:
161 ~PrimitiveBoolExprImpl() override {}
163 int argno_;
164 ErrorCode::ArgType is_32bit_;
165 uint64_t mask_;
166 uint64_t value_;
168 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl);
171 class NegateBoolExprImpl : public internal::BoolExprImpl {
172 public:
173 explicit NegateBoolExprImpl(const BoolExpr& cond) : cond_(cond) {}
175 ErrorCode Compile(PolicyCompiler* pc,
176 ErrorCode true_ec,
177 ErrorCode false_ec) const override {
178 return cond_->Compile(pc, false_ec, true_ec);
181 private:
182 ~NegateBoolExprImpl() override {}
184 BoolExpr cond_;
186 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl);
189 class AndBoolExprImpl : public internal::BoolExprImpl {
190 public:
191 AndBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
192 : lhs_(lhs), rhs_(rhs) {}
194 ErrorCode Compile(PolicyCompiler* pc,
195 ErrorCode true_ec,
196 ErrorCode false_ec) const override {
197 return lhs_->Compile(pc, rhs_->Compile(pc, true_ec, false_ec), false_ec);
200 private:
201 ~AndBoolExprImpl() override {}
203 BoolExpr lhs_;
204 BoolExpr rhs_;
206 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl);
209 class OrBoolExprImpl : public internal::BoolExprImpl {
210 public:
211 OrBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
212 : lhs_(lhs), rhs_(rhs) {}
214 ErrorCode Compile(PolicyCompiler* pc,
215 ErrorCode true_ec,
216 ErrorCode false_ec) const override {
217 return lhs_->Compile(pc, true_ec, rhs_->Compile(pc, true_ec, false_ec));
220 private:
221 ~OrBoolExprImpl() override {}
223 BoolExpr lhs_;
224 BoolExpr rhs_;
226 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl);
229 } // namespace
231 namespace internal {
233 bool ResultExprImpl::HasUnsafeTraps() const {
234 return false;
237 bool ResultExprImpl::IsAllow() const {
238 return false;
241 bool ResultExprImpl::IsDeny() const {
242 return false;
245 uint64_t DefaultMask(size_t size) {
246 switch (size) {
247 case 4:
248 return std::numeric_limits<uint32_t>::max();
249 case 8:
250 return std::numeric_limits<uint64_t>::max();
251 default:
252 CHECK(false) << "Unimplemented DefaultMask case";
253 return 0;
257 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) {
258 CHECK(size == 4 || size == 8);
260 // TODO(mdempsky): Should we just always use TP_64BIT?
261 const ErrorCode::ArgType arg_type =
262 (size == 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT;
264 return BoolExpr(new const PrimitiveBoolExprImpl(num, arg_type, mask, val));
267 } // namespace internal
269 ResultExpr Allow() {
270 return ResultExpr(new const AllowResultExprImpl());
273 ResultExpr Error(int err) {
274 return ResultExpr(new const ErrorResultExprImpl(err));
277 ResultExpr Kill(const char* msg) {
278 return Trap(BPFFailure, msg);
281 ResultExpr Trace(uint16_t aux) {
282 return ResultExpr(new const TraceResultExprImpl(aux));
285 ResultExpr Trap(TrapRegistry::TrapFnc trap_func, const void* aux) {
286 return ResultExpr(
287 new const TrapResultExprImpl(trap_func, aux, true /* safe */));
290 ResultExpr UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux) {
291 return ResultExpr(
292 new const TrapResultExprImpl(trap_func, aux, false /* unsafe */));
295 BoolExpr BoolConst(bool value) {
296 return BoolExpr(new const ConstBoolExprImpl(value));
299 BoolExpr operator!(const BoolExpr& cond) {
300 return BoolExpr(new const NegateBoolExprImpl(cond));
303 BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs) {
304 return BoolExpr(new const AndBoolExprImpl(lhs, rhs));
307 BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs) {
308 return BoolExpr(new const OrBoolExprImpl(lhs, rhs));
311 Elser If(const BoolExpr& cond, const ResultExpr& then_result) {
312 return Elser(nullptr).ElseIf(cond, then_result);
315 Elser::Elser(cons::List<Clause> clause_list) : clause_list_(clause_list) {
318 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) {
321 Elser::~Elser() {
324 Elser Elser::ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const {
325 return Elser(Cons(std::make_pair(cond, then_result), clause_list_));
328 ResultExpr Elser::Else(const ResultExpr& else_result) const {
329 // We finally have the default result expression for this
330 // if/then/else sequence. Also, we've already accumulated all
331 // if/then pairs into a list of reverse order (i.e., lower priority
332 // conditions are listed before higher priority ones). E.g., an
333 // expression like
335 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
337 // will have built up a list like
339 // [(b3, e3), (b2, e2), (b1, e1)].
341 // Now that we have e4, we can walk the list and create a ResultExpr
342 // tree like:
344 // expr = e4
345 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
346 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
347 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
349 // and end up with an appropriately chained tree.
351 ResultExpr expr = else_result;
352 for (const Clause& clause : clause_list_) {
353 expr = ResultExpr(
354 new const IfThenResultExprImpl(clause.first, clause.second, expr));
356 return expr;
359 } // namespace bpf_dsl
360 } // namespace sandbox
362 template class scoped_refptr<const sandbox::bpf_dsl::internal::BoolExprImpl>;
363 template class scoped_refptr<const sandbox::bpf_dsl::internal::ResultExprImpl>;