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 <errno.h> | 5 #include <errno.h> |
6 #include <pthread.h> | 6 #include <pthread.h> |
7 #include <sched.h> | 7 #include <sched.h> |
8 #include <signal.h> | 8 #include <signal.h> |
9 #include <sys/prctl.h> | 9 #include <sys/prctl.h> |
10 #include <sys/ptrace.h> | 10 #include <sys/ptrace.h> |
(...skipping 16 matching lines...) Expand all Loading... | |
27 #include "base/macros.h" | 27 #include "base/macros.h" |
28 #include "base/memory/scoped_ptr.h" | 28 #include "base/memory/scoped_ptr.h" |
29 #include "base/posix/eintr_wrapper.h" | 29 #include "base/posix/eintr_wrapper.h" |
30 #include "build/build_config.h" | 30 #include "build/build_config.h" |
31 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 31 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
32 #include "sandbox/linux/seccomp-bpf/syscall.h" | 32 #include "sandbox/linux/seccomp-bpf/syscall.h" |
33 #include "sandbox/linux/seccomp-bpf/trap.h" | 33 #include "sandbox/linux/seccomp-bpf/trap.h" |
34 #include "sandbox/linux/seccomp-bpf/verifier.h" | 34 #include "sandbox/linux/seccomp-bpf/verifier.h" |
35 #include "sandbox/linux/services/broker_process.h" | 35 #include "sandbox/linux/services/broker_process.h" |
36 #include "sandbox/linux/services/linux_syscalls.h" | 36 #include "sandbox/linux/services/linux_syscalls.h" |
37 #include "sandbox/linux/tests/scoped_temporary_file.h" | |
37 #include "sandbox/linux/tests/unit_tests.h" | 38 #include "sandbox/linux/tests/unit_tests.h" |
38 #include "testing/gtest/include/gtest/gtest.h" | 39 #include "testing/gtest/include/gtest/gtest.h" |
39 | 40 |
40 // Workaround for Android's prctl.h file. | 41 // Workaround for Android's prctl.h file. |
41 #ifndef PR_GET_ENDIAN | 42 #ifndef PR_GET_ENDIAN |
42 #define PR_GET_ENDIAN 19 | 43 #define PR_GET_ENDIAN 19 |
43 #endif | 44 #endif |
44 #ifndef PR_CAPBSET_READ | 45 #ifndef PR_CAPBSET_READ |
45 #define PR_CAPBSET_READ 23 | 46 #define PR_CAPBSET_READ 23 |
46 #define PR_CAPBSET_DROP 24 | 47 #define PR_CAPBSET_DROP 24 |
47 #endif | 48 #endif |
48 | 49 |
49 namespace sandbox { | 50 namespace sandbox { |
50 | 51 |
51 namespace { | 52 namespace { |
52 | 53 |
53 const int kExpectedReturnValue = 42; | 54 const int kExpectedReturnValue = 42; |
54 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; | 55 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; |
55 | 56 |
57 // Set the global environment to allow the use of UnsafeTrap() policies. | |
58 void EnableUnsafeTraps() { | |
59 // The use of UnsafeTrap() causes us to print a warning message. This is | |
60 // generally desirable, but it results in the unittest failing, as it doesn't | |
61 // expect any messages on "stderr". So, temporarily disable messages. The | |
62 // BPF_TEST() is guaranteed to turn messages back on, after the policy | |
63 // function has completed. | |
64 setenv(kSandboxDebuggingEnv, "t", 0); | |
65 Die::SuppressInfoMessages(true); | |
66 } | |
67 | |
56 // This test should execute no matter whether we have kernel support. So, | 68 // This test should execute no matter whether we have kernel support. So, |
57 // we make it a TEST() instead of a BPF_TEST(). | 69 // we make it a TEST() instead of a BPF_TEST(). |
58 TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupports)) { | 70 TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupports)) { |
59 // We check that we don't crash, but it's ok if the kernel doesn't | 71 // We check that we don't crash, but it's ok if the kernel doesn't |
60 // support it. | 72 // support it. |
61 bool seccomp_bpf_supported = | 73 bool seccomp_bpf_supported = |
62 SandboxBPF::SupportsSeccompSandbox(-1) == SandboxBPF::STATUS_AVAILABLE; | 74 SandboxBPF::SupportsSeccompSandbox(-1) == SandboxBPF::STATUS_AVAILABLE; |
63 // We want to log whether or not seccomp BPF is actually supported | 75 // We want to log whether or not seccomp BPF is actually supported |
64 // since actual test coverage depends on it. | 76 // since actual test coverage depends on it. |
65 RecordProperty("SeccompBPFSupported", | 77 RecordProperty("SeccompBPFSupported", |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
473 // Verify that within the callback function all filtering is temporarily | 485 // Verify that within the callback function all filtering is temporarily |
474 // disabled. | 486 // disabled. |
475 BPF_ASSERT(syscall(__NR_getpid) > 1); | 487 BPF_ASSERT(syscall(__NR_getpid) > 1); |
476 | 488 |
477 // Verify that we can now call the underlying system call without causing | 489 // Verify that we can now call the underlying system call without causing |
478 // infinite recursion. | 490 // infinite recursion. |
479 return SandboxBPF::ForwardSyscall(args); | 491 return SandboxBPF::ForwardSyscall(args); |
480 } | 492 } |
481 | 493 |
482 ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, int* aux) { | 494 ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, int* aux) { |
483 // The use of UnsafeTrap() causes us to print a warning message. This is | 495 // Set the global environment for unsafe traps once. |
484 // generally desirable, but it results in the unittest failing, as it doesn't | 496 if (sysno == MIN_SYSCALL) { |
485 // expect any messages on "stderr". So, temporarily disable messages. The | 497 EnableUnsafeTraps(); |
486 // BPF_TEST() is guaranteed to turn messages back on, after the policy | 498 } |
487 // function has completed. | |
488 setenv(kSandboxDebuggingEnv, "t", 0); | |
489 Die::SuppressInfoMessages(true); | |
490 | 499 |
491 // Some system calls must always be allowed, if our policy wants to make | 500 // Some system calls must always be allowed, if our policy wants to make |
492 // use of UnsafeTrap() | 501 // use of UnsafeTrap() |
493 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn | 502 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn |
494 #if defined(__NR_sigprocmask) | 503 #if defined(__NR_sigprocmask) |
495 || | 504 || |
496 sysno == __NR_sigprocmask | 505 sysno == __NR_sigprocmask |
497 #endif | 506 #endif |
498 #if defined(__NR_sigreturn) | 507 #if defined(__NR_sigreturn) |
499 || | 508 || |
(...skipping 1552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2052 | 2061 |
2053 default: | 2062 default: |
2054 // Allow all other syscalls. | 2063 // Allow all other syscalls. |
2055 break; | 2064 break; |
2056 } | 2065 } |
2057 | 2066 |
2058 BPF_ASSERT_NE(-1, ptrace(PTRACE_CONT, pid, NULL, NULL)); | 2067 BPF_ASSERT_NE(-1, ptrace(PTRACE_CONT, pid, NULL, NULL)); |
2059 } | 2068 } |
2060 } | 2069 } |
2061 | 2070 |
2071 // Android does not expose pread64 nor pwrite64. | |
2072 #if !defined(OS_ANDROID) | |
2073 | |
2074 bool FullPwrite64(int fd, const char* buffer, size_t count, off64_t offset) { | |
2075 while (count > 0) { | |
2076 const ssize_t transfered = | |
2077 HANDLE_EINTR(pwrite64(fd, buffer, count, offset)); | |
2078 if (transfered <= 0 || static_cast<size_t>(transfered) > count) { | |
2079 return false; | |
2080 } | |
2081 count -= transfered; | |
2082 buffer += transfered; | |
2083 offset += transfered; | |
2084 } | |
2085 return true; | |
2086 } | |
2087 | |
2088 bool FullPread64(int fd, char* buffer, size_t count, off64_t offset) { | |
2089 while (count > 0) { | |
2090 const ssize_t transfered = HANDLE_EINTR(pread64(fd, buffer, count, offset)); | |
2091 if (transfered <= 0 || static_cast<size_t>(transfered) > count) { | |
2092 return false; | |
2093 } | |
2094 count -= transfered; | |
2095 buffer += transfered; | |
2096 offset += transfered; | |
2097 } | |
2098 return true; | |
2099 } | |
2100 | |
2101 bool pread_64_was_forwarded = false; | |
2102 | |
2103 class TrapPread64Policy : public SandboxBPFPolicy { | |
2104 public: | |
2105 TrapPread64Policy() {} | |
2106 virtual ~TrapPread64Policy() {} | |
2107 | |
2108 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, | |
2109 int system_call_number) const OVERRIDE { | |
2110 // Set the global environment for unsafe traps once. | |
2111 if (system_call_number == MIN_SYSCALL) { | |
2112 EnableUnsafeTraps(); | |
2113 } | |
2114 | |
2115 if (system_call_number == __NR_pread64) { | |
2116 return sandbox_compiler->UnsafeTrap(ForwardPreadHandler, NULL); | |
2117 } | |
2118 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
2119 } | |
2120 | |
2121 private: | |
2122 static intptr_t ForwardPreadHandler(const struct arch_seccomp_data& args, | |
2123 void* aux) { | |
2124 BPF_ASSERT(args.nr == __NR_pread64); | |
2125 pread_64_was_forwarded = true; | |
2126 | |
2127 return SandboxBPF::ForwardSyscall(args); | |
2128 } | |
2129 DISALLOW_COPY_AND_ASSIGN(TrapPread64Policy); | |
2130 }; | |
2131 | |
2132 // pread(2) takes a 64 bits offset. On 32 bits systems, it will be split | |
2133 // between two arguments. In this test, we make sure that ForwardSyscall() can | |
2134 // forward it properly. | |
2135 BPF_TEST_C(SandboxBPF, Pread64, TrapPread64Policy) { | |
2136 ScopedTemporaryFile temp_file; | |
2137 const uint64_t kLargeOffset = (static_cast<uint64_t>(1) << 32) | 0xBEEF; | |
mdempsky
2014/06/27 00:37:24
Might also be worth testing an offset in [2^31, 2^
jln (very slow on Chromium)
2014/06/27 01:25:14
Great point! I'll land as-is because of a time con
| |
2138 const char kTestString[] = "This is a test!"; | |
2139 BPF_ASSERT(FullPwrite64( | |
2140 temp_file.fd(), kTestString, sizeof(kTestString), kLargeOffset)); | |
2141 | |
2142 char read_test_string[sizeof(kTestString)] = {0}; | |
2143 BPF_ASSERT(FullPread64(temp_file.fd(), | |
2144 read_test_string, | |
2145 sizeof(read_test_string), | |
2146 kLargeOffset)); | |
2147 BPF_ASSERT_EQ(0, memcmp(kTestString, read_test_string, sizeof(kTestString))); | |
2148 BPF_ASSERT(pread_64_was_forwarded); | |
2149 } | |
2150 | |
2151 #endif // !defined(OS_ANDROID) | |
2152 | |
2062 } // namespace | 2153 } // namespace |
2063 | 2154 |
2064 } // namespace sandbox | 2155 } // namespace sandbox |
OLD | NEW |