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 #include "sandbox/linux/seccomp-bpf/codegen.h" | 5 #include "sandbox/linux/seccomp-bpf/codegen.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include <set> | 9 #include <set> |
10 | 10 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 | 174 |
175 Instruction* CodeGen::MakeInstruction(uint16_t code, | 175 Instruction* CodeGen::MakeInstruction(uint16_t code, |
176 uint32_t k, | 176 uint32_t k, |
177 Instruction* jt, | 177 Instruction* jt, |
178 Instruction* jf) { | 178 Instruction* jf) { |
179 // We can handle all conditional jumps. They are followed by both a | 179 // We can handle all conditional jumps. They are followed by both a |
180 // "true" and a "false" branch. | 180 // "true" and a "false" branch. |
181 if (BPF_CLASS(code) != BPF_JMP || BPF_OP(code) == BPF_JA) { | 181 if (BPF_CLASS(code) != BPF_JMP || BPF_OP(code) == BPF_JA) { |
182 SANDBOX_DIE("Expected a BPF_JMP instruction"); | 182 SANDBOX_DIE("Expected a BPF_JMP instruction"); |
183 } | 183 } |
184 if (!jt && !jf) { | 184 if (!jt || !jf) { |
185 // We allow callers to defer specifying exactly one of the branch | |
186 // targets. It must then be set later by calling "JoinInstructions". | |
187 SANDBOX_DIE("Branches must jump to a valid instruction"); | 185 SANDBOX_DIE("Branches must jump to a valid instruction"); |
188 } | 186 } |
189 Instruction* insn = new Instruction(code, k, jt, jf); | 187 Instruction* insn = new Instruction(code, k, jt, jf); |
190 instructions_.push_back(insn); | 188 instructions_.push_back(insn); |
191 return insn; | 189 return insn; |
192 } | 190 } |
193 | 191 |
194 void CodeGen::JoinInstructions(Instruction* head, Instruction* tail) { | |
195 // Merge two instructions, or set the branch target for an "always" jump. | |
196 // This function should be called, if the caller didn't initially provide | |
197 // a value for "next" when creating the instruction. | |
198 if (BPF_CLASS(head->code) == BPF_JMP) { | |
199 if (BPF_OP(head->code) == BPF_JA) { | |
200 if (head->jt_ptr) { | |
201 SANDBOX_DIE("Cannot append instructions in the middle of a sequence"); | |
202 } | |
203 head->jt_ptr = tail; | |
204 } else { | |
205 if (!head->jt_ptr && head->jf_ptr) { | |
206 head->jt_ptr = tail; | |
207 } else if (!head->jf_ptr && head->jt_ptr) { | |
208 head->jf_ptr = tail; | |
209 } else { | |
210 SANDBOX_DIE("Cannot append instructions after a jump"); | |
211 } | |
212 } | |
213 } else if (BPF_CLASS(head->code) == BPF_RET) { | |
214 SANDBOX_DIE("Cannot append instructions after a return statement"); | |
215 } else if (head->next) { | |
216 SANDBOX_DIE("Cannot append instructions in the middle of a sequence"); | |
217 } else { | |
218 head->next = tail; | |
219 } | |
220 return; | |
221 } | |
222 | |
223 void CodeGen::Traverse(Instruction* instruction, | 192 void CodeGen::Traverse(Instruction* instruction, |
224 void (*fnc)(Instruction*, void*), | 193 void (*fnc)(Instruction*, void*), |
225 void* aux) { | 194 void* aux) { |
226 std::set<Instruction*> visited; | 195 std::set<Instruction*> visited; |
227 TraverseRecursively(&visited, instruction); | 196 TraverseRecursively(&visited, instruction); |
228 for (std::set<Instruction*>::const_iterator iter = visited.begin(); | 197 for (std::set<Instruction*>::const_iterator iter = visited.begin(); |
229 iter != visited.end(); | 198 iter != visited.end(); |
230 ++iter) { | 199 ++iter) { |
231 fnc(*iter, aux); | 200 fnc(*iter, aux); |
232 } | 201 } |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks); | 726 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks); |
758 MergeTails(&all_blocks); | 727 MergeTails(&all_blocks); |
759 BasicBlocks basic_blocks; | 728 BasicBlocks basic_blocks; |
760 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks); | 729 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks); |
761 ComputeRelativeJumps(&basic_blocks, all_blocks); | 730 ComputeRelativeJumps(&basic_blocks, all_blocks); |
762 ConcatenateBasicBlocks(basic_blocks, program); | 731 ConcatenateBasicBlocks(basic_blocks, program); |
763 return; | 732 return; |
764 } | 733 } |
765 | 734 |
766 } // namespace sandbox | 735 } // namespace sandbox |
OLD | NEW |