Chromium Code Reviews| 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 | |
|
jln (very slow on Chromium)
2012/11/21 01:22:03
I think it's worth explaining a tad more.
"It is
| |
| 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. | |
| 295 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); | |
| 296 | |
| 274 // Kill the program and print an error message. | 297 // Kill the program and print an error message. |
| 275 static ErrorCode Kill(const char *msg); | 298 static ErrorCode Kill(const char *msg); |
| 276 | 299 |
| 277 // This is the main public entry point. It finds all system calls that | 300 // 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 | 301 // need rewriting, sets up the resources needed by the sandbox, and |
| 279 // enters Seccomp mode. | 302 // enters Seccomp mode. |
| 280 static void startSandbox() { startSandboxInternal(false); } | 303 static void startSandbox() { startSandboxInternal(false); } |
| 281 | 304 |
| 282 private: | 305 private: |
| 283 friend class ErrorCode; | 306 friend class ErrorCode; |
| 284 friend class CodeGen; | 307 friend class CodeGen; |
| 285 friend class SandboxUnittestHelper; | 308 friend class SandboxUnittestHelper; |
| 286 friend class Util; | 309 friend class Util; |
| 287 friend class Verifier; | 310 friend class Verifier; |
| 288 | 311 |
| 289 typedef std::vector<struct sock_filter> Program; | 312 typedef std::vector<struct sock_filter> Program; |
| 290 | 313 |
| 291 struct Range { | 314 struct Range { |
| 292 Range(uint32_t f, uint32_t t, const ErrorCode& e) : | 315 Range(uint32_t f, uint32_t t, const ErrorCode& e) |
| 293 from(f), | 316 : from(f), |
| 294 to(t), | 317 to(t), |
| 295 err(e) { | 318 err(e) { |
| 296 } | 319 } |
| 297 uint32_t from, to; | 320 uint32_t from, to; |
| 298 ErrorCode err; | 321 ErrorCode err; |
| 299 }; | 322 }; |
| 323 struct TrapKey { | |
| 324 TrapKey(TrapFnc f, const void *a, bool s) | |
| 325 : fnc(f), | |
| 326 aux(a), | |
| 327 safe(s) { | |
| 328 } | |
| 329 TrapFnc fnc; | |
| 330 const void *aux; | |
| 331 bool safe; | |
| 332 bool operator<(const TrapKey&) const; | |
| 333 }; | |
| 300 typedef std::vector<Range> Ranges; | 334 typedef std::vector<Range> Ranges; |
| 301 typedef std::map<uint32_t, ErrorCode> ErrMap; | 335 typedef std::map<uint32_t, ErrorCode> ErrMap; |
| 302 typedef std::vector<ErrorCode> Traps; | 336 typedef std::vector<ErrorCode> Traps; |
| 303 typedef std::map<std::pair<TrapFnc, const void *>, int> TrapIds; | 337 typedef std::map<TrapKey, uint16_t> TrapIds; |
| 304 | 338 |
| 305 // Get a file descriptor pointing to "/proc", if currently available. | 339 // Get a file descriptor pointing to "/proc", if currently available. |
| 306 static int proc_fd() { return proc_fd_; } | 340 static int proc_fd() { return proc_fd_; } |
| 307 | 341 |
| 308 static ErrorCode probeEvaluator(int sysnum, void *) __attribute__((const)); | 342 static ErrorCode probeEvaluator(int sysnum, void *) __attribute__((const)); |
| 309 static void probeProcess(void); | 343 static void probeProcess(void); |
| 310 static ErrorCode allowAllEvaluator(int sysnum, void *aux); | 344 static ErrorCode allowAllEvaluator(int sysnum, void *aux); |
| 311 static void tryVsyscallProcess(void); | 345 static void tryVsyscallProcess(void); |
| 312 static bool kernelSupportSeccompBPF(int proc_fd); | 346 static bool kernelSupportSeccompBPF(int proc_fd); |
| 313 static bool RunFunctionInPolicy(void (*function)(), | 347 static bool RunFunctionInPolicy(void (*function)(), |
| 314 EvaluateSyscall syscallEvaluator, | 348 EvaluateSyscall syscallEvaluator, |
| 315 void *aux, | 349 void *aux, |
| 316 int proc_fd); | 350 int proc_fd); |
| 317 static void startSandboxInternal(bool quiet); | 351 static void startSandboxInternal(bool quiet); |
| 318 static bool isSingleThreaded(int proc_fd); | 352 static bool isSingleThreaded(int proc_fd); |
| 319 static bool isDenied(const ErrorCode& code); | 353 static bool isDenied(const ErrorCode& code); |
| 320 static bool disableFilesystem(); | 354 static bool disableFilesystem(); |
| 321 static void policySanityChecks(EvaluateSyscall syscallEvaluator, | 355 static void policySanityChecks(EvaluateSyscall syscallEvaluator, |
| 322 void *aux); | 356 void *aux); |
| 357 | |
| 358 // Function that can be passed as a callback function to CodeGen::Traverse(). | |
| 359 // Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it | |
| 360 // sets the "bool" variable pointed to by "aux". | |
| 361 static void CheckForUnsafeErrorCodes(Instruction *insn, void *aux); | |
| 362 | |
| 363 // Function that can be passed as a callback function to CodeGen::Traverse(). | |
| 364 // Checks whether the "insn" returns an errno value from a BPF filter. If so, | |
| 365 // it rewrites the instruction to instead call a Trap() handler that does | |
| 366 // the same thing. "aux" is ignored. | |
| 367 static void RedirectToUserspace(Instruction *insn, void *aux); | |
| 368 | |
| 369 // Stackable wrapper around an Evaluators handler. Changes ErrorCodes | |
| 370 // returned by a system call evaluator to match the changes made by | |
| 371 // RedirectToUserspace(). "aux" should be pointer to wrapped system call | |
| 372 // evaluator. | |
| 373 static ErrorCode RedirectToUserspaceEvalWrapper(int sysnum, void *aux); | |
| 374 | |
| 323 static void installFilter(bool quiet); | 375 static void installFilter(bool quiet); |
| 324 static void findRanges(Ranges *ranges); | 376 static void findRanges(Ranges *ranges); |
| 325 static Instruction *assembleJumpTable(CodeGen *gen, | 377 static Instruction *assembleJumpTable(CodeGen *gen, |
| 326 Ranges::const_iterator start, | 378 Ranges::const_iterator start, |
| 327 Ranges::const_iterator stop); | 379 Ranges::const_iterator stop); |
| 328 static void sigSys(int nr, siginfo_t *info, void *void_context); | 380 static void sigSys(int nr, siginfo_t *info, void *void_context); |
| 381 static ErrorCode MakeTrap(ErrorCode::TrapFnc fn, const void *aux, bool safe); | |
| 382 | |
| 383 // A Trap() handler that returns an "errno" value. The value is encoded | |
| 384 // in the "aux" parameter. | |
| 385 static intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux); | |
| 386 | |
| 329 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); | 387 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); |
| 330 static int getTrapId(TrapFnc fnc, const void *aux); | 388 static int getTrapId(TrapFnc fnc, const void *aux); |
| 331 | 389 |
| 332 static SandboxStatus status_; | 390 static SandboxStatus status_; |
| 333 static int proc_fd_; | 391 static int proc_fd_; |
| 334 static Evaluators evaluators_; | 392 static Evaluators evaluators_; |
| 335 static ErrMap errMap_; | |
| 336 static Traps *traps_; | 393 static Traps *traps_; |
| 337 static TrapIds trapIds_; | 394 static TrapIds trapIds_; |
| 338 static ErrorCode *trapArray_; | 395 static ErrorCode *trapArray_; |
| 339 static size_t trapArraySize_; | 396 static size_t trapArraySize_; |
| 397 static bool has_unsafe_traps_; | |
| 340 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); | 398 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); |
| 341 }; | 399 }; |
| 342 | 400 |
| 343 } // namespace | 401 } // namespace |
| 344 | 402 |
| 345 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ | 403 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ |
| OLD | NEW |