Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: sandbox/linux/seccomp-bpf/codegen.h

Issue 699633003: CodeGen: rewrite implementation [3/3] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@codegen-api-2
Patch Set: Use size_t instead of uint32_t as semantically appropriate Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <stddef.h>
8 #include <stdint.h> 9 #include <stdint.h>
9 10
10 #include <map> 11 #include <map>
11 #include <vector> 12 #include <vector>
12 13
14 #include "base/macros.h"
15 #include "base/tuple.h"
13 #include "sandbox/sandbox_export.h" 16 #include "sandbox/sandbox_export.h"
14 17
15 struct sock_filter; 18 struct sock_filter;
16 19
17 namespace sandbox { 20 namespace sandbox {
18 struct BasicBlock;
19 struct Instruction;
20
21 typedef std::vector<Instruction*> Instructions;
22 typedef std::vector<BasicBlock*> BasicBlocks;
23 typedef std::map<const Instruction*, int> BranchTargets;
24 typedef std::map<const Instruction*, BasicBlock*> TargetsToBlocks;
25 typedef std::map<const BasicBlock*, int> IncomingBranches;
26 21
27 // The code generator instantiates a basic compiler that can convert a 22 // The code generator instantiates a basic compiler that can convert a
28 // graph of BPF instructions into a well-formed stream of BPF instructions. 23 // graph of BPF instructions into a well-formed stream of BPF instructions.
29 // Most notably, it ensures that jumps are always forward and don't exceed 24 // Most notably, it ensures that jumps are always forward and don't exceed
30 // the limit of 255 instructions imposed by the instruction set. 25 // the limit of 255 instructions imposed by the instruction set.
31 // 26 //
32 // Callers would typically create a new CodeGen object and then use it to 27 // Callers would typically create a new CodeGen object and then use it to
33 // build a DAG of Instructions. They'll eventually call Compile() to convert 28 // build a DAG of Instructions. They'll eventually call Compile() to convert
34 // this DAG to a Program. 29 // this DAG to a Program.
35 // 30 //
(...skipping 19 matching lines...) Expand all
55 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 50 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
56 // 51 //
57 class SANDBOX_EXPORT CodeGen { 52 class SANDBOX_EXPORT CodeGen {
58 public: 53 public:
59 // A vector of BPF instructions that need to be installed as a filter 54 // A vector of BPF instructions that need to be installed as a filter
60 // program in the kernel. 55 // program in the kernel.
61 typedef std::vector<struct sock_filter> Program; 56 typedef std::vector<struct sock_filter> Program;
62 57
63 // Addr represents a logical location within the program being compiled. 58 // Addr represents a logical location within the program being compiled.
64 // Identical code suffixes may be collapsed to a single location. 59 // Identical code suffixes may be collapsed to a single location.
65 using Addr = Instruction*; 60 using Addr = Program::size_type;
66 61
67 // kNullAddr represents the "null" address value; i.e., the reserved 62 // kNullAddr represents the "null" address value; i.e., the reserved
68 // address value guaranteed to not equal any actual address values. 63 // address value guaranteed to not equal any actual address values.
69 static const Addr kNullAddr; 64 static const Addr kNullAddr = -1;
70 65
71 CodeGen(); 66 CodeGen();
72 ~CodeGen(); 67 ~CodeGen();
73 68
74 // Create a new instruction. Instructions form a DAG. The instruction objects 69 // MakeInstruction creates a new node in the instruction DAG and
75 // are owned by the CodeGen object. They do not need to be explicitly 70 // returns the node's address, or returns the address of an existing
76 // deleted. 71 // equivalent node if one exists.
72 //
77 // For details on the possible parameters refer to <linux/filter.h> 73 // For details on the possible parameters refer to <linux/filter.h>
74 // Note: Callers need not worry about explicitly creating "jump
75 // always" instructions (i.e., BPF_JMP+BPF_JA), as CodeGen inserts
76 // these as needed.
78 Addr MakeInstruction(uint16_t code, 77 Addr MakeInstruction(uint16_t code,
79 uint32_t k, 78 uint32_t k,
80 Addr jt = kNullAddr, 79 Addr jt = kNullAddr,
81 Addr jf = kNullAddr); 80 Addr jf = kNullAddr);
82 81
83 // Compiles the graph of instructions into a BPF program that can be passed 82 // Compile linearizes the instruction DAG into an equivalent flat
84 // to the kernel. Please note that this function modifies the graph in place 83 // BPF program that can be passed to the kernel.
85 // and must therefore only be called once per graph. 84 void Compile(Addr instructions, Program* program);
86 void Compile(Addr head, Program* program);
87 85
88 private: 86 private:
89 friend class CodeGenUnittestHelper; 87 using CacheKey = Tuple4<uint16_t, uint32_t, Addr, Addr>;
88 struct CacheKeyLess {
89 bool operator()(const CacheKey& lhs, const CacheKey& rhs) const;
90 };
90 91
91 // Find all the instructions that are the target of BPF_JMPs. 92 // Offset returns how many instructions exist in |program_| after |target|.
92 void FindBranchTargets(const Instruction& instructions, 93 size_t Offset(Addr target) const;
93 BranchTargets* branch_targets);
94 94
95 // Combine instructions between "head" and "tail" into a new basic block. 95 // Jump appends a jump-always instruction.
96 // Basic blocks are defined as sequences of instructions whose only branch 96 Addr Jump(Addr next);
97 // target is the very first instruction; furthermore, any BPF_JMP or BPF_RET
98 // instruction must be at the very end of the basic block.
99 BasicBlock* MakeBasicBlock(Instruction* head, Instruction* tail);
100 97
101 // Creates a basic block and adds it to "basic_blocks"; sets "first_block" 98 // Append adds a new instruction to the end of |program_|.
102 // if it is still NULL. 99 Addr Append(uint16_t code, uint32_t k, size_t jt, size_t jf);
103 void AddBasicBlock(Instruction* head,
104 Instruction* tail,
105 const BranchTargets& branch_targets,
106 TargetsToBlocks* basic_blocks,
107 BasicBlock** first_block);
108 100
109 // Cuts the DAG of instructions into basic blocks. 101 void CheckValid(Addr addr) const;
110 BasicBlock* CutGraphIntoBasicBlocks(Instruction* instructions,
111 const BranchTargets& branch_targets,
112 TargetsToBlocks* blocks);
113 102
114 // Find common tail sequences of basic blocks and coalesce them. 103 // NOTE: program_ is the compiled program in *reverse*.
115 void MergeTails(TargetsToBlocks* blocks); 104 Program program_;
116 105
117 // For each basic block, compute the number of incoming branches. 106 std::map<CacheKey, Addr, CacheKeyLess> cache_;
118 void ComputeIncomingBranches(BasicBlock* block,
119 const TargetsToBlocks& targets_to_blocks,
120 IncomingBranches* incoming_branches);
121 107
122 // Topologically sort the basic blocks so that all jumps are forward jumps. 108 DISALLOW_COPY_AND_ASSIGN(CodeGen);
123 // This is a requirement for any well-formed BPF program.
124 void TopoSortBasicBlocks(BasicBlock* first_block,
125 const TargetsToBlocks& blocks,
126 BasicBlocks* basic_blocks);
127
128 // Convert jt_ptr_ and jf_ptr_ fields in BPF_JMP instructions to valid
129 // jt_ and jf_ jump offsets. This can result in BPF_JA instructions being
130 // inserted, if we need to jump over more than 256 instructions.
131 void ComputeRelativeJumps(BasicBlocks* basic_blocks,
132 const TargetsToBlocks& targets_to_blocks);
133
134 // Concatenate instructions from all basic blocks into a BPF program that
135 // can be passed to the kernel.
136 void ConcatenateBasicBlocks(const BasicBlocks&, Program* program);
137
138 // We stick all instructions and basic blocks into pools that get destroyed
139 // when the CodeGen object is destroyed. This way, we neither need to worry
140 // about explicitly managing ownership, nor do we need to worry about using
141 // smart pointers in the presence of circular references.
142 Instructions instructions_;
143 BasicBlocks basic_blocks_;
144
145 // Compile() must only ever be called once as it makes destructive changes
146 // to the DAG.
147 bool compiled_;
148 }; 109 };
149 110
150 } // namespace sandbox 111 } // namespace sandbox
151 112
152 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ 113 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698