| 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_SANDBOX_BPF_H__ | 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| 6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| 7 | 7 |
| 8 #include <endian.h> | |
| 9 #include <errno.h> | |
| 10 #include <fcntl.h> | |
| 11 // #include <linux/audit.h> | |
| 12 #include <linux/filter.h> | |
| 13 // #include <linux/seccomp.h> | |
| 14 #include <linux/unistd.h> | |
| 15 #include <netinet/in.h> | |
| 16 #include <netinet/tcp.h> | |
| 17 #include <netinet/udp.h> | |
| 18 #include <sched.h> | |
| 19 #include <signal.h> | |
| 20 #include <stddef.h> | 8 #include <stddef.h> |
| 21 #include <stdint.h> | |
| 22 #include <stdio.h> | |
| 23 #include <stdlib.h> | |
| 24 #include <string.h> | |
| 25 #include <sys/ioctl.h> | |
| 26 #include <sys/ipc.h> | |
| 27 #include <sys/mman.h> | |
| 28 #include <sys/prctl.h> | |
| 29 #include <sys/stat.h> | |
| 30 #include <sys/types.h> | 9 #include <sys/types.h> |
| 31 #include <sys/uio.h> | |
| 32 #include <sys/wait.h> | 10 #include <sys/wait.h> |
| 33 #include <time.h> | |
| 34 #include <unistd.h> | |
| 35 | 11 |
| 36 #include <algorithm> | 12 #include <algorithm> |
| 37 #include <limits> | 13 #include <limits> |
| 38 #include <map> | 14 #include <map> |
| 39 #include <set> | 15 #include <set> |
| 40 #include <utility> | 16 #include <utility> |
| 41 #include <vector> | 17 #include <vector> |
| 42 | 18 |
| 43 #if !defined(SECCOMP_BPF_STANDALONE) | |
| 44 #include "base/basictypes.h" | |
| 45 #include "base/logging.h" | |
| 46 #include "base/posix/eintr_wrapper.h" | |
| 47 #endif | |
| 48 | |
| 49 | |
| 50 // The Seccomp2 kernel ABI is not part of older versions of glibc. | |
| 51 // As we can't break compilation with these versions of the library, | |
| 52 // we explicitly define all missing symbols. | |
| 53 | |
| 54 // For audit.h | |
| 55 #ifndef EM_ARM | |
| 56 #define EM_ARM 40 | |
| 57 #endif | |
| 58 #ifndef EM_386 | |
| 59 #define EM_386 3 | |
| 60 #endif | |
| 61 #ifndef EM_X86_64 | |
| 62 #define EM_X86_64 62 | |
| 63 #endif | |
| 64 | |
| 65 #ifndef __AUDIT_ARCH_64BIT | |
| 66 #define __AUDIT_ARCH_64BIT 0x80000000 | |
| 67 #endif | |
| 68 #ifndef __AUDIT_ARCH_LE | |
| 69 #define __AUDIT_ARCH_LE 0x40000000 | |
| 70 #endif | |
| 71 #ifndef AUDIT_ARCH_ARM | |
| 72 #define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE) | |
| 73 #endif | |
| 74 #ifndef AUDIT_ARCH_I386 | |
| 75 #define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE) | |
| 76 #endif | |
| 77 #ifndef AUDIT_ARCH_X86_64 | |
| 78 #define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) | |
| 79 #endif | |
| 80 | |
| 81 // For prctl.h | |
| 82 #ifndef PR_SET_SECCOMP | |
| 83 #define PR_SET_SECCOMP 22 | |
| 84 #define PR_GET_SECCOMP 21 | |
| 85 #endif | |
| 86 #ifndef PR_SET_NO_NEW_PRIVS | |
| 87 #define PR_SET_NO_NEW_PRIVS 38 | |
| 88 #define PR_GET_NO_NEW_PRIVS 39 | |
| 89 #endif | |
| 90 #ifndef IPC_64 | |
| 91 #define IPC_64 0x0100 | |
| 92 #endif | |
| 93 | |
| 94 #ifndef BPF_MOD | |
| 95 #define BPF_MOD 0x90 | |
| 96 #endif | |
| 97 #ifndef BPF_XOR | |
| 98 #define BPF_XOR 0xA0 | |
| 99 #endif | |
| 100 | |
| 101 // In order to build will older tool chains, we currently have to avoid | |
| 102 // including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on | |
| 103 // our own definitions of the seccomp kernel ABI. | |
| 104 #ifndef SECCOMP_MODE_FILTER | |
| 105 #define SECCOMP_MODE_DISABLED 0 | |
| 106 #define SECCOMP_MODE_STRICT 1 | |
| 107 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter | |
| 108 #endif | |
| 109 | |
| 110 #ifndef SECCOMP_RET_KILL | |
| 111 // Return values supported for BPF filter programs. Please note that the | |
| 112 // "illegal" SECCOMP_RET_INVALID is not supported by the kernel, should only | |
| 113 // ever be used internally, and would result in the kernel killing our process. | |
| 114 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately | |
| 115 #define SECCOMP_RET_INVALID 0x00010000U // Illegal return value | |
| 116 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS | |
| 117 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno | |
| 118 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow | |
| 119 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow | |
| 120 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value | |
| 121 #define SECCOMP_RET_DATA 0x0000ffffU // sections | |
| 122 #else | |
| 123 #define SECCOMP_RET_INVALID 0x00010000U // Illegal return value | |
| 124 #endif | |
| 125 | |
| 126 #ifndef SYS_SECCOMP | |
| 127 #define SYS_SECCOMP 1 | |
| 128 #endif | |
| 129 | |
| 130 // Impose some reasonable maximum BPF program size. Realistically, the | |
| 131 // kernel probably has much lower limits. But by limiting to less than | |
| 132 // 30 bits, we can ease requirements on some of our data types. | |
| 133 #define SECCOMP_MAX_PROGRAM_SIZE (1<<30) | |
| 134 | |
| 135 #if defined(__i386__) | |
| 136 #define MIN_SYSCALL 0u | |
| 137 #define MAX_PUBLIC_SYSCALL 1024u | |
| 138 #define MAX_SYSCALL MAX_PUBLIC_SYSCALL | |
| 139 #define SECCOMP_ARCH AUDIT_ARCH_I386 | |
| 140 | |
| 141 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) | |
| 142 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_EAX) | |
| 143 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_EAX) | |
| 144 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_EIP) | |
| 145 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_EBX) | |
| 146 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_ECX) | |
| 147 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_EDX) | |
| 148 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_ESI) | |
| 149 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_EDI) | |
| 150 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_EBP) | |
| 151 #define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) | |
| 152 #define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) | |
| 153 #define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ | |
| 154 instruction_pointer) + 4) | |
| 155 #define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ | |
| 156 instruction_pointer) + 0) | |
| 157 #define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
| 158 8*(nr) + 4) | |
| 159 #define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
| 160 8*(nr) + 0) | |
| 161 | |
| 162 #elif defined(__x86_64__) | |
| 163 #define MIN_SYSCALL 0u | |
| 164 #define MAX_PUBLIC_SYSCALL 1024u | |
| 165 #define MAX_SYSCALL MAX_PUBLIC_SYSCALL | |
| 166 #define SECCOMP_ARCH AUDIT_ARCH_X86_64 | |
| 167 | |
| 168 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) | |
| 169 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_RAX) | |
| 170 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_RAX) | |
| 171 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_RIP) | |
| 172 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_RDI) | |
| 173 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_RSI) | |
| 174 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_RDX) | |
| 175 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_R10) | |
| 176 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_R8) | |
| 177 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_R9) | |
| 178 #define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) | |
| 179 #define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) | |
| 180 #define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ | |
| 181 instruction_pointer) + 4) | |
| 182 #define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ | |
| 183 instruction_pointer) + 0) | |
| 184 #define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
| 185 8*(nr) + 4) | |
| 186 #define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
| 187 8*(nr) + 0) | |
| 188 | |
| 189 #elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)) | |
| 190 // ARM EABI includes "ARM private" system calls starting at |__ARM_NR_BASE|, | |
| 191 // and a "ghost syscall private to the kernel", cmpxchg, | |
| 192 // at |__ARM_NR_BASE+0x00fff0|. | |
| 193 // See </arch/arm/include/asm/unistd.h> in the Linux kernel. | |
| 194 #define MIN_SYSCALL ((unsigned int)__NR_SYSCALL_BASE) | |
| 195 #define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u) | |
| 196 #define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE) | |
| 197 #define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u) | |
| 198 #define MIN_GHOST_SYSCALL ((unsigned int)__ARM_NR_BASE + 0xfff0u) | |
| 199 #define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u) | |
| 200 | |
| 201 #define SECCOMP_ARCH AUDIT_ARCH_ARM | |
| 202 | |
| 203 // ARM sigcontext_t is different from i386/x86_64. | |
| 204 // See </arch/arm/include/asm/sigcontext.h> in the Linux kernel. | |
| 205 #define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.arm_##_reg) | |
| 206 // ARM EABI syscall convention. | |
| 207 #define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, r0) | |
| 208 #define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, r7) | |
| 209 #define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, pc) | |
| 210 #define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, r0) | |
| 211 #define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, r1) | |
| 212 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, r2) | |
| 213 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) | |
| 214 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) | |
| 215 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) | |
| 216 #define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) | |
| 217 #define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) | |
| 218 #define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ | |
| 219 instruction_pointer) + 4) | |
| 220 #define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ | |
| 221 instruction_pointer) + 0) | |
| 222 #define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
| 223 8*(nr) + 4) | |
| 224 #define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ | |
| 225 8*(nr) + 0) | |
| 226 | |
| 227 #else | |
| 228 #error Unsupported target platform | |
| 229 | |
| 230 #endif | |
| 231 | |
| 232 #if defined(SECCOMP_BPF_STANDALONE) | |
| 233 #define arraysize(x) (sizeof(x)/sizeof(*(x))) | |
| 234 #define HANDLE_EINTR TEMP_FAILURE_RETRY | |
| 235 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ | |
| 236 TypeName(); \ | |
| 237 TypeName(const TypeName&); \ | |
| 238 void operator=(const TypeName&) | |
| 239 | |
| 240 template <bool> | |
| 241 struct CompileAssert { | |
| 242 }; | |
| 243 #define COMPILE_ASSERT(expr, msg) \ | |
| 244 typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] | |
| 245 #endif | |
| 246 | |
| 247 #include "sandbox/linux/seccomp-bpf/die.h" | 19 #include "sandbox/linux/seccomp-bpf/die.h" |
| 248 #include "sandbox/linux/seccomp-bpf/errorcode.h" | 20 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
| 21 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" |
| 22 #include "sandbox/linux/seccomp-bpf/port.h" |
| 23 |
| 249 | 24 |
| 250 namespace playground2 { | 25 namespace playground2 { |
| 251 | 26 |
| 252 struct arch_seccomp_data { | 27 struct arch_seccomp_data { |
| 253 int nr; | 28 int nr; |
| 254 uint32_t arch; | 29 uint32_t arch; |
| 255 uint64_t instruction_pointer; | 30 uint64_t instruction_pointer; |
| 256 uint64_t args[6]; | 31 uint64_t args[6]; |
| 257 }; | 32 }; |
| 258 | 33 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 274 STATUS_UNAVAILABLE, // Currently unavailable but might work again later | 49 STATUS_UNAVAILABLE, // Currently unavailable but might work again later |
| 275 STATUS_AVAILABLE, // Sandboxing is available but not currently active | 50 STATUS_AVAILABLE, // Sandboxing is available but not currently active |
| 276 STATUS_ENABLED // The sandbox is now active | 51 STATUS_ENABLED // The sandbox is now active |
| 277 }; | 52 }; |
| 278 | 53 |
| 279 // When calling setSandboxPolicy(), the caller can provide an arbitrary | 54 // When calling setSandboxPolicy(), the caller can provide an arbitrary |
| 280 // pointer. This pointer will then be forwarded to the sandbox policy | 55 // pointer. This pointer will then be forwarded to the sandbox policy |
| 281 // each time a call is made through an EvaluateSyscall function pointer. | 56 // each time a call is made through an EvaluateSyscall function pointer. |
| 282 // One common use case would be to pass the "aux" pointer as an argument | 57 // One common use case would be to pass the "aux" pointer as an argument |
| 283 // to Trap() functions. | 58 // to Trap() functions. |
| 284 typedef ErrorCode (*EvaluateSyscall)(int sysnum, void *aux); | 59 typedef ErrorCode (*EvaluateSyscall)(Sandbox *sb, int sysnum, void *aux); |
| 285 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators; | 60 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators; |
| 286 | 61 |
| 287 // A vector of BPF instructions that need to be installed as a filter | 62 // A vector of BPF instructions that need to be installed as a filter |
| 288 // program in the kernel. | 63 // program in the kernel. |
| 289 typedef std::vector<struct sock_filter> Program; | 64 typedef std::vector<struct sock_filter> Program; |
| 290 | 65 |
| 66 // Constructors and destructors. |
| 67 Sandbox(); |
| 68 ~Sandbox(); |
| 69 |
| 291 // Checks whether a particular system call number is valid on the current | 70 // Checks whether a particular system call number is valid on the current |
| 292 // architecture. E.g. on ARM there's a non-contiguous range of private | 71 // architecture. E.g. on ARM there's a non-contiguous range of private |
| 293 // system calls. | 72 // system calls. |
| 294 static bool IsValidSyscallNumber(int sysnum); | 73 static bool IsValidSyscallNumber(int sysnum); |
| 295 | 74 |
| 296 // There are a lot of reasons why the Seccomp sandbox might not be available. | 75 // There are a lot of reasons why the Seccomp sandbox might not be available. |
| 297 // This could be because the kernel does not support Seccomp mode, or it | 76 // This could be because the kernel does not support Seccomp mode, or it |
| 298 // could be because another sandbox is already active. | 77 // could be because another sandbox is already active. |
| 299 // "proc_fd" should be a file descriptor for "/proc", or -1 if not | 78 // "proc_fd" should be a file descriptor for "/proc", or -1 if not |
| 300 // provided by the caller. | 79 // provided by the caller. |
| 301 static SandboxStatus SupportsSeccompSandbox(int proc_fd); | 80 static SandboxStatus SupportsSeccompSandbox(int proc_fd); |
| 302 | 81 |
| 303 // The sandbox needs to be able to access files in "/proc/self". If this | 82 // The sandbox needs to be able to access files in "/proc/self". If this |
| 304 // directory is not accessible when "startSandbox()" gets called, the caller | 83 // directory is not accessible when "startSandbox()" gets called, the caller |
| 305 // can provide an already opened file descriptor by calling "set_proc_fd()". | 84 // can provide an already opened file descriptor by calling "set_proc_fd()". |
| 306 // The sandbox becomes the new owner of this file descriptor and will | 85 // The sandbox becomes the new owner of this file descriptor and will |
| 307 // eventually close it when "startSandbox()" executes. | 86 // eventually close it when "StartSandbox()" executes. |
| 308 static void set_proc_fd(int proc_fd); | 87 void set_proc_fd(int proc_fd); |
| 309 | 88 |
| 310 // The system call evaluator function is called with the system | 89 // The system call evaluator function is called with the system |
| 311 // call number. It can decide to allow the system call unconditionally | 90 // call number. It can decide to allow the system call unconditionally |
| 312 // by returning ERR_ALLOWED; it can deny the system call unconditionally by | 91 // by returning ERR_ALLOWED; it can deny the system call unconditionally by |
| 313 // returning an appropriate "errno" value; or it can request inspection | 92 // returning an appropriate "errno" value; or it can request inspection |
| 314 // of system call argument(s) by returning a suitable ErrorCode. | 93 // of system call argument(s) by returning a suitable ErrorCode. |
| 315 // The "aux" parameter can be used to pass optional data to the system call | 94 // The "aux" parameter can be used to pass optional data to the system call |
| 316 // evaluator. There are different possible uses for this data, but one of the | 95 // evaluator. There are different possible uses for this data, but one of the |
| 317 // use cases would be for the policy to then forward this pointer to a Trap() | 96 // use cases would be for the policy to then forward this pointer to a Trap() |
| 318 // handler. In this case, of course, the data that is pointed to must remain | 97 // handler. In this case, of course, the data that is pointed to must remain |
| 319 // valid for the entire time that Trap() handlers can be called; typically, | 98 // valid for the entire time that Trap() handlers can be called; typically, |
| 320 // this would be the lifetime of the program. | 99 // this would be the lifetime of the program. |
| 321 static void SetSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); | 100 void SetSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); |
| 322 | 101 |
| 323 // We can use ErrorCode to request calling of a trap handler. This method | 102 // We can use ErrorCode to request calling of a trap handler. This method |
| 324 // performs the required wrapping of the callback function into an | 103 // performs the required wrapping of the callback function into an |
| 325 // ErrorCode object. | 104 // ErrorCode object. |
| 326 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall | 105 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall |
| 327 // for a description of how to pass data from setSandboxPolicy() to a Trap() | 106 // for a description of how to pass data from SetSandboxPolicy() to a Trap() |
| 328 // handler. | 107 // handler. |
| 329 static ErrorCode Trap(Trap::TrapFnc fnc, const void *aux); | 108 ErrorCode Trap(Trap::TrapFnc fnc, const void *aux); |
| 330 | 109 |
| 331 // Calls a user-space trap handler and disables all sandboxing for system | 110 // Calls a user-space trap handler and disables all sandboxing for system |
| 332 // calls made from this trap handler. | 111 // calls made from this trap handler. |
| 333 // This feature is available only if explicitly enabled by the user having | 112 // This feature is available only if explicitly enabled by the user having |
| 334 // set the CHROME_SANDBOX_DEBUGGING environment variable. | 113 // set the CHROME_SANDBOX_DEBUGGING environment variable. |
| 335 // Returns an ET_INVALID ErrorCode, if called when not enabled. | 114 // Returns an ET_INVALID ErrorCode, if called when not enabled. |
| 336 // NOTE: This feature, by definition, disables all security features of | 115 // NOTE: This feature, by definition, disables all security features of |
| 337 // the sandbox. It should never be used in production, but it can be | 116 // the sandbox. It should never be used in production, but it can be |
| 338 // very useful to diagnose code that is incompatible with the sandbox. | 117 // very useful to diagnose code that is incompatible with the sandbox. |
| 339 // If even a single system call returns "UnsafeTrap", the security of | 118 // If even a single system call returns "UnsafeTrap", the security of |
| 340 // entire sandbox should be considered compromised. | 119 // entire sandbox should be considered compromised. |
| 341 static ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void *aux); | 120 ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void *aux); |
| 342 | 121 |
| 343 // From within an UnsafeTrap() it is often useful to be able to execute | 122 // From within an UnsafeTrap() it is often useful to be able to execute |
| 344 // the system call that triggered the trap. The ForwardSyscall() method | 123 // the system call that triggered the trap. The ForwardSyscall() method |
| 345 // makes this easy. It is more efficient than calling glibc's syscall() | 124 // makes this easy. It is more efficient than calling glibc's syscall() |
| 346 // function, as it avoid the extra round-trip to the signal handler. And | 125 // function, as it avoid the extra round-trip to the signal handler. And |
| 347 // it automatically does the correct thing to report kernel-style error | 126 // it automatically does the correct thing to report kernel-style error |
| 348 // conditions, rather than setting errno. See the comments for TrapFnc for | 127 // conditions, rather than setting errno. See the comments for TrapFnc for |
| 349 // details. In other words, the return value from ForwardSyscall() is | 128 // details. In other words, the return value from ForwardSyscall() is |
| 350 // directly suitable as a return value for a trap handler. | 129 // directly suitable as a return value for a trap handler. |
| 351 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); | 130 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); |
| 352 | 131 |
| 353 // We can also use ErrorCode to request evaluation of a conditional | 132 // We can also use ErrorCode to request evaluation of a conditional |
| 354 // statement based on inspection of system call parameters. | 133 // statement based on inspection of system call parameters. |
| 355 // This method wrap an ErrorCode object around the conditional statement. | 134 // This method wrap an ErrorCode object around the conditional statement. |
| 356 // Argument "argno" (1..6) will be compared to "value" using comparator | 135 // Argument "argno" (1..6) will be compared to "value" using comparator |
| 357 // "op". If the condition is true "passed" will be returned, otherwise | 136 // "op". If the condition is true "passed" will be returned, otherwise |
| 358 // "failed". | 137 // "failed". |
| 359 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) | 138 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) |
| 360 // If it is outside this range, the sandbox treats the system call just | 139 // If it is outside this range, the sandbox treats the system call just |
| 361 // the same as any other ABI violation (i.e. it aborts with an error | 140 // the same as any other ABI violation (i.e. it aborts with an error |
| 362 // message). | 141 // message). |
| 363 static ErrorCode Cond(int argno, ErrorCode::ArgType is_32bit, | 142 ErrorCode Cond(int argno, ErrorCode::ArgType is_32bit, |
| 364 ErrorCode::Operation op, | 143 ErrorCode::Operation op, |
| 365 uint64_t value, const ErrorCode& passed, | 144 uint64_t value, const ErrorCode& passed, |
| 366 const ErrorCode& failed); | 145 const ErrorCode& failed); |
| 367 | 146 |
| 368 // Kill the program and print an error message. | 147 // Kill the program and print an error message. |
| 369 static ErrorCode Kill(const char *msg); | 148 ErrorCode Kill(const char *msg); |
| 370 | 149 |
| 371 // This is the main public entry point. It finds all system calls that | 150 // This is the main public entry point. It finds all system calls that |
| 372 // need rewriting, sets up the resources needed by the sandbox, and | 151 // need rewriting, sets up the resources needed by the sandbox, and |
| 373 // enters Seccomp mode. | 152 // enters Seccomp mode. |
| 374 static void StartSandbox() { StartSandboxInternal(false); } | 153 // It is possible to stack multiple sandboxes by creating separate "Sandbox" |
| 154 // objects and calling "StartSandbox()" on each of them. Please note, that |
| 155 // this requires special care, though, as newly stacked sandboxes can never |
| 156 // relax restrictions imposed by earlier sandboxes. Furthermore, installing |
| 157 // a new policy requires making system calls, that might already be |
| 158 // disallowed. |
| 159 // Finally, stacking does add more kernel overhead than having a single |
| 160 // combined policy. So, it should only be used if there are no alternatives. |
| 161 void StartSandbox(); |
| 375 | 162 |
| 376 // Assembles a BPF filter program from the current policy. After calling this | 163 // Assembles a BPF filter program from the current policy. After calling this |
| 377 // function, you must not call any other sandboxing function. | 164 // function, you must not call any other sandboxing function. |
| 378 // Typically, AssembleFilter() is only used by unit tests and by sandbox | 165 // Typically, AssembleFilter() is only used by unit tests and by sandbox |
| 379 // internals. It should not be used by production code. | 166 // internals. It should not be used by production code. |
| 380 // For performance reasons, we normally only run the assembled BPF program | 167 // For performance reasons, we normally only run the assembled BPF program |
| 381 // through the verifier, iff the program was built in debug mode. | 168 // through the verifier, iff the program was built in debug mode. |
| 382 // But by setting "force_verification", the caller can request that the | 169 // But by setting "force_verification", the caller can request that the |
| 383 // verifier is run unconditionally. This is useful for unittests. | 170 // verifier is run unconditionally. This is useful for unittests. |
| 384 static Program *AssembleFilter(bool force_verification); | 171 Program *AssembleFilter(bool force_verification); |
| 172 |
| 173 // Returns the fatal ErrorCode that is used to indicate that somebody |
| 174 // attempted to pass a 64bit value in a 32bit system call argument. |
| 175 // This method is primarily needed for testing purposes. |
| 176 ErrorCode Unexpected64bitArgument(); |
| 385 | 177 |
| 386 private: | 178 private: |
| 387 friend class CodeGen; | 179 friend class CodeGen; |
| 388 friend class SandboxUnittestHelper; | 180 friend class SandboxUnittestHelper; |
| 389 friend class ErrorCode; | 181 friend class ErrorCode; |
| 390 friend class Util; | |
| 391 friend class Verifier; | |
| 392 | 182 |
| 393 struct Range { | 183 struct Range { |
| 394 Range(uint32_t f, uint32_t t, const ErrorCode& e) | 184 Range(uint32_t f, uint32_t t, const ErrorCode& e) |
| 395 : from(f), | 185 : from(f), |
| 396 to(t), | 186 to(t), |
| 397 err(e) { | 187 err(e) { |
| 398 } | 188 } |
| 399 uint32_t from, to; | 189 uint32_t from, to; |
| 400 ErrorCode err; | 190 ErrorCode err; |
| 401 }; | 191 }; |
| 402 typedef std::vector<Range> Ranges; | 192 typedef std::vector<Range> Ranges; |
| 403 typedef std::map<uint32_t, ErrorCode> ErrMap; | 193 typedef std::map<uint32_t, ErrorCode> ErrMap; |
| 404 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; | 194 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; |
| 405 | 195 |
| 406 // Get a file descriptor pointing to "/proc", if currently available. | 196 // Get a file descriptor pointing to "/proc", if currently available. |
| 407 static int proc_fd() { return proc_fd_; } | 197 int proc_fd() { return proc_fd_; } |
| 408 | 198 |
| 409 static ErrorCode ProbeEvaluator(int sysnum, void *) __attribute__((const)); | 199 // Creates a subprocess and runs "code_in_sandbox" inside of the specified |
| 410 static void ProbeProcess(void); | 200 // policy. The caller has to make sure that "this" has not yet been |
| 411 static ErrorCode AllowAllEvaluator(int sysnum, void *aux); | 201 // initialized with any other policies. |
| 412 static void TryVsyscallProcess(void); | 202 bool RunFunctionInPolicy(void (*code_in_sandbox)(), |
| 413 static bool KernelSupportSeccompBPF(int proc_fd); | 203 EvaluateSyscall syscall_evaluator, void *aux); |
| 414 static bool RunFunctionInPolicy(void (*function)(), | |
| 415 EvaluateSyscall syscall_evaluator, | |
| 416 void *aux, | |
| 417 int proc_fd); | |
| 418 static void StartSandboxInternal(bool quiet); | |
| 419 static bool IsSingleThreaded(int proc_fd); | |
| 420 static bool IsDenied(const ErrorCode& code); | |
| 421 static bool DisableFilesystem(); | |
| 422 static void PolicySanityChecks(EvaluateSyscall syscall_evaluator, | |
| 423 void *aux); | |
| 424 | 204 |
| 425 // Function that can be passed as a callback function to CodeGen::Traverse(). | 205 // Performs a couple of sanity checks to verify that the kernel supports the |
| 426 // Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it | 206 // features that we need for successful sandboxing. |
| 427 // sets the "bool" variable pointed to by "aux". | 207 // The caller has to make sure that "this" has not yet been initialized with |
| 428 static void CheckForUnsafeErrorCodes(Instruction *insn, void *aux); | 208 // any other policies. |
| 209 bool KernelSupportSeccompBPF(); |
| 429 | 210 |
| 430 // Function that can be passed as a callback function to CodeGen::Traverse(). | 211 // Verify that the current policy passes some basic sanity checks. |
| 431 // Checks whether the "insn" returns an errno value from a BPF filter. If so, | 212 void PolicySanityChecks(EvaluateSyscall syscall_evaluator, void *aux); |
| 432 // it rewrites the instruction to instead call a Trap() handler that does | |
| 433 // the same thing. "aux" is ignored. | |
| 434 static void RedirectToUserspace(Instruction *insn, void *aux); | |
| 435 | |
| 436 // Stackable wrapper around an Evaluators handler. Changes ErrorCodes | |
| 437 // returned by a system call evaluator to match the changes made by | |
| 438 // RedirectToUserspace(). "aux" should be pointer to wrapped system call | |
| 439 // evaluator. | |
| 440 static ErrorCode RedirectToUserspaceEvalWrapper(int sysnum, void *aux); | |
| 441 | 213 |
| 442 // Assembles and installs a filter based on the policy that has previously | 214 // Assembles and installs a filter based on the policy that has previously |
| 443 // been configured with SetSandboxPolicy(). | 215 // been configured with SetSandboxPolicy(). |
| 444 static void InstallFilter(bool quiet); | 216 void InstallFilter(); |
| 445 | 217 |
| 446 // Verify the correctness of a compiled program by comparing it against the | 218 // Verify the correctness of a compiled program by comparing it against the |
| 447 // current policy. This function should only ever be called by unit tests and | 219 // current policy. This function should only ever be called by unit tests and |
| 448 // by the sandbox internals. It should not be used by production code. | 220 // by the sandbox internals. It should not be used by production code. |
| 449 static void VerifyProgram(const Program& program, bool has_unsafe_traps); | 221 void VerifyProgram(const Program& program, bool has_unsafe_traps); |
| 450 | 222 |
| 451 // Finds all the ranges of system calls that need to be handled. Ranges are | 223 // Finds all the ranges of system calls that need to be handled. Ranges are |
| 452 // sorted in ascending order of system call numbers. There are no gaps in the | 224 // sorted in ascending order of system call numbers. There are no gaps in the |
| 453 // ranges. System calls with identical ErrorCodes are coalesced into a single | 225 // ranges. System calls with identical ErrorCodes are coalesced into a single |
| 454 // range. | 226 // range. |
| 455 static void FindRanges(Ranges *ranges); | 227 void FindRanges(Ranges *ranges); |
| 456 | 228 |
| 457 // Returns a BPF program snippet that implements a jump table for the | 229 // Returns a BPF program snippet that implements a jump table for the |
| 458 // given range of system call numbers. This function runs recursively. | 230 // given range of system call numbers. This function runs recursively. |
| 459 static Instruction *AssembleJumpTable(CodeGen *gen, | 231 Instruction *AssembleJumpTable(CodeGen *gen, |
| 460 Ranges::const_iterator start, | 232 Ranges::const_iterator start, |
| 461 Ranges::const_iterator stop); | 233 Ranges::const_iterator stop); |
| 462 | 234 |
| 463 // Returns a BPF program snippet that makes the BPF filter program exit | 235 // Returns a BPF program snippet that makes the BPF filter program exit |
| 464 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a | 236 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a |
| 465 // conditional expression; if so, this function will recursively call | 237 // conditional expression; if so, this function will recursively call |
| 466 // CondExpression() and possibly RetExpression() to build a complex set of | 238 // CondExpression() and possibly RetExpression() to build a complex set of |
| 467 // instructions. | 239 // instructions. |
| 468 static Instruction *RetExpression(CodeGen *gen, const ErrorCode& err); | 240 Instruction *RetExpression(CodeGen *gen, const ErrorCode& err); |
| 469 | 241 |
| 470 // Returns a BPF program that evaluates the conditional expression in | 242 // Returns a BPF program that evaluates the conditional expression in |
| 471 // "cond" and returns the appropriate value from the BPF filter program. | 243 // "cond" and returns the appropriate value from the BPF filter program. |
| 472 // This function recursively calls RetExpression(); it should only ever be | 244 // This function recursively calls RetExpression(); it should only ever be |
| 473 // called from RetExpression(). | 245 // called from RetExpression(). |
| 474 static Instruction *CondExpression(CodeGen *gen, const ErrorCode& cond); | 246 Instruction *CondExpression(CodeGen *gen, const ErrorCode& cond); |
| 475 | |
| 476 // Returns the fatal ErrorCode that is used to indicate that somebody | |
| 477 // attempted to pass a 64bit value in a 32bit system call argument. | |
| 478 static ErrorCode Unexpected64bitArgument(); | |
| 479 | |
| 480 // A Trap() handler that returns an "errno" value. The value is encoded | |
| 481 // in the "aux" parameter. | |
| 482 static intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux); | |
| 483 | |
| 484 static intptr_t BpfFailure(const struct arch_seccomp_data& data, void *aux); | |
| 485 | 247 |
| 486 static SandboxStatus status_; | 248 static SandboxStatus status_; |
| 487 static int proc_fd_; | |
| 488 static Evaluators evaluators_; | |
| 489 static Conds conds_; | |
| 490 | 249 |
| 491 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); | 250 bool quiet_; |
| 251 int proc_fd_; |
| 252 Evaluators *evaluators_; |
| 253 Conds *conds_; |
| 254 |
| 255 DISALLOW_COPY_AND_ASSIGN(Sandbox); |
| 492 }; | 256 }; |
| 493 | 257 |
| 494 } // namespace | 258 } // namespace |
| 495 | 259 |
| 496 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 260 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| OLD | NEW |