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 |