Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf.cc

Issue 10833044: Refactored ErrorCode into it's own class (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased, and removed "protected" as requested by jln Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include <time.h> 5 #include <time.h>
6 6
7 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 7 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
8 #include "sandbox/linux/seccomp-bpf/verifier.h" 8 #include "sandbox/linux/seccomp-bpf/verifier.h"
9 9
10 // The kernel gives us a sandbox, we turn it into a playground :-) 10 // The kernel gives us a sandbox, we turn it into a playground :-)
11 // This is version 2 of the playground; version 1 was built on top of 11 // This is version 2 of the playground; version 1 was built on top of
12 // pre-BPF seccomp mode. 12 // pre-BPF seccomp mode.
13 namespace playground2 { 13 namespace playground2 {
14 14
15 // We define a really simple sandbox policy. It is just good enough for us 15 // We define a really simple sandbox policy. It is just good enough for us
16 // to tell that the sandbox has actually been activated. 16 // to tell that the sandbox has actually been activated.
17 Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) { 17 ErrorCode Sandbox::probeEvaluator(int signo) {
18 switch (signo) { 18 switch (signo) {
19 case __NR_getpid: 19 case __NR_getpid:
20 // Return EPERM so that we can check that the filter actually ran. 20 // Return EPERM so that we can check that the filter actually ran.
21 return EPERM; 21 return EPERM;
22 case __NR_exit_group: 22 case __NR_exit_group:
23 // Allow exit() with a non-default return code. 23 // Allow exit() with a non-default return code.
24 return SB_ALLOWED; 24 return SB_ALLOWED;
25 default: 25 default:
26 // Make everything else fail in an easily recognizable way. 26 // Make everything else fail in an easily recognizable way.
27 return EINVAL; 27 return EINVAL;
28 } 28 }
29 } 29 }
30 30
31 void Sandbox::probeProcess(void) { 31 void Sandbox::probeProcess(void) {
32 if (syscall(__NR_getpid) < 0 && errno == EPERM) { 32 if (syscall(__NR_getpid) < 0 && errno == EPERM) {
33 syscall(__NR_exit_group, (intptr_t)100); 33 syscall(__NR_exit_group, (intptr_t)100);
34 } 34 }
35 } 35 }
36 36
37 Sandbox::ErrorCode Sandbox::allowAllEvaluator(int signo) { 37 ErrorCode Sandbox::allowAllEvaluator(int signo) {
38 if (signo < static_cast<int>(MIN_SYSCALL) || 38 if (signo < static_cast<int>(MIN_SYSCALL) ||
39 signo > static_cast<int>(MAX_SYSCALL)) { 39 signo > static_cast<int>(MAX_SYSCALL)) {
40 return ENOSYS; 40 return ENOSYS;
41 } 41 }
42 return Sandbox::SB_ALLOWED; 42 return Sandbox::SB_ALLOWED;
43 } 43 }
44 44
45 void Sandbox::tryVsyscallProcess(void) { 45 void Sandbox::tryVsyscallProcess(void) {
46 time_t current_time; 46 time_t current_time;
47 // time() is implemented as a vsyscall. With an older glibc, with 47 // time() is implemented as a vsyscall. With an older glibc, with
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 131 }
132 if (HANDLE_EINTR(close(fds[0]))) { 132 if (HANDLE_EINTR(close(fds[0]))) {
133 die("close() failed"); 133 die("close() failed");
134 } 134 }
135 135
136 return rc; 136 return rc;
137 137
138 } 138 }
139 139
140 bool Sandbox::kernelSupportSeccompBPF(int proc_fd) { 140 bool Sandbox::kernelSupportSeccompBPF(int proc_fd) {
141 #ifdef SECCOMP_BPF_VALGRIND_HACKS
142 if (RUNNING_ON_VALGRIND) {
143 // Valgrind doesn't like our run-time test. Disable testing and assume we
144 // always support sandboxing. This feature should only ever be enabled when
145 // debugging.
146 return true;
147 }
148 #endif
149
141 return RunFunctionInPolicy(probeProcess, Sandbox::probeEvaluator, proc_fd) && 150 return RunFunctionInPolicy(probeProcess, Sandbox::probeEvaluator, proc_fd) &&
142 RunFunctionInPolicy(tryVsyscallProcess, Sandbox::allowAllEvaluator, 151 RunFunctionInPolicy(tryVsyscallProcess, Sandbox::allowAllEvaluator,
143 proc_fd); 152 proc_fd);
144 } 153 }
145 154
146 Sandbox::SandboxStatus Sandbox::supportsSeccompSandbox(int proc_fd) { 155 Sandbox::SandboxStatus Sandbox::supportsSeccompSandbox(int proc_fd) {
147 // It the sandbox is currently active, we clearly must have support for 156 // It the sandbox is currently active, we clearly must have support for
148 // sandboxing. 157 // sandboxing.
149 if (status_ == STATUS_ENABLED) { 158 if (status_ == STATUS_ENABLED) {
150 return status_; 159 return status_;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 sb.st_nlink != 3 || 251 sb.st_nlink != 3 ||
243 HANDLE_EINTR(close(task))) { 252 HANDLE_EINTR(close(task))) {
244 if (task >= 0) { 253 if (task >= 0) {
245 if (HANDLE_EINTR(close(task))) { } 254 if (HANDLE_EINTR(close(task))) { }
246 } 255 }
247 return false; 256 return false;
248 } 257 }
249 return true; 258 return true;
250 } 259 }
251 260
252 static bool isDenied(const Sandbox::ErrorCode& code) { 261 bool Sandbox::isDenied(ErrorCode code) {
jln (very slow on Chromium) 2012/07/27 19:46:30 Shouldn't this be a const reference ?
253 return (code & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP || 262 return (code.err_ & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP ||
254 (code >= (SECCOMP_RET_ERRNO + 1) && 263 (code.err_ >= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MIN_ERRNO) &&
255 code <= (SECCOMP_RET_ERRNO + 4095)); 264 code.err_ <= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MAX_ERRNO));
jln (very slow on Chromium) 2012/07/27 19:46:30 Please create an accessor err() in the ErrorCode c
256 } 265 }
257 266
258 void Sandbox::policySanityChecks(EvaluateSyscall syscallEvaluator, 267 void Sandbox::policySanityChecks(EvaluateSyscall syscallEvaluator,
259 EvaluateArguments) { 268 EvaluateArguments) {
260 // Do some sanity checks on the policy. This will warn users if they do 269 // Do some sanity checks on the policy. This will warn users if they do
261 // things that are likely unsafe and unintended. 270 // things that are likely unsafe and unintended.
262 // We also have similar checks later, when we actually compile the BPF 271 // We also have similar checks later, when we actually compile the BPF
263 // program. That catches problems with incorrectly stacked evaluators. 272 // program. That catches problems with incorrectly stacked evaluators.
264 if (!isDenied(syscallEvaluator(-1))) { 273 if (!isDenied(syscallEvaluator(-1))) {
265 die("Negative system calls should always be disallowed by policy"); 274 die("Negative system calls should always be disallowed by policy");
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 355
347 // If the architecture doesn't match SECCOMP_ARCH, disallow the 356 // If the architecture doesn't match SECCOMP_ARCH, disallow the
348 // system call. 357 // system call.
349 program->push_back((struct sock_filter) 358 program->push_back((struct sock_filter)
350 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch))); 359 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch)));
351 program->push_back((struct sock_filter) 360 program->push_back((struct sock_filter)
352 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0)); 361 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0));
353 362
354 program->push_back((struct sock_filter) 363 program->push_back((struct sock_filter)
355 BPF_STMT(BPF_RET+BPF_K, 364 BPF_STMT(BPF_RET+BPF_K,
356 ErrorCode(bpfFailure, 365 Kill("Invalid audit architecture in BPF filter").err_));
357 "Invalid audit architecture in BPF filter")));
358 366
359 // Grab the system call number, so that we can implement jump tables. 367 // Grab the system call number, so that we can implement jump tables.
360 program->push_back((struct sock_filter) 368 program->push_back((struct sock_filter)
361 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr))); 369 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr)));
362 370
363 // On Intel architectures, verify that system call numbers are in the 371 // On Intel architectures, verify that system call numbers are in the
364 // expected number range. The older i386 and x86-64 APIs clear bit 30 372 // expected number range. The older i386 and x86-64 APIs clear bit 30
365 // on all system calls. The newer x86-32 API always sets bit 30. 373 // on all system calls. The newer x86-32 API always sets bit 30.
366 #if defined(__i386__) || defined(__x86_64__) 374 #if defined(__i386__) || defined(__x86_64__)
367 #if defined(__x86_64__) && defined(__ILP32__) 375 #if defined(__x86_64__) && defined(__ILP32__)
368 program->push_back((struct sock_filter) 376 program->push_back((struct sock_filter)
369 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0)); 377 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0));
370 #else 378 #else
371 program->push_back((struct sock_filter) 379 program->push_back((struct sock_filter)
372 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1)); 380 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1));
373 #endif 381 #endif
374 program->push_back((struct sock_filter) 382 program->push_back((struct sock_filter)
375 BPF_STMT(BPF_RET+BPF_K, 383 BPF_STMT(BPF_RET+BPF_K,
376 ErrorCode(bpfFailure, 384 Kill("Illegal mixing of system call ABIs").err_));
377 "Illegal mixing of system call ABIs")));
378 #endif 385 #endif
379 386
380 387
381 { 388 {
382 // Evaluate all possible system calls and group their ErrorCodes into 389 // Evaluate all possible system calls and group their ErrorCodes into
383 // ranges of identical codes. 390 // ranges of identical codes.
384 Ranges ranges; 391 Ranges ranges;
385 findRanges(&ranges); 392 findRanges(&ranges);
386 393
387 // Compile the system call ranges to an optimized BPF program 394 // Compile the system call ranges to an optimized BPF program
(...skipping 24 matching lines...) Expand all
412 // system memory allocator that is in effect, these operators can result 419 // system memory allocator that is in effect, these operators can result
413 // in system calls to things like munmap() or brk(). 420 // in system calls to things like munmap() or brk().
414 struct sock_filter bpf[program->size()]; 421 struct sock_filter bpf[program->size()];
415 const struct sock_fprog prog = { 422 const struct sock_fprog prog = {
416 static_cast<unsigned short>(program->size()), bpf }; 423 static_cast<unsigned short>(program->size()), bpf };
417 memcpy(bpf, &(*program)[0], sizeof(bpf)); 424 memcpy(bpf, &(*program)[0], sizeof(bpf));
418 delete program; 425 delete program;
419 426
420 // Release memory that is no longer needed 427 // Release memory that is no longer needed
421 evaluators_.clear(); 428 evaluators_.clear();
429 errMap_.clear();
422 430
423 // Install BPF filter program 431 #ifdef SECCOMP_BPF_VALGRIND_HACKS
424 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 432 // Valgrind is really not happy about our sandbox. Disable it when running
425 die(dryRun_ ? NULL : "Kernel refuses to enable no-new-privs"); 433 // in Valgrind. This feature is dangerous and should never be enabled by
426 } else { 434 // default. We protect it behind a pre-processor option.
427 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 435 if (!RUNNING_ON_VALGRIND)
428 die(dryRun_ ? NULL : "Kernel refuses to turn on BPF filters"); 436 #endif
437 {
438 // Install BPF filter program
439 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
440 die(dryRun_ ? NULL : "Kernel refuses to enable no-new-privs");
441 } else {
442 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
443 die(dryRun_ ? NULL : "Kernel refuses to turn on BPF filters");
444 }
429 } 445 }
430 } 446 }
431 447
432 return; 448 return;
433 } 449 }
434 450
435 void Sandbox::findRanges(Ranges *ranges) { 451 void Sandbox::findRanges(Ranges *ranges) {
436 // Please note that "struct seccomp_data" defines system calls as a signed 452 // Please note that "struct seccomp_data" defines system calls as a signed
437 // int32_t, but BPF instructions always operate on unsigned quantities. We 453 // int32_t, but BPF instructions always operate on unsigned quantities. We
438 // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL, 454 // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL,
439 // and then verifying that the rest of the number range (both positive and 455 // and then verifying that the rest of the number range (both positive and
440 // negative) all return the same ErrorCode. 456 // negative) all return the same ErrorCode.
441 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first; 457 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first;
442 uint32_t oldSysnum = 0; 458 uint32_t oldSysnum = 0;
443 ErrorCode oldErr = evaluateSyscall(oldSysnum); 459 ErrorCode oldErr = evaluateSyscall(oldSysnum);
444 for (uint32_t sysnum = std::max(1u, MIN_SYSCALL); 460 for (uint32_t sysnum = std::max(1u, MIN_SYSCALL);
445 sysnum <= MAX_SYSCALL + 1; 461 sysnum <= MAX_SYSCALL + 1;
446 ++sysnum) { 462 ++sysnum) {
447 ErrorCode err = evaluateSyscall(static_cast<int>(sysnum)); 463 ErrorCode err = evaluateSyscall(static_cast<int>(sysnum));
448 if (err != oldErr) { 464 if (!err.isEqual(oldErr)) {
449 ranges->push_back(Range(oldSysnum, sysnum-1, oldErr)); 465 ranges->push_back(Range(oldSysnum, sysnum-1, oldErr));
450 oldSysnum = sysnum; 466 oldSysnum = sysnum;
451 oldErr = err; 467 oldErr = err;
452 } 468 }
453 } 469 }
454 470
455 // As we looped all the way past the valid system calls (i.e. MAX_SYSCALL+1), 471 // As we looped all the way past the valid system calls (i.e. MAX_SYSCALL+1),
456 // "oldErr" should at this point be the "default" policy for all system call 472 // "oldErr" should at this point be the "default" policy for all system call
457 // numbers that don't have an explicit handler in the system call evaluator. 473 // numbers that don't have an explicit handler in the system call evaluator.
458 // But as we are quite paranoid, we perform some more sanity checks to verify 474 // But as we are quite paranoid, we perform some more sanity checks to verify
459 // that there actually is a consistent "default" policy in the first place. 475 // that there actually is a consistent "default" policy in the first place.
460 // We don't actually iterate over all possible 2^32 values, though. We just 476 // We don't actually iterate over all possible 2^32 values, though. We just
461 // perform spot checks at the boundaries. 477 // perform spot checks at the boundaries.
462 // The cases that we test are: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF. 478 // The cases that we test are: 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF.
463 if (oldErr != evaluateSyscall(std::numeric_limits<int>::max()) || 479 if (!oldErr.isEqual(evaluateSyscall(std::numeric_limits<int>::max())) ||
464 oldErr != evaluateSyscall(std::numeric_limits<int>::min()) || 480 !oldErr.isEqual(evaluateSyscall(std::numeric_limits<int>::min())) ||
465 oldErr != evaluateSyscall(-1)) { 481 !oldErr.isEqual(evaluateSyscall(-1))) {
466 die("Invalid seccomp policy"); 482 die("Invalid seccomp policy");
467 } 483 }
468 ranges->push_back( 484 ranges->push_back(
469 Range(oldSysnum, std::numeric_limits<unsigned>::max(), oldErr)); 485 Range(oldSysnum, std::numeric_limits<unsigned>::max(), oldErr));
470 } 486 }
471 487
472 void Sandbox::emitJumpStatements(Program *program, RetInsns *rets, 488 void Sandbox::emitJumpStatements(Program *program, RetInsns *rets,
473 Ranges::const_iterator start, 489 Ranges::const_iterator start,
474 Ranges::const_iterator stop) { 490 Ranges::const_iterator stop) {
475 // We convert the list of system call ranges into jump table that performs 491 // We convert the list of system call ranges into jump table that performs
(...skipping 23 matching lines...) Expand all
499 // less than the range object at the mid point of the list. 515 // less than the range object at the mid point of the list.
500 if (mid - start == 1) { 516 if (mid - start == 1) {
501 // If we have narrowed things down to a single range object, we can 517 // If we have narrowed things down to a single range object, we can
502 // return from the BPF filter program. 518 // return from the BPF filter program.
503 // Instead of emitting a BPF_RET statement, we want to coalesce all 519 // Instead of emitting a BPF_RET statement, we want to coalesce all
504 // identical BPF_RET statements into a single instance. This results in 520 // identical BPF_RET statements into a single instance. This results in
505 // a more efficient BPF program that uses less CPU cache. 521 // a more efficient BPF program that uses less CPU cache.
506 // Since all branches in BPF programs have to be forward branches, we 522 // Since all branches in BPF programs have to be forward branches, we
507 // keep track of our current instruction pointer and then fix up the 523 // keep track of our current instruction pointer and then fix up the
508 // branch when we emit the BPF_RET statement in emitReturnStatements(). 524 // branch when we emit the BPF_RET statement in emitReturnStatements().
509 (*rets)[start->err].push_back(FixUp(jmp, false)); 525 (*rets)[start->err.err_].push_back(FixUp(jmp, false));
510 } else { 526 } else {
511 // Sub-divide the list of ranges and continue recursively. 527 // Sub-divide the list of ranges and continue recursively.
512 emitJumpStatements(program, rets, start, mid); 528 emitJumpStatements(program, rets, start, mid);
513 } 529 }
514 530
515 // The comparison turned out to be true; i.e. our system call number is 531 // The comparison turned out to be true; i.e. our system call number is
516 // greater or equal to the range object at the mid point of the list. 532 // greater or equal to the range object at the mid point of the list.
517 if (stop - mid == 1) { 533 if (stop - mid == 1) {
518 // We narrowed things down to a single range object. Remember instruction 534 // We narrowed things down to a single range object. Remember instruction
519 // pointer and exit code, so that we can patch up the target of the jump 535 // pointer and exit code, so that we can patch up the target of the jump
520 // instruction in emitReturnStatements(). 536 // instruction in emitReturnStatements().
521 (*rets)[mid->err].push_back(FixUp(jmp, true)); 537 (*rets)[mid->err.err_].push_back(FixUp(jmp, true));
522 } else { 538 } else {
523 // We now know where the block of instructions for the "true" comparison 539 // We now know where the block of instructions for the "true" comparison
524 // starts. Patch up the jump target of the BPF_JMP instruction that we 540 // starts. Patch up the jump target of the BPF_JMP instruction that we
525 // emitted earlier. 541 // emitted earlier.
526 int distance = program->size() - jmp - 1; 542 int distance = program->size() - jmp - 1;
527 if (distance < 0 || distance > 255) { 543 if (distance < 0 || distance > 255) {
528 goto compiler_err; 544 goto compiler_err;
529 } 545 }
530 (*program)[jmp].jt = distance; 546 (*program)[jmp].jt = distance;
531 547
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 648
633 // Update the CPU register that stores the return code of the system call 649 // Update the CPU register that stores the return code of the system call
634 // that we just handled, and restore "errno" to the value that it had 650 // that we just handled, and restore "errno" to the value that it had
635 // before entering the signal handler. 651 // before entering the signal handler.
636 ctx->uc_mcontext.gregs[REG_RESULT] = static_cast<greg_t>(rc); 652 ctx->uc_mcontext.gregs[REG_RESULT] = static_cast<greg_t>(rc);
637 errno = old_errno; 653 errno = old_errno;
638 654
639 return; 655 return;
640 } 656 }
641 657
642 intptr_t Sandbox::bpfFailure(const struct arch_seccomp_data&, void *aux) { 658 ErrorCode Sandbox::Trap(ErrorCode::TrapFnc fnc, const void *aux) {
643 die(static_cast<char *>(aux));
644 }
645
646 int Sandbox::getTrapId(Sandbox::TrapFnc fnc, const void *aux) {
647 // Each unique pair of TrapFnc and auxiliary data make up a distinct instance 659 // Each unique pair of TrapFnc and auxiliary data make up a distinct instance
648 // of a SECCOMP_RET_TRAP. 660 // of a SECCOMP_RET_TRAP.
649 std::pair<TrapFnc, const void *> key(fnc, aux); 661 std::pair<ErrorCode::TrapFnc, const void *> key(fnc, aux);
650 TrapIds::const_iterator iter = trapIds_.find(key); 662 TrapIds::const_iterator iter = trapIds_.find(key);
663 uint16_t id;
651 if (iter != trapIds_.end()) { 664 if (iter != trapIds_.end()) {
652 // We have seen this pair before. Return the same id that we assigned 665 // We have seen this pair before. Return the same id that we assigned
653 // earlier. 666 // earlier.
654 return iter->second; 667 id = iter->second;
655 } else { 668 } else {
656 // This is a new pair. Remember it and assign a new id. 669 // This is a new pair. Remember it and assign a new id.
657 // Please note that we have to store traps in memory that doesn't get 670 // Please note that we have to store traps in memory that doesn't get
658 // deallocated when the program is shutting down. A memory leak is 671 // deallocated when the program is shutting down. A memory leak is
659 // intentional, because we might otherwise not be able to execute 672 // intentional, because we might otherwise not be able to execute
660 // system calls part way through the program shutting down 673 // system calls part way through the program shutting down
661 if (!traps_) { 674 if (!traps_) {
662 traps_ = new Traps(); 675 traps_ = new Traps();
663 } 676 }
664 Traps::size_type id = traps_->size() + 1; 677 if (traps_->size() >= SECCOMP_RET_DATA) {
665 if (id > SECCOMP_RET_DATA) {
666 // In practice, this is pretty much impossible to trigger, as there 678 // In practice, this is pretty much impossible to trigger, as there
667 // are other kernel limitations that restrict overall BPF program sizes. 679 // are other kernel limitations that restrict overall BPF program sizes.
668 die("Too many SECCOMP_RET_TRAP callback instances"); 680 die("Too many SECCOMP_RET_TRAP callback instances");
669 } 681 }
682 id = traps_->size() + 1;
670 683
671 traps_->push_back(ErrorCode(fnc, aux, id)); 684 traps_->push_back(ErrorCode(fnc, aux, id));
672 trapIds_[key] = id; 685 trapIds_[key] = id;
673 686
674 // We want to access the traps_ vector from our signal handler. But 687 // We want to access the traps_ vector from our signal handler. But
675 // we are not assured that doing so is async-signal safe. On the other 688 // we are not assured that doing so is async-signal safe. On the other
676 // hand, C++ guarantees that the contents of a vector is stored in a 689 // hand, C++ guarantees that the contents of a vector is stored in a
677 // contiguous C-style array. 690 // contiguous C-style array.
678 // So, we look up the address and size of this array outside of the 691 // So, we look up the address and size of this array outside of the
679 // signal handler, where we can safely do so. 692 // signal handler, where we can safely do so.
680 trapArray_ = &(*traps_)[0]; 693 trapArray_ = &(*traps_)[0];
681 trapArraySize_ = id; 694 trapArraySize_ = id;
682 return id;
683 } 695 }
696
697 ErrorCode err = ErrorCode(fnc, aux, id);
698 return errMap_[err.err_] = err;
699 }
700
701 intptr_t Sandbox::bpfFailure(const struct arch_seccomp_data&, void *aux) {
702 die(static_cast<char *>(aux));
703 }
704
705 ErrorCode Sandbox::Kill(const char *msg) {
706 return Trap(bpfFailure, const_cast<char *>(msg));
684 } 707 }
685 708
686 bool Sandbox::dryRun_ = false; 709 bool Sandbox::dryRun_ = false;
687 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 710 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
688 int Sandbox::proc_fd_ = -1; 711 int Sandbox::proc_fd_ = -1;
689 Sandbox::Evaluators Sandbox::evaluators_; 712 Sandbox::Evaluators Sandbox::evaluators_;
713 Sandbox::ErrMap Sandbox::errMap_;
690 Sandbox::Traps *Sandbox::traps_ = NULL; 714 Sandbox::Traps *Sandbox::traps_ = NULL;
691 Sandbox::TrapIds Sandbox::trapIds_; 715 Sandbox::TrapIds Sandbox::trapIds_;
692 Sandbox::ErrorCode *Sandbox::trapArray_ = NULL; 716 ErrorCode *Sandbox::trapArray_ = NULL;
693 size_t Sandbox::trapArraySize_ = 0; 717 size_t Sandbox::trapArraySize_ = 0;
694 718
695 } // namespace 719 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698