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 <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 <stddef.h> |
| 20 #include <stdint.h> |
| 21 #include <stdio.h> |
| 22 #include <stdlib.h> |
| 23 #include <string.h> |
| 24 #include <sys/ioctl.h> |
| 25 #include <sys/ipc.h> |
| 26 #include <sys/mman.h> |
| 27 #include <sys/prctl.h> |
| 28 #include <sys/shm.h> |
| 29 #include <sys/stat.h> |
| 30 #include <sys/types.h> |
| 31 #include <sys/uio.h> |
| 32 #include <sys/wait.h> |
| 33 #include <unistd.h> |
| 34 |
| 35 #include <algorithm> |
| 36 #include <utility> |
| 37 #include <vector> |
| 38 |
| 39 #ifndef SECCOMP_BPF_STANDALONE |
| 40 #include "base/basictypes.h" |
| 41 #include "base/eintr_wrapper.h" |
| 42 #include "base/logging.h" |
| 43 #endif |
| 44 |
| 45 // The Seccomp2 kernel ABI is not part of older versions of glibc. |
| 46 // As we can't break compilation with these versions of the library, |
| 47 // we explicitly define all missing symbols. |
| 48 |
| 49 #ifndef PR_SET_NO_NEW_PRIVS |
| 50 #define PR_SET_NO_NEW_PRIVS 38 |
| 51 #define PR_GET_NO_NEW_PRIVS 39 |
| 52 #endif |
| 53 #ifndef IPC_64 |
| 54 #define IPC_64 0x0100 |
| 55 #endif |
| 56 #ifndef SECCOMP_MODE_FILTER |
| 57 #define SECCOMP_MODE_DISABLED 0 |
| 58 #define SECCOMP_MODE_STRICT 1 |
| 59 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter |
| 60 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately |
| 61 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS |
| 62 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno |
| 63 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow |
| 64 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow |
| 65 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value |
| 66 #define SECCOMP_RET_DATA 0x0000ffffU // sections |
| 67 #endif |
| 68 #define SECCOMP_DENY_ERRNO EPERM |
| 69 #ifndef SYS_SECCOMP |
| 70 #define SYS_SECCOMP 1 |
| 71 #endif |
| 72 |
| 73 #if defined(__i386__) |
| 74 #define MIN_SYSCALL 0 |
| 75 #define MAX_SYSCALL 512 |
| 76 #define SECCOMP_ARCH AUDIT_ARCH_I386 |
| 77 #define REG_RESULT REG_EAX |
| 78 #define REG_SYSCALL REG_EAX |
| 79 #define REG_PARM1 REG_EBX |
| 80 #define REG_PARM2 REG_ECX |
| 81 #define REG_PARM3 REG_EDX |
| 82 #define REG_PARM4 REG_ESI |
| 83 #define REG_PARM5 REG_EDI |
| 84 #define REG_PARM6 REG_EBP |
| 85 #elif defined(__x86_64__) |
| 86 #define MIN_SYSCALL 0 |
| 87 #define MAX_SYSCALL 512 |
| 88 #define SECCOMP_ARCH AUDIT_ARCH_X86_64 |
| 89 #define REG_RESULT REG_RAX |
| 90 #define REG_SYSCALL REG_RAX |
| 91 #define REG_PARM1 REG_RDI |
| 92 #define REG_PARM2 REG_RSI |
| 93 #define REG_PARM3 REG_RDX |
| 94 #define REG_PARM4 REG_R10 |
| 95 #define REG_PARM5 REG_R8 |
| 96 #define REG_PARM6 REG_R9 |
| 97 #else |
| 98 #error Unsupported target platform |
| 99 #endif |
| 100 |
| 101 struct arch_seccomp_data { |
| 102 int nr; |
| 103 uint32_t arch; |
| 104 uint64_t instruction_pointer; |
| 105 uint64_t args[6]; |
| 106 }; |
| 107 |
| 108 #ifdef SECCOMP_BPF_STANDALONE |
| 109 #define arraysize(x) sizeof(x)/sizeof(*(x))) |
| 110 #define HANDLE_EINTR TEMP_FAILURE_RETRY |
| 111 #endif |
| 112 |
| 113 |
| 114 namespace playground2 { |
| 115 |
| 116 class Sandbox { |
| 117 friend class Util; |
| 118 |
| 119 public: |
| 120 enum SandboxStatus { |
| 121 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() |
| 122 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing |
| 123 STATUS_UNAVAILABLE, // Currently unavailable but might work again later |
| 124 STATUS_AVAILABLE, // Sandboxing is available but not currently active |
| 125 STATUS_ENABLED // The sandbox is now active |
| 126 }; |
| 127 |
| 128 enum ErrorCode { |
| 129 SB_TRAP = -1, |
| 130 SB_ALLOWED = 0x0000, |
| 131 SB_INSPECT_ARG_1 = 0x8001, |
| 132 SB_INSPECT_ARG_2 = 0x8002, |
| 133 SB_INSPECT_ARG_3 = 0x8004, |
| 134 SB_INSPECT_ARG_4 = 0x8008, |
| 135 SB_INSPECT_ARG_5 = 0x8010, |
| 136 SB_INSPECT_ARG_6 = 0x8020 |
| 137 }; |
| 138 |
| 139 enum Operation { |
| 140 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, |
| 141 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, |
| 142 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS |
| 143 }; |
| 144 |
| 145 struct Constraint { |
| 146 bool is32bit; |
| 147 Operation op; |
| 148 uint32_t value; |
| 149 ErrorCode passed; |
| 150 ErrorCode failed; |
| 151 }; |
| 152 |
| 153 typedef ErrorCode (*EvaluateSyscall)(int sysno); |
| 154 typedef int (*EvaluateArguments)(int sysno, int arg, |
| 155 Constraint *constraint); |
| 156 |
| 157 // There are a lot of reasons why the Seccomp sandbox might not be available. |
| 158 // This could be because the kernel does not support Seccomp mode, or it |
| 159 // could be because another sandbox is already active. |
| 160 // "proc_fd" should be a file descriptor for "/proc", or -1 if not |
| 161 // provided by the caller. |
| 162 static SandboxStatus supportsSeccompSandbox(int proc_fd); |
| 163 |
| 164 // The sandbox needs to be able to access files in "/proc/self". If this |
| 165 // directory is not accessible when "startSandbox()" gets called, the caller |
| 166 // can provide an already opened file descriptor by calling "setProcFd()". |
| 167 // The sandbox becomes the new owner of this file descriptor and will |
| 168 // eventually close it when "startSandbox()" executes. |
| 169 static void setProcFd(int proc_fd); |
| 170 |
| 171 // The system call evaluator function is called with the system |
| 172 // call number. It can decide to allow the system call unconditionally |
| 173 // by returning "0"; it can deny the system call unconditionally by |
| 174 // returning an appropriate "errno" value; or it can request inspection |
| 175 // of system call argument(s) by returning a suitable combination of |
| 176 // SB_INSPECT_ARG_x bits. |
| 177 // The system argument evaluator is called (if needed) to query additional |
| 178 // constraints for the system call arguments. In the vast majority of |
| 179 // cases, it will set a "Constraint" that forces a new "errno" value. |
| 180 // But for more complex filters, it is possible to return another mask |
| 181 // of SB_INSPECT_ARG_x bits. |
| 182 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, |
| 183 EvaluateArguments argumentEvaluator); |
| 184 |
| 185 // This is the main public entry point. It finds all system calls that |
| 186 // need rewriting, sets up the resources needed by the sandbox, and |
| 187 // enters Seccomp mode. |
| 188 static void startSandbox(); |
| 189 |
| 190 protected: |
| 191 // Print an error message and terminate the program. Used for fatal errors. |
| 192 static void die(const char *msg) __attribute__((noreturn)) { |
| 193 if (!suppressLogging_) { |
| 194 #ifdef SECCOMP_BPF_STANDALONE |
| 195 if (msg) { |
| 196 HANDLE_EINTR(write(2, msg, strlen(msg))); |
| 197 HANDLE_EINTR(write(2, "\n", 1)); |
| 198 } |
| 199 #else |
| 200 LOG(FATAL) << msg; |
| 201 #endif |
| 202 } |
| 203 for (;;) { |
| 204 // exit_group() should exit our program. After all, it is defined as a |
| 205 // function that doesn't return. But things can theoretically go wrong. |
| 206 // Especially, since we are dealing with system call filters. Continuing |
| 207 // execution would be very bad in most cases where die() gets called. |
| 208 // So, if there is no way for us to ask for the program to exit, the next |
| 209 // best thing we can do is to loop indefinitely. Maybe, somebody will |
| 210 // notice and file a bug... |
| 211 syscall(__NR_exit_group, 1); |
| 212 _exit(1); |
| 213 } |
| 214 } |
| 215 |
| 216 // Get a file descriptor pointing to "/proc", if currently available. |
| 217 static int getProcFd() { return proc_fd_; } |
| 218 |
| 219 private: |
| 220 static bool isSingleThreaded(int proc_fd); |
| 221 static bool disableFilesystem(); |
| 222 static void installFilter(); |
| 223 static void sigSys(int nr, siginfo_t *info, void *void_context); |
| 224 |
| 225 static bool suppressLogging_; |
| 226 static SandboxStatus status_; |
| 227 static int proc_fd_; |
| 228 static std::vector<std::pair<EvaluateSyscall, |
| 229 EvaluateArguments> > evaluators_; |
| 230 }; |
| 231 |
| 232 } // namespace |
| 233 |
| 234 #endif // SANDBOX_BPF_H__ |
OLD | NEW |