Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / sandbox / linux / bpf_dsl / policy_compiler.h
blobe81404fb57073dcdec98fd63df7b68d3d2318d1a
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_
8 #include <stdint.h>
10 #include <vector>
12 #include "base/macros.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
15 #include "sandbox/linux/bpf_dsl/codegen.h"
16 #include "sandbox/linux/bpf_dsl/trap_registry.h"
17 #include "sandbox/sandbox_export.h"
19 namespace sandbox {
20 namespace bpf_dsl {
21 class Policy;
23 // PolicyCompiler implements the bpf_dsl compiler, allowing users to
24 // transform bpf_dsl policies into BPF programs to be executed by the
25 // Linux kernel.
26 class SANDBOX_EXPORT PolicyCompiler {
27 public:
28 using PanicFunc = bpf_dsl::ResultExpr (*)(const char* error);
30 PolicyCompiler(const Policy* policy, TrapRegistry* registry);
31 ~PolicyCompiler();
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 // DangerousSetEscapePC sets the "escape PC" that is allowed to issue any
38 // system calls, regardless of policy.
39 void DangerousSetEscapePC(uint64_t escapepc);
41 // SetPanicFunc sets the callback function used for handling faulty
42 // system call conditions. The default behavior is to immediately kill
43 // the process.
44 // TODO(mdempsky): Move this into Policy?
45 void SetPanicFunc(PanicFunc panic_func);
47 // UnsafeTraps require some syscalls to always be allowed.
48 // This helper function returns true for these calls.
49 static bool IsRequiredForUnsafeTrap(int sysno);
51 // Functions below are meant for use within bpf_dsl itself.
53 // Return returns a CodeGen::Node that returns the specified seccomp
54 // return value.
55 CodeGen::Node Return(uint32_t ret);
57 // Trap returns a CodeGen::Node to indicate the system call should
58 // instead invoke a trap handler.
59 CodeGen::Node Trap(TrapRegistry::TrapFnc fnc, const void* aux, bool safe);
61 // MaskedEqual returns a CodeGen::Node that represents a conditional branch.
62 // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared
63 // to "value"; if equal, then "passed" will be executed, otherwise "failed".
64 // If "width" is 4, the argument must in the range of 0x0..(1u << 32 - 1)
65 // If it is outside this range, the sandbox treats the system call just
66 // the same as any other ABI violation (i.e., it panics).
67 CodeGen::Node MaskedEqual(int argno,
68 size_t width,
69 uint64_t mask,
70 uint64_t value,
71 CodeGen::Node passed,
72 CodeGen::Node failed);
74 private:
75 struct Range;
76 typedef std::vector<Range> Ranges;
78 // Used by MaskedEqualHalf to track which half of the argument it's
79 // emitting instructions for.
80 enum class ArgHalf {
81 LOWER,
82 UPPER,
85 // Compile the configured policy into a complete instruction sequence.
86 CodeGen::Node AssemblePolicy();
88 // Return an instruction sequence that checks the
89 // arch_seccomp_data's "arch" field is valid, and then passes
90 // control to |passed| if so.
91 CodeGen::Node CheckArch(CodeGen::Node passed);
93 // If |has_unsafe_traps_| is true, returns an instruction sequence
94 // that allows all system calls from |escapepc_|, and otherwise
95 // passes control to |rest|. Otherwise, simply returns |rest|.
96 CodeGen::Node MaybeAddEscapeHatch(CodeGen::Node rest);
98 // Return an instruction sequence that loads and checks the system
99 // call number, performs a binary search, and then dispatches to an
100 // appropriate instruction sequence compiled from the current
101 // policy.
102 CodeGen::Node DispatchSyscall();
104 // Return an instruction sequence that checks the system call number
105 // (expected to be loaded in register A) and if valid, passes
106 // control to |passed| (with register A still valid).
107 CodeGen::Node CheckSyscallNumber(CodeGen::Node passed);
109 // Finds all the ranges of system calls that need to be handled. Ranges are
110 // sorted in ascending order of system call numbers. There are no gaps in the
111 // ranges. System calls with identical CodeGen::Nodes are coalesced into a
112 // single
113 // range.
114 void FindRanges(Ranges* ranges);
116 // Returns a BPF program snippet that implements a jump table for the
117 // given range of system call numbers. This function runs recursively.
118 CodeGen::Node AssembleJumpTable(Ranges::const_iterator start,
119 Ranges::const_iterator stop);
121 // CompileResult compiles an individual result expression into a
122 // CodeGen node.
123 CodeGen::Node CompileResult(const ResultExpr& res);
125 // Returns a BPF program that evaluates half of a conditional expression;
126 // it should only ever be called from CondExpression().
127 CodeGen::Node MaskedEqualHalf(int argno,
128 size_t width,
129 uint64_t full_mask,
130 uint64_t full_value,
131 ArgHalf half,
132 CodeGen::Node passed,
133 CodeGen::Node failed);
135 // Returns the fatal CodeGen::Node that is used to indicate that somebody
136 // attempted to pass a 64bit value in a 32bit system call argument.
137 CodeGen::Node Unexpected64bitArgument();
139 const Policy* policy_;
140 TrapRegistry* registry_;
141 uint64_t escapepc_;
142 PanicFunc panic_func_;
144 CodeGen gen_;
145 bool has_unsafe_traps_;
147 DISALLOW_COPY_AND_ASSIGN(PolicyCompiler);
150 } // namespace bpf_dsl
151 } // namespace sandbox
153 #endif // SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_