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"
14 #include "sandbox/linux/system_headers/linux_seccomp.h"
20 class AllowResultExprImpl
: public internal::ResultExprImpl
{
22 AllowResultExprImpl() {}
24 CodeGen::Node
Compile(PolicyCompiler
* pc
) const override
{
25 return pc
->Return(SECCOMP_RET_ALLOW
);
28 bool IsAllow() const override
{ return true; }
31 ~AllowResultExprImpl() override
{}
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 CodeGen::Node
Compile(PolicyCompiler
* pc
) const override
{
43 return pc
->Return(SECCOMP_RET_ERRNO
+ err_
);
46 bool IsDeny() const override
{ return true; }
49 ~ErrorResultExprImpl() override
{}
53 DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl
);
56 class KillResultExprImpl
: public internal::ResultExprImpl
{
58 KillResultExprImpl() {}
60 CodeGen::Node
Compile(PolicyCompiler
* pc
) const override
{
61 return pc
->Return(SECCOMP_RET_KILL
);
64 bool IsDeny() const override
{ return true; }
67 ~KillResultExprImpl() override
{}
69 DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl
);
72 class TraceResultExprImpl
: public internal::ResultExprImpl
{
74 TraceResultExprImpl(uint16_t aux
) : aux_(aux
) {}
76 CodeGen::Node
Compile(PolicyCompiler
* pc
) const override
{
77 return pc
->Return(SECCOMP_RET_TRACE
+ aux_
);
81 ~TraceResultExprImpl() override
{}
85 DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl
);
88 class TrapResultExprImpl
: public internal::ResultExprImpl
{
90 TrapResultExprImpl(TrapRegistry::TrapFnc func
, const void* arg
, bool safe
)
91 : func_(func
), arg_(arg
), safe_(safe
) {
95 CodeGen::Node
Compile(PolicyCompiler
* pc
) const override
{
96 return pc
->Trap(func_
, arg_
, safe_
);
99 bool HasUnsafeTraps() const override
{ return safe_
== false; }
101 bool IsDeny() const override
{ return true; }
104 ~TrapResultExprImpl() override
{}
106 TrapRegistry::TrapFnc func_
;
110 DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl
);
113 class IfThenResultExprImpl
: public internal::ResultExprImpl
{
115 IfThenResultExprImpl(const BoolExpr
& cond
,
116 const ResultExpr
& then_result
,
117 const ResultExpr
& else_result
)
118 : cond_(cond
), then_result_(then_result
), else_result_(else_result
) {}
120 CodeGen::Node
Compile(PolicyCompiler
* pc
) const override
{
121 // We compile the "then" and "else" expressions in separate statements so
122 // they have a defined sequencing. See https://crbug.com/529480.
123 CodeGen::Node then_node
= then_result_
->Compile(pc
);
124 CodeGen::Node else_node
= else_result_
->Compile(pc
);
125 return cond_
->Compile(pc
, then_node
, else_node
);
128 bool HasUnsafeTraps() const override
{
129 return then_result_
->HasUnsafeTraps() || else_result_
->HasUnsafeTraps();
133 ~IfThenResultExprImpl() override
{}
136 ResultExpr then_result_
;
137 ResultExpr else_result_
;
139 DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl
);
142 class ConstBoolExprImpl
: public internal::BoolExprImpl
{
144 ConstBoolExprImpl(bool value
) : value_(value
) {}
146 CodeGen::Node
Compile(PolicyCompiler
* pc
,
147 CodeGen::Node then_node
,
148 CodeGen::Node else_node
) const override
{
149 return value_
? then_node
: else_node
;
153 ~ConstBoolExprImpl() override
{}
157 DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl
);
160 class MaskedEqualBoolExprImpl
: public internal::BoolExprImpl
{
162 MaskedEqualBoolExprImpl(int argno
,
166 : argno_(argno
), width_(width
), mask_(mask
), value_(value
) {}
168 CodeGen::Node
Compile(PolicyCompiler
* pc
,
169 CodeGen::Node then_node
,
170 CodeGen::Node else_node
) const override
{
171 return pc
->MaskedEqual(argno_
, width_
, mask_
, value_
, then_node
, else_node
);
175 ~MaskedEqualBoolExprImpl() override
{}
182 DISALLOW_COPY_AND_ASSIGN(MaskedEqualBoolExprImpl
);
185 class NegateBoolExprImpl
: public internal::BoolExprImpl
{
187 explicit NegateBoolExprImpl(const BoolExpr
& cond
) : cond_(cond
) {}
189 CodeGen::Node
Compile(PolicyCompiler
* pc
,
190 CodeGen::Node then_node
,
191 CodeGen::Node else_node
) const override
{
192 return cond_
->Compile(pc
, else_node
, then_node
);
196 ~NegateBoolExprImpl() override
{}
200 DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl
);
203 class AndBoolExprImpl
: public internal::BoolExprImpl
{
205 AndBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
206 : lhs_(lhs
), rhs_(rhs
) {}
208 CodeGen::Node
Compile(PolicyCompiler
* pc
,
209 CodeGen::Node then_node
,
210 CodeGen::Node else_node
) const override
{
211 return lhs_
->Compile(pc
, rhs_
->Compile(pc
, then_node
, else_node
),
216 ~AndBoolExprImpl() override
{}
221 DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl
);
224 class OrBoolExprImpl
: public internal::BoolExprImpl
{
226 OrBoolExprImpl(const BoolExpr
& lhs
, const BoolExpr
& rhs
)
227 : lhs_(lhs
), rhs_(rhs
) {}
229 CodeGen::Node
Compile(PolicyCompiler
* pc
,
230 CodeGen::Node then_node
,
231 CodeGen::Node else_node
) const override
{
232 return lhs_
->Compile(pc
, then_node
,
233 rhs_
->Compile(pc
, then_node
, else_node
));
237 ~OrBoolExprImpl() override
{}
242 DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl
);
249 bool ResultExprImpl::HasUnsafeTraps() const {
253 bool ResultExprImpl::IsAllow() const {
257 bool ResultExprImpl::IsDeny() 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 // If this is changed, update Arg<T>::EqualTo's static_cast rules
276 CHECK(size
== 4 || size
== 8);
278 return BoolExpr(new const MaskedEqualBoolExprImpl(num
, size
, mask
, val
));
281 } // namespace internal
284 return ResultExpr(new const AllowResultExprImpl());
287 ResultExpr
Error(int err
) {
288 return ResultExpr(new const ErrorResultExprImpl(err
));
292 return ResultExpr(new const KillResultExprImpl());
295 ResultExpr
Trace(uint16_t aux
) {
296 return ResultExpr(new const TraceResultExprImpl(aux
));
299 ResultExpr
Trap(TrapRegistry::TrapFnc trap_func
, const void* aux
) {
301 new const TrapResultExprImpl(trap_func
, aux
, true /* safe */));
304 ResultExpr
UnsafeTrap(TrapRegistry::TrapFnc trap_func
, const void* aux
) {
306 new const TrapResultExprImpl(trap_func
, aux
, false /* unsafe */));
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
>;