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/bpf_dsl/bpf_dsl_impl.h"
14 #include "sandbox/linux/seccomp-bpf/errorcode.h"
15 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
16 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
22 class AllowResultExprImpl
: public internal::ResultExprImpl
{
24 AllowResultExprImpl() {}
26 virtual ErrorCode
Compile(SandboxBPF
* sb
) const override
{
27 return ErrorCode(ErrorCode::ERR_ALLOWED
);
31 virtual ~AllowResultExprImpl() {}
33 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl
);
36 class ErrorResultExprImpl
: public internal::ResultExprImpl
{
38 explicit ErrorResultExprImpl(int err
) : err_(err
) {
39 CHECK(err_
>= ErrorCode::ERR_MIN_ERRNO
&& err_
<= ErrorCode::ERR_MAX_ERRNO
);
42 virtual ErrorCode
Compile(SandboxBPF
* sb
) const override
{
43 return sb
->Error(err_
);
47 virtual ~ErrorResultExprImpl() {}
51 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl
);
54 class KillResultExprImpl
: public internal::ResultExprImpl
{
56 explicit KillResultExprImpl(const char* msg
) : msg_(msg
) { DCHECK(msg_
); }
58 virtual ErrorCode
Compile(SandboxBPF
* sb
) const override
{
59 return sb
->Kill(msg_
);
63 virtual ~KillResultExprImpl() {}
67 DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl
);
70 class TraceResultExprImpl
: public internal::ResultExprImpl
{
72 TraceResultExprImpl(uint16_t aux
) : aux_(aux
) {}
74 virtual ErrorCode
Compile(SandboxBPF
* sb
) const override
{
75 return ErrorCode(ErrorCode::ERR_TRACE
+ aux_
);
79 virtual ~TraceResultExprImpl() {}
83 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl
);
86 class TrapResultExprImpl
: public internal::ResultExprImpl
{
88 TrapResultExprImpl(Trap::TrapFnc func
, const void* arg
)
89 : func_(func
), arg_(arg
) {
93 virtual ErrorCode
Compile(SandboxBPF
* sb
) const override
{
94 return sb
->Trap(func_
, arg_
);
98 virtual ~TrapResultExprImpl() {}
103 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl
);
106 class UnsafeTrapResultExprImpl
: public internal::ResultExprImpl
{
108 UnsafeTrapResultExprImpl(Trap::TrapFnc func
, const void* arg
)
109 : func_(func
), arg_(arg
) {
113 virtual ErrorCode
Compile(SandboxBPF
* sb
) const override
{
114 return sb
->UnsafeTrap(func_
, arg_
);
117 virtual bool HasUnsafeTraps() const override
{ return true; }
120 virtual ~UnsafeTrapResultExprImpl() {}
125 DISALLOW_COPY_AND_ASSIGN(UnsafeTrapResultExprImpl
);
128 class IfThenResultExprImpl
: public internal::ResultExprImpl
{
130 IfThenResultExprImpl(const BoolExpr
& cond
,
131 const ResultExpr
& then_result
,
132 const ResultExpr
& else_result
)
133 : cond_(cond
), then_result_(then_result
), else_result_(else_result
) {}
135 virtual ErrorCode
Compile(SandboxBPF
* sb
) const override
{
136 return cond_
->Compile(
137 sb
, then_result_
->Compile(sb
), else_result_
->Compile(sb
));
140 virtual bool HasUnsafeTraps() const override
{
141 return then_result_
->HasUnsafeTraps() || else_result_
->HasUnsafeTraps();
145 virtual ~IfThenResultExprImpl() {}
148 ResultExpr then_result_
;
149 ResultExpr else_result_
;
151 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl
);
154 class ConstBoolExprImpl
: public internal::BoolExprImpl
{
156 ConstBoolExprImpl(bool value
) : value_(value
) {}
158 virtual ErrorCode
Compile(SandboxBPF
* sb
,
160 ErrorCode false_ec
) const override
{
161 return value_
? true_ec
: false_ec
;
165 virtual ~ConstBoolExprImpl() {}
169 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl
);
172 class PrimitiveBoolExprImpl
: public internal::BoolExprImpl
{
174 PrimitiveBoolExprImpl(int argno
,
175 ErrorCode::ArgType is_32bit
,
178 : argno_(argno
), is_32bit_(is_32bit
), mask_(mask
), value_(value
) {}
180 virtual ErrorCode
Compile(SandboxBPF
* sb
,
182 ErrorCode false_ec
) const override
{
183 return sb
->CondMaskedEqual(
184 argno_
, is_32bit_
, mask_
, value_
, true_ec
, false_ec
);
188 virtual ~PrimitiveBoolExprImpl() {}
191 ErrorCode::ArgType is_32bit_
;
195 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl
);
198 class NegateBoolExprImpl
: public internal::BoolExprImpl
{
200 explicit NegateBoolExprImpl(const BoolExpr
& cond
) : cond_(cond
) {}
202 virtual ErrorCode
Compile(SandboxBPF
* sb
,
204 ErrorCode false_ec
) const override
{
205 return cond_
->Compile(sb
, false_ec
, true_ec
);
209 virtual ~NegateBoolExprImpl() {}
213 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl
);
216 class AndBoolExprImpl
: public internal::BoolExprImpl
{
218 AndBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
219 : lhs_(lhs
), rhs_(rhs
) {}
221 virtual ErrorCode
Compile(SandboxBPF
* sb
,
223 ErrorCode false_ec
) const override
{
224 return lhs_
->Compile(sb
, rhs_
->Compile(sb
, true_ec
, false_ec
), false_ec
);
228 virtual ~AndBoolExprImpl() {}
233 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl
);
236 class OrBoolExprImpl
: public internal::BoolExprImpl
{
238 OrBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
239 : lhs_(lhs
), rhs_(rhs
) {}
241 virtual ErrorCode
Compile(SandboxBPF
* sb
,
243 ErrorCode false_ec
) const override
{
244 return lhs_
->Compile(sb
, true_ec
, rhs_
->Compile(sb
, true_ec
, false_ec
));
248 virtual ~OrBoolExprImpl() {}
253 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl
);
260 bool ResultExprImpl::HasUnsafeTraps() const {
264 uint64_t DefaultMask(size_t size
) {
267 return std::numeric_limits
<uint32_t>::max();
269 return std::numeric_limits
<uint64_t>::max();
271 CHECK(false) << "Unimplemented DefaultMask case";
276 BoolExpr
ArgEq(int num
, size_t size
, uint64_t mask
, uint64_t val
) {
277 CHECK(size
== 4 || size
== 8);
279 // TODO(mdempsky): Should we just always use TP_64BIT?
280 const ErrorCode::ArgType arg_type
=
281 (size
== 4) ? ErrorCode::TP_32BIT
: ErrorCode::TP_64BIT
;
283 return BoolExpr(new const PrimitiveBoolExprImpl(num
, arg_type
, mask
, val
));
286 } // namespace internal
289 return ResultExpr(new const AllowResultExprImpl());
292 ResultExpr
Error(int err
) {
293 return ResultExpr(new const ErrorResultExprImpl(err
));
296 ResultExpr
Kill(const char* msg
) {
297 return ResultExpr(new const KillResultExprImpl(msg
));
300 ResultExpr
Trace(uint16_t aux
) {
301 return ResultExpr(new const TraceResultExprImpl(aux
));
304 ResultExpr
Trap(Trap::TrapFnc trap_func
, const void* aux
) {
305 return ResultExpr(new const TrapResultExprImpl(trap_func
, aux
));
308 ResultExpr
UnsafeTrap(Trap::TrapFnc trap_func
, const void* aux
) {
309 return ResultExpr(new const UnsafeTrapResultExprImpl(trap_func
, aux
));
312 BoolExpr
BoolConst(bool value
) {
313 return BoolExpr(new const ConstBoolExprImpl(value
));
316 BoolExpr
operator!(const BoolExpr
& cond
) {
317 return BoolExpr(new const NegateBoolExprImpl(cond
));
320 BoolExpr
operator&&(const BoolExpr
& lhs
, const BoolExpr
& rhs
) {
321 return BoolExpr(new const AndBoolExprImpl(lhs
, rhs
));
324 BoolExpr
operator||(const BoolExpr
& lhs
, const BoolExpr
& rhs
) {
325 return BoolExpr(new const OrBoolExprImpl(lhs
, rhs
));
328 Elser
If(const BoolExpr
& cond
, const ResultExpr
& then_result
) {
329 return Elser(nullptr).ElseIf(cond
, then_result
);
332 Elser::Elser(cons::List
<Clause
> clause_list
) : clause_list_(clause_list
) {
335 Elser::Elser(const Elser
& elser
) : clause_list_(elser
.clause_list_
) {
341 Elser
Elser::ElseIf(const BoolExpr
& cond
, const ResultExpr
& then_result
) const {
342 return Elser(Cons(std::make_pair(cond
, then_result
), clause_list_
));
345 ResultExpr
Elser::Else(const ResultExpr
& else_result
) const {
346 // We finally have the default result expression for this
347 // if/then/else sequence. Also, we've already accumulated all
348 // if/then pairs into a list of reverse order (i.e., lower priority
349 // conditions are listed before higher priority ones). E.g., an
352 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
354 // will have built up a list like
356 // [(b3, e3), (b2, e2), (b1, e1)].
358 // Now that we have e4, we can walk the list and create a ResultExpr
362 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
363 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
364 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
366 // and end up with an appropriately chained tree.
368 ResultExpr expr
= else_result
;
369 for (const Clause
& clause
: clause_list_
) {
371 new const IfThenResultExprImpl(clause
.first
, clause
.second
, expr
));
376 ResultExpr
SandboxBPFDSLPolicy::InvalidSyscall() const {
377 return Error(ENOSYS
);
380 ErrorCode
SandboxBPFDSLPolicy::EvaluateSyscall(SandboxBPF
* sb
,
382 return EvaluateSyscall(sysno
)->Compile(sb
);
385 ErrorCode
SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF
* sb
) const {
386 return InvalidSyscall()->Compile(sb
);
389 bool SandboxBPFDSLPolicy::HasUnsafeTraps() const {
390 for (SyscallIterator
iter(false); !iter
.Done();) {
391 uint32_t sysnum
= iter
.Next();
392 if (SyscallIterator::IsValid(sysnum
) &&
393 EvaluateSyscall(sysnum
)->HasUnsafeTraps()) {
397 return InvalidSyscall()->HasUnsafeTraps();
400 ResultExpr
SandboxBPFDSLPolicy::Trap(Trap::TrapFnc trap_func
, const void* aux
) {
401 return bpf_dsl::Trap(trap_func
, aux
);
404 } // namespace bpf_dsl
405 } // namespace sandbox
407 template class scoped_refptr
<const sandbox::bpf_dsl::internal::BoolExprImpl
>;
408 template class scoped_refptr
<const sandbox::bpf_dsl::internal::ResultExprImpl
>;