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"
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"
20 intptr_t BPFFailure(const struct arch_seccomp_data
&, void* aux
) {
21 SANDBOX_DIE(static_cast<char*>(aux
));
24 class AllowResultExprImpl
: public internal::ResultExprImpl
{
26 AllowResultExprImpl() {}
28 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
29 return ErrorCode(ErrorCode::ERR_ALLOWED
);
32 bool IsAllow() const override
{ return true; }
35 ~AllowResultExprImpl() override
{}
37 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl
);
40 class ErrorResultExprImpl
: public internal::ResultExprImpl
{
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; }
53 ~ErrorResultExprImpl() override
{}
57 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl
);
60 class TraceResultExprImpl
: public internal::ResultExprImpl
{
62 TraceResultExprImpl(uint16_t aux
) : aux_(aux
) {}
64 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
65 return ErrorCode(ErrorCode::ERR_TRACE
+ aux_
);
69 ~TraceResultExprImpl() override
{}
73 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl
);
76 class TrapResultExprImpl
: public internal::ResultExprImpl
{
78 TrapResultExprImpl(TrapRegistry::TrapFnc func
, const void* arg
, bool safe
)
79 : func_(func
), arg_(arg
), safe_(safe
) {
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; }
92 ~TrapResultExprImpl() override
{}
94 TrapRegistry::TrapFnc func_
;
98 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl
);
101 class IfThenResultExprImpl
: public internal::ResultExprImpl
{
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();
118 ~IfThenResultExprImpl() override
{}
121 ResultExpr then_result_
;
122 ResultExpr else_result_
;
124 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl
);
127 class ConstBoolExprImpl
: public internal::BoolExprImpl
{
129 ConstBoolExprImpl(bool value
) : value_(value
) {}
131 ErrorCode
Compile(PolicyCompiler
* pc
,
133 ErrorCode false_ec
) const override
{
134 return value_
? true_ec
: false_ec
;
138 ~ConstBoolExprImpl() override
{}
142 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl
);
145 class PrimitiveBoolExprImpl
: public internal::BoolExprImpl
{
147 PrimitiveBoolExprImpl(int argno
,
148 ErrorCode::ArgType is_32bit
,
151 : argno_(argno
), is_32bit_(is_32bit
), mask_(mask
), value_(value
) {}
153 ErrorCode
Compile(PolicyCompiler
* pc
,
155 ErrorCode false_ec
) const override
{
156 return pc
->CondMaskedEqual(
157 argno_
, is_32bit_
, mask_
, value_
, true_ec
, false_ec
);
161 ~PrimitiveBoolExprImpl() override
{}
164 ErrorCode::ArgType is_32bit_
;
168 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl
);
171 class NegateBoolExprImpl
: public internal::BoolExprImpl
{
173 explicit NegateBoolExprImpl(const BoolExpr
& cond
) : cond_(cond
) {}
175 ErrorCode
Compile(PolicyCompiler
* pc
,
177 ErrorCode false_ec
) const override
{
178 return cond_
->Compile(pc
, false_ec
, true_ec
);
182 ~NegateBoolExprImpl() override
{}
186 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl
);
189 class AndBoolExprImpl
: public internal::BoolExprImpl
{
191 AndBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
192 : lhs_(lhs
), rhs_(rhs
) {}
194 ErrorCode
Compile(PolicyCompiler
* pc
,
196 ErrorCode false_ec
) const override
{
197 return lhs_
->Compile(pc
, rhs_
->Compile(pc
, true_ec
, false_ec
), false_ec
);
201 ~AndBoolExprImpl() override
{}
206 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl
);
209 class OrBoolExprImpl
: public internal::BoolExprImpl
{
211 OrBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
212 : lhs_(lhs
), rhs_(rhs
) {}
214 ErrorCode
Compile(PolicyCompiler
* pc
,
216 ErrorCode false_ec
) const override
{
217 return lhs_
->Compile(pc
, true_ec
, rhs_
->Compile(pc
, true_ec
, false_ec
));
221 ~OrBoolExprImpl() override
{}
226 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl
);
233 bool ResultExprImpl::HasUnsafeTraps() const {
237 bool ResultExprImpl::IsAllow() const {
241 bool ResultExprImpl::IsDeny() const {
245 uint64_t DefaultMask(size_t size
) {
248 return std::numeric_limits
<uint32_t>::max();
250 return std::numeric_limits
<uint64_t>::max();
252 CHECK(false) << "Unimplemented DefaultMask case";
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
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
) {
287 new const TrapResultExprImpl(trap_func
, aux
, true /* safe */));
290 ResultExpr
UnsafeTrap(TrapRegistry::TrapFnc trap_func
, const void* aux
) {
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_
) {
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
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
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_
) {
354 new const IfThenResultExprImpl(clause
.first
, clause
.second
, 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
>;