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_BPF_H__ |
| 6 #define SANDBOX_BPF_H__ |
| 7 |
| 8 #include <algorithm> |
| 9 #include <endian.h> |
| 10 #include <errno.h> |
| 11 #include <fcntl.h> |
| 12 #include <linux/audit.h> |
| 13 #include <linux/filter.h> |
| 14 //#include <linux/seccomp.h> |
| 15 #include <linux/unistd.h> |
| 16 #include <netinet/in.h> |
| 17 #include <netinet/tcp.h> |
| 18 #include <netinet/udp.h> |
| 19 #include <sched.h> |
| 20 #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/shm.h> |
| 30 #include <sys/stat.h> |
| 31 #include <sys/types.h> |
| 32 #include <sys/uio.h> |
| 33 #include <sys/wait.h> |
| 34 #include <unistd.h> |
| 35 #include <vector> |
| 36 |
| 37 #include "util.h" |
| 38 |
| 39 |
| 40 // The Seccomp2 kernel ABI is not part of older versions of glibc. |
| 41 // As we can't break compilation with these versions of the library, |
| 42 // we explicitly define all missing symbols. |
| 43 |
| 44 #ifndef PR_SET_NO_NEW_PRIVS |
| 45 #define PR_SET_NO_NEW_PRIVS 38 |
| 46 #define PR_GET_NO_NEW_PRIVS 39 |
| 47 #endif |
| 48 #ifndef IPC_64 |
| 49 #define IPC_64 0x0100 |
| 50 #endif |
| 51 #ifndef SECCOMP_MODE_FILTER |
| 52 #define SECCOMP_MODE_DISABLED 0 |
| 53 #define SECCOMP_MODE_STRICT 1 |
| 54 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter |
| 55 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately |
| 56 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS |
| 57 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno |
| 58 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow |
| 59 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow |
| 60 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value |
| 61 #define SECCOMP_RET_DATA 0x0000ffffU // sections |
| 62 #endif |
| 63 #define SECCOMP_RET_DENY (SECCOMP_RET_ERRNO|EPERM) |
| 64 #ifndef SYS_SECCOMP |
| 65 #define SYS_SECCOMP 1 |
| 66 #endif |
| 67 |
| 68 #if defined(__i386__) |
| 69 #define MAX_SYSCALL 512 |
| 70 #define SECCOMP_ARCH AUDIT_ARCH_I386 |
| 71 #define REG_RESULT REG_EAX |
| 72 #define REG_SYSCALL REG_EAX |
| 73 #define REG_PARM1 REG_EBX |
| 74 #define REG_PARM2 REG_ECX |
| 75 #define REG_PARM3 REG_EDX |
| 76 #define REG_PARM4 REG_ESI |
| 77 #define REG_PARM5 REG_EDI |
| 78 #define REG_PARM6 REG_EBP |
| 79 #elif defined(__x86_64__) |
| 80 #define MAX_SYSCALL 512 |
| 81 #define SECCOMP_ARCH AUDIT_ARCH_X86_64 |
| 82 #define REG_RESULT REG_RAX |
| 83 #define REG_SYSCALL REG_RAX |
| 84 #define REG_PARM1 REG_RDI |
| 85 #define REG_PARM2 REG_RSI |
| 86 #define REG_PARM3 REG_RDX |
| 87 #define REG_PARM4 REG_R10 |
| 88 #define REG_PARM5 REG_R8 |
| 89 #define REG_PARM6 REG_R9 |
| 90 #else |
| 91 #define Unsupported target platform |
| 92 #endif |
| 93 |
| 94 struct arch_seccomp_data { |
| 95 int nr; |
| 96 uint32_t arch; |
| 97 uint64_t instruction_pointer; |
| 98 uint64_t args[6]; |
| 99 }; |
| 100 |
| 101 |
| 102 #define ARRAYSIZE(x) \ |
| 103 (int)(sizeof(x)/sizeof(*(x))) |
| 104 |
| 105 |
| 106 namespace playground2 { |
| 107 |
| 108 class Sandbox { |
| 109 friend class Util; |
| 110 |
| 111 public: |
| 112 enum ErrorCode { |
| 113 SB_TRAP = -1, |
| 114 SB_ALLOWED = 0x0000, |
| 115 SB_INSPECT_ARG_1 = 0x8001, |
| 116 SB_INSPECT_ARG_2 = 0x8002, |
| 117 SB_INSPECT_ARG_3 = 0x8004, |
| 118 SB_INSPECT_ARG_4 = 0x8008, |
| 119 SB_INSPECT_ARG_5 = 0x8010, |
| 120 SB_INSPECT_ARG_6 = 0x8020 |
| 121 }; |
| 122 |
| 123 enum Operation { |
| 124 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, |
| 125 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, |
| 126 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS |
| 127 }; |
| 128 |
| 129 struct Constraint { |
| 130 bool is32bit; |
| 131 Operation op; |
| 132 uint32_t value; |
| 133 ErrorCode passed; |
| 134 ErrorCode failed; |
| 135 }; |
| 136 |
| 137 typedef ErrorCode (*EvaluateSyscall)(int sysno); |
| 138 typedef int (*EvaluateArguments)(int sysno, int arg, |
| 139 Constraint *constraint); |
| 140 |
| 141 // There are a lot of reasons why the Seccomp sandbox might not be available. |
| 142 // This could be because the kernel does not support Seccomp mode, or it |
| 143 // could be because another sandbox is already active. |
| 144 // "proc_fd" should be a file descriptor for "/proc", or -1 if not |
| 145 // provided by the caller. |
| 146 static int supportsSeccompSandbox(int proc_fd) |
| 147 asm("SupportsSeccomp2Sandbox"); |
| 148 |
| 149 // The sandbox needs to be able to access files in "/proc/self". If this |
| 150 // directory is not accessible when "startSandbox()" gets called, the caller |
| 151 // can provide an already opened file descriptor by calling "setProcFd()". |
| 152 // The sandbox becomes the newer owner of this file descriptor and will |
| 153 // eventually close it when "startSandbox()" executes. |
| 154 static void setProcFd(int proc_fd) asm("Seccomp2SandboxSetProcFd"); |
| 155 |
| 156 // This is the main public entry point. It finds all system calls that |
| 157 // need rewriting, sets up the resources needed by the sandbox, and |
| 158 // enters Seccomp mode. |
| 159 static void startSandbox() asm("StartSeccomp2Sandbox"); |
| 160 |
| 161 // This optional call can be used to provide a non-standard sandbox |
| 162 // policy. |
| 163 // The system call evaluator function is called with the system |
| 164 // call number. It can decide to allow the system call unconditionally |
| 165 // by returning "0"; it can deny the system call unconditionally by |
| 166 // returning an appropriate "errno" value; or it can request inspection |
| 167 // of system call argument(s) by returning a suitable combination of |
| 168 // SB_INSPECT_ARG_x bits. |
| 169 // The system argument evaluator is called (if needed) to query additional |
| 170 // constraints for the system call arguments. In the vast majority of |
| 171 // cases, it will set a "Constraint" that forces a new "errno" value. |
| 172 // But for more complex filters, it is possible to return another mask |
| 173 // of SB_INSPECT_ARG_x bits. |
| 174 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, |
| 175 EvaluateArguments argumentEvaluator); |
| 176 |
| 177 protected: |
| 178 // Print an error message and terminate the program. Used for fatal errors. |
| 179 static void die(const char *msg = 0) __attribute__((noreturn)) { |
| 180 if (msg) { |
| 181 TEMP_FAILURE_RETRY(write(2, msg, strlen(msg))); |
| 182 TEMP_FAILURE_RETRY(write(2, "\n", 1)); |
| 183 } |
| 184 for (;;) { |
| 185 syscall(__NR_exit_group, 1); |
| 186 _exit(1); |
| 187 } |
| 188 } |
| 189 |
| 190 // Get a file descriptor pointing to "/proc", if currently available. |
| 191 static int getProcFd() { return proc_fd_; } |
| 192 |
| 193 private: |
| 194 enum SandboxStatus { |
| 195 STATUS_UNKNOWN, STATUS_UNSUPPORTED, STATUS_AVAILABLE, STATUS_ENABLED |
| 196 }; |
| 197 |
| 198 static bool isSingleThreaded(int proc_fd); |
| 199 static bool disableFilesystem(); |
| 200 static int jumpTableSize(int numSyscalls, bool recursing = false); |
| 201 static void verifyJumpTable(struct sock_filter *filter, int numInsn, |
| 202 const int *syscallList, int numSyscalls); |
| 203 static int jumpTable(struct sock_filter *filter, int *idx, |
| 204 const int *syscallList, int numSyscalls, |
| 205 int ret, bool sorted = false, |
| 206 bool recursing = false); |
| 207 static void installFilter(); |
| 208 static void sigSys(int nr, siginfo_t *info, void *void_context); |
| 209 |
| 210 static SandboxStatus status_; |
| 211 static int proc_fd_; |
| 212 static std::vector<std::pair<EvaluateSyscall, |
| 213 EvaluateArguments> > evaluators_; |
| 214 }; |
| 215 |
| 216 } // namespace |
| 217 |
| 218 #endif // SANDBOX_BPF_H__ |
OLD | NEW |