| 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> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "sandbox/sandbox_export.h" | 13 #include "sandbox/sandbox_export.h" |
| 14 | 14 |
| 15 struct sock_filter; | 15 struct sock_filter; |
| 16 | 16 |
| 17 namespace sandbox { | 17 namespace sandbox { |
| 18 struct BasicBlock; | 18 struct BasicBlock; |
| 19 struct Instruction; | 19 struct Instruction; |
| 20 | 20 |
| 21 typedef std::vector<Instruction*> Instructions; | 21 typedef std::vector<Instruction*> Instructions; |
| 22 typedef std::vector<BasicBlock*> BasicBlocks; | 22 typedef std::vector<BasicBlock*> BasicBlocks; |
| 23 typedef std::map<const Instruction*, int> BranchTargets; | 23 typedef std::map<const Instruction*, int> BranchTargets; |
| 24 typedef std::map<const Instruction*, BasicBlock*> TargetsToBlocks; | 24 typedef std::map<const Instruction*, BasicBlock*> TargetsToBlocks; |
| 25 typedef std::map<const BasicBlock*, int> IncomingBranches; | 25 typedef std::map<const BasicBlock*, int> IncomingBranches; |
| 26 | 26 |
| 27 // The code generator instantiates a basic compiler that can convert a | 27 // The code generator implements a basic assembler 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 array of BPF |
| 29 // Most notably, it ensures that jumps are always forward and don't exceed | 29 // instructions. Most notably, it ensures that jumps are always |
| 30 // the limit of 255 instructions imposed by the instruction set. | 30 // forward and don't exceed the limit of 255 instructions imposed by |
| 31 // the instruction set. |
| 31 // | 32 // |
| 32 // Callers would typically create a new CodeGen object and then use it to | 33 // Callers would typically create a new CodeGen object and then use it |
| 33 // build a DAG of Instructions. They'll eventually call Compile() to convert | 34 // to build a DAG of instruction nodes. They'll eventually call |
| 34 // this DAG to a Program. | 35 // Compile() to convert this DAG to a Program. |
| 35 // | 36 // |
| 36 // CodeGen gen; | 37 // CodeGen gen; |
| 37 // Instruction *allow, *branch, *dag; | 38 // CodeGen::Node allow, branch, dag; |
| 38 // | 39 // |
| 39 // allow = | 40 // allow = |
| 40 // gen.MakeInstruction(BPF_RET+BPF_K, | 41 // gen.MakeInstruction(BPF_RET+BPF_K, |
| 41 // ErrorCode(ErrorCode::ERR_ALLOWED).err())); | 42 // ErrorCode(ErrorCode::ERR_ALLOWED).err())); |
| 42 // branch = | 43 // branch = |
| 43 // gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid, | 44 // gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid, |
| 44 // Trap(GetPidHandler, NULL), allow); | 45 // Trap(GetPidHandler, NULL), allow); |
| 45 // dag = | 46 // dag = |
| 46 // gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS, | 47 // gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS, |
| 47 // offsetof(struct arch_seccomp_data, nr), branch); | 48 // offsetof(struct arch_seccomp_data, nr), branch); |
| 48 // | 49 // |
| 49 // // Simplified code follows; in practice, it is important to avoid calling | 50 // // Simplified code follows; in practice, it is important to avoid calling |
| 50 // // any C++ destructors after starting the sandbox. | 51 // // any C++ destructors after starting the sandbox. |
| 51 // CodeGen::Program program; | 52 // CodeGen::Program program; |
| 52 // gen.Compile(dag, program); | 53 // gen.Compile(dag, program); |
| 53 // const struct sock_fprog prog = { | 54 // const struct sock_fprog prog = { |
| 54 // static_cast<unsigned short>(program->size()), &program[0] }; | 55 // static_cast<unsigned short>(program->size()), &program[0] }; |
| 55 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); | 56 // prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); |
| 56 // | 57 // |
| 57 class SANDBOX_EXPORT CodeGen { | 58 class SANDBOX_EXPORT CodeGen { |
| 58 public: | 59 public: |
| 59 // A vector of BPF instructions that need to be installed as a filter | 60 // A vector of BPF instructions that need to be installed as a filter |
| 60 // program in the kernel. | 61 // program in the kernel. |
| 61 typedef std::vector<struct sock_filter> Program; | 62 typedef std::vector<struct sock_filter> Program; |
| 62 | 63 |
| 64 // Node represents a node within the instruction DAG being compiled. |
| 65 // Nodes are owned by the CodeGen object and need not be explicitly |
| 66 // deleted. |
| 67 using Node = Instruction*; |
| 68 |
| 69 // kNullNode represents the "null" node; i.e., the reserved node |
| 70 // value guaranteed to not equal any actual nodes. |
| 71 static const Node kNullNode; |
| 72 |
| 63 CodeGen(); | 73 CodeGen(); |
| 64 ~CodeGen(); | 74 ~CodeGen(); |
| 65 | 75 |
| 66 // Create a new instruction. Instructions form a DAG. The instruction objects | 76 // MakeInstruction creates a node representing the specified |
| 67 // are owned by the CodeGen object. They do not need to be explicitly | 77 // instruction. For details on the possible parameters refer to |
| 68 // deleted. | 78 // https://www.kernel.org/doc/Documentation/networking/filter.txt. |
| 69 // For details on the possible parameters refer to <linux/filter.h> | 79 // TODO(mdempsky): Reconsider using default arguments here. |
| 70 Instruction* MakeInstruction(uint16_t code, | 80 Node MakeInstruction(uint16_t code, |
| 71 uint32_t k, | 81 uint32_t k, |
| 72 Instruction* next = nullptr); | 82 Node jt = kNullNode, |
| 73 Instruction* MakeInstruction(uint16_t code, | 83 Node jf = kNullNode); |
| 74 uint32_t k, | |
| 75 Instruction* jt, | |
| 76 Instruction* jf); | |
| 77 | 84 |
| 78 // Compiles the graph of instructions into a BPF program that can be passed | 85 // Compile linearizes the instruction DAG into a BPF program that |
| 79 // to the kernel. Please note that this function modifies the graph in place | 86 // can be executed by a BPF virtual machine. Please note that this |
| 80 // and must therefore only be called once per graph. | 87 // function modifies the graph in place and must therefore only be |
| 81 void Compile(Instruction* instructions, Program* program); | 88 // called once per graph. |
| 89 void Compile(Node head, Program* program); |
| 82 | 90 |
| 83 private: | 91 private: |
| 84 friend class CodeGenUnittestHelper; | 92 friend class CodeGenUnittestHelper; |
| 85 | 93 |
| 86 // Find all the instructions that are the target of BPF_JMPs. | 94 // Find all the instructions that are the target of BPF_JMPs. |
| 87 void FindBranchTargets(const Instruction& instructions, | 95 void FindBranchTargets(const Instruction& instructions, |
| 88 BranchTargets* branch_targets); | 96 BranchTargets* branch_targets); |
| 89 | 97 |
| 90 // Combine instructions between "head" and "tail" into a new basic block. | 98 // Combine instructions between "head" and "tail" into a new basic block. |
| 91 // Basic blocks are defined as sequences of instructions whose only branch | 99 // 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_; | 146 BasicBlocks basic_blocks_; |
| 139 | 147 |
| 140 // Compile() must only ever be called once as it makes destructive changes | 148 // Compile() must only ever be called once as it makes destructive changes |
| 141 // to the DAG. | 149 // to the DAG. |
| 142 bool compiled_; | 150 bool compiled_; |
| 143 }; | 151 }; |
| 144 | 152 |
| 145 } // namespace sandbox | 153 } // namespace sandbox |
| 146 | 154 |
| 147 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ | 155 #endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__ |
| OLD | NEW |