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/errorcode.h"
13 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
19 class AllowResultExprImpl
: public internal::ResultExprImpl
{
21 AllowResultExprImpl() {}
23 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
24 return ErrorCode(ErrorCode::ERR_ALLOWED
);
27 bool IsAllow() const override
{ return true; }
30 ~AllowResultExprImpl() override
{}
32 DISALLOW_COPY_AND_ASSIGN(AllowResultExprImpl
);
35 class ErrorResultExprImpl
: public internal::ResultExprImpl
{
37 explicit ErrorResultExprImpl(int err
) : err_(err
) {
38 CHECK(err_
>= ErrorCode::ERR_MIN_ERRNO
&& err_
<= ErrorCode::ERR_MAX_ERRNO
);
41 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
42 return pc
->Error(err_
);
45 bool IsDeny() const override
{ return true; }
48 ~ErrorResultExprImpl() override
{}
52 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl
);
55 class KillResultExprImpl
: public internal::ResultExprImpl
{
57 KillResultExprImpl() {}
59 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
60 return ErrorCode(ErrorCode::ERR_KILL
);
63 bool IsDeny() const override
{ return true; }
66 ~KillResultExprImpl() override
{}
68 DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl
);
71 class TraceResultExprImpl
: public internal::ResultExprImpl
{
73 TraceResultExprImpl(uint16_t aux
) : aux_(aux
) {}
75 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
76 return ErrorCode(ErrorCode::ERR_TRACE
+ aux_
);
80 ~TraceResultExprImpl() override
{}
84 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl
);
87 class TrapResultExprImpl
: public internal::ResultExprImpl
{
89 TrapResultExprImpl(TrapRegistry::TrapFnc func
, const void* arg
, bool safe
)
90 : func_(func
), arg_(arg
), safe_(safe
) {
94 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
95 return pc
->Trap(func_
, arg_
, safe_
);
98 bool HasUnsafeTraps() const override
{ return safe_
== false; }
100 bool IsDeny() const override
{ return true; }
103 ~TrapResultExprImpl() override
{}
105 TrapRegistry::TrapFnc func_
;
109 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl
);
112 class IfThenResultExprImpl
: public internal::ResultExprImpl
{
114 IfThenResultExprImpl(const BoolExpr
& cond
,
115 const ResultExpr
& then_result
,
116 const ResultExpr
& else_result
)
117 : cond_(cond
), then_result_(then_result
), else_result_(else_result
) {}
119 ErrorCode
Compile(PolicyCompiler
* pc
) const override
{
120 return cond_
->Compile(
121 pc
, then_result_
->Compile(pc
), else_result_
->Compile(pc
));
124 bool HasUnsafeTraps() const override
{
125 return then_result_
->HasUnsafeTraps() || else_result_
->HasUnsafeTraps();
129 ~IfThenResultExprImpl() override
{}
132 ResultExpr then_result_
;
133 ResultExpr else_result_
;
135 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl
);
138 class ConstBoolExprImpl
: public internal::BoolExprImpl
{
140 ConstBoolExprImpl(bool value
) : value_(value
) {}
142 ErrorCode
Compile(PolicyCompiler
* pc
,
144 ErrorCode false_ec
) const override
{
145 return value_
? true_ec
: false_ec
;
149 ~ConstBoolExprImpl() override
{}
153 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl
);
156 class PrimitiveBoolExprImpl
: public internal::BoolExprImpl
{
158 PrimitiveBoolExprImpl(int argno
,
159 ErrorCode::ArgType is_32bit
,
162 : argno_(argno
), is_32bit_(is_32bit
), mask_(mask
), value_(value
) {}
164 ErrorCode
Compile(PolicyCompiler
* pc
,
166 ErrorCode false_ec
) const override
{
167 return pc
->CondMaskedEqual(
168 argno_
, is_32bit_
, mask_
, value_
, true_ec
, false_ec
);
172 ~PrimitiveBoolExprImpl() override
{}
175 ErrorCode::ArgType is_32bit_
;
179 DISALLOW_COPY_AND_ASSIGN(PrimitiveBoolExprImpl
);
182 class NegateBoolExprImpl
: public internal::BoolExprImpl
{
184 explicit NegateBoolExprImpl(const BoolExpr
& cond
) : cond_(cond
) {}
186 ErrorCode
Compile(PolicyCompiler
* pc
,
188 ErrorCode false_ec
) const override
{
189 return cond_
->Compile(pc
, false_ec
, true_ec
);
193 ~NegateBoolExprImpl() override
{}
197 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl
);
200 class AndBoolExprImpl
: public internal::BoolExprImpl
{
202 AndBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
203 : lhs_(lhs
), rhs_(rhs
) {}
205 ErrorCode
Compile(PolicyCompiler
* pc
,
207 ErrorCode false_ec
) const override
{
208 return lhs_
->Compile(pc
, rhs_
->Compile(pc
, true_ec
, false_ec
), false_ec
);
212 ~AndBoolExprImpl() override
{}
217 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl
);
220 class OrBoolExprImpl
: public internal::BoolExprImpl
{
222 OrBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
223 : lhs_(lhs
), rhs_(rhs
) {}
225 ErrorCode
Compile(PolicyCompiler
* pc
,
227 ErrorCode false_ec
) const override
{
228 return lhs_
->Compile(pc
, true_ec
, rhs_
->Compile(pc
, true_ec
, false_ec
));
232 ~OrBoolExprImpl() override
{}
237 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl
);
244 bool ResultExprImpl::HasUnsafeTraps() const {
248 bool ResultExprImpl::IsAllow() const {
252 bool ResultExprImpl::IsDeny() const {
256 uint64_t DefaultMask(size_t size
) {
259 return std::numeric_limits
<uint32_t>::max();
261 return std::numeric_limits
<uint64_t>::max();
263 CHECK(false) << "Unimplemented DefaultMask case";
268 BoolExpr
ArgEq(int num
, size_t size
, uint64_t mask
, uint64_t val
) {
269 // If this is changed, update Arg<T>::EqualTo's static_cast rules
271 CHECK(size
== 4 || size
== 8);
273 // TODO(mdempsky): Should we just always use TP_64BIT?
274 const ErrorCode::ArgType arg_type
=
275 (size
== 4) ? ErrorCode::TP_32BIT
: ErrorCode::TP_64BIT
;
277 return BoolExpr(new const PrimitiveBoolExprImpl(num
, arg_type
, mask
, val
));
280 } // namespace internal
283 return ResultExpr(new const AllowResultExprImpl());
286 ResultExpr
Error(int err
) {
287 return ResultExpr(new const ErrorResultExprImpl(err
));
291 return ResultExpr(new const KillResultExprImpl());
294 ResultExpr
Trace(uint16_t aux
) {
295 return ResultExpr(new const TraceResultExprImpl(aux
));
298 ResultExpr
Trap(TrapRegistry::TrapFnc trap_func
, const void* aux
) {
300 new const TrapResultExprImpl(trap_func
, aux
, true /* safe */));
303 ResultExpr
UnsafeTrap(TrapRegistry::TrapFnc trap_func
, const void* aux
) {
305 new const TrapResultExprImpl(trap_func
, aux
, false /* unsafe */));
308 BoolExpr
BoolConst(bool value
) {
309 return BoolExpr(new const ConstBoolExprImpl(value
));
312 BoolExpr
operator!(const BoolExpr
& cond
) {
313 return BoolExpr(new const NegateBoolExprImpl(cond
));
316 BoolExpr
operator&&(const BoolExpr
& lhs
, const BoolExpr
& rhs
) {
317 return BoolExpr(new const AndBoolExprImpl(lhs
, rhs
));
320 BoolExpr
operator||(const BoolExpr
& lhs
, const BoolExpr
& rhs
) {
321 return BoolExpr(new const OrBoolExprImpl(lhs
, rhs
));
324 Elser
If(const BoolExpr
& cond
, const ResultExpr
& then_result
) {
325 return Elser(nullptr).ElseIf(cond
, then_result
);
328 Elser::Elser(cons::List
<Clause
> clause_list
) : clause_list_(clause_list
) {
331 Elser::Elser(const Elser
& elser
) : clause_list_(elser
.clause_list_
) {
337 Elser
Elser::ElseIf(const BoolExpr
& cond
, const ResultExpr
& then_result
) const {
338 return Elser(Cons(std::make_pair(cond
, then_result
), clause_list_
));
341 ResultExpr
Elser::Else(const ResultExpr
& else_result
) const {
342 // We finally have the default result expression for this
343 // if/then/else sequence. Also, we've already accumulated all
344 // if/then pairs into a list of reverse order (i.e., lower priority
345 // conditions are listed before higher priority ones). E.g., an
348 // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4)
350 // will have built up a list like
352 // [(b3, e3), (b2, e2), (b1, e1)].
354 // Now that we have e4, we can walk the list and create a ResultExpr
358 // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4)
359 // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4))
360 // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4)))
362 // and end up with an appropriately chained tree.
364 ResultExpr expr
= else_result
;
365 for (const Clause
& clause
: clause_list_
) {
367 new const IfThenResultExprImpl(clause
.first
, clause
.second
, expr
));
372 } // namespace bpf_dsl
373 } // namespace sandbox
375 template class scoped_refptr
<const sandbox::bpf_dsl::internal::BoolExprImpl
>;
376 template class scoped_refptr
<const sandbox::bpf_dsl::internal::ResultExprImpl
>;