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

Side by Side Diff: sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc

Issue 935333002: Update from https://crrev.com/316786 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 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
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « sandbox/linux/integration_tests/DEPS ('k') | sandbox/linux/integration_tests/namespace_unix_domain_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698