OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ | 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ |
6 #define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ | 6 #define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <map> | 10 #include <map> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "sandbox/sandbox_export.h" | 13 #include "sandbox/sandbox_export.h" |
14 | 14 |
15 struct sock_filter; | 15 struct sock_filter; |
16 | 16 |
17 namespace sandbox { | 17 namespace sandbox { |
18 struct BasicBlock; | 18 struct BasicBlock; |
19 struct Instruction; | 19 struct Instruction; |
20 | 20 |
21 typedef std::vector<Instruction*> Instructions; | 21 typedef std::vector<Instruction*> Instructions; |
22 typedef std::vector<BasicBlock*> BasicBlocks; | 22 typedef std::vector<BasicBlock*> BasicBlocks; |
23 typedef std::map<const Instruction*, int> BranchTargets; | 23 typedef std::map<const Instruction*, int> BranchTargets; |
24 typedef std::map<const Instruction*, BasicBlock*> TargetsToBlocks; | 24 typedef std::map<const Instruction*, BasicBlock*> TargetsToBlocks; |
25 typedef std::map<const BasicBlock*, int> IncomingBranches; | 25 typedef std::map<const BasicBlock*, int> IncomingBranches; |
26 | 26 |
27 // The code generator instantiates a basic compiler that can convert a | 27 // The code generator implements a basic assembler that can convert a |
28 // graph of BPF instructions into a well-formed stream of BPF instructions. | 28 // graph of BPF instructions into a well-formed array of BPF |
29 // Most notably, it ensures that jumps are always forward and don't exceed | 29 // instructions. Most notably, it ensures that jumps are always |
30 // the limit of 255 instructions imposed by the instruction set. | 30 // forward and don't exceed the limit of 255 instructions imposed by |
| 31 // the instruction set. |
31 // | 32 // |
32 // Callers would typically create a new CodeGen object and then use it to | 33 // Callers would typically create a new CodeGen object and then use it |
33 // build a DAG of Instructions. They'll eventually call Compile() to convert | 34 // to build a DAG of instruction nodes. They'll eventually call |
34 // this DAG to a Program. | 35 // Compile() to convert this DAG to a Program. |
35 // | 36 // |
36 // CodeGen gen; | 37 // CodeGen gen; |
37 // Instruction *allow, *branch, *dag; | 38 // CodeGen::Node allow, branch, dag; |
38 // | 39 // |
39 // allow = | 40 // allow = |
40 // gen.MakeInstruction(BPF_RET+BPF_K, | 41 // gen.MakeInstruction(BPF_RET+BPF_K, |
41 // ErrorCode(ErrorCode::ERR_ALLOWED).err())); | 42 // ErrorCode(ErrorCode::ERR_ALLOWED).err())); |
42 // branch = | 43 // branch = |
43 // gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid, | 44 // gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid, |
44 // Trap(GetPidHandler, NULL), allow); | 45 // Trap(GetPidHandler, NULL), allow); |
45 // dag = | 46 // dag = |
46 // gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS, | 47 // gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS, |
47 // offsetof(struct arch_seccomp_data, nr), branch); | 48 // offsetof(struct arch_seccomp_data, nr), branch); |
48 // | 49 // |
49 // // Simplified code follows; in practice, it is important to avoid calling | 50 // // Simplified code follows; in practice, it is important to avoid calling |
50 // // any C++ destructors after starting the sandbox. | 51 // // any C++ destructors after starting the sandbox. |
51 // CodeGen::Program program; | 52 // CodeGen::Program program; |
52 // gen.Compile(dag, program); | 53 // gen.Compile(dag, program); |
53 // const struct sock_fprog prog = { | 54 // const struct sock_fprog prog = { |
54 // static_cast<unsigned short>(program->size()), &program[0] }; | 55 // static_cast<unsigned short>(program->size()), &program[0] }; |
55 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); | 56 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); |
56 // | 57 // |
57 class SANDBOX_EXPORT CodeGen { | 58 class SANDBOX_EXPORT CodeGen { |
58 public: | 59 public: |
59 // A vector of BPF instructions that need to be installed as a filter | 60 // A vector of BPF instructions that need to be installed as a filter |
60 // program in the kernel. | 61 // program in the kernel. |
61 typedef std::vector<struct sock_filter> Program; | 62 typedef std::vector<struct sock_filter> Program; |
62 | 63 |
| 64 // Node represents a node within the instruction DAG being compiled. |
| 65 // Nodes are owned by the CodeGen object and need not be explicitly |
| 66 // deleted. |
| 67 using Node = Instruction*; |
| 68 |
| 69 // kNullNode represents the "null" node; i.e., the reserved node |
| 70 // value guaranteed to not equal any actual nodes. |
| 71 static const Node kNullNode; |
| 72 |
63 CodeGen(); | 73 CodeGen(); |
64 ~CodeGen(); | 74 ~CodeGen(); |
65 | 75 |
66 // Create a new instruction. Instructions form a DAG. The instruction objects | 76 // MakeInstruction creates a node representing the specified |
67 // are owned by the CodeGen object. They do not need to be explicitly | 77 // instruction. For details on the possible parameters refer to |
68 // deleted. | 78 // https://www.kernel.org/doc/Documentation/networking/filter.txt. |
69 // For details on the possible parameters refer to <linux/filter.h> | 79 // TODO(mdempsky): Reconsider using default arguments here. |
70 Instruction* MakeInstruction(uint16_t code, | 80 Node MakeInstruction(uint16_t code, |
71 uint32_t k, | 81 uint32_t k, |
72 Instruction* next = nullptr); | 82 Node jt = kNullNode, |
73 Instruction* MakeInstruction(uint16_t code, | 83 Node jf = kNullNode); |
74 uint32_t k, | |
75 Instruction* jt, | |
76 Instruction* jf); | |
77 | 84 |
78 // Compiles the graph of instructions into a BPF program that can be passed | 85 // Compile linearizes the instruction DAG into a BPF program that |
79 // to the kernel. Please note that this function modifies the graph in place | 86 // can be executed by a BPF virtual machine. Please note that this |
80 // and must therefore only be called once per graph. | 87 // function modifies the graph in place and must therefore only be |
81 void Compile(Instruction* instructions, Program* program); | 88 // called once per graph. |
| 89 void Compile(Node head, Program* program); |
82 | 90 |
83 private: | 91 private: |
84 friend class CodeGenUnittestHelper; | 92 friend class CodeGenUnittestHelper; |
85 | 93 |
86 // Find all the instructions that are the target of BPF_JMPs. | 94 // Find all the instructions that are the target of BPF_JMPs. |
87 void FindBranchTargets(const Instruction& instructions, | 95 void FindBranchTargets(const Instruction& instructions, |
88 BranchTargets* branch_targets); | 96 BranchTargets* branch_targets); |
89 | 97 |
90 // Combine instructions between "head" and "tail" into a new basic block. | 98 // Combine instructions between "head" and "tail" into a new basic block. |
91 // Basic blocks are defined as sequences of instructions whose only branch | 99 // Basic blocks are defined as sequences of instructions whose only branch |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 BasicBlocks basic_blocks_; | 146 BasicBlocks basic_blocks_; |
139 | 147 |
140 // Compile() must only ever be called once as it makes destructive changes | 148 // Compile() must only ever be called once as it makes destructive changes |
141 // to the DAG. | 149 // to the DAG. |
142 bool compiled_; | 150 bool compiled_; |
143 }; | 151 }; |
144 | 152 |
145 } // namespace sandbox | 153 } // namespace sandbox |
146 | 154 |
147 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ | 155 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ |
OLD | NEW |