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/errorcode.h"
19 class AllowResultExprImpl
: public internal::ResultExprImpl
{
21 AllowResultExprImpl() {}
23 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
24 return ErrorCode(ErrorCode::ERR_ALLOWED
);
28 ~AllowResultExprImpl() override
{}
30 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl
);
33 class ErrorResultExprImpl
: public internal::ResultExprImpl
{
35 explicit ErrorResultExprImpl(int err
) : err_(err
) {
36 CHECK(err_
>= ErrorCode::ERR_MIN_ERRNO
&& err_
<= ErrorCode::ERR_MAX_ERRNO
);
39 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
40 return pc
->Error(err_
);
44 ~ErrorResultExprImpl() override
{}
48 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl
);
51 class KillResultExprImpl
: public internal::ResultExprImpl
{
53 explicit KillResultExprImpl(const char* msg
) : msg_(msg
) { DCHECK(msg_
); }
55 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
56 return pc
->Kill(msg_
);
60 ~KillResultExprImpl() override
{}
64 DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl
);
67 class TraceResultExprImpl
: public internal::ResultExprImpl
{
69 TraceResultExprImpl(uint16_t aux
) : aux_(aux
) {}
71 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
72 return ErrorCode(ErrorCode::ERR_TRACE
+ aux_
);
76 ~TraceResultExprImpl() override
{}
80 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl
);
83 class TrapResultExprImpl
: public internal::ResultExprImpl
{
85 TrapResultExprImpl(TrapRegistry::TrapFnc func
, const void* arg
)
86 : func_(func
), arg_(arg
) {
90 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
91 return pc
->Trap(func_
, arg_
);
95 ~TrapResultExprImpl() override
{}
97 TrapRegistry::TrapFnc func_
;
100 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl
);
103 class UnsafeTrapResultExprImpl
: public internal::ResultExprImpl
{
105 UnsafeTrapResultExprImpl(TrapRegistry::TrapFnc func
, const void* arg
)
106 : func_(func
), arg_(arg
) {
110 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
111 return pc
->UnsafeTrap(func_
, arg_
);
114 bool HasUnsafeTraps() const override
{ return true; }
117 ~UnsafeTrapResultExprImpl() override
{}
119 TrapRegistry::TrapFnc func_
;
122 DISALLOW_COPY_AND_ASSIGN(UnsafeTrapResultExprImpl
);
125 class IfThenResultExprImpl
: public internal::ResultExprImpl
{
127 IfThenResultExprImpl(const BoolExpr
& cond
,
128 const ResultExpr
& then_result
,
129 const ResultExpr
& else_result
)
130 : cond_(cond
), then_result_(then_result
), else_result_(else_result
) {}
132 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
133 return cond_
->Compile(
134 pc
, then_result_
->Compile(pc
), else_result_
->Compile(pc
));
137 bool HasUnsafeTraps() const override
{
138 return then_result_
->HasUnsafeTraps() || else_result_
->HasUnsafeTraps();
142 ~IfThenResultExprImpl() override
{}
145 ResultExpr then_result_
;
146 ResultExpr else_result_
;
148 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl
);
151 class ConstBoolExprImpl
: public internal::BoolExprImpl
{
153 ConstBoolExprImpl(bool value
) : value_(value
) {}
155 ErrorCode
Compile(PolicyCompiler
* pc
,
157 ErrorCode false_ec
) const override
{
158 return value_
? true_ec
: false_ec
;
162 ~ConstBoolExprImpl() override
{}
166 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl
);
169 class PrimitiveBoolExprImpl
: public internal::BoolExprImpl
{
171 PrimitiveBoolExprImpl(int argno
,
172 ErrorCode::ArgType is_32bit
,
175 : argno_(argno
), is_32bit_(is_32bit
), mask_(mask
), value_(value
) {}
177 ErrorCode
Compile(PolicyCompiler
* pc
,
179 ErrorCode false_ec
) const override
{
180 return pc
->CondMaskedEqual(
181 argno_
, is_32bit_
, mask_
, value_
, true_ec
, false_ec
);
185 ~PrimitiveBoolExprImpl() override
{}
188 ErrorCode::ArgType is_32bit_
;
192 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl
);
195 class NegateBoolExprImpl
: public internal::BoolExprImpl
{
197 explicit NegateBoolExprImpl(const BoolExpr
& cond
) : cond_(cond
) {}
199 ErrorCode
Compile(PolicyCompiler
* pc
,
201 ErrorCode false_ec
) const override
{
202 return cond_
->Compile(pc
, false_ec
, true_ec
);
206 ~NegateBoolExprImpl() override
{}
210 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl
);
213 class AndBoolExprImpl
: public internal::BoolExprImpl
{
215 AndBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
216 : lhs_(lhs
), rhs_(rhs
) {}
218 ErrorCode
Compile(PolicyCompiler
* pc
,
220 ErrorCode false_ec
) const override
{
221 return lhs_
->Compile(pc
, rhs_
->Compile(pc
, true_ec
, false_ec
), false_ec
);
225 ~AndBoolExprImpl() override
{}
230 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl
);
233 class OrBoolExprImpl
: public internal::BoolExprImpl
{
235 OrBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
236 : lhs_(lhs
), rhs_(rhs
) {}
238 ErrorCode
Compile(PolicyCompiler
* pc
,
240 ErrorCode false_ec
) const override
{
241 return lhs_
->Compile(pc
, true_ec
, rhs_
->Compile(pc
, true_ec
, false_ec
));
245 ~OrBoolExprImpl() override
{}
250 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl
);
257 bool ResultExprImpl::HasUnsafeTraps() const {
261 uint64_t DefaultMask(size_t size
) {
264 return std::numeric_limits
<uint32_t>::max();
266 return std::numeric_limits
<uint64_t>::max();
268 CHECK(false) << "Unimplemented DefaultMask case";
273 BoolExpr
ArgEq(int num
, size_t size
, uint64_t mask
, uint64_t val
) {
274 CHECK(size
== 4 || size
== 8);
276 // TODO(mdempsky): Should we just always use TP_64BIT?
277 const ErrorCode::ArgType arg_type
=
278 (size
== 4) ? ErrorCode::TP_32BIT
: ErrorCode::TP_64BIT
;
280 return BoolExpr(new const PrimitiveBoolExprImpl(num
, arg_type
, mask
, val
));
283 } // namespace internal
286 return ResultExpr(new const AllowResultExprImpl());
289 ResultExpr
Error(int err
) {
290 return ResultExpr(new const ErrorResultExprImpl(err
));
293 ResultExpr
Kill(const char* msg
) {
294 return ResultExpr(new const KillResultExprImpl(msg
));
297 ResultExpr
Trace(uint16_t aux
) {
298 return ResultExpr(new const TraceResultExprImpl(aux
));
301 ResultExpr
Trap(TrapRegistry::TrapFnc trap_func
, const void* aux
) {
302 return ResultExpr(new const TrapResultExprImpl(trap_func
, aux
));
305 ResultExpr
UnsafeTrap(TrapRegistry::TrapFnc trap_func
, const void* aux
) {
306 return ResultExpr(new const UnsafeTrapResultExprImpl(trap_func
, aux
));
309 BoolExpr
BoolConst(bool value
) {
310 return BoolExpr(new const ConstBoolExprImpl(value
));
313 BoolExpr
operator!(const BoolExpr
& cond
) {
314 return BoolExpr(new const NegateBoolExprImpl(cond
));
317 BoolExpr
operator&&(const BoolExpr
& lhs
, const BoolExpr
& rhs
) {
318 return BoolExpr(new const AndBoolExprImpl(lhs
, rhs
));
321 BoolExpr
operator||(const BoolExpr
& lhs
, const BoolExpr
& rhs
) {
322 return BoolExpr(new const OrBoolExprImpl(lhs
, rhs
));
325 Elser
If(const BoolExpr
& cond
, const ResultExpr
& then_result
) {
326 return Elser(nullptr).ElseIf(cond
, then_result
);
329 Elser::Elser(cons::List
<Clause
> clause_list
) : clause_list_(clause_list
) {
332 Elser::Elser(const Elser
& elser
) : clause_list_(elser
.clause_list_
) {
338 Elser
Elser::ElseIf(const BoolExpr
& cond
, const ResultExpr
& then_result
) const {
339 return Elser(Cons(std::make_pair(cond
, then_result
), clause_list_
));
342 ResultExpr
Elser::Else(const ResultExpr
& else_result
) const {
343 // We finally have the default result expression for this
344 // if/then/else sequence. Also, we've already accumulated all
345 // if/then pairs into a list of reverse order (i.e., lower priority
346 // conditions are listed before higher priority ones). E.g., an
349 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
351 // will have built up a list like
353 // [(b3, e3), (b2, e2), (b1, e1)].
355 // Now that we have e4, we can walk the list and create a ResultExpr
359 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
360 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
361 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
363 // and end up with an appropriately chained tree.
365 ResultExpr expr
= else_result
;
366 for (const Clause
& clause
: clause_list_
) {
368 new const IfThenResultExprImpl(clause
.first
, clause
.second
, expr
));
373 } // namespace bpf_dsl
374 } // namespace sandbox
376 template class scoped_refptr
<const sandbox::bpf_dsl::internal::BoolExprImpl
>;
377 template class scoped_refptr
<const sandbox::bpf_dsl::internal::ResultExprImpl
>;