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

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

Issue 754433003: Update from https://crrev.com/305340 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: 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
« no previous file with comments | « sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc ('k') | sandbox/linux/seccomp-bpf/codegen.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 implements a basic assembler that can convert a 22 // The code generator implements a basic assembler that can convert a
28 // graph of BPF instructions into a well-formed array of BPF 23 // graph of BPF instructions into a well-formed array of BPF
29 // instructions. Most notably, it ensures that jumps are always 24 // instructions. Most notably, it ensures that jumps are always
30 // forward and don't exceed the limit of 255 instructions imposed by 25 // forward and don't exceed the limit of 255 instructions imposed by
31 // the instruction set. 26 // the instruction set.
32 // 27 //
33 // Callers would typically create a new CodeGen object and then use it 28 // Callers would typically create a new CodeGen object and then use it
34 // to build a DAG of instruction nodes. They'll eventually call 29 // to build a DAG of instruction nodes. They'll eventually call
35 // Compile() to convert this DAG to a Program. 30 // Compile() to convert this DAG to a Program.
36 // 31 //
37 // CodeGen gen; 32 // CodeGen gen;
38 // CodeGen::Node allow, branch, dag; 33 // CodeGen::Node allow, branch, dag;
39 // 34 //
(...skipping 15 matching lines...) Expand all
55 // static_cast<unsigned short>(program->size()), &program[0] }; 50 // static_cast<unsigned short>(program->size()), &program[0] };
56 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 51 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
57 // 52 //
58 class SANDBOX_EXPORT CodeGen { 53 class SANDBOX_EXPORT CodeGen {
59 public: 54 public:
60 // A vector of BPF instructions that need to be installed as a filter 55 // A vector of BPF instructions that need to be installed as a filter
61 // program in the kernel. 56 // program in the kernel.
62 typedef std::vector<struct sock_filter> Program; 57 typedef std::vector<struct sock_filter> Program;
63 58
64 // Node represents a node within the instruction DAG being compiled. 59 // Node represents a node within the instruction DAG being compiled.
65 // Nodes are owned by the CodeGen object and need not be explicitly 60 using Node = Program::size_type;
66 // deleted.
67 using Node = Instruction*;
68 61
69 // kNullNode represents the "null" node; i.e., the reserved node 62 // kNullNode represents the "null" node; i.e., the reserved node
70 // value guaranteed to not equal any actual nodes. 63 // value guaranteed to not equal any actual nodes.
71 static const Node kNullNode; 64 static const Node kNullNode = -1;
72 65
73 CodeGen(); 66 CodeGen();
74 ~CodeGen(); 67 ~CodeGen();
75 68
76 // MakeInstruction creates a node representing the specified 69 // MakeInstruction creates a node representing the specified
77 // instruction. For details on the possible parameters refer to 70 // instruction, or returns and existing equivalent node if one
71 // exists. For details on the possible parameters refer to
78 // https://www.kernel.org/doc/Documentation/networking/filter.txt. 72 // https://www.kernel.org/doc/Documentation/networking/filter.txt.
79 // TODO(mdempsky): Reconsider using default arguments here. 73 // TODO(mdempsky): Reconsider using default arguments here.
80 Node MakeInstruction(uint16_t code, 74 Node MakeInstruction(uint16_t code,
81 uint32_t k, 75 uint32_t k,
82 Node jt = kNullNode, 76 Node jt = kNullNode,
83 Node jf = kNullNode); 77 Node jf = kNullNode);
84 78
85 // Compile linearizes the instruction DAG into a BPF program that 79 // Compile linearizes the instruction DAG rooted at |head| into a
86 // can be executed by a BPF virtual machine. Please note that this 80 // program that can be executed by a BPF virtual machine.
87 // function modifies the graph in place and must therefore only be
88 // called once per graph.
89 void Compile(Node head, Program* program); 81 void Compile(Node head, Program* program);
90 82
91 private: 83 private:
92 friend class CodeGenUnittestHelper; 84 using MemoKey = Tuple4<uint16_t, uint32_t, Node, Node>;
85 struct MemoKeyLess {
86 bool operator()(const MemoKey& lhs, const MemoKey& rhs) const;
87 };
93 88
94 // Find all the instructions that are the target of BPF_JMPs. 89 // AppendInstruction adds a new instruction, ensuring that |jt| and
95 void FindBranchTargets(const Instruction& instructions, 90 // |jf| are within range as necessary for |code|.
96 BranchTargets* branch_targets); 91 Node AppendInstruction(uint16_t code, uint32_t k, Node jt, Node jf);
97 92
98 // Combine instructions between "head" and "tail" into a new basic block. 93 // WithinRange returns a node equivalent to |next| that is at most
99 // Basic blocks are defined as sequences of instructions whose only branch 94 // |range| instructions away from the (logical) beginning of the
100 // target is the very first instruction; furthermore, any BPF_JMP or BPF_RET 95 // program.
101 // instruction must be at the very end of the basic block. 96 Node WithinRange(Node next, size_t range);
102 BasicBlock* MakeBasicBlock(Instruction* head, Instruction* tail);
103 97
104 // Creates a basic block and adds it to "basic_blocks"; sets "first_block" 98 // Append appends a new instruction to the physical end (i.e.,
105 // if it is still NULL. 99 // logical beginning) of |program_|.
106 void AddBasicBlock(Instruction* head, 100 Node Append(uint16_t code, uint32_t k, size_t jt, size_t jf);
107 Instruction* tail,
108 const BranchTargets& branch_targets,
109 TargetsToBlocks* basic_blocks,
110 BasicBlock** first_block);
111 101
112 // Cuts the DAG of instructions into basic blocks. 102 // Offset returns how many instructions exist in |program_| after |target|.
113 BasicBlock* CutGraphIntoBasicBlocks(Instruction* instructions, 103 size_t Offset(Node target) const;
114 const BranchTargets& branch_targets,
115 TargetsToBlocks* blocks);
116 104
117 // Find common tail sequences of basic blocks and coalesce them. 105 // NOTE: program_ is the compiled program in *reverse*, so that
118 void MergeTails(TargetsToBlocks* blocks); 106 // indices remain stable as we add instructions.
107 Program program_;
119 108
120 // For each basic block, compute the number of incoming branches. 109 std::map<MemoKey, Node, MemoKeyLess> memos_;
121 void ComputeIncomingBranches(BasicBlock* block,
122 const TargetsToBlocks& targets_to_blocks,
123 IncomingBranches* incoming_branches);
124 110
125 // Topologically sort the basic blocks so that all jumps are forward jumps. 111 DISALLOW_COPY_AND_ASSIGN(CodeGen);
126 // This is a requirement for any well-formed BPF program.
127 void TopoSortBasicBlocks(BasicBlock* first_block,
128 const TargetsToBlocks& blocks,
129 BasicBlocks* basic_blocks);
130
131 // Convert jt_ptr_ and jf_ptr_ fields in BPF_JMP instructions to valid
132 // jt_ and jf_ jump offsets. This can result in BPF_JA instructions being
133 // inserted, if we need to jump over more than 256 instructions.
134 void ComputeRelativeJumps(BasicBlocks* basic_blocks,
135 const TargetsToBlocks& targets_to_blocks);
136
137 // Concatenate instructions from all basic blocks into a BPF program that
138 // can be passed to the kernel.
139 void ConcatenateBasicBlocks(const BasicBlocks&, Program* program);
140
141 // We stick all instructions and basic blocks into pools that get destroyed
142 // when the CodeGen object is destroyed. This way, we neither need to worry
143 // about explicitly managing ownership, nor do we need to worry about using
144 // smart pointers in the presence of circular references.
145 Instructions instructions_;
146 BasicBlocks basic_blocks_;
147
148 // Compile() must only ever be called once as it makes destructive changes
149 // to the DAG.
150 bool compiled_;
151 }; 112 };
152 113
153 } // namespace sandbox 114 } // namespace sandbox
154 115
155 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ 116 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc ('k') | sandbox/linux/seccomp-bpf/codegen.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698