| 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 |