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 <stdio.h> | 5 #include <stdio.h> |
6 | 6 |
| 7 #include "base/logging.h" |
7 #include "sandbox/linux/seccomp-bpf/codegen.h" | 8 #include "sandbox/linux/seccomp-bpf/codegen.h" |
8 | 9 |
9 namespace { | 10 namespace { |
10 | 11 |
11 // Helper function for Traverse(). | 12 // Helper function for Traverse(). |
12 void TraverseRecursively(std::set<sandbox::Instruction*>* visited, | 13 void TraverseRecursively(std::set<sandbox::Instruction*>* visited, |
13 sandbox::Instruction* instruction) { | 14 sandbox::Instruction* instruction) { |
14 if (visited->find(instruction) == visited->end()) { | 15 if (visited->find(instruction) == visited->end()) { |
15 visited->insert(instruction); | 16 visited->insert(instruction); |
16 switch (BPF_CLASS(instruction->code)) { | 17 switch (BPF_CLASS(instruction->code)) { |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 // Return <0, 0, or >0 depending on the ordering of "block1" and "block2". | 426 // Return <0, 0, or >0 depending on the ordering of "block1" and "block2". |
426 // If we are looking at the exact same block, this is trivial and we don't | 427 // If we are looking at the exact same block, this is trivial and we don't |
427 // need to do a full comparison. | 428 // need to do a full comparison. |
428 if (block1 == block2) { | 429 if (block1 == block2) { |
429 return 0; | 430 return 0; |
430 } | 431 } |
431 | 432 |
432 // We compare the sequence of instructions in both basic blocks. | 433 // We compare the sequence of instructions in both basic blocks. |
433 const Instructions& insns1 = block1->instructions; | 434 const Instructions& insns1 = block1->instructions; |
434 const Instructions& insns2 = block2->instructions; | 435 const Instructions& insns2 = block2->instructions; |
| 436 // Basic blocks should never be empty. |
| 437 CHECK(!insns1.empty()); |
| 438 CHECK(!insns2.empty()); |
| 439 |
435 Instructions::const_iterator iter1 = insns1.begin(); | 440 Instructions::const_iterator iter1 = insns1.begin(); |
436 Instructions::const_iterator iter2 = insns2.begin(); | 441 Instructions::const_iterator iter2 = insns2.begin(); |
437 for (;; ++iter1, ++iter2) { | 442 for (;; ++iter1, ++iter2) { |
438 // If we have reached the end of the sequence of instructions in one or | 443 // If we have reached the end of the sequence of instructions in one or |
439 // both basic blocks, we know the relative ordering between the two blocks | 444 // both basic blocks, we know the relative ordering between the two blocks |
440 // and can return. | 445 // and can return. |
441 if (iter1 == insns1.end()) { | 446 if (iter1 == insns1.end()) { |
442 return iter2 == insns2.end() ? 0 : -1; | 447 if (iter2 == insns2.end()) { |
| 448 // If the two blocks are the same length (and have elementwise-equal |
| 449 // code and k fields, which is the only way we can reach this point), |
| 450 // and the last instruction isn't a JMP or a RET, then we must compare |
| 451 // their successors. |
| 452 Instruction* const insns1_last = insns1.back(); |
| 453 Instruction* const insns2_last = insns2.back(); |
| 454 if (BPF_CLASS(insns1_last->code) != BPF_JMP && |
| 455 BPF_CLASS(insns1_last->code) != BPF_RET) { |
| 456 // Non jumping instructions will always have a valid next instruction. |
| 457 CHECK(insns1_last->next); |
| 458 CHECK(insns2_last->next); |
| 459 return PointerCompare(blocks.find(insns1_last->next)->second, |
| 460 blocks.find(insns2_last->next)->second, |
| 461 blocks); |
| 462 } else { |
| 463 return 0; |
| 464 } |
| 465 } |
| 466 return -1; |
443 } else if (iter2 == insns2.end()) { | 467 } else if (iter2 == insns2.end()) { |
444 return 1; | 468 return 1; |
445 } | 469 } |
446 | 470 |
447 // Compare the individual fields for both instructions. | 471 // Compare the individual fields for both instructions. |
448 const Instruction& insn1 = **iter1; | 472 const Instruction& insn1 = **iter1; |
449 const Instruction& insn2 = **iter2; | 473 const Instruction& insn2 = **iter2; |
450 if (insn1.code == insn2.code) { | 474 if (insn1.code == insn2.code) { |
451 if (insn1.k == insn2.k) { | 475 if (insn1.k == insn2.k) { |
452 // Only conditional jump instructions use the jt_ptr and jf_ptr | 476 // Only conditional jump instructions use the jt_ptr and jf_ptr |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks); | 765 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks); |
742 MergeTails(&all_blocks); | 766 MergeTails(&all_blocks); |
743 BasicBlocks basic_blocks; | 767 BasicBlocks basic_blocks; |
744 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks); | 768 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks); |
745 ComputeRelativeJumps(&basic_blocks, all_blocks); | 769 ComputeRelativeJumps(&basic_blocks, all_blocks); |
746 ConcatenateBasicBlocks(basic_blocks, program); | 770 ConcatenateBasicBlocks(basic_blocks, program); |
747 return; | 771 return; |
748 } | 772 } |
749 | 773 |
750 } // namespace sandbox | 774 } // namespace sandbox |
OLD | NEW |