OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ |
| 6 #define SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ |
| 7 |
| 8 #include <stdint.h> |
| 9 |
| 10 #include <map> |
| 11 #include <set> |
| 12 #include <vector> |
| 13 |
| 14 #include "base/macros.h" |
| 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "sandbox/linux/seccomp-bpf/codegen.h" |
| 17 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
| 18 #include "sandbox/sandbox_export.h" |
| 19 |
| 20 namespace sandbox { |
| 21 struct Instruction; |
| 22 |
| 23 namespace bpf_dsl { |
| 24 class SandboxBPFDSLPolicy; |
| 25 |
| 26 // PolicyCompiler implements the bpf_dsl compiler, allowing users to |
| 27 // transform bpf_dsl policies into BPF programs to be executed by the |
| 28 // Linux kernel. |
| 29 class SANDBOX_EXPORT PolicyCompiler { |
| 30 public: |
| 31 PolicyCompiler(const SandboxBPFDSLPolicy* policy, TrapRegistry* registry); |
| 32 ~PolicyCompiler(); |
| 33 |
| 34 // Compile registers any trap handlers needed by the policy and |
| 35 // compiles the policy to a BPF program, which it returns. |
| 36 scoped_ptr<CodeGen::Program> Compile(); |
| 37 |
| 38 // Error returns an ErrorCode to indicate the system call should fail with |
| 39 // the specified error number. |
| 40 ErrorCode Error(int err); |
| 41 |
| 42 // We can use ErrorCode to request calling of a trap handler. This method |
| 43 // performs the required wrapping of the callback function into an |
| 44 // ErrorCode object. |
| 45 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall |
| 46 // for a description of how to pass data from SetSandboxPolicy() to a Trap() |
| 47 // handler. |
| 48 ErrorCode Trap(TrapRegistry::TrapFnc fnc, const void* aux); |
| 49 |
| 50 // Calls a user-space trap handler and disables all sandboxing for system |
| 51 // calls made from this trap handler. |
| 52 // This feature is available only if explicitly enabled by the user having |
| 53 // set the CHROME_SANDBOX_DEBUGGING environment variable. |
| 54 // Returns an ET_INVALID ErrorCode, if called when not enabled. |
| 55 // NOTE: This feature, by definition, disables all security features of |
| 56 // the sandbox. It should never be used in production, but it can be |
| 57 // very useful to diagnose code that is incompatible with the sandbox. |
| 58 // If even a single system call returns "UnsafeTrap", the security of |
| 59 // entire sandbox should be considered compromised. |
| 60 ErrorCode UnsafeTrap(TrapRegistry::TrapFnc fnc, const void* aux); |
| 61 |
| 62 // UnsafeTraps require some syscalls to always be allowed. |
| 63 // This helper function returns true for these calls. |
| 64 static bool IsRequiredForUnsafeTrap(int sysno); |
| 65 |
| 66 // We can also use ErrorCode to request evaluation of a conditional |
| 67 // statement based on inspection of system call parameters. |
| 68 // This method wrap an ErrorCode object around the conditional statement. |
| 69 // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared |
| 70 // to "value"; if equal, then "passed" will be returned, otherwise "failed". |
| 71 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) |
| 72 // If it is outside this range, the sandbox treats the system call just |
| 73 // the same as any other ABI violation (i.e. it aborts with an error |
| 74 // message). |
| 75 ErrorCode CondMaskedEqual(int argno, |
| 76 ErrorCode::ArgType is_32bit, |
| 77 uint64_t mask, |
| 78 uint64_t value, |
| 79 const ErrorCode& passed, |
| 80 const ErrorCode& failed); |
| 81 |
| 82 // Kill the program and print an error message. |
| 83 ErrorCode Kill(const char* msg); |
| 84 |
| 85 // Returns the fatal ErrorCode that is used to indicate that somebody |
| 86 // attempted to pass a 64bit value in a 32bit system call argument. |
| 87 // This method is primarily needed for testing purposes. |
| 88 ErrorCode Unexpected64bitArgument(); |
| 89 |
| 90 private: |
| 91 struct Range; |
| 92 typedef std::vector<Range> Ranges; |
| 93 typedef std::map<uint32_t, ErrorCode> ErrMap; |
| 94 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; |
| 95 |
| 96 // Used by CondExpressionHalf to track which half of the argument it's |
| 97 // emitting instructions for. |
| 98 enum ArgHalf { |
| 99 LowerHalf, |
| 100 UpperHalf, |
| 101 }; |
| 102 |
| 103 // Compile the configured policy into a complete instruction sequence. |
| 104 Instruction* AssemblePolicy(); |
| 105 |
| 106 // Return an instruction sequence that checks the |
| 107 // arch_seccomp_data's "arch" field is valid, and then passes |
| 108 // control to |passed| if so. |
| 109 Instruction* CheckArch(Instruction* passed); |
| 110 |
| 111 // If |has_unsafe_traps_| is true, returns an instruction sequence |
| 112 // that allows all system calls from Syscall::Call(), and otherwise |
| 113 // passes control to |rest|. Otherwise, simply returns |rest|. |
| 114 Instruction* MaybeAddEscapeHatch(Instruction* rest); |
| 115 |
| 116 // Return an instruction sequence that loads and checks the system |
| 117 // call number, performs a binary search, and then dispatches to an |
| 118 // appropriate instruction sequence compiled from the current |
| 119 // policy. |
| 120 Instruction* DispatchSyscall(); |
| 121 |
| 122 // Return an instruction sequence that checks the system call number |
| 123 // (expected to be loaded in register A) and if valid, passes |
| 124 // control to |passed| (with register A still valid). |
| 125 Instruction* CheckSyscallNumber(Instruction* passed); |
| 126 |
| 127 // Finds all the ranges of system calls that need to be handled. Ranges are |
| 128 // sorted in ascending order of system call numbers. There are no gaps in the |
| 129 // ranges. System calls with identical ErrorCodes are coalesced into a single |
| 130 // range. |
| 131 void FindRanges(Ranges* ranges); |
| 132 |
| 133 // Returns a BPF program snippet that implements a jump table for the |
| 134 // given range of system call numbers. This function runs recursively. |
| 135 Instruction* AssembleJumpTable(Ranges::const_iterator start, |
| 136 Ranges::const_iterator stop); |
| 137 |
| 138 // Returns a BPF program snippet that makes the BPF filter program exit |
| 139 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a |
| 140 // conditional expression; if so, this function will recursively call |
| 141 // CondExpression() and possibly RetExpression() to build a complex set of |
| 142 // instructions. |
| 143 Instruction* RetExpression(const ErrorCode& err); |
| 144 |
| 145 // Returns a BPF program that evaluates the conditional expression in |
| 146 // "cond" and returns the appropriate value from the BPF filter program. |
| 147 // This function recursively calls RetExpression(); it should only ever be |
| 148 // called from RetExpression(). |
| 149 Instruction* CondExpression(const ErrorCode& cond); |
| 150 |
| 151 // Returns a BPF program that evaluates half of a conditional expression; |
| 152 // it should only ever be called from CondExpression(). |
| 153 Instruction* CondExpressionHalf(const ErrorCode& cond, |
| 154 ArgHalf half, |
| 155 Instruction* passed, |
| 156 Instruction* failed); |
| 157 |
| 158 // MakeTrap is the common implementation for Trap and UnsafeTrap. |
| 159 ErrorCode MakeTrap(TrapRegistry::TrapFnc fnc, const void* aux, bool safe); |
| 160 |
| 161 const SandboxBPFDSLPolicy* policy_; |
| 162 TrapRegistry* registry_; |
| 163 |
| 164 Conds conds_; |
| 165 CodeGen gen_; |
| 166 bool has_unsafe_traps_; |
| 167 |
| 168 DISALLOW_COPY_AND_ASSIGN(PolicyCompiler); |
| 169 }; |
| 170 |
| 171 } // namespace bpf_dsl |
| 172 } // namespace sandbox |
| 173 |
| 174 #endif // SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ |
OLD | NEW |