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" |
36 #include "sandbox/linux/bpf_dsl/policy.h" | 35 #include "sandbox/linux/bpf_dsl/policy.h" |
37 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 36 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
38 #include "sandbox/linux/seccomp-bpf/die.h" | 37 #include "sandbox/linux/seccomp-bpf/die.h" |
39 #include "sandbox/linux/seccomp-bpf/errorcode.h" | 38 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
40 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" | 39 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" |
41 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 40 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
42 #include "sandbox/linux/seccomp-bpf/syscall.h" | 41 #include "sandbox/linux/seccomp-bpf/syscall.h" |
43 #include "sandbox/linux/seccomp-bpf/trap.h" | 42 #include "sandbox/linux/seccomp-bpf/trap.h" |
44 #include "sandbox/linux/services/linux_syscalls.h" | |
45 #include "sandbox/linux/services/syscall_wrappers.h" | 43 #include "sandbox/linux/services/syscall_wrappers.h" |
46 #include "sandbox/linux/services/thread_helpers.h" | 44 #include "sandbox/linux/services/thread_helpers.h" |
47 #include "sandbox/linux/syscall_broker/broker_file_permission.h" | 45 #include "sandbox/linux/system_headers/linux_syscalls.h" |
48 #include "sandbox/linux/syscall_broker/broker_process.h" | |
49 #include "sandbox/linux/tests/scoped_temporary_file.h" | 46 #include "sandbox/linux/tests/scoped_temporary_file.h" |
50 #include "sandbox/linux/tests/unit_tests.h" | 47 #include "sandbox/linux/tests/unit_tests.h" |
51 #include "testing/gtest/include/gtest/gtest.h" | 48 #include "testing/gtest/include/gtest/gtest.h" |
52 | 49 |
53 // Workaround for Android's prctl.h file. | 50 // Workaround for Android's prctl.h file. |
54 #ifndef PR_GET_ENDIAN | 51 #ifndef PR_GET_ENDIAN |
55 #define PR_GET_ENDIAN 19 | 52 #define PR_GET_ENDIAN 19 |
56 #endif | 53 #endif |
57 #ifndef PR_CAPBSET_READ | 54 #ifndef PR_CAPBSET_READ |
58 #define PR_CAPBSET_READ 23 | 55 #define PR_CAPBSET_READ 23 |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 // would make system calls, but it allows us to verify that we don't | 724 // would make system calls, but it allows us to verify that we don't |
728 // accidentally mess with errno, when we shouldn't. | 725 // accidentally mess with errno, when we shouldn't. |
729 errno = 0; | 726 errno = 0; |
730 struct arch_seccomp_data args = {}; | 727 struct arch_seccomp_data args = {}; |
731 args.nr = __NR_close; | 728 args.nr = __NR_close; |
732 args.args[0] = -1; | 729 args.args[0] = -1; |
733 BPF_ASSERT(SandboxBPF::ForwardSyscall(args) == -EBADF); | 730 BPF_ASSERT(SandboxBPF::ForwardSyscall(args) == -EBADF); |
734 BPF_ASSERT(errno == 0); | 731 BPF_ASSERT(errno == 0); |
735 } | 732 } |
736 | 733 |
737 bool NoOpCallback() { | |
738 return true; | |
739 } | |
740 | |
741 // Test a trap handler that makes use of a broker process to open(). | |
742 | |
743 class InitializedOpenBroker { | |
744 public: | |
745 InitializedOpenBroker() : initialized_(false) { | |
746 std::vector<syscall_broker::BrokerFilePermission> permissions; | |
747 permissions.push_back( | |
748 syscall_broker::BrokerFilePermission::ReadOnly("/proc/allowed")); | |
749 permissions.push_back( | |
750 syscall_broker::BrokerFilePermission::ReadOnly("/proc/cpuinfo")); | |
751 | |
752 broker_process_.reset( | |
753 new syscall_broker::BrokerProcess(EPERM, permissions)); | |
754 BPF_ASSERT(broker_process() != NULL); | |
755 BPF_ASSERT(broker_process_->Init(base::Bind(&NoOpCallback))); | |
756 | |
757 initialized_ = true; | |
758 } | |
759 bool initialized() { return initialized_; } | |
760 class syscall_broker::BrokerProcess* broker_process() { | |
761 return broker_process_.get(); | |
762 } | |
763 | |
764 private: | |
765 bool initialized_; | |
766 scoped_ptr<class syscall_broker::BrokerProcess> broker_process_; | |
767 DISALLOW_COPY_AND_ASSIGN(InitializedOpenBroker); | |
768 }; | |
769 | |
770 intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args, | |
771 void* aux) { | |
772 BPF_ASSERT(aux); | |
773 syscall_broker::BrokerProcess* broker_process = | |
774 static_cast<syscall_broker::BrokerProcess*>(aux); | |
775 switch (args.nr) { | |
776 case __NR_faccessat: // access is a wrapper of faccessat in android | |
777 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); | |
778 return broker_process->Access(reinterpret_cast<const char*>(args.args[1]), | |
779 static_cast<int>(args.args[2])); | |
780 #if defined(__NR_access) | |
781 case __NR_access: | |
782 return broker_process->Access(reinterpret_cast<const char*>(args.args[0]), | |
783 static_cast<int>(args.args[1])); | |
784 #endif | |
785 #if defined(__NR_open) | |
786 case __NR_open: | |
787 return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), | |
788 static_cast<int>(args.args[1])); | |
789 #endif | |
790 case __NR_openat: | |
791 // We only call open() so if we arrive here, it's because glibc uses | |
792 // the openat() system call. | |
793 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); | |
794 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), | |
795 static_cast<int>(args.args[2])); | |
796 default: | |
797 BPF_ASSERT(false); | |
798 return -ENOSYS; | |
799 } | |
800 } | |
801 | |
802 class DenyOpenPolicy : public Policy { | |
803 public: | |
804 explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {} | |
805 ~DenyOpenPolicy() override {} | |
806 | |
807 ResultExpr EvaluateSyscall(int sysno) const override { | |
808 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | |
809 | |
810 switch (sysno) { | |
811 case __NR_faccessat: | |
812 #if defined(__NR_access) | |
813 case __NR_access: | |
814 #endif | |
815 #if defined(__NR_open) | |
816 case __NR_open: | |
817 #endif | |
818 case __NR_openat: | |
819 // We get a InitializedOpenBroker class, but our trap handler wants | |
820 // the syscall_broker::BrokerProcess object. | |
821 return Trap(BrokerOpenTrapHandler, iob_->broker_process()); | |
822 default: | |
823 return Allow(); | |
824 } | |
825 } | |
826 | |
827 private: | |
828 InitializedOpenBroker* iob_; | |
829 | |
830 DISALLOW_COPY_AND_ASSIGN(DenyOpenPolicy); | |
831 }; | |
832 | |
833 // We use a InitializedOpenBroker class, so that we can run unsandboxed | |
834 // code in its constructor, which is the only way to do so in a BPF_TEST. | |
835 BPF_TEST(SandboxBPF, | |
836 UseOpenBroker, | |
837 DenyOpenPolicy, | |
838 InitializedOpenBroker /* (*BPF_AUX) */) { | |
839 BPF_ASSERT(BPF_AUX->initialized()); | |
840 syscall_broker::BrokerProcess* broker_process = BPF_AUX->broker_process(); | |
841 BPF_ASSERT(broker_process != NULL); | |
842 | |
843 // First, use the broker "manually" | |
844 BPF_ASSERT(broker_process->Open("/proc/denied", O_RDONLY) == -EPERM); | |
845 BPF_ASSERT(broker_process->Access("/proc/denied", R_OK) == -EPERM); | |
846 BPF_ASSERT(broker_process->Open("/proc/allowed", O_RDONLY) == -ENOENT); | |
847 BPF_ASSERT(broker_process->Access("/proc/allowed", R_OK) == -ENOENT); | |
848 | |
849 // Now use glibc's open() as an external library would. | |
850 BPF_ASSERT(open("/proc/denied", O_RDONLY) == -1); | |
851 BPF_ASSERT(errno == EPERM); | |
852 | |
853 BPF_ASSERT(open("/proc/allowed", O_RDONLY) == -1); | |
854 BPF_ASSERT(errno == ENOENT); | |
855 | |
856 // Also test glibc's openat(), some versions of libc use it transparently | |
857 // instead of open(). | |
858 BPF_ASSERT(openat(AT_FDCWD, "/proc/denied", O_RDONLY) == -1); | |
859 BPF_ASSERT(errno == EPERM); | |
860 | |
861 BPF_ASSERT(openat(AT_FDCWD, "/proc/allowed", O_RDONLY) == -1); | |
862 BPF_ASSERT(errno == ENOENT); | |
863 | |
864 // And test glibc's access(). | |
865 BPF_ASSERT(access("/proc/denied", R_OK) == -1); | |
866 BPF_ASSERT(errno == EPERM); | |
867 | |
868 BPF_ASSERT(access("/proc/allowed", R_OK) == -1); | |
869 BPF_ASSERT(errno == ENOENT); | |
870 | |
871 // This is also white listed and does exist. | |
872 int cpu_info_access = access("/proc/cpuinfo", R_OK); | |
873 BPF_ASSERT(cpu_info_access == 0); | |
874 int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY); | |
875 BPF_ASSERT(cpu_info_fd >= 0); | |
876 char buf[1024]; | |
877 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); | |
878 } | |
879 | |
880 // Simple test demonstrating how to use SandboxBPF::Cond() | 734 // Simple test demonstrating how to use SandboxBPF::Cond() |
881 | 735 |
882 class SimpleCondTestPolicy : public Policy { | 736 class SimpleCondTestPolicy : public Policy { |
883 public: | 737 public: |
884 SimpleCondTestPolicy() {} | 738 SimpleCondTestPolicy() {} |
885 ~SimpleCondTestPolicy() override {} | 739 ~SimpleCondTestPolicy() override {} |
886 | 740 |
887 ResultExpr EvaluateSyscall(int sysno) const override; | 741 ResultExpr EvaluateSyscall(int sysno) const override; |
888 | 742 |
889 private: | 743 private: |
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2390 BPF_ASSERT_EQ(ENOSYS, errno); | 2244 BPF_ASSERT_EQ(ENOSYS, errno); |
2391 | 2245 |
2392 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300)); | 2246 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300)); |
2393 BPF_ASSERT_EQ(EPERM, errno); | 2247 BPF_ASSERT_EQ(EPERM, errno); |
2394 } | 2248 } |
2395 | 2249 |
2396 } // namespace | 2250 } // namespace |
2397 | 2251 |
2398 } // namespace bpf_dsl | 2252 } // namespace bpf_dsl |
2399 } // namespace sandbox | 2253 } // namespace sandbox |
OLD | NEW |