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"
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"
20 class AllowResultExprImpl : public internal::ResultExprImpl {
22 AllowResultExprImpl() {}
24 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
25 return ErrorCode(ErrorCode::ERR_ALLOWED);
29 virtual ~AllowResultExprImpl() {}
31 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl);
34 class ErrorResultExprImpl : public internal::ResultExprImpl {
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_);
45 virtual ~ErrorResultExprImpl() {}
49 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl);
52 class KillResultExprImpl : public internal::ResultExprImpl {
54 explicit KillResultExprImpl(const char* msg) : msg_(msg) { DCHECK(msg_); }
56 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
57 return sb->Kill(msg_);
61 virtual ~KillResultExprImpl() {}
65 DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl);
68 class TraceResultExprImpl : public internal::ResultExprImpl {
70 TraceResultExprImpl(uint16_t aux) : aux_(aux) {}
72 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
73 return ErrorCode(ErrorCode::ERR_TRACE + aux_);
77 virtual ~TraceResultExprImpl() {}
81 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl);
84 class TrapResultExprImpl : public internal::ResultExprImpl {
86 TrapResultExprImpl(Trap::TrapFnc func, const void* arg)
87 : func_(func), arg_(arg) {
91 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
92 return sb->Trap(func_, arg_);
96 virtual ~TrapResultExprImpl() {}
101 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
104 class UnsafeTrapResultExprImpl : public internal::ResultExprImpl {
106 UnsafeTrapResultExprImpl(Trap::TrapFnc func, const void* arg)
107 : func_(func), arg_(arg) {
111 virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
112 return sb->UnsafeTrap(func_, arg_);
116 virtual ~UnsafeTrapResultExprImpl() {}
121 DISALLOW_COPY_AND_ASSIGN(UnsafeTrapResultExprImpl);
124 class IfThenResultExprImpl : public internal::ResultExprImpl {
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));
137 virtual ~IfThenResultExprImpl() {}
140 ResultExpr then_result_;
141 ResultExpr else_result_;
143 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl);
146 class ConstBoolExprImpl : public internal::BoolExprImpl {
148 ConstBoolExprImpl(bool value) : value_(value) {}
150 virtual ErrorCode Compile(SandboxBPF* sb,
152 ErrorCode false_ec) const OVERRIDE {
153 return value_ ? true_ec : false_ec;
157 virtual ~ConstBoolExprImpl() {}
161 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl);
164 class PrimitiveBoolExprImpl : public internal::BoolExprImpl {
166 PrimitiveBoolExprImpl(int argno,
167 ErrorCode::ArgType is_32bit,
170 : argno_(argno), is_32bit_(is_32bit), mask_(mask), value_(value) {}
172 virtual ErrorCode Compile(SandboxBPF* sb,
174 ErrorCode false_ec) const OVERRIDE {
175 return sb->CondMaskedEqual(
176 argno_, is_32bit_, mask_, value_, true_ec, false_ec);
180 virtual ~PrimitiveBoolExprImpl() {}
183 ErrorCode::ArgType is_32bit_;
187 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl);
190 class NegateBoolExprImpl : public internal::BoolExprImpl {
192 explicit NegateBoolExprImpl(const BoolExpr& cond) : cond_(cond) {}
194 virtual ErrorCode Compile(SandboxBPF* sb,
196 ErrorCode false_ec) const OVERRIDE {
197 return cond_->Compile(sb, false_ec, true_ec);
201 virtual ~NegateBoolExprImpl() {}
205 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl);
208 class AndBoolExprImpl : public internal::BoolExprImpl {
210 AndBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
211 : lhs_(lhs), rhs_(rhs) {}
213 virtual ErrorCode Compile(SandboxBPF* sb,
215 ErrorCode false_ec) const OVERRIDE {
216 return lhs_->Compile(sb, rhs_->Compile(sb, true_ec, false_ec), false_ec);
220 virtual ~AndBoolExprImpl() {}
225 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl);
228 class OrBoolExprImpl : public internal::BoolExprImpl {
230 OrBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs)
231 : lhs_(lhs), rhs_(rhs) {}
233 virtual ErrorCode Compile(SandboxBPF* sb,
235 ErrorCode false_ec) const OVERRIDE {
236 return lhs_->Compile(sb, true_ec, rhs_->Compile(sb, true_ec, false_ec));
240 virtual ~OrBoolExprImpl() {}
245 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl);
252 uint64_t DefaultMask(size_t size) {
255 return std::numeric_limits<uint32_t>::max();
257 return std::numeric_limits<uint64_t>::max();
259 CHECK(false) << "Unimplemented DefaultMask case";
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
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_) {
329 Elser Elser::ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const {
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
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
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();
361 new const IfThenResultExprImpl(clause.first, clause.second, expr));
366 ResultExpr SandboxBPFDSLPolicy::InvalidSyscall() const {
367 return Error(ENOSYS);
370 ErrorCode SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF* sb,
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