| 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_BPF_H__ | 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| 6 #define SANDBOX_BPF_H__ | 6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| 7 | 7 |
| 8 #include <endian.h> | 8 #include <endian.h> |
| 9 #include <errno.h> | 9 #include <errno.h> |
| 10 #include <fcntl.h> | 10 #include <fcntl.h> |
| 11 #include <linux/audit.h> | 11 #include <linux/audit.h> |
| 12 #include <linux/filter.h> | 12 #include <linux/filter.h> |
| 13 // #include <linux/seccomp.h> | 13 // #include <linux/seccomp.h> |
| 14 #include <linux/unistd.h> | 14 #include <linux/unistd.h> |
| 15 #include <netinet/in.h> | 15 #include <netinet/in.h> |
| 16 #include <netinet/tcp.h> | 16 #include <netinet/tcp.h> |
| (...skipping 21 matching lines...) Expand all Loading... |
| 38 #include <map> | 38 #include <map> |
| 39 #include <utility> | 39 #include <utility> |
| 40 #include <vector> | 40 #include <vector> |
| 41 | 41 |
| 42 #ifndef SECCOMP_BPF_STANDALONE | 42 #ifndef SECCOMP_BPF_STANDALONE |
| 43 #include "base/basictypes.h" | 43 #include "base/basictypes.h" |
| 44 #include "base/eintr_wrapper.h" | 44 #include "base/eintr_wrapper.h" |
| 45 #include "base/logging.h" | 45 #include "base/logging.h" |
| 46 #endif | 46 #endif |
| 47 | 47 |
| 48 #if defined(SECCOMP_BPF_VALGRIND_HACKS) |
| 49 #ifndef SECCOMP_BPF_STANDALONE |
| 50 #include "base/third_party/valgrind/valgrind.h" |
| 51 #endif |
| 52 #endif |
| 53 |
| 54 |
| 48 // The Seccomp2 kernel ABI is not part of older versions of glibc. | 55 // The Seccomp2 kernel ABI is not part of older versions of glibc. |
| 49 // As we can't break compilation with these versions of the library, | 56 // As we can't break compilation with these versions of the library, |
| 50 // we explicitly define all missing symbols. | 57 // we explicitly define all missing symbols. |
| 51 | 58 |
| 52 #ifndef PR_SET_NO_NEW_PRIVS | 59 #ifndef PR_SET_NO_NEW_PRIVS |
| 53 #define PR_SET_NO_NEW_PRIVS 38 | 60 #define PR_SET_NO_NEW_PRIVS 38 |
| 54 #define PR_GET_NO_NEW_PRIVS 39 | 61 #define PR_GET_NO_NEW_PRIVS 39 |
| 55 #endif | 62 #endif |
| 56 #ifndef IPC_64 | 63 #ifndef IPC_64 |
| 57 #define IPC_64 0x0100 | 64 #define IPC_64 0x0100 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) | 145 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) |
| 139 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) | 146 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) |
| 140 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) | 147 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) |
| 141 | 148 |
| 142 #else | 149 #else |
| 143 #error Unsupported target platform | 150 #error Unsupported target platform |
| 144 | 151 |
| 145 #endif | 152 #endif |
| 146 | 153 |
| 147 #include "sandbox/linux/seccomp-bpf/die.h" | 154 #include "sandbox/linux/seccomp-bpf/die.h" |
| 155 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
| 148 | 156 |
| 157 namespace playground2 { |
| 149 | 158 |
| 150 struct arch_seccomp_data { | 159 struct arch_seccomp_data { |
| 151 int nr; | 160 int nr; |
| 152 uint32_t arch; | 161 uint32_t arch; |
| 153 uint64_t instruction_pointer; | 162 uint64_t instruction_pointer; |
| 154 uint64_t args[6]; | 163 uint64_t args[6]; |
| 155 }; | 164 }; |
| 156 | 165 |
| 157 struct arch_sigsys { | 166 struct arch_sigsys { |
| 158 void *ip; | 167 void *ip; |
| 159 int nr; | 168 int nr; |
| 160 unsigned int arch; | 169 unsigned int arch; |
| 161 }; | 170 }; |
| 162 | 171 |
| 163 #ifdef SECCOMP_BPF_STANDALONE | 172 #if defined(SECCOMP_BPF_STANDALONE) |
| 164 #define arraysize(x) sizeof(x)/sizeof(*(x))) | 173 #define arraysize(x) sizeof(x)/sizeof(*(x))) |
| 165 #define HANDLE_EINTR TEMP_FAILURE_RETRY | 174 #define HANDLE_EINTR TEMP_FAILURE_RETRY |
| 166 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ | 175 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ |
| 167 TypeName(); \ | 176 TypeName(); \ |
| 168 TypeName(const TypeName&); \ | 177 TypeName(const TypeName&); \ |
| 169 void operator=(const TypeName&) | 178 void operator=(const TypeName&) |
| 170 #endif | 179 #endif |
| 171 | 180 |
| 172 | |
| 173 namespace playground2 { | |
| 174 | |
| 175 class Sandbox { | 181 class Sandbox { |
| 176 public: | 182 public: |
| 177 enum SandboxStatus { | 183 enum SandboxStatus { |
| 178 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() | 184 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() |
| 179 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing | 185 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing |
| 180 STATUS_UNAVAILABLE, // Currently unavailable but might work again later | 186 STATUS_UNAVAILABLE, // Currently unavailable but might work again later |
| 181 STATUS_AVAILABLE, // Sandboxing is available but not currently active | 187 STATUS_AVAILABLE, // Sandboxing is available but not currently active |
| 182 STATUS_ENABLED // The sandbox is now active | 188 STATUS_ENABLED // The sandbox is now active |
| 183 }; | 189 }; |
| 184 | 190 |
| 185 enum { | |
| 186 SB_INVALID = -1, | |
| 187 SB_ALLOWED = 0x0000, | |
| 188 SB_INSPECT_ARG_1 = 0x8001, | |
| 189 SB_INSPECT_ARG_2 = 0x8002, | |
| 190 SB_INSPECT_ARG_3 = 0x8004, | |
| 191 SB_INSPECT_ARG_4 = 0x8008, | |
| 192 SB_INSPECT_ARG_5 = 0x8010, | |
| 193 SB_INSPECT_ARG_6 = 0x8020 | |
| 194 }; | |
| 195 | |
| 196 // TrapFnc is a pointer to a function that handles Seccomp traps in | 191 // TrapFnc is a pointer to a function that handles Seccomp traps in |
| 197 // user-space. The seccomp policy can request that a trap handler gets | 192 // user-space. The seccomp policy can request that a trap handler gets |
| 198 // installed; it does so by returning a suitable ErrorCode() from the | 193 // installed; it does so by returning a suitable ErrorCode() from the |
| 199 // syscallEvaluator. See the ErrorCode() constructor for how to pass in | 194 // syscallEvaluator. See the ErrorCode() constructor for how to pass in |
| 200 // the function pointer. | 195 // the function pointer. |
| 201 // Please note that TrapFnc is executed from signal context and must be | 196 // Please note that TrapFnc is executed from signal context and must be |
| 202 // async-signal safe: | 197 // async-signal safe: |
| 203 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html | 198 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html |
| 204 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); | 199 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); |
| 205 | 200 |
| 206 class ErrorCode { | |
| 207 friend class Sandbox; | |
| 208 public: | |
| 209 // We can either wrap a symbolic ErrorCode (i.e. enum values), an errno | |
| 210 // value (in the range 1..4095), or a pointer to a TrapFnc callback | |
| 211 // handling a SECCOMP_RET_TRAP trap. | |
| 212 // All of these different values are stored in the "err_" field. So, code | |
| 213 // that is using the ErrorCode class typically operates on a single 32bit | |
| 214 // field. | |
| 215 // This is not only quiet efficient, it also makes the API really easy to | |
| 216 // use. | |
| 217 ErrorCode(int err = SB_INVALID) | |
| 218 : id_(0), | |
| 219 fnc_(NULL), | |
| 220 aux_(NULL) { | |
| 221 switch (err) { | |
| 222 case SB_INVALID: | |
| 223 err_ = SECCOMP_RET_INVALID; | |
| 224 break; | |
| 225 case SB_ALLOWED: | |
| 226 err_ = SECCOMP_RET_ALLOW; | |
| 227 break; | |
| 228 case SB_INSPECT_ARG_1...SB_INSPECT_ARG_6: | |
| 229 SANDBOX_DIE("Not implemented"); | |
| 230 break; | |
| 231 case 1 ... 4095: | |
| 232 err_ = SECCOMP_RET_ERRNO + err; | |
| 233 break; | |
| 234 default: | |
| 235 SANDBOX_DIE("Invalid use of ErrorCode object"); | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 // If we are wrapping a callback, we must assign a unique id. This id is | |
| 240 // how the kernel tells us which one of our different SECCOMP_RET_TRAP | |
| 241 // cases has been triggered. | |
| 242 // The getTrapId() function assigns one unique id (starting at 1) for | |
| 243 // each distinct pair of TrapFnc and auxiliary data. | |
| 244 ErrorCode(TrapFnc fnc, const void *aux, int id = 0) : | |
| 245 id_(id ? id : getTrapId(fnc, aux)), | |
| 246 fnc_(fnc), | |
| 247 aux_(const_cast<void *>(aux)), | |
| 248 err_(SECCOMP_RET_TRAP + id_) { | |
| 249 } | |
| 250 | |
| 251 // Destructor doesn't need to do anything. | |
| 252 ~ErrorCode() { } | |
| 253 | |
| 254 // Always return the value that goes into the BPF filter program. | |
| 255 operator uint32_t() const { return err_; } | |
| 256 | |
| 257 protected: | |
| 258 // Fields needed for SECCOMP_RET_TRAP callbacks | |
| 259 int id_; | |
| 260 TrapFnc fnc_; | |
| 261 void *aux_; | |
| 262 | |
| 263 // 32bit field used for all possible types of ErrorCode values | |
| 264 uint32_t err_; | |
| 265 }; | |
| 266 | |
| 267 enum Operation { | 201 enum Operation { |
| 268 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, | 202 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, |
| 269 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, | 203 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, |
| 270 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS | 204 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS |
| 271 }; | 205 }; |
| 272 | 206 |
| 273 struct Constraint { | 207 struct Constraint { |
| 274 bool is32bit; | 208 bool is32bit; |
| 275 Operation op; | 209 Operation op; |
| 276 uint32_t value; | 210 uint32_t value; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 304 // of system call argument(s) by returning a suitable combination of | 238 // of system call argument(s) by returning a suitable combination of |
| 305 // SB_INSPECT_ARG_x bits. | 239 // SB_INSPECT_ARG_x bits. |
| 306 // The system argument evaluator is called (if needed) to query additional | 240 // The system argument evaluator is called (if needed) to query additional |
| 307 // constraints for the system call arguments. In the vast majority of | 241 // constraints for the system call arguments. In the vast majority of |
| 308 // cases, it will set a "Constraint" that forces a new "errno" value. | 242 // cases, it will set a "Constraint" that forces a new "errno" value. |
| 309 // But for more complex filters, it is possible to return another mask | 243 // But for more complex filters, it is possible to return another mask |
| 310 // of SB_INSPECT_ARG_x bits. | 244 // of SB_INSPECT_ARG_x bits. |
| 311 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, | 245 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, |
| 312 EvaluateArguments argumentEvaluator); | 246 EvaluateArguments argumentEvaluator); |
| 313 | 247 |
| 248 // We can use ErrorCode to request calling of a trap handler. This method |
| 249 // performs the required wrapping of the callback function into an |
| 250 // ErrorCode object. |
| 251 static ErrorCode Trap(ErrorCode::TrapFnc fnc, const void *aux); |
| 252 |
| 253 // Kill the program and print an error message. |
| 254 static ErrorCode Kill(const char *msg); |
| 255 |
| 314 // This is the main public entry point. It finds all system calls that | 256 // This is the main public entry point. It finds all system calls that |
| 315 // need rewriting, sets up the resources needed by the sandbox, and | 257 // need rewriting, sets up the resources needed by the sandbox, and |
| 316 // enters Seccomp mode. | 258 // enters Seccomp mode. |
| 317 static void startSandbox() { startSandboxInternal(false); } | 259 static void startSandbox() { startSandboxInternal(false); } |
| 318 | 260 |
| 319 protected: | |
| 320 // Get a file descriptor pointing to "/proc", if currently available. | |
| 321 static int getProcFd() { return proc_fd_; } | |
| 322 | |
| 323 private: | 261 private: |
| 262 friend class ErrorCode; |
| 324 friend class Util; | 263 friend class Util; |
| 325 friend class Verifier; | 264 friend class Verifier; |
| 265 |
| 266 |
| 326 struct Range { | 267 struct Range { |
| 327 Range(uint32_t f, uint32_t t, const ErrorCode& e) : | 268 Range(uint32_t f, uint32_t t, const ErrorCode& e) : |
| 328 from(f), | 269 from(f), |
| 329 to(t), | 270 to(t), |
| 330 err(e) { | 271 err(e) { |
| 331 } | 272 } |
| 332 uint32_t from, to; | 273 uint32_t from, to; |
| 333 ErrorCode err; | 274 ErrorCode err; |
| 334 }; | 275 }; |
| 335 struct FixUp { | 276 struct FixUp { |
| 336 FixUp(unsigned int a, bool j) : | 277 FixUp(unsigned int a, bool j) : |
| 337 jt(j), addr(a) { } | 278 jt(j), addr(a) { } |
| 338 bool jt:1; | 279 bool jt:1; |
| 339 unsigned addr:31; | 280 unsigned addr:31; |
| 340 }; | 281 }; |
| 341 typedef std::vector<Range> Ranges; | 282 typedef std::vector<Range> Ranges; |
| 342 typedef std::map<uint32_t, std::vector<FixUp> > RetInsns; | 283 typedef std::map<uint32_t, std::vector<FixUp> > RetInsns; |
| 343 typedef std::vector<struct sock_filter> Program; | 284 typedef std::vector<struct sock_filter> Program; |
| 285 typedef std::map<uint32_t, ErrorCode> ErrMap; |
| 344 typedef std::vector<ErrorCode> Traps; | 286 typedef std::vector<ErrorCode> Traps; |
| 345 typedef std::map<std::pair<TrapFnc, const void *>, int> TrapIds; | 287 typedef std::map<std::pair<TrapFnc, const void *>, int> TrapIds; |
| 346 | 288 |
| 289 // Get a file descriptor pointing to "/proc", if currently available. |
| 290 static int proc_fd() { return proc_fd_; } |
| 291 |
| 347 static ErrorCode probeEvaluator(int signo) __attribute__((const)); | 292 static ErrorCode probeEvaluator(int signo) __attribute__((const)); |
| 348 static void probeProcess(void); | 293 static void probeProcess(void); |
| 349 static ErrorCode allowAllEvaluator(int signo); | 294 static ErrorCode allowAllEvaluator(int signo); |
| 350 static void tryVsyscallProcess(void); | 295 static void tryVsyscallProcess(void); |
| 351 static bool kernelSupportSeccompBPF(int proc_fd); | 296 static bool kernelSupportSeccompBPF(int proc_fd); |
| 352 static bool RunFunctionInPolicy(void (*function)(), | 297 static bool RunFunctionInPolicy(void (*function)(), |
| 353 EvaluateSyscall syscallEvaluator, | 298 EvaluateSyscall syscallEvaluator, |
| 354 int proc_fd); | 299 int proc_fd); |
| 355 static void startSandboxInternal(bool quiet); | 300 static void startSandboxInternal(bool quiet); |
| 356 static bool isSingleThreaded(int proc_fd); | 301 static bool isSingleThreaded(int proc_fd); |
| 302 static bool isDenied(const ErrorCode& code); |
| 357 static bool disableFilesystem(); | 303 static bool disableFilesystem(); |
| 358 static void policySanityChecks(EvaluateSyscall syscallEvaluator, | 304 static void policySanityChecks(EvaluateSyscall syscallEvaluator, |
| 359 EvaluateArguments argumentEvaluator); | 305 EvaluateArguments argumentEvaluator); |
| 360 static void installFilter(bool quiet); | 306 static void installFilter(bool quiet); |
| 361 static void findRanges(Ranges *ranges); | 307 static void findRanges(Ranges *ranges); |
| 362 static void emitJumpStatements(Program *program, RetInsns *rets, | 308 static void emitJumpStatements(Program *program, RetInsns *rets, |
| 363 Ranges::const_iterator start, | 309 Ranges::const_iterator start, |
| 364 Ranges::const_iterator stop); | 310 Ranges::const_iterator stop); |
| 365 static void emitReturnStatements(Program *prog, const RetInsns& rets); | 311 static void emitReturnStatements(Program *prog, const RetInsns& rets); |
| 366 static void sigSys(int nr, siginfo_t *info, void *void_context); | 312 static void sigSys(int nr, siginfo_t *info, void *void_context); |
| 367 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); | 313 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); |
| 368 static int getTrapId(TrapFnc fnc, const void *aux); | 314 static int getTrapId(TrapFnc fnc, const void *aux); |
| 369 | 315 |
| 370 static SandboxStatus status_; | 316 static SandboxStatus status_; |
| 371 static int proc_fd_; | 317 static int proc_fd_; |
| 372 static Evaluators evaluators_; | 318 static Evaluators evaluators_; |
| 319 static ErrMap errMap_; |
| 373 static Traps *traps_; | 320 static Traps *traps_; |
| 374 static TrapIds trapIds_; | 321 static TrapIds trapIds_; |
| 375 static ErrorCode *trapArray_; | 322 static ErrorCode *trapArray_; |
| 376 static size_t trapArraySize_; | 323 static size_t trapArraySize_; |
| 377 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); | 324 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); |
| 378 }; | 325 }; |
| 379 | 326 |
| 380 } // namespace | 327 } // namespace |
| 381 | 328 |
| 382 #endif // SANDBOX_BPF_H__ | 329 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| OLD | NEW |