| 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 #include <sys/prctl.h> | 5 #include <sys/prctl.h> |
| 6 #include <sys/utsname.h> | 6 #include <sys/utsname.h> |
| 7 | 7 |
| 8 #include <ostream> | 8 #include <ostream> |
| 9 | 9 |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 10 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
| 12 #include "sandbox/linux/seccomp-bpf/verifier.h" | 11 #include "sandbox/linux/seccomp-bpf/verifier.h" |
| 13 #include "sandbox/linux/services/broker_process.h" | |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 13 |
| 16 using namespace playground2; | 14 using namespace playground2; |
| 17 using sandbox::BrokerProcess; | |
| 18 | 15 |
| 19 namespace { | 16 namespace { |
| 20 | 17 |
| 21 const int kExpectedReturnValue = 42; | 18 const int kExpectedReturnValue = 42; |
| 22 | 19 |
| 23 // This test should execute no matter whether we have kernel support. So, | 20 // This test should execute no matter whether we have kernel support. So, |
| 24 // we make it a TEST() instead of a BPF_TEST(). | 21 // we make it a TEST() instead of a BPF_TEST(). |
| 25 TEST(SandboxBpf, CallSupports) { | 22 TEST(SandboxBpf, CallSupports) { |
| 26 // We check that we don't crash, but it's ok if the kernel doesn't | 23 // We check that we don't crash, but it's ok if the kernel doesn't |
| 27 // support it. | 24 // support it. |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 // would make system calls, but it allows us to verify that we don't | 473 // would make system calls, but it allows us to verify that we don't |
| 477 // accidentally mess with errno, when we shouldn't. | 474 // accidentally mess with errno, when we shouldn't. |
| 478 errno = 0; | 475 errno = 0; |
| 479 struct arch_seccomp_data args = { }; | 476 struct arch_seccomp_data args = { }; |
| 480 args.nr = __NR_close; | 477 args.nr = __NR_close; |
| 481 args.args[0] = -1; | 478 args.args[0] = -1; |
| 482 BPF_ASSERT(Sandbox::ForwardSyscall(args) == -EBADF); | 479 BPF_ASSERT(Sandbox::ForwardSyscall(args) == -EBADF); |
| 483 BPF_ASSERT(errno == 0); | 480 BPF_ASSERT(errno == 0); |
| 484 } | 481 } |
| 485 | 482 |
| 486 // Test a trap handler that makes use of a broker process to open(). | |
| 487 | |
| 488 class InitializedOpenBroker { | |
| 489 public: | |
| 490 InitializedOpenBroker() : initialized_(false) { | |
| 491 std::vector<std::string> allowed_files; | |
| 492 allowed_files.push_back("/proc/allowed"); | |
| 493 allowed_files.push_back("/proc/cpuinfo"); | |
| 494 | |
| 495 broker_process_.reset(new BrokerProcess(allowed_files, | |
| 496 std::vector<std::string>())); | |
| 497 BPF_ASSERT(broker_process() != NULL); | |
| 498 BPF_ASSERT(broker_process_->Init(NULL)); | |
| 499 | |
| 500 initialized_ = true; | |
| 501 } | |
| 502 bool initialized() { return initialized_; } | |
| 503 class BrokerProcess* broker_process() { return broker_process_.get(); } | |
| 504 private: | |
| 505 bool initialized_; | |
| 506 scoped_ptr<class BrokerProcess> broker_process_; | |
| 507 DISALLOW_COPY_AND_ASSIGN(InitializedOpenBroker); | |
| 508 }; | |
| 509 | |
| 510 intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args, | |
| 511 void *aux) { | |
| 512 BPF_ASSERT(aux); | |
| 513 BrokerProcess* broker_process = static_cast<BrokerProcess*>(aux); | |
| 514 switch(args.nr) { | |
| 515 case __NR_open: | |
| 516 return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), | |
| 517 static_cast<int>(args.args[1])); | |
| 518 case __NR_openat: | |
| 519 // We only call open() so if we arrive here, it's because glibc uses | |
| 520 // the openat() system call. | |
| 521 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); | |
| 522 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), | |
| 523 static_cast<int>(args.args[2])); | |
| 524 default: | |
| 525 BPF_ASSERT(false); | |
| 526 return -ENOSYS; | |
| 527 } | |
| 528 } | |
| 529 | |
| 530 ErrorCode DenyOpenPolicy(int sysno, void *aux) { | |
| 531 InitializedOpenBroker* iob = static_cast<InitializedOpenBroker*>(aux); | |
| 532 if (!Sandbox::isValidSyscallNumber(sysno)) { | |
| 533 return ErrorCode(ENOSYS); | |
| 534 } | |
| 535 | |
| 536 switch (sysno) { | |
| 537 case __NR_open: | |
| 538 case __NR_openat: | |
| 539 // We get a InitializedOpenBroker class, but our trap handler wants | |
| 540 // the BrokerProcess object. | |
| 541 return ErrorCode(Sandbox::Trap(BrokerOpenTrapHandler, | |
| 542 iob->broker_process())); | |
| 543 default: | |
| 544 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
| 545 } | |
| 546 } | |
| 547 | |
| 548 // We use a InitializedOpenBroker class, so that we can run unsandboxed | |
| 549 // code in its constructor, which is the only way to do so in a BPF_TEST. | |
| 550 BPF_TEST(SandboxBpf, UseOpenBroker, DenyOpenPolicy, | |
| 551 InitializedOpenBroker /* BPF_AUX */) { | |
| 552 BPF_ASSERT(BPF_AUX.initialized()); | |
| 553 BrokerProcess* broker_process = BPF_AUX.broker_process(); | |
| 554 BPF_ASSERT(broker_process != NULL); | |
| 555 | |
| 556 // First, use the broker "manually" | |
| 557 BPF_ASSERT(broker_process->Open("/proc/denied", O_RDONLY) == -EPERM); | |
| 558 BPF_ASSERT(broker_process->Open("/proc/allowed", O_RDONLY) == -ENOENT); | |
| 559 | |
| 560 // Now use glibc's open() as an external library would. | |
| 561 BPF_ASSERT(open("/proc/denied", O_RDONLY) == -1); | |
| 562 BPF_ASSERT(errno == EPERM); | |
| 563 | |
| 564 BPF_ASSERT(open("/proc/allowed", O_RDONLY) == -1); | |
| 565 BPF_ASSERT(errno == ENOENT); | |
| 566 | |
| 567 // Also test glibc's openat(), some versions of libc use it transparently | |
| 568 // instead of open(). | |
| 569 BPF_ASSERT(openat(AT_FDCWD, "/proc/denied", O_RDONLY) == -1); | |
| 570 BPF_ASSERT(errno == EPERM); | |
| 571 | |
| 572 BPF_ASSERT(openat(AT_FDCWD, "/proc/allowed", O_RDONLY) == -1); | |
| 573 BPF_ASSERT(errno == ENOENT); | |
| 574 | |
| 575 | |
| 576 // This is also white listed and does exist. | |
| 577 int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY); | |
| 578 BPF_ASSERT(cpu_info_fd >= 0); | |
| 579 char buf[1024]; | |
| 580 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); | |
| 581 } | |
| 582 | |
| 583 } // namespace | 483 } // namespace |
| OLD | NEW |