Chromium Code Reviews| 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 |