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

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc

Issue 348853006: Linux sandbox: add test to ensure that pread64 can be forwarded. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Exclude Android from new test. Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « sandbox/linux/sandbox_linux_test_sources.gypi ('k') | sandbox/linux/seccomp-bpf/syscall_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698