| 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 <linux/filter.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "sandbox/linux/seccomp-bpf/basicblock.h" | 12 #include "sandbox/linux/seccomp-bpf/basicblock.h" |
| 13 #include "sandbox/linux/seccomp-bpf/die.h" | 13 #include "sandbox/linux/seccomp-bpf/die.h" |
| 14 #include "sandbox/linux/seccomp-bpf/instruction.h" | 14 #include "sandbox/linux/seccomp-bpf/instruction.h" |
| 15 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" | |
| 16 #include "sandbox/linux/seccomp-bpf/trap.h" | |
| 17 | 15 |
| 18 namespace sandbox { | 16 namespace sandbox { |
| 19 | 17 |
| 20 CodeGen::CodeGen() : compiled_(false) {} | 18 CodeGen::CodeGen() : compiled_(false) {} |
| 21 | 19 |
| 22 CodeGen::~CodeGen() { | 20 CodeGen::~CodeGen() { |
| 23 for (Instructions::iterator iter = instructions_.begin(); | 21 for (Instructions::iterator iter = instructions_.begin(); |
| 24 iter != instructions_.end(); | 22 iter != instructions_.end(); |
| 25 ++iter) { | 23 ++iter) { |
| 26 delete *iter; | 24 delete *iter; |
| 27 } | 25 } |
| 28 for (BasicBlocks::iterator iter = basic_blocks_.begin(); | 26 for (BasicBlocks::iterator iter = basic_blocks_.begin(); |
| 29 iter != basic_blocks_.end(); | 27 iter != basic_blocks_.end(); |
| 30 ++iter) { | 28 ++iter) { |
| 31 delete *iter; | 29 delete *iter; |
| 32 } | 30 } |
| 33 } | 31 } |
| 34 | 32 |
| 35 void CodeGen::PrintProgram(const Program& program) { | |
| 36 for (Program::const_iterator iter = program.begin(); iter != program.end(); | |
| 37 ++iter) { | |
| 38 int ip = (int)(iter - program.begin()); | |
| 39 fprintf(stderr, "%3d) ", ip); | |
| 40 switch (BPF_CLASS(iter->code)) { | |
| 41 case BPF_LD: | |
| 42 if (iter->code == BPF_LD + BPF_W + BPF_ABS) { | |
| 43 fprintf(stderr, "LOAD %d // ", (int)iter->k); | |
| 44 if (iter->k == offsetof(struct arch_seccomp_data, nr)) { | |
| 45 fprintf(stderr, "System call number\n"); | |
| 46 } else if (iter->k == offsetof(struct arch_seccomp_data, arch)) { | |
| 47 fprintf(stderr, "Architecture\n"); | |
| 48 } else if (iter->k == | |
| 49 offsetof(struct arch_seccomp_data, instruction_pointer)) { | |
| 50 fprintf(stderr, "Instruction pointer (LSB)\n"); | |
| 51 } else if (iter->k == | |
| 52 offsetof(struct arch_seccomp_data, instruction_pointer) + | |
| 53 4) { | |
| 54 fprintf(stderr, "Instruction pointer (MSB)\n"); | |
| 55 } else if (iter->k >= offsetof(struct arch_seccomp_data, args) && | |
| 56 iter->k < offsetof(struct arch_seccomp_data, args) + 48 && | |
| 57 (iter->k - offsetof(struct arch_seccomp_data, args)) % 4 == | |
| 58 0) { | |
| 59 fprintf( | |
| 60 stderr, | |
| 61 "Argument %d (%cSB)\n", | |
| 62 (int)(iter->k - offsetof(struct arch_seccomp_data, args)) / 8, | |
| 63 (iter->k - offsetof(struct arch_seccomp_data, args)) % 8 ? 'M' | |
| 64 : 'L'); | |
| 65 } else { | |
| 66 fprintf(stderr, "???\n"); | |
| 67 } | |
| 68 } else { | |
| 69 fprintf(stderr, "LOAD ???\n"); | |
| 70 } | |
| 71 break; | |
| 72 case BPF_JMP: | |
| 73 if (BPF_OP(iter->code) == BPF_JA) { | |
| 74 fprintf(stderr, "JMP %d\n", ip + iter->k + 1); | |
| 75 } else { | |
| 76 fprintf(stderr, "if A %s 0x%x; then JMP %d else JMP %d\n", | |
| 77 BPF_OP(iter->code) == BPF_JSET ? "&" : | |
| 78 BPF_OP(iter->code) == BPF_JEQ ? "==" : | |
| 79 BPF_OP(iter->code) == BPF_JGE ? ">=" : | |
| 80 BPF_OP(iter->code) == BPF_JGT ? ">" : "???", | |
| 81 (int)iter->k, | |
| 82 ip + iter->jt + 1, ip + iter->jf + 1); | |
| 83 } | |
| 84 break; | |
| 85 case BPF_RET: | |
| 86 fprintf(stderr, "RET 0x%x // ", iter->k); | |
| 87 if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP) { | |
| 88 fprintf(stderr, "Trap #%d\n", iter->k & SECCOMP_RET_DATA); | |
| 89 } else if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { | |
| 90 fprintf(stderr, "errno = %d\n", iter->k & SECCOMP_RET_DATA); | |
| 91 } else if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRACE) { | |
| 92 fprintf(stderr, "Trace #%d\n", iter->k & SECCOMP_RET_DATA); | |
| 93 } else if (iter->k == SECCOMP_RET_ALLOW) { | |
| 94 fprintf(stderr, "Allowed\n"); | |
| 95 } else { | |
| 96 fprintf(stderr, "???\n"); | |
| 97 } | |
| 98 break; | |
| 99 case BPF_ALU: | |
| 100 fprintf(stderr, BPF_OP(iter->code) == BPF_NEG | |
| 101 ? "A := -A\n" : "A := A %s 0x%x\n", | |
| 102 BPF_OP(iter->code) == BPF_ADD ? "+" : | |
| 103 BPF_OP(iter->code) == BPF_SUB ? "-" : | |
| 104 BPF_OP(iter->code) == BPF_MUL ? "*" : | |
| 105 BPF_OP(iter->code) == BPF_DIV ? "/" : | |
| 106 BPF_OP(iter->code) == BPF_MOD ? "%" : | |
| 107 BPF_OP(iter->code) == BPF_OR ? "|" : | |
| 108 BPF_OP(iter->code) == BPF_XOR ? "^" : | |
| 109 BPF_OP(iter->code) == BPF_AND ? "&" : | |
| 110 BPF_OP(iter->code) == BPF_LSH ? "<<" : | |
| 111 BPF_OP(iter->code) == BPF_RSH ? ">>" : "???", | |
| 112 (int)iter->k); | |
| 113 break; | |
| 114 default: | |
| 115 fprintf(stderr, "???\n"); | |
| 116 break; | |
| 117 } | |
| 118 } | |
| 119 return; | |
| 120 } | |
| 121 | |
| 122 Instruction* CodeGen::MakeInstruction(uint16_t code, | 33 Instruction* CodeGen::MakeInstruction(uint16_t code, |
| 123 uint32_t k, | 34 uint32_t k, |
| 124 Instruction* next) { | 35 Instruction* next) { |
| 125 // We can handle non-jumping instructions and "always" jumps. Both of | 36 // We can handle non-jumping instructions and "always" jumps. Both of |
| 126 // them are followed by exactly one "next" instruction. | 37 // them are followed by exactly one "next" instruction. |
| 127 // We allow callers to defer specifying "next", but then they must call | 38 // We allow callers to defer specifying "next", but then they must call |
| 128 // "joinInstructions" later. | 39 // "joinInstructions" later. |
| 129 if (BPF_CLASS(code) == BPF_JMP && BPF_OP(code) != BPF_JA) { | 40 if (BPF_CLASS(code) == BPF_JMP && BPF_OP(code) != BPF_JA) { |
| 130 SANDBOX_DIE( | 41 SANDBOX_DIE( |
| 131 "Must provide both \"true\" and \"false\" branch " | 42 "Must provide both \"true\" and \"false\" branch " |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks); | 600 CutGraphIntoBasicBlocks(instructions, branch_targets, &all_blocks); |
| 690 MergeTails(&all_blocks); | 601 MergeTails(&all_blocks); |
| 691 BasicBlocks basic_blocks; | 602 BasicBlocks basic_blocks; |
| 692 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks); | 603 TopoSortBasicBlocks(first_block, all_blocks, &basic_blocks); |
| 693 ComputeRelativeJumps(&basic_blocks, all_blocks); | 604 ComputeRelativeJumps(&basic_blocks, all_blocks); |
| 694 ConcatenateBasicBlocks(basic_blocks, program); | 605 ConcatenateBasicBlocks(basic_blocks, program); |
| 695 return; | 606 return; |
| 696 } | 607 } |
| 697 | 608 |
| 698 } // namespace sandbox | 609 } // namespace sandbox |
| OLD | NEW |