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

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

Issue 670183003: Update from chromium 62675d9fb31fb8cedc40f68e78e8445a74f362e7 (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
(Empty)
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.
4
5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
6 #define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
7
8 #include <stdint.h>
9
10 #include <map>
11 #include <vector>
12
13 #include "sandbox/sandbox_export.h"
14
15 struct sock_filter;
16
17 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
27 // The code generator instantiates a basic compiler that can convert a
28 // 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
30 // the limit of 255 instructions imposed by the instruction set.
31 //
32 // 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
34 // this DAG to a Program.
35 //
36 // CodeGen gen;
37 // Instruction *allow, *branch, *dag;
38 //
39 // allow =
40 // gen.MakeInstruction(BPF_RET+BPF_K,
41 // ErrorCode(ErrorCode::ERR_ALLOWED).err()));
42 // branch =
43 // gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid,
44 // Trap(GetPidHandler, NULL), allow);
45 // dag =
46 // gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS,
47 // offsetof(struct arch_seccomp_data, nr), branch);
48 //
49 // // Simplified code follows; in practice, it is important to avoid calling
50 // // any C++ destructors after starting the sandbox.
51 // CodeGen::Program program;
52 // gen.Compile(dag, program);
53 // const struct sock_fprog prog = {
54 // static_cast<unsigned short>(program->size()), &program[0] };
55 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
56 //
57 class SANDBOX_EXPORT CodeGen {
58 public:
59 // A vector of BPF instructions that need to be installed as a filter
60 // program in the kernel.
61 typedef std::vector<struct sock_filter> Program;
62
63 CodeGen();
64 ~CodeGen();
65
66 // This is a helper method that can be used for debugging purposes. It is
67 // not normally called.
68 static void PrintProgram(const Program& program);
69
70 // Create a new instruction. Instructions form a DAG. The instruction objects
71 // are owned by the CodeGen object. They do not need to be explicitly
72 // deleted.
73 // For details on the possible parameters refer to <linux/filter.h>
74 Instruction* MakeInstruction(uint16_t code,
75 uint32_t k,
76 Instruction* next = nullptr);
77 Instruction* MakeInstruction(uint16_t code,
78 uint32_t k,
79 Instruction* jt,
80 Instruction* jf);
81
82 // Compiles the graph of instructions into a BPF program that can be passed
83 // to the kernel. Please note that this function modifies the graph in place
84 // and must therefore only be called once per graph.
85 void Compile(Instruction* instructions, Program* program);
86
87 private:
88 friend class CodeGenUnittestHelper;
89
90 // Find all the instructions that are the target of BPF_JMPs.
91 void FindBranchTargets(const Instruction& instructions,
92 BranchTargets* branch_targets);
93
94 // Combine instructions between "head" and "tail" into a new basic block.
95 // Basic blocks are defined as sequences of instructions whose only branch
96 // target is the very first instruction; furthermore, any BPF_JMP or BPF_RET
97 // instruction must be at the very end of the basic block.
98 BasicBlock* MakeBasicBlock(Instruction* head, Instruction* tail);
99
100 // Creates a basic block and adds it to "basic_blocks"; sets "first_block"
101 // if it is still NULL.
102 void AddBasicBlock(Instruction* head,
103 Instruction* tail,
104 const BranchTargets& branch_targets,
105 TargetsToBlocks* basic_blocks,
106 BasicBlock** first_block);
107
108 // Cuts the DAG of instructions into basic blocks.
109 BasicBlock* CutGraphIntoBasicBlocks(Instruction* instructions,
110 const BranchTargets& branch_targets,
111 TargetsToBlocks* blocks);
112
113 // Find common tail sequences of basic blocks and coalesce them.
114 void MergeTails(TargetsToBlocks* blocks);
115
116 // For each basic block, compute the number of incoming branches.
117 void ComputeIncomingBranches(BasicBlock* block,
118 const TargetsToBlocks& targets_to_blocks,
119 IncomingBranches* incoming_branches);
120
121 // Topologically sort the basic blocks so that all jumps are forward jumps.
122 // This is a requirement for any well-formed BPF program.
123 void TopoSortBasicBlocks(BasicBlock* first_block,
124 const TargetsToBlocks& blocks,
125 BasicBlocks* basic_blocks);
126
127 // Convert jt_ptr_ and jf_ptr_ fields in BPF_JMP instructions to valid
128 // jt_ and jf_ jump offsets. This can result in BPF_JA instructions being
129 // inserted, if we need to jump over more than 256 instructions.
130 void ComputeRelativeJumps(BasicBlocks* basic_blocks,
131 const TargetsToBlocks& targets_to_blocks);
132
133 // Concatenate instructions from all basic blocks into a BPF program that
134 // can be passed to the kernel.
135 void ConcatenateBasicBlocks(const BasicBlocks&, Program* program);
136
137 // We stick all instructions and basic blocks into pools that get destroyed
138 // when the CodeGen object is destroyed. This way, we neither need to worry
139 // about explicitly managing ownership, nor do we need to worry about using
140 // smart pointers in the presence of circular references.
141 Instructions instructions_;
142 BasicBlocks basic_blocks_;
143
144 // Compile() must only ever be called once as it makes destructive changes
145 // to the DAG.
146 bool compiled_;
147 };
148
149 } // namespace sandbox
150
151 #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