Chromium Code Reviews| 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 #ifndef SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ | 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ |
| 6 #define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ | 6 #define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ |
| 7 | 7 |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 // The code generator instantiates a basic compiler that can convert a | 27 // The code generator instantiates a basic compiler that can convert a |
| 28 // graph of BPF instructions into a well-formed stream of BPF instructions. | 28 // graph of BPF instructions into a well-formed stream of BPF instructions. |
| 29 // Most notably, it ensures that jumps are always forward and don't exceed | 29 // Most notably, it ensures that jumps are always forward and don't exceed |
| 30 // the limit of 255 instructions imposed by the instruction set. | 30 // the limit of 255 instructions imposed by the instruction set. |
| 31 // | 31 // |
| 32 // Callers would typically create a new CodeGen object and then use it to | 32 // Callers would typically create a new CodeGen object and then use it to |
| 33 // build a DAG of Instructions. They'll eventually call Compile() to convert | 33 // build a DAG of Instructions. They'll eventually call Compile() to convert |
| 34 // this DAG to a Program. | 34 // this DAG to a Program. |
| 35 // | 35 // |
| 36 // CodeGen gen; | 36 // CodeGen gen; |
| 37 // Instruction *allow, *branch, *dag; | 37 // CodeGen::Addr allow, branch, dag; |
| 38 // | 38 // |
| 39 // allow = | 39 // allow = |
| 40 // gen.MakeInstruction(BPF_RET+BPF_K, | 40 // gen.MakeInstruction(BPF_RET+BPF_K, |
| 41 // ErrorCode(ErrorCode::ERR_ALLOWED).err())); | 41 // ErrorCode(ErrorCode::ERR_ALLOWED).err())); |
| 42 // branch = | 42 // branch = |
| 43 // gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid, | 43 // gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid, |
| 44 // Trap(GetPidHandler, NULL), allow); | 44 // Trap(GetPidHandler, NULL), allow); |
| 45 // dag = | 45 // dag = |
| 46 // gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS, | 46 // gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS, |
| 47 // offsetof(struct arch_seccomp_data, nr), branch); | 47 // offsetof(struct arch_seccomp_data, nr), branch); |
| 48 // | 48 // |
| 49 // // Simplified code follows; in practice, it is important to avoid calling | 49 // // Simplified code follows; in practice, it is important to avoid calling |
| 50 // // any C++ destructors after starting the sandbox. | 50 // // any C++ destructors after starting the sandbox. |
| 51 // CodeGen::Program program; | 51 // CodeGen::Program program; |
| 52 // gen.Compile(dag, program); | 52 // gen.Compile(dag, program); |
| 53 // const struct sock_fprog prog = { | 53 // const struct sock_fprog prog = { |
| 54 // static_cast<unsigned short>(program->size()), &program[0] }; | 54 // static_cast<unsigned short>(program->size()), &program[0] }; |
| 55 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); | 55 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); |
| 56 // | 56 // |
| 57 class SANDBOX_EXPORT CodeGen { | 57 class SANDBOX_EXPORT CodeGen { |
| 58 public: | 58 public: |
| 59 // A vector of BPF instructions that need to be installed as a filter | 59 // A vector of BPF instructions that need to be installed as a filter |
| 60 // program in the kernel. | 60 // program in the kernel. |
| 61 typedef std::vector<struct sock_filter> Program; | 61 typedef std::vector<struct sock_filter> Program; |
| 62 | 62 |
| 63 // Addr represents a logical location within the program being compiled. | |
| 64 // Identical code suffixes may be collapsed to a single location. | |
| 65 using Addr = Instruction*; | |
|
mdempsky
2014/11/04 01:31:15
(As a side note: I'm not particularly attached to
| |
| 66 | |
| 67 // kNullAddr represents the "null" address value; i.e., the reserved | |
| 68 // address value guaranteed to not equal any actual address values. | |
| 69 static const Addr kNullAddr; | |
| 70 | |
| 63 CodeGen(); | 71 CodeGen(); |
| 64 ~CodeGen(); | 72 ~CodeGen(); |
| 65 | 73 |
| 66 // Create a new instruction. Instructions form a DAG. The instruction objects | 74 // Create a new instruction. Instructions form a DAG. The instruction objects |
| 67 // are owned by the CodeGen object. They do not need to be explicitly | 75 // are owned by the CodeGen object. They do not need to be explicitly |
| 68 // deleted. | 76 // deleted. |
| 69 // For details on the possible parameters refer to <linux/filter.h> | 77 // For details on the possible parameters refer to <linux/filter.h> |
| 70 Instruction* MakeInstruction(uint16_t code, | 78 Addr MakeInstruction(uint16_t code, |
| 71 uint32_t k, | 79 uint32_t k, |
| 72 Instruction* next = nullptr); | 80 Addr jt = kNullAddr, |
| 73 Instruction* MakeInstruction(uint16_t code, | 81 Addr jf = kNullAddr); |
|
jln (very slow on Chromium)
2014/11/11 08:40:48
These are normally illegal. Overload are better to
mdempsky
2014/11/17 22:11:07
I've decided to just add a TODO to reconsider the
| |
| 74 uint32_t k, | |
| 75 Instruction* jt, | |
| 76 Instruction* jf); | |
| 77 | 82 |
| 78 // Compiles the graph of instructions into a BPF program that can be passed | 83 // Compiles the graph of instructions into a BPF program that can be passed |
| 79 // to the kernel. Please note that this function modifies the graph in place | 84 // to the kernel. Please note that this function modifies the graph in place |
| 80 // and must therefore only be called once per graph. | 85 // and must therefore only be called once per graph. |
| 81 void Compile(Instruction* instructions, Program* program); | 86 void Compile(Addr head, Program* program); |
| 82 | 87 |
| 83 private: | 88 private: |
| 84 friend class CodeGenUnittestHelper; | 89 friend class CodeGenUnittestHelper; |
| 85 | 90 |
| 86 // Find all the instructions that are the target of BPF_JMPs. | 91 // Find all the instructions that are the target of BPF_JMPs. |
| 87 void FindBranchTargets(const Instruction& instructions, | 92 void FindBranchTargets(const Instruction& instructions, |
| 88 BranchTargets* branch_targets); | 93 BranchTargets* branch_targets); |
| 89 | 94 |
| 90 // Combine instructions between "head" and "tail" into a new basic block. | 95 // Combine instructions between "head" and "tail" into a new basic block. |
| 91 // Basic blocks are defined as sequences of instructions whose only branch | 96 // Basic blocks are defined as sequences of instructions whose only branch |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 BasicBlocks basic_blocks_; | 143 BasicBlocks basic_blocks_; |
| 139 | 144 |
| 140 // Compile() must only ever be called once as it makes destructive changes | 145 // Compile() must only ever be called once as it makes destructive changes |
| 141 // to the DAG. | 146 // to the DAG. |
| 142 bool compiled_; | 147 bool compiled_; |
| 143 }; | 148 }; |
| 144 | 149 |
| 145 } // namespace sandbox | 150 } // namespace sandbox |
| 146 | 151 |
| 147 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ | 152 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ |
| OLD | NEW |