Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / sandbox / linux / bpf_dsl / bpf_dsl.cc
blob100cc8b851dbe2c59b62f407a12acc92ffa55595
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/errorcode.h"
13 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
14 #include "sandbox/linux/system_headers/linux_seccomp.h"
16 namespace sandbox {
17 namespace bpf_dsl {
18 namespace {
20 class ReturnResultExprImpl : public internal::ResultExprImpl {
21 public:
22 explicit ReturnResultExprImpl(uint32_t ret) : ret_(ret) {}
24 CodeGen::Node Compile(PolicyCompiler* pc) const override {
25 return pc->Return(ret_);
28 bool IsAllow() const override { return IsAction(SECCOMP_RET_ALLOW); }
30 bool IsDeny() const override {
31 return IsAction(SECCOMP_RET_ERRNO) || IsAction(SECCOMP_RET_KILL);
34 private:
35 ~ReturnResultExprImpl() override {}
37 bool IsAction(uint32_t action) const {
38 return (ret_ & SECCOMP_RET_ACTION) == action;
41 uint32_t ret_;
43 DISALLOW_COPY_AND_ASSIGN(ReturnResultExprImpl);
46 class TrapResultExprImpl : public internal::ResultExprImpl {
47 public:
48 TrapResultExprImpl(TrapRegistry::TrapFnc func, const void* arg, bool safe)
49 : func_(func), arg_(arg), safe_(safe) {
50 DCHECK(func_);
53 CodeGen::Node Compile(PolicyCompiler* pc) const override {
54 return pc->Trap(func_, arg_, safe_);
57 bool HasUnsafeTraps() const override { return safe_ == false; }
59 bool IsDeny() const override { return true; }
61 private:
62 ~TrapResultExprImpl() override {}
64 TrapRegistry::TrapFnc func_;
65 const void* arg_;
66 bool safe_;
68 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
71 class IfThenResultExprImpl : public internal::ResultExprImpl {
72 public:
73 IfThenResultExprImpl(const BoolExpr& cond,
74 const ResultExpr& then_result,
75 const ResultExpr& else_result)
76 : cond_(cond), then_result_(then_result), else_result_(else_result) {}
78 CodeGen::Node Compile(PolicyCompiler* pc) const override {
79 // We compile the "then" and "else" expressions in separate statements so
80 // they have a defined sequencing. See https://crbug.com/529480.
81 CodeGen::Node then_node = then_result_->Compile(pc);
82 CodeGen::Node else_node = else_result_->Compile(pc);
83 return cond_->Compile(pc, then_node, else_node);
86 bool HasUnsafeTraps() const override {
87 return then_result_->HasUnsafeTraps() || else_result_->HasUnsafeTraps();
90 private:
91 ~IfThenResultExprImpl() override {}
93 BoolExpr cond_;
94 ResultExpr then_result_;
95 ResultExpr else_result_;
97 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl);
100 class ConstBoolExprImpl : public internal::BoolExprImpl {
101 public:
102 ConstBoolExprImpl(bool value) : value_(value) {}
104 CodeGen::Node Compile(PolicyCompiler* pc,
105 CodeGen::Node then_node,
106 CodeGen::Node else_node) const override {
107 return value_ ? then_node : else_node;
110 private:
111 ~ConstBoolExprImpl() override {}
113 bool value_;
115 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl);
118 class MaskedEqualBoolExprImpl : public internal::BoolExprImpl {
119 public:
120 MaskedEqualBoolExprImpl(int argno,
121 size_t width,
122 uint64_t mask,
123 uint64_t value)
124 : argno_(argno), width_(width), mask_(mask), value_(value) {}
126 CodeGen::Node Compile(PolicyCompiler* pc,
127 CodeGen::Node then_node,
128 CodeGen::Node else_node) const override {
129 return pc->MaskedEqual(argno_, width_, mask_, value_, then_node, else_node);
132 private:
133 ~MaskedEqualBoolExprImpl() override {}
135 int argno_;
136 size_t width_;
137 uint64_t mask_;
138 uint64_t value_;
140 DISALLOW_COPY_AND_ASSIGN(MaskedEqualBoolExprImpl);
143 class NegateBoolExprImpl : public internal::BoolExprImpl {
144 public:
145 explicit NegateBoolExprImpl(const BoolExpr& cond) : cond_(cond) {}
147 CodeGen::Node Compile(PolicyCompiler* pc,
148 CodeGen::Node then_node,
149 CodeGen::Node else_node) const override {
150 return cond_->Compile(pc, else_node, then_node);
153 private:
154 ~NegateBoolExprImpl() override {}
156 BoolExpr cond_;
158 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl);
161 class AndBoolExprImpl : public internal::BoolExprImpl {
162 public:
163 AndBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
164 : lhs_(lhs), rhs_(rhs) {}
166 CodeGen::Node Compile(PolicyCompiler* pc,
167 CodeGen::Node then_node,
168 CodeGen::Node else_node) const override {
169 return lhs_->Compile(pc, rhs_->Compile(pc, then_node, else_node),
170 else_node);
173 private:
174 ~AndBoolExprImpl() override {}
176 BoolExpr lhs_;
177 BoolExpr rhs_;
179 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl);
182 class OrBoolExprImpl : public internal::BoolExprImpl {
183 public:
184 OrBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
185 : lhs_(lhs), rhs_(rhs) {}
187 CodeGen::Node Compile(PolicyCompiler* pc,
188 CodeGen::Node then_node,
189 CodeGen::Node else_node) const override {
190 return lhs_->Compile(pc, then_node,
191 rhs_->Compile(pc, then_node, else_node));
194 private:
195 ~OrBoolExprImpl() override {}
197 BoolExpr lhs_;
198 BoolExpr rhs_;
200 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl);
203 } // namespace
205 namespace internal {
207 bool ResultExprImpl::HasUnsafeTraps() const {
208 return false;
211 bool ResultExprImpl::IsAllow() const {
212 return false;
215 bool ResultExprImpl::IsDeny() const {
216 return false;
219 uint64_t DefaultMask(size_t size) {
220 switch (size) {
221 case 4:
222 return std::numeric_limits<uint32_t>::max();
223 case 8:
224 return std::numeric_limits<uint64_t>::max();
225 default:
226 CHECK(false) << "Unimplemented DefaultMask case";
227 return 0;
231 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) {
232 // If this is changed, update Arg<T>::EqualTo's static_cast rules
233 // accordingly.
234 CHECK(size == 4 || size == 8);
236 return BoolExpr(new const MaskedEqualBoolExprImpl(num, size, mask, val));
239 } // namespace internal
241 ResultExpr Allow() {
242 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_ALLOW));
245 ResultExpr Error(int err) {
246 CHECK(err >= ErrorCode::ERR_MIN_ERRNO && err <= ErrorCode::ERR_MAX_ERRNO);
247 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_ERRNO + err));
250 ResultExpr Kill() {
251 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_KILL));
254 ResultExpr Trace(uint16_t aux) {
255 return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_TRACE + aux));
258 ResultExpr Trap(TrapRegistry::TrapFnc trap_func, const void* aux) {
259 return ResultExpr(
260 new const TrapResultExprImpl(trap_func, aux, true /* safe */));
263 ResultExpr UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux) {
264 return ResultExpr(
265 new const TrapResultExprImpl(trap_func, aux, false /* unsafe */));
268 BoolExpr BoolConst(bool value) {
269 return BoolExpr(new const ConstBoolExprImpl(value));
272 BoolExpr operator!(const BoolExpr& cond) {
273 return BoolExpr(new const NegateBoolExprImpl(cond));
276 BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs) {
277 return BoolExpr(new const AndBoolExprImpl(lhs, rhs));
280 BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs) {
281 return BoolExpr(new const OrBoolExprImpl(lhs, rhs));
284 Elser If(const BoolExpr& cond, const ResultExpr& then_result) {
285 return Elser(nullptr).ElseIf(cond, then_result);
288 Elser::Elser(cons::List<Clause> clause_list) : clause_list_(clause_list) {
291 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) {
294 Elser::~Elser() {
297 Elser Elser::ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const {
298 return Elser(Cons(std::make_pair(cond, then_result), clause_list_));
301 ResultExpr Elser::Else(const ResultExpr& else_result) const {
302 // We finally have the default result expression for this
303 // if/then/else sequence. Also, we've already accumulated all
304 // if/then pairs into a list of reverse order (i.e., lower priority
305 // conditions are listed before higher priority ones). E.g., an
306 // expression like
308 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
310 // will have built up a list like
312 // [(b3, e3), (b2, e2), (b1, e1)].
314 // Now that we have e4, we can walk the list and create a ResultExpr
315 // tree like:
317 // expr = e4
318 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
319 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
320 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
322 // and end up with an appropriately chained tree.
324 ResultExpr expr = else_result;
325 for (const Clause& clause : clause_list_) {
326 expr = ResultExpr(
327 new const IfThenResultExprImpl(clause.first, clause.second, expr));
329 return expr;
332 } // namespace bpf_dsl
333 } // namespace sandbox
335 template class scoped_refptr<const sandbox::bpf_dsl::internal::BoolExprImpl>;
336 template class scoped_refptr<const sandbox::bpf_dsl::internal::ResultExprImpl>;