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_
12 #include "base/macros.h"
13 #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
14 #include "sandbox/linux/bpf_dsl/codegen.h"
15 #include "sandbox/linux/bpf_dsl/trap_registry.h"
16 #include "sandbox/sandbox_export.h"
22 // PolicyCompiler implements the bpf_dsl compiler, allowing users to
23 // transform bpf_dsl policies into BPF programs to be executed by the
25 class SANDBOX_EXPORT PolicyCompiler
{
27 using PanicFunc
= bpf_dsl::ResultExpr (*)(const char* error
);
29 PolicyCompiler(const Policy
* policy
, TrapRegistry
* registry
);
32 // Compile registers any trap handlers needed by the policy and
33 // compiles the policy to a BPF program, which it returns.
34 CodeGen::Program
Compile();
36 // DangerousSetEscapePC sets the "escape PC" that is allowed to issue any
37 // system calls, regardless of policy.
38 void DangerousSetEscapePC(uint64_t escapepc
);
40 // SetPanicFunc sets the callback function used for handling faulty
41 // system call conditions. The default behavior is to immediately kill
43 // TODO(mdempsky): Move this into Policy?
44 void SetPanicFunc(PanicFunc panic_func
);
46 // UnsafeTraps require some syscalls to always be allowed.
47 // This helper function returns true for these calls.
48 static bool IsRequiredForUnsafeTrap(int sysno
);
50 // Functions below are meant for use within bpf_dsl itself.
52 // Return returns a CodeGen::Node that returns the specified seccomp
54 CodeGen::Node
Return(uint32_t ret
);
56 // Trap returns a CodeGen::Node to indicate the system call should
57 // instead invoke a trap handler.
58 CodeGen::Node
Trap(TrapRegistry::TrapFnc fnc
, const void* aux
, bool safe
);
60 // MaskedEqual returns a CodeGen::Node that represents a conditional branch.
61 // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared
62 // to "value"; if equal, then "passed" will be executed, otherwise "failed".
63 // If "width" is 4, the argument must in the range of 0x0..(1u << 32 - 1)
64 // If it is outside this range, the sandbox treats the system call just
65 // the same as any other ABI violation (i.e., it panics).
66 CodeGen::Node
MaskedEqual(int argno
,
71 CodeGen::Node failed
);
75 typedef std::vector
<Range
> Ranges
;
77 // Used by MaskedEqualHalf to track which half of the argument it's
78 // emitting instructions for.
84 // Compile the configured policy into a complete instruction sequence.
85 CodeGen::Node
AssemblePolicy();
87 // Return an instruction sequence that checks the
88 // arch_seccomp_data's "arch" field is valid, and then passes
89 // control to |passed| if so.
90 CodeGen::Node
CheckArch(CodeGen::Node passed
);
92 // If |has_unsafe_traps_| is true, returns an instruction sequence
93 // that allows all system calls from |escapepc_|, and otherwise
94 // passes control to |rest|. Otherwise, simply returns |rest|.
95 CodeGen::Node
MaybeAddEscapeHatch(CodeGen::Node rest
);
97 // Return an instruction sequence that loads and checks the system
98 // call number, performs a binary search, and then dispatches to an
99 // appropriate instruction sequence compiled from the current
101 CodeGen::Node
DispatchSyscall();
103 // Return an instruction sequence that checks the system call number
104 // (expected to be loaded in register A) and if valid, passes
105 // control to |passed| (with register A still valid).
106 CodeGen::Node
CheckSyscallNumber(CodeGen::Node passed
);
108 // Finds all the ranges of system calls that need to be handled. Ranges are
109 // sorted in ascending order of system call numbers. There are no gaps in the
110 // ranges. System calls with identical CodeGen::Nodes are coalesced into a
113 void FindRanges(Ranges
* ranges
);
115 // Returns a BPF program snippet that implements a jump table for the
116 // given range of system call numbers. This function runs recursively.
117 CodeGen::Node
AssembleJumpTable(Ranges::const_iterator start
,
118 Ranges::const_iterator stop
);
120 // CompileResult compiles an individual result expression into a
122 CodeGen::Node
CompileResult(const ResultExpr
& res
);
124 // Returns a BPF program that evaluates half of a conditional expression;
125 // it should only ever be called from CondExpression().
126 CodeGen::Node
MaskedEqualHalf(int argno
,
131 CodeGen::Node passed
,
132 CodeGen::Node failed
);
134 // Returns the fatal CodeGen::Node that is used to indicate that somebody
135 // attempted to pass a 64bit value in a 32bit system call argument.
136 CodeGen::Node
Unexpected64bitArgument();
138 const Policy
* policy_
;
139 TrapRegistry
* registry_
;
141 PanicFunc panic_func_
;
144 bool has_unsafe_traps_
;
146 DISALLOW_COPY_AND_ASSIGN(PolicyCompiler
);
149 } // namespace bpf_dsl
150 } // namespace sandbox
152 #endif // SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_