1 // Copyright (c) 2012 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 #ifndef SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_
6 #define SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_
14 #include "base/macros.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
17 #include "sandbox/linux/bpf_dsl/codegen.h"
18 #include "sandbox/linux/seccomp-bpf/errorcode.h"
19 #include "sandbox/sandbox_export.h"
25 // PolicyCompiler implements the bpf_dsl compiler, allowing users to
26 // transform bpf_dsl policies into BPF programs to be executed by the
28 class SANDBOX_EXPORT PolicyCompiler
{
30 PolicyCompiler(const Policy
* policy
, TrapRegistry
* registry
);
33 // Compile registers any trap handlers needed by the policy and
34 // compiles the policy to a BPF program, which it returns.
35 scoped_ptr
<CodeGen::Program
> Compile();
37 // Error returns an ErrorCode to indicate the system call should fail with
38 // the specified error number.
39 ErrorCode
Error(int err
);
41 // Trap returns an ErrorCode to indicate the system call should
42 // instead invoke a trap handler.
43 ErrorCode
Trap(TrapRegistry::TrapFnc fnc
, const void* aux
, bool safe
);
45 // UnsafeTraps require some syscalls to always be allowed.
46 // This helper function returns true for these calls.
47 static bool IsRequiredForUnsafeTrap(int sysno
);
49 // We can also use ErrorCode to request evaluation of a conditional
50 // statement based on inspection of system call parameters.
51 // This method wrap an ErrorCode object around the conditional statement.
52 // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared
53 // to "value"; if equal, then "passed" will be returned, otherwise "failed".
54 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1)
55 // If it is outside this range, the sandbox treats the system call just
56 // the same as any other ABI violation (i.e. it aborts with an error
58 ErrorCode
CondMaskedEqual(int argno
,
59 ErrorCode::ArgType is_32bit
,
62 const ErrorCode
& passed
,
63 const ErrorCode
& failed
);
65 // Returns the fatal ErrorCode that is used to indicate that somebody
66 // attempted to pass a 64bit value in a 32bit system call argument.
67 // This method is primarily needed for testing purposes.
68 ErrorCode
Unexpected64bitArgument();
72 typedef std::vector
<Range
> Ranges
;
73 typedef std::set
<ErrorCode
, struct ErrorCode::LessThan
> Conds
;
75 // Used by CondExpressionHalf to track which half of the argument it's
76 // emitting instructions for.
82 // Compile the configured policy into a complete instruction sequence.
83 CodeGen::Node
AssemblePolicy();
85 // Return an instruction sequence that checks the
86 // arch_seccomp_data's "arch" field is valid, and then passes
87 // control to |passed| if so.
88 CodeGen::Node
CheckArch(CodeGen::Node passed
);
90 // If |has_unsafe_traps_| is true, returns an instruction sequence
91 // that allows all system calls from Syscall::Call(), and otherwise
92 // passes control to |rest|. Otherwise, simply returns |rest|.
93 CodeGen::Node
MaybeAddEscapeHatch(CodeGen::Node rest
);
95 // Return an instruction sequence that loads and checks the system
96 // call number, performs a binary search, and then dispatches to an
97 // appropriate instruction sequence compiled from the current
99 CodeGen::Node
DispatchSyscall();
101 // Return an instruction sequence that checks the system call number
102 // (expected to be loaded in register A) and if valid, passes
103 // control to |passed| (with register A still valid).
104 CodeGen::Node
CheckSyscallNumber(CodeGen::Node passed
);
106 // Finds all the ranges of system calls that need to be handled. Ranges are
107 // sorted in ascending order of system call numbers. There are no gaps in the
108 // ranges. System calls with identical ErrorCodes are coalesced into a single
110 void FindRanges(Ranges
* ranges
);
112 // Returns a BPF program snippet that implements a jump table for the
113 // given range of system call numbers. This function runs recursively.
114 CodeGen::Node
AssembleJumpTable(Ranges::const_iterator start
,
115 Ranges::const_iterator stop
);
117 // CompileResult compiles an individual result expression into a
119 CodeGen::Node
CompileResult(const ResultExpr
& res
);
121 // Returns a BPF program snippet that makes the BPF filter program exit
122 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a
123 // conditional expression; if so, this function will recursively call
124 // CondExpression() and possibly RetExpression() to build a complex set of
126 CodeGen::Node
RetExpression(const ErrorCode
& err
);
128 // Returns a BPF program that evaluates the conditional expression in
129 // "cond" and returns the appropriate value from the BPF filter program.
130 // This function recursively calls RetExpression(); it should only ever be
131 // called from RetExpression().
132 CodeGen::Node
CondExpression(const ErrorCode
& cond
);
134 // Returns a BPF program that evaluates half of a conditional expression;
135 // it should only ever be called from CondExpression().
136 CodeGen::Node
CondExpressionHalf(const ErrorCode
& cond
,
138 CodeGen::Node passed
,
139 CodeGen::Node failed
);
141 const Policy
* policy_
;
142 TrapRegistry
* registry_
;
146 bool has_unsafe_traps_
;
148 DISALLOW_COPY_AND_ASSIGN(PolicyCompiler
);
151 } // namespace bpf_dsl
152 } // namespace sandbox
154 #endif // SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_