| 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> | 8 #include <endian.h> |
| 9 #include <errno.h> | 9 #include <errno.h> |
| 10 #include <fcntl.h> | 10 #include <fcntl.h> |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 }; | 200 }; |
| 201 | 201 |
| 202 // TrapFnc is a pointer to a function that handles Seccomp traps in | 202 // TrapFnc is a pointer to a function that handles Seccomp traps in |
| 203 // user-space. The seccomp policy can request that a trap handler gets | 203 // user-space. The seccomp policy can request that a trap handler gets |
| 204 // installed; it does so by returning a suitable ErrorCode() from the | 204 // installed; it does so by returning a suitable ErrorCode() from the |
| 205 // syscallEvaluator. See the ErrorCode() constructor for how to pass in | 205 // syscallEvaluator. See the ErrorCode() constructor for how to pass in |
| 206 // the function pointer. | 206 // the function pointer. |
| 207 // Please note that TrapFnc is executed from signal context and must be | 207 // Please note that TrapFnc is executed from signal context and must be |
| 208 // async-signal safe: | 208 // async-signal safe: |
| 209 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html | 209 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html |
| 210 // Also note that it follows the calling convention of native system calls. |
| 211 // In other words, it reports an error by returning an exit code in the |
| 212 // range -1..-4096. It should not set errno when reporting errors; on the |
| 213 // other hand, accidentally modifying errno is harmless and the changes will |
| 214 // be undone afterwards. |
| 210 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); | 215 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); |
| 211 | 216 |
| 212 enum Operation { | 217 enum Operation { |
| 213 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, | 218 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS, |
| 214 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, | 219 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL, |
| 215 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS | 220 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS |
| 216 }; | 221 }; |
| 217 | 222 |
| 218 struct Constraint { | 223 struct Constraint { |
| 219 bool is32bit; | 224 bool is32bit; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); | 269 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); |
| 265 | 270 |
| 266 // We can use ErrorCode to request calling of a trap handler. This method | 271 // We can use ErrorCode to request calling of a trap handler. This method |
| 267 // performs the required wrapping of the callback function into an | 272 // performs the required wrapping of the callback function into an |
| 268 // ErrorCode object. | 273 // ErrorCode object. |
| 269 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall | 274 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall |
| 270 // for a description of how to pass data from setSandboxPolicy() to a Trap() | 275 // for a description of how to pass data from setSandboxPolicy() to a Trap() |
| 271 // handler. | 276 // handler. |
| 272 static ErrorCode Trap(ErrorCode::TrapFnc fnc, const void *aux); | 277 static ErrorCode Trap(ErrorCode::TrapFnc fnc, const void *aux); |
| 273 | 278 |
| 279 // Calls a user-space trap handler and disables all sandboxing for system |
| 280 // calls made from this trap handler. |
| 281 // NOTE: This feature, by definition, disables all security features of |
| 282 // the sandbox. It should never be used in production, but it can be |
| 283 // very useful to diagnose code that is incompatible with the sandbox. |
| 284 // If even a single system call returns "UnsafeTrap", the security of |
| 285 // entire sandbox should be considered compromised. |
| 286 static ErrorCode UnsafeTrap(ErrorCode::TrapFnc fnc, const void *aux); |
| 287 |
| 288 // From within an UnsafeTrap() it is often useful to be able to execute |
| 289 // the system call that triggered the trap. The ForwardSyscall() method |
| 290 // makes this easy. It is more efficient than calling glibc's syscall() |
| 291 // function, as it avoid the extra round-trip to the signal handler. And |
| 292 // it automatically does the correct thing to report kernel-style error |
| 293 // conditions, rather than setting errno. See the comments for TrapFnc for |
| 294 // details. In other words, the return value from ForwardSyscall() is |
| 295 // directly suitable as a return value for a trap handler. |
| 296 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); |
| 297 |
| 274 // Kill the program and print an error message. | 298 // Kill the program and print an error message. |
| 275 static ErrorCode Kill(const char *msg); | 299 static ErrorCode Kill(const char *msg); |
| 276 | 300 |
| 277 // This is the main public entry point. It finds all system calls that | 301 // This is the main public entry point. It finds all system calls that |
| 278 // need rewriting, sets up the resources needed by the sandbox, and | 302 // need rewriting, sets up the resources needed by the sandbox, and |
| 279 // enters Seccomp mode. | 303 // enters Seccomp mode. |
| 280 static void startSandbox() { startSandboxInternal(false); } | 304 static void startSandbox() { startSandboxInternal(false); } |
| 281 | 305 |
| 282 private: | 306 private: |
| 283 friend class ErrorCode; | 307 friend class ErrorCode; |
| 284 friend class CodeGen; | 308 friend class CodeGen; |
| 285 friend class SandboxUnittestHelper; | 309 friend class SandboxUnittestHelper; |
| 286 friend class Util; | 310 friend class Util; |
| 287 friend class Verifier; | 311 friend class Verifier; |
| 288 | 312 |
| 289 typedef std::vector<struct sock_filter> Program; | 313 typedef std::vector<struct sock_filter> Program; |
| 290 | 314 |
| 291 struct Range { | 315 struct Range { |
| 292 Range(uint32_t f, uint32_t t, const ErrorCode& e) : | 316 Range(uint32_t f, uint32_t t, const ErrorCode& e) |
| 293 from(f), | 317 : from(f), |
| 294 to(t), | 318 to(t), |
| 295 err(e) { | 319 err(e) { |
| 296 } | 320 } |
| 297 uint32_t from, to; | 321 uint32_t from, to; |
| 298 ErrorCode err; | 322 ErrorCode err; |
| 299 }; | 323 }; |
| 324 struct TrapKey { |
| 325 TrapKey(TrapFnc f, const void *a, bool s) |
| 326 : fnc(f), |
| 327 aux(a), |
| 328 safe(s) { |
| 329 } |
| 330 TrapFnc fnc; |
| 331 const void *aux; |
| 332 bool safe; |
| 333 bool operator<(const TrapKey&) const; |
| 334 }; |
| 300 typedef std::vector<Range> Ranges; | 335 typedef std::vector<Range> Ranges; |
| 301 typedef std::map<uint32_t, ErrorCode> ErrMap; | 336 typedef std::map<uint32_t, ErrorCode> ErrMap; |
| 302 typedef std::vector<ErrorCode> Traps; | 337 typedef std::vector<ErrorCode> Traps; |
| 303 typedef std::map<std::pair<TrapFnc, const void *>, int> TrapIds; | 338 typedef std::map<TrapKey, uint16_t> TrapIds; |
| 304 | 339 |
| 305 // Get a file descriptor pointing to "/proc", if currently available. | 340 // Get a file descriptor pointing to "/proc", if currently available. |
| 306 static int proc_fd() { return proc_fd_; } | 341 static int proc_fd() { return proc_fd_; } |
| 307 | 342 |
| 308 static ErrorCode probeEvaluator(int sysnum, void *) __attribute__((const)); | 343 static ErrorCode probeEvaluator(int sysnum, void *) __attribute__((const)); |
| 309 static void probeProcess(void); | 344 static void probeProcess(void); |
| 310 static ErrorCode allowAllEvaluator(int sysnum, void *aux); | 345 static ErrorCode allowAllEvaluator(int sysnum, void *aux); |
| 311 static void tryVsyscallProcess(void); | 346 static void tryVsyscallProcess(void); |
| 312 static bool kernelSupportSeccompBPF(int proc_fd); | 347 static bool kernelSupportSeccompBPF(int proc_fd); |
| 313 static bool RunFunctionInPolicy(void (*function)(), | 348 static bool RunFunctionInPolicy(void (*function)(), |
| 314 EvaluateSyscall syscallEvaluator, | 349 EvaluateSyscall syscallEvaluator, |
| 315 void *aux, | 350 void *aux, |
| 316 int proc_fd); | 351 int proc_fd); |
| 317 static void startSandboxInternal(bool quiet); | 352 static void startSandboxInternal(bool quiet); |
| 318 static bool isSingleThreaded(int proc_fd); | 353 static bool isSingleThreaded(int proc_fd); |
| 319 static bool isDenied(const ErrorCode& code); | 354 static bool isDenied(const ErrorCode& code); |
| 320 static bool disableFilesystem(); | 355 static bool disableFilesystem(); |
| 321 static void policySanityChecks(EvaluateSyscall syscallEvaluator, | 356 static void policySanityChecks(EvaluateSyscall syscallEvaluator, |
| 322 void *aux); | 357 void *aux); |
| 358 |
| 359 // Function that can be passed as a callback function to CodeGen::Traverse(). |
| 360 // Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it |
| 361 // sets the "bool" variable pointed to by "aux". |
| 362 static void CheckForUnsafeErrorCodes(Instruction *insn, void *aux); |
| 363 |
| 364 // Function that can be passed as a callback function to CodeGen::Traverse(). |
| 365 // Checks whether the "insn" returns an errno value from a BPF filter. If so, |
| 366 // it rewrites the instruction to instead call a Trap() handler that does |
| 367 // the same thing. "aux" is ignored. |
| 368 static void RedirectToUserspace(Instruction *insn, void *aux); |
| 369 |
| 370 // Stackable wrapper around an Evaluators handler. Changes ErrorCodes |
| 371 // returned by a system call evaluator to match the changes made by |
| 372 // RedirectToUserspace(). "aux" should be pointer to wrapped system call |
| 373 // evaluator. |
| 374 static ErrorCode RedirectToUserspaceEvalWrapper(int sysnum, void *aux); |
| 375 |
| 323 static void installFilter(bool quiet); | 376 static void installFilter(bool quiet); |
| 324 static void findRanges(Ranges *ranges); | 377 static void findRanges(Ranges *ranges); |
| 325 static Instruction *assembleJumpTable(CodeGen *gen, | 378 static Instruction *assembleJumpTable(CodeGen *gen, |
| 326 Ranges::const_iterator start, | 379 Ranges::const_iterator start, |
| 327 Ranges::const_iterator stop); | 380 Ranges::const_iterator stop); |
| 328 static void sigSys(int nr, siginfo_t *info, void *void_context); | 381 static void sigSys(int nr, siginfo_t *info, void *void_context); |
| 382 static ErrorCode MakeTrap(ErrorCode::TrapFnc fn, const void *aux, bool safe); |
| 383 |
| 384 // A Trap() handler that returns an "errno" value. The value is encoded |
| 385 // in the "aux" parameter. |
| 386 static intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux); |
| 387 |
| 329 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); | 388 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); |
| 330 static int getTrapId(TrapFnc fnc, const void *aux); | 389 static int getTrapId(TrapFnc fnc, const void *aux); |
| 331 | 390 |
| 332 static SandboxStatus status_; | 391 static SandboxStatus status_; |
| 333 static int proc_fd_; | 392 static int proc_fd_; |
| 334 static Evaluators evaluators_; | 393 static Evaluators evaluators_; |
| 335 static ErrMap errMap_; | |
| 336 static Traps *traps_; | 394 static Traps *traps_; |
| 337 static TrapIds trapIds_; | 395 static TrapIds trapIds_; |
| 338 static ErrorCode *trapArray_; | 396 static ErrorCode *trapArray_; |
| 339 static size_t trapArraySize_; | 397 static size_t trapArraySize_; |
| 398 static bool has_unsafe_traps_; |
| 340 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); | 399 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); |
| 341 }; | 400 }; |
| 342 | 401 |
| 343 } // namespace | 402 } // namespace |
| 344 | 403 |
| 345 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 404 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| OLD | NEW |