| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "sandbox/linux/bpf_dsl/bpf_dsl.h" | |
| 6 | |
| 7 #include <errno.h> | 5 #include <errno.h> |
| 8 #include <fcntl.h> | 6 #include <fcntl.h> |
| 9 #include <pthread.h> | 7 #include <pthread.h> |
| 10 #include <sched.h> | 8 #include <sched.h> |
| 11 #include <signal.h> | 9 #include <signal.h> |
| 12 #include <sys/prctl.h> | 10 #include <sys/prctl.h> |
| 13 #include <sys/ptrace.h> | 11 #include <sys/ptrace.h> |
| 14 #include <sys/syscall.h> | 12 #include <sys/syscall.h> |
| 15 #include <sys/time.h> | 13 #include <sys/time.h> |
| 16 #include <sys/types.h> | 14 #include <sys/types.h> |
| 17 #include <sys/utsname.h> | 15 #include <sys/utsname.h> |
| 18 #include <unistd.h> | 16 #include <unistd.h> |
| 19 #include <sys/socket.h> | 17 #include <sys/socket.h> |
| 20 | 18 |
| 21 #if defined(ANDROID) | 19 #if defined(ANDROID) |
| 22 // Work-around for buggy headers in Android's NDK | 20 // Work-around for buggy headers in Android's NDK |
| 23 #define __user | 21 #define __user |
| 24 #endif | 22 #endif |
| 25 #include <linux/futex.h> | 23 #include <linux/futex.h> |
| 26 | 24 |
| 27 #include "base/bind.h" | 25 #include "base/bind.h" |
| 28 #include "base/logging.h" | 26 #include "base/logging.h" |
| 29 #include "base/macros.h" | 27 #include "base/macros.h" |
| 30 #include "base/memory/scoped_ptr.h" | 28 #include "base/memory/scoped_ptr.h" |
| 31 #include "base/posix/eintr_wrapper.h" | 29 #include "base/posix/eintr_wrapper.h" |
| 32 #include "base/synchronization/waitable_event.h" | 30 #include "base/synchronization/waitable_event.h" |
| 33 #include "base/sys_info.h" | 31 #include "base/sys_info.h" |
| 34 #include "base/threading/thread.h" | 32 #include "base/threading/thread.h" |
| 35 #include "build/build_config.h" | 33 #include "build/build_config.h" |
| 34 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" |
| 35 #include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h" |
| 36 #include "sandbox/linux/bpf_dsl/policy.h" | 36 #include "sandbox/linux/bpf_dsl/policy.h" |
| 37 #include "sandbox/linux/bpf_dsl/seccomp_macros.h" |
| 37 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 38 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
| 38 #include "sandbox/linux/seccomp-bpf/die.h" | 39 #include "sandbox/linux/seccomp-bpf/die.h" |
| 39 #include "sandbox/linux/seccomp-bpf/errorcode.h" | 40 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
| 40 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" | |
| 41 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 41 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
| 42 #include "sandbox/linux/seccomp-bpf/syscall.h" | 42 #include "sandbox/linux/seccomp-bpf/syscall.h" |
| 43 #include "sandbox/linux/seccomp-bpf/trap.h" | 43 #include "sandbox/linux/seccomp-bpf/trap.h" |
| 44 #include "sandbox/linux/services/linux_syscalls.h" | |
| 45 #include "sandbox/linux/services/syscall_wrappers.h" | 44 #include "sandbox/linux/services/syscall_wrappers.h" |
| 46 #include "sandbox/linux/syscall_broker/broker_file_permission.h" | 45 #include "sandbox/linux/services/thread_helpers.h" |
| 47 #include "sandbox/linux/syscall_broker/broker_process.h" | 46 #include "sandbox/linux/system_headers/linux_syscalls.h" |
| 48 #include "sandbox/linux/tests/scoped_temporary_file.h" | 47 #include "sandbox/linux/tests/scoped_temporary_file.h" |
| 49 #include "sandbox/linux/tests/unit_tests.h" | 48 #include "sandbox/linux/tests/unit_tests.h" |
| 50 #include "testing/gtest/include/gtest/gtest.h" | 49 #include "testing/gtest/include/gtest/gtest.h" |
| 51 | 50 |
| 52 // Workaround for Android's prctl.h file. | 51 // Workaround for Android's prctl.h file. |
| 53 #ifndef PR_GET_ENDIAN | 52 #ifndef PR_GET_ENDIAN |
| 54 #define PR_GET_ENDIAN 19 | 53 #define PR_GET_ENDIAN 19 |
| 55 #endif | 54 #endif |
| 56 #ifndef PR_CAPBSET_READ | 55 #ifndef PR_CAPBSET_READ |
| 57 #define PR_CAPBSET_READ 23 | 56 #define PR_CAPBSET_READ 23 |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 // would make system calls, but it allows us to verify that we don't | 725 // would make system calls, but it allows us to verify that we don't |
| 727 // accidentally mess with errno, when we shouldn't. | 726 // accidentally mess with errno, when we shouldn't. |
| 728 errno = 0; | 727 errno = 0; |
| 729 struct arch_seccomp_data args = {}; | 728 struct arch_seccomp_data args = {}; |
| 730 args.nr = __NR_close; | 729 args.nr = __NR_close; |
| 731 args.args[0] = -1; | 730 args.args[0] = -1; |
| 732 BPF_ASSERT(SandboxBPF::ForwardSyscall(args) == -EBADF); | 731 BPF_ASSERT(SandboxBPF::ForwardSyscall(args) == -EBADF); |
| 733 BPF_ASSERT(errno == 0); | 732 BPF_ASSERT(errno == 0); |
| 734 } | 733 } |
| 735 | 734 |
| 736 bool NoOpCallback() { | |
| 737 return true; | |
| 738 } | |
| 739 | |
| 740 // Test a trap handler that makes use of a broker process to open(). | |
| 741 | |
| 742 class InitializedOpenBroker { | |
| 743 public: | |
| 744 InitializedOpenBroker() : initialized_(false) { | |
| 745 std::vector<syscall_broker::BrokerFilePermission> permissions; | |
| 746 permissions.push_back( | |
| 747 syscall_broker::BrokerFilePermission::ReadOnly("/proc/allowed")); | |
| 748 permissions.push_back( | |
| 749 syscall_broker::BrokerFilePermission::ReadOnly("/proc/cpuinfo")); | |
| 750 | |
| 751 broker_process_.reset( | |
| 752 new syscall_broker::BrokerProcess(EPERM, permissions)); | |
| 753 BPF_ASSERT(broker_process() != NULL); | |
| 754 BPF_ASSERT(broker_process_->Init(base::Bind(&NoOpCallback))); | |
| 755 | |
| 756 initialized_ = true; | |
| 757 } | |
| 758 bool initialized() { return initialized_; } | |
| 759 class syscall_broker::BrokerProcess* broker_process() { | |
| 760 return broker_process_.get(); | |
| 761 } | |
| 762 | |
| 763 private: | |
| 764 bool initialized_; | |
| 765 scoped_ptr<class syscall_broker::BrokerProcess> broker_process_; | |
| 766 DISALLOW_COPY_AND_ASSIGN(InitializedOpenBroker); | |
| 767 }; | |
| 768 | |
| 769 intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args, | |
| 770 void* aux) { | |
| 771 BPF_ASSERT(aux); | |
| 772 syscall_broker::BrokerProcess* broker_process = | |
| 773 static_cast<syscall_broker::BrokerProcess*>(aux); | |
| 774 switch (args.nr) { | |
| 775 case __NR_faccessat: // access is a wrapper of faccessat in android | |
| 776 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); | |
| 777 return broker_process->Access(reinterpret_cast<const char*>(args.args[1]), | |
| 778 static_cast<int>(args.args[2])); | |
| 779 #if defined(__NR_access) | |
| 780 case __NR_access: | |
| 781 return broker_process->Access(reinterpret_cast<const char*>(args.args[0]), | |
| 782 static_cast<int>(args.args[1])); | |
| 783 #endif | |
| 784 #if defined(__NR_open) | |
| 785 case __NR_open: | |
| 786 return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), | |
| 787 static_cast<int>(args.args[1])); | |
| 788 #endif | |
| 789 case __NR_openat: | |
| 790 // We only call open() so if we arrive here, it's because glibc uses | |
| 791 // the openat() system call. | |
| 792 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); | |
| 793 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), | |
| 794 static_cast<int>(args.args[2])); | |
| 795 default: | |
| 796 BPF_ASSERT(false); | |
| 797 return -ENOSYS; | |
| 798 } | |
| 799 } | |
| 800 | |
| 801 class DenyOpenPolicy : public Policy { | |
| 802 public: | |
| 803 explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {} | |
| 804 ~DenyOpenPolicy() override {} | |
| 805 | |
| 806 ResultExpr EvaluateSyscall(int sysno) const override { | |
| 807 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | |
| 808 | |
| 809 switch (sysno) { | |
| 810 case __NR_faccessat: | |
| 811 #if defined(__NR_access) | |
| 812 case __NR_access: | |
| 813 #endif | |
| 814 #if defined(__NR_open) | |
| 815 case __NR_open: | |
| 816 #endif | |
| 817 case __NR_openat: | |
| 818 // We get a InitializedOpenBroker class, but our trap handler wants | |
| 819 // the syscall_broker::BrokerProcess object. | |
| 820 return Trap(BrokerOpenTrapHandler, iob_->broker_process()); | |
| 821 default: | |
| 822 return Allow(); | |
| 823 } | |
| 824 } | |
| 825 | |
| 826 private: | |
| 827 InitializedOpenBroker* iob_; | |
| 828 | |
| 829 DISALLOW_COPY_AND_ASSIGN(DenyOpenPolicy); | |
| 830 }; | |
| 831 | |
| 832 // We use a InitializedOpenBroker class, so that we can run unsandboxed | |
| 833 // code in its constructor, which is the only way to do so in a BPF_TEST. | |
| 834 BPF_TEST(SandboxBPF, | |
| 835 UseOpenBroker, | |
| 836 DenyOpenPolicy, | |
| 837 InitializedOpenBroker /* (*BPF_AUX) */) { | |
| 838 BPF_ASSERT(BPF_AUX->initialized()); | |
| 839 syscall_broker::BrokerProcess* broker_process = BPF_AUX->broker_process(); | |
| 840 BPF_ASSERT(broker_process != NULL); | |
| 841 | |
| 842 // First, use the broker "manually" | |
| 843 BPF_ASSERT(broker_process->Open("/proc/denied", O_RDONLY) == -EPERM); | |
| 844 BPF_ASSERT(broker_process->Access("/proc/denied", R_OK) == -EPERM); | |
| 845 BPF_ASSERT(broker_process->Open("/proc/allowed", O_RDONLY) == -ENOENT); | |
| 846 BPF_ASSERT(broker_process->Access("/proc/allowed", R_OK) == -ENOENT); | |
| 847 | |
| 848 // Now use glibc's open() as an external library would. | |
| 849 BPF_ASSERT(open("/proc/denied", O_RDONLY) == -1); | |
| 850 BPF_ASSERT(errno == EPERM); | |
| 851 | |
| 852 BPF_ASSERT(open("/proc/allowed", O_RDONLY) == -1); | |
| 853 BPF_ASSERT(errno == ENOENT); | |
| 854 | |
| 855 // Also test glibc's openat(), some versions of libc use it transparently | |
| 856 // instead of open(). | |
| 857 BPF_ASSERT(openat(AT_FDCWD, "/proc/denied", O_RDONLY) == -1); | |
| 858 BPF_ASSERT(errno == EPERM); | |
| 859 | |
| 860 BPF_ASSERT(openat(AT_FDCWD, "/proc/allowed", O_RDONLY) == -1); | |
| 861 BPF_ASSERT(errno == ENOENT); | |
| 862 | |
| 863 // And test glibc's access(). | |
| 864 BPF_ASSERT(access("/proc/denied", R_OK) == -1); | |
| 865 BPF_ASSERT(errno == EPERM); | |
| 866 | |
| 867 BPF_ASSERT(access("/proc/allowed", R_OK) == -1); | |
| 868 BPF_ASSERT(errno == ENOENT); | |
| 869 | |
| 870 // This is also white listed and does exist. | |
| 871 int cpu_info_access = access("/proc/cpuinfo", R_OK); | |
| 872 BPF_ASSERT(cpu_info_access == 0); | |
| 873 int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY); | |
| 874 BPF_ASSERT(cpu_info_fd >= 0); | |
| 875 char buf[1024]; | |
| 876 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); | |
| 877 } | |
| 878 | |
| 879 // Simple test demonstrating how to use SandboxBPF::Cond() | 735 // Simple test demonstrating how to use SandboxBPF::Cond() |
| 880 | 736 |
| 881 class SimpleCondTestPolicy : public Policy { | 737 class SimpleCondTestPolicy : public Policy { |
| 882 public: | 738 public: |
| 883 SimpleCondTestPolicy() {} | 739 SimpleCondTestPolicy() {} |
| 884 ~SimpleCondTestPolicy() override {} | 740 ~SimpleCondTestPolicy() override {} |
| 885 | 741 |
| 886 ResultExpr EvaluateSyscall(int sysno) const override; | 742 ResultExpr EvaluateSyscall(int sysno) const override; |
| 887 | 743 |
| 888 private: | 744 private: |
| (...skipping 1412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2301 | 2157 |
| 2302 ResultExpr EvaluateSyscall(int sysno) const override { return Allow(); } | 2158 ResultExpr EvaluateSyscall(int sysno) const override { return Allow(); } |
| 2303 | 2159 |
| 2304 private: | 2160 private: |
| 2305 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy); | 2161 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy); |
| 2306 }; | 2162 }; |
| 2307 | 2163 |
| 2308 SANDBOX_DEATH_TEST( | 2164 SANDBOX_DEATH_TEST( |
| 2309 SandboxBPF, | 2165 SandboxBPF, |
| 2310 StartMultiThreadedAsSingleThreaded, | 2166 StartMultiThreadedAsSingleThreaded, |
| 2311 DEATH_MESSAGE("Cannot start sandbox; process is already multi-threaded")) { | 2167 DEATH_MESSAGE( |
| 2168 ThreadHelpers::GetAssertSingleThreadedErrorMessageForTests())) { |
| 2312 base::Thread thread("sandbox.linux.StartMultiThreadedAsSingleThreaded"); | 2169 base::Thread thread("sandbox.linux.StartMultiThreadedAsSingleThreaded"); |
| 2313 BPF_ASSERT(thread.Start()); | 2170 BPF_ASSERT(thread.Start()); |
| 2314 | 2171 |
| 2315 SandboxBPF sandbox(new AllowAllPolicy()); | 2172 SandboxBPF sandbox(new AllowAllPolicy()); |
| 2316 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED)); | 2173 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED)); |
| 2317 } | 2174 } |
| 2318 | 2175 |
| 2319 // http://crbug.com/407357 | 2176 // http://crbug.com/407357 |
| 2320 #if !defined(THREAD_SANITIZER) | 2177 #if !defined(THREAD_SANITIZER) |
| 2321 SANDBOX_DEATH_TEST( | 2178 SANDBOX_DEATH_TEST( |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2388 BPF_ASSERT_EQ(ENOSYS, errno); | 2245 BPF_ASSERT_EQ(ENOSYS, errno); |
| 2389 | 2246 |
| 2390 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300)); | 2247 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300)); |
| 2391 BPF_ASSERT_EQ(EPERM, errno); | 2248 BPF_ASSERT_EQ(EPERM, errno); |
| 2392 } | 2249 } |
| 2393 | 2250 |
| 2394 } // namespace | 2251 } // namespace |
| 2395 | 2252 |
| 2396 } // namespace bpf_dsl | 2253 } // namespace bpf_dsl |
| 2397 } // namespace sandbox | 2254 } // namespace sandbox |
| OLD | NEW |