[GCM] Investigatory CHECKs for crash in parsing stream
[chromium-blink-merge.git] / sandbox / linux / bpf_dsl / bpf_dsl.cc
blob8144d805490722e9806d85d3e079f0154a322696
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 <errno.h>
9 #include <limits>
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "sandbox/linux/seccomp-bpf/errorcode.h"
14 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
16 namespace sandbox {
17 namespace bpf_dsl {
18 namespace {
20 class AllowResultExprImpl : public internal::ResultExprImpl {
21 public:
22 AllowResultExprImpl() {}
24 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
25 return ErrorCode(ErrorCode::ERR_ALLOWED);
28 private:
29 virtual ~AllowResultExprImpl() {}
31 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl);
34 class ErrorResultExprImpl : public internal::ResultExprImpl {
35 public:
36 explicit ErrorResultExprImpl(int err) : err_(err) {
37 CHECK(err_ >= ErrorCode::ERR_MIN_ERRNO && err_ <= ErrorCode::ERR_MAX_ERRNO);
40 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
41 return ErrorCode(err_);
44 private:
45 virtual ~ErrorResultExprImpl() {}
47 int err_;
49 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl);
52 class KillResultExprImpl : public internal::ResultExprImpl {
53 public:
54 explicit KillResultExprImpl(const char* msg) : msg_(msg) { DCHECK(msg_); }
56 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
57 return sb->Kill(msg_);
60 private:
61 virtual ~KillResultExprImpl() {}
63 const char* msg_;
65 DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl);
68 class TraceResultExprImpl : public internal::ResultExprImpl {
69 public:
70 TraceResultExprImpl(uint16_t aux) : aux_(aux) {}
72 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
73 return ErrorCode(ErrorCode::ERR_TRACE + aux_);
76 private:
77 virtual ~TraceResultExprImpl() {}
79 uint16_t aux_;
81 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl);
84 class TrapResultExprImpl : public internal::ResultExprImpl {
85 public:
86 TrapResultExprImpl(Trap::TrapFnc func, const void* arg)
87 : func_(func), arg_(arg) {
88 DCHECK(func_);
91 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
92 return sb->Trap(func_, arg_);
95 private:
96 virtual ~TrapResultExprImpl() {}
98 Trap::TrapFnc func_;
99 const void* arg_;
101 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
104 class UnsafeTrapResultExprImpl : public internal::ResultExprImpl {
105 public:
106 UnsafeTrapResultExprImpl(Trap::TrapFnc func, const void* arg)
107 : func_(func), arg_(arg) {
108 DCHECK(func_);
111 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
112 return sb->UnsafeTrap(func_, arg_);
115 private:
116 virtual ~UnsafeTrapResultExprImpl() {}
118 Trap::TrapFnc func_;
119 const void* arg_;
121 DISALLOW_COPY_AND_ASSIGN(UnsafeTrapResultExprImpl);
124 class IfThenResultExprImpl : public internal::ResultExprImpl {
125 public:
126 IfThenResultExprImpl(const BoolExpr& cond,
127 const ResultExpr& then_result,
128 const ResultExpr& else_result)
129 : cond_(cond), then_result_(then_result), else_result_(else_result) {}
131 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
132 return cond_->Compile(
133 sb, then_result_->Compile(sb), else_result_->Compile(sb));
136 private:
137 virtual ~IfThenResultExprImpl() {}
139 BoolExpr cond_;
140 ResultExpr then_result_;
141 ResultExpr else_result_;
143 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl);
146 class ConstBoolExprImpl : public internal::BoolExprImpl {
147 public:
148 ConstBoolExprImpl(bool value) : value_(value) {}
150 virtual ErrorCode Compile(SandboxBPF* sb,
151 ErrorCode true_ec,
152 ErrorCode false_ec) const OVERRIDE {
153 return value_ ? true_ec : false_ec;
156 private:
157 virtual ~ConstBoolExprImpl() {}
159 bool value_;
161 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl);
164 class PrimitiveBoolExprImpl : public internal::BoolExprImpl {
165 public:
166 PrimitiveBoolExprImpl(int argno,
167 ErrorCode::ArgType is_32bit,
168 uint64_t mask,
169 uint64_t value)
170 : argno_(argno), is_32bit_(is_32bit), mask_(mask), value_(value) {}
172 virtual ErrorCode Compile(SandboxBPF* sb,
173 ErrorCode true_ec,
174 ErrorCode false_ec) const OVERRIDE {
175 return sb->CondMaskedEqual(
176 argno_, is_32bit_, mask_, value_, true_ec, false_ec);
179 private:
180 virtual ~PrimitiveBoolExprImpl() {}
182 int argno_;
183 ErrorCode::ArgType is_32bit_;
184 uint64_t mask_;
185 uint64_t value_;
187 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl);
190 class NegateBoolExprImpl : public internal::BoolExprImpl {
191 public:
192 explicit NegateBoolExprImpl(const BoolExpr& cond) : cond_(cond) {}
194 virtual ErrorCode Compile(SandboxBPF* sb,
195 ErrorCode true_ec,
196 ErrorCode false_ec) const OVERRIDE {
197 return cond_->Compile(sb, false_ec, true_ec);
200 private:
201 virtual ~NegateBoolExprImpl() {}
203 BoolExpr cond_;
205 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl);
208 class AndBoolExprImpl : public internal::BoolExprImpl {
209 public:
210 AndBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
211 : lhs_(lhs), rhs_(rhs) {}
213 virtual ErrorCode Compile(SandboxBPF* sb,
214 ErrorCode true_ec,
215 ErrorCode false_ec) const OVERRIDE {
216 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec);
219 private:
220 virtual ~AndBoolExprImpl() {}
222 BoolExpr lhs_;
223 BoolExpr rhs_;
225 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl);
228 class OrBoolExprImpl : public internal::BoolExprImpl {
229 public:
230 OrBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
231 : lhs_(lhs), rhs_(rhs) {}
233 virtual ErrorCode Compile(SandboxBPF* sb,
234 ErrorCode true_ec,
235 ErrorCode false_ec) const OVERRIDE {
236 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec));
239 private:
240 virtual ~OrBoolExprImpl() {}
242 BoolExpr lhs_;
243 BoolExpr rhs_;
245 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl);
248 } // namespace
250 namespace internal {
252 uint64_t DefaultMask(size_t size) {
253 switch (size) {
254 case 4:
255 return std::numeric_limits<uint32_t>::max();
256 case 8:
257 return std::numeric_limits<uint64_t>::max();
258 default:
259 CHECK(false) << "Unimplemented DefaultMask case";
260 return 0;
264 BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) {
265 CHECK(size == 4 || size == 8);
267 // TODO(mdempsky): Should we just always use TP_64BIT?
268 const ErrorCode::ArgType arg_type =
269 (size == 4) ? ErrorCode::TP_32BIT : ErrorCode::TP_64BIT;
271 return BoolExpr(new const PrimitiveBoolExprImpl(num, arg_type, mask, val));
274 } // namespace internal
276 ResultExpr Allow() {
277 return ResultExpr(new const AllowResultExprImpl());
280 ResultExpr Error(int err) {
281 return ResultExpr(new const ErrorResultExprImpl(err));
284 ResultExpr Kill(const char* msg) {
285 return ResultExpr(new const KillResultExprImpl(msg));
288 ResultExpr Trace(uint16_t aux) {
289 return ResultExpr(new const TraceResultExprImpl(aux));
292 ResultExpr Trap(Trap::TrapFnc trap_func, const void* aux) {
293 return ResultExpr(new const TrapResultExprImpl(trap_func, aux));
296 ResultExpr UnsafeTrap(Trap::TrapFnc trap_func, const void* aux) {
297 return ResultExpr(new const UnsafeTrapResultExprImpl(trap_func, aux));
300 BoolExpr BoolConst(bool value) {
301 return BoolExpr(new const ConstBoolExprImpl(value));
304 BoolExpr operator!(const BoolExpr& cond) {
305 return BoolExpr(new const NegateBoolExprImpl(cond));
308 BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs) {
309 return BoolExpr(new const AndBoolExprImpl(lhs, rhs));
312 BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs) {
313 return BoolExpr(new const OrBoolExprImpl(lhs, rhs));
316 Elser If(const BoolExpr& cond, const ResultExpr& then_result) {
317 return Elser(Cons<Elser::Clause>::List()).ElseIf(cond, then_result);
320 Elser::Elser(Cons<Clause>::List clause_list) : clause_list_(clause_list) {
323 Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) {
326 Elser::~Elser() {
329 Elser Elser::ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const {
330 return Elser(
331 Cons<Clause>::Make(std::make_pair(cond, then_result), clause_list_));
334 ResultExpr Elser::Else(const ResultExpr& else_result) const {
335 // We finally have the default result expression for this
336 // if/then/else sequence. Also, we've already accumulated all
337 // if/then pairs into a list of reverse order (i.e., lower priority
338 // conditions are listed before higher priority ones). E.g., an
339 // expression like
341 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
343 // will have built up a list like
345 // [(b3, e3), (b2, e2), (b1, e1)].
347 // Now that we have e4, we can walk the list and create a ResultExpr
348 // tree like:
350 // expr = e4
351 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
352 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
353 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
355 // and end up with an appropriately chained tree.
357 ResultExpr expr = else_result;
358 for (Cons<Clause>::List it = clause_list_; it.get(); it = it->tail()) {
359 Clause clause = it->head();
360 expr = ResultExpr(
361 new const IfThenResultExprImpl(clause.first, clause.second, expr));
363 return expr;
366 ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const {
367 return Error(ENOSYS);
370 ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb,
371 int sysno) const {
372 return EvaluateSyscall(sysno)->Compile(sb);
375 ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const {
376 return InvalidSyscall()->Compile(sb);
379 ResultExpr SandboxBPFDSLPolicy::Trap(Trap::TrapFnc trap_func, const void* aux) {
380 return bpf_dsl::Trap(trap_func, aux);
383 } // namespace bpf_dsl
384 } // namespace sandbox