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 10 matching lines...) Expand all Loading... |
21 #endif | 21 #endif |
22 #include <linux/futex.h> | 22 #include <linux/futex.h> |
23 | 23 |
24 #include <ostream> | 24 #include <ostream> |
25 | 25 |
26 #include "base/bind.h" | 26 #include "base/bind.h" |
27 #include "base/logging.h" | 27 #include "base/logging.h" |
28 #include "base/macros.h" | 28 #include "base/macros.h" |
29 #include "base/memory/scoped_ptr.h" | 29 #include "base/memory/scoped_ptr.h" |
30 #include "base/posix/eintr_wrapper.h" | 30 #include "base/posix/eintr_wrapper.h" |
| 31 #include "base/synchronization/waitable_event.h" |
| 32 #include "base/threading/thread.h" |
31 #include "build/build_config.h" | 33 #include "build/build_config.h" |
32 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 34 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
33 #include "sandbox/linux/seccomp-bpf/syscall.h" | 35 #include "sandbox/linux/seccomp-bpf/syscall.h" |
34 #include "sandbox/linux/seccomp-bpf/trap.h" | 36 #include "sandbox/linux/seccomp-bpf/trap.h" |
35 #include "sandbox/linux/seccomp-bpf/verifier.h" | 37 #include "sandbox/linux/seccomp-bpf/verifier.h" |
36 #include "sandbox/linux/services/broker_process.h" | 38 #include "sandbox/linux/services/broker_process.h" |
37 #include "sandbox/linux/services/linux_syscalls.h" | 39 #include "sandbox/linux/services/linux_syscalls.h" |
38 #include "sandbox/linux/tests/scoped_temporary_file.h" | 40 #include "sandbox/linux/tests/scoped_temporary_file.h" |
39 #include "sandbox/linux/tests/unit_tests.h" | 41 #include "sandbox/linux/tests/unit_tests.h" |
40 #include "testing/gtest/include/gtest/gtest.h" | 42 #include "testing/gtest/include/gtest/gtest.h" |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { | 146 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
145 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 147 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
146 switch (sysno) { | 148 switch (sysno) { |
147 case __NR_nanosleep: | 149 case __NR_nanosleep: |
148 return ErrorCode(EACCES); | 150 return ErrorCode(EACCES); |
149 default: | 151 default: |
150 return ErrorCode(ErrorCode::ERR_ALLOWED); | 152 return ErrorCode(ErrorCode::ERR_ALLOWED); |
151 } | 153 } |
152 } | 154 } |
153 | 155 |
| 156 static void AssertNanosleepFails() { |
| 157 const struct timespec ts = {0, 0}; |
| 158 errno = 0; |
| 159 BPF_ASSERT_EQ(-1, HANDLE_EINTR(syscall(__NR_nanosleep, &ts, NULL))); |
| 160 BPF_ASSERT_EQ(EACCES, errno); |
| 161 } |
| 162 |
154 private: | 163 private: |
155 DISALLOW_COPY_AND_ASSIGN(BlacklistNanosleepPolicy); | 164 DISALLOW_COPY_AND_ASSIGN(BlacklistNanosleepPolicy); |
156 }; | 165 }; |
157 | 166 |
158 BPF_TEST_C(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { | 167 BPF_TEST_C(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { |
159 // nanosleep() should be denied | 168 BlacklistNanosleepPolicy::AssertNanosleepFails(); |
160 const struct timespec ts = {0, 0}; | |
161 errno = 0; | |
162 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); | |
163 BPF_ASSERT(errno == EACCES); | |
164 } | 169 } |
165 | 170 |
166 // Now do a simple whitelist test | 171 // Now do a simple whitelist test |
167 | 172 |
168 class WhitelistGetpidPolicy : public SandboxBPFPolicy { | 173 class WhitelistGetpidPolicy : public SandboxBPFPolicy { |
169 public: | 174 public: |
170 WhitelistGetpidPolicy() {} | 175 WhitelistGetpidPolicy() {} |
171 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { | 176 virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
172 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); | 177 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
173 switch (sysno) { | 178 switch (sysno) { |
(...skipping 1993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2167 BPF_ASSERT(FullPread64(temp_file.fd(), | 2172 BPF_ASSERT(FullPread64(temp_file.fd(), |
2168 read_test_string, | 2173 read_test_string, |
2169 sizeof(read_test_string), | 2174 sizeof(read_test_string), |
2170 kLargeOffset)); | 2175 kLargeOffset)); |
2171 BPF_ASSERT_EQ(0, memcmp(kTestString, read_test_string, sizeof(kTestString))); | 2176 BPF_ASSERT_EQ(0, memcmp(kTestString, read_test_string, sizeof(kTestString))); |
2172 BPF_ASSERT(pread_64_was_forwarded); | 2177 BPF_ASSERT(pread_64_was_forwarded); |
2173 } | 2178 } |
2174 | 2179 |
2175 #endif // !defined(OS_ANDROID) | 2180 #endif // !defined(OS_ANDROID) |
2176 | 2181 |
| 2182 void* TsyncApplyToTwoThreadsFunc(void* cond_ptr) { |
| 2183 base::WaitableEvent* event = static_cast<base::WaitableEvent*>(cond_ptr); |
| 2184 |
| 2185 // Wait for the main thread to signal that the filter has been applied. |
| 2186 if (!event->IsSignaled()) { |
| 2187 event->Wait(); |
| 2188 } |
| 2189 |
| 2190 BPF_ASSERT(event->IsSignaled()); |
| 2191 |
| 2192 BlacklistNanosleepPolicy::AssertNanosleepFails(); |
| 2193 |
| 2194 return NULL; |
| 2195 } |
| 2196 |
| 2197 SANDBOX_TEST(SandboxBPF, Tsync) { |
| 2198 if (SandboxBPF::SupportsSeccompThreadFilterSynchronization() != |
| 2199 SandboxBPF::STATUS_AVAILABLE) { |
| 2200 return; |
| 2201 } |
| 2202 |
| 2203 base::WaitableEvent event(true, false); |
| 2204 |
| 2205 // Create a thread on which to invoke the blocked syscall. |
| 2206 pthread_t thread; |
| 2207 BPF_ASSERT_EQ(0, |
| 2208 pthread_create(&thread, NULL, &TsyncApplyToTwoThreadsFunc, &event)); |
| 2209 |
| 2210 // Test that nanoseelp success. |
| 2211 const struct timespec ts = {0, 0}; |
| 2212 BPF_ASSERT_EQ(0, HANDLE_EINTR(syscall(__NR_nanosleep, &ts, NULL))); |
| 2213 |
| 2214 // Engage the sandbox. |
| 2215 SandboxBPF sandbox; |
| 2216 sandbox.SetSandboxPolicy(new BlacklistNanosleepPolicy()); |
| 2217 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_MULTI_THREADED)); |
| 2218 |
| 2219 // This thread should have the filter applied as well. |
| 2220 BlacklistNanosleepPolicy::AssertNanosleepFails(); |
| 2221 |
| 2222 // Signal the condition to invoke the system call. |
| 2223 event.Signal(); |
| 2224 |
| 2225 // Wait for the thread to finish. |
| 2226 BPF_ASSERT_EQ(0, pthread_join(thread, NULL)); |
| 2227 } |
| 2228 |
| 2229 class AllowAllPolicy : public SandboxBPFPolicy { |
| 2230 public: |
| 2231 AllowAllPolicy() : SandboxBPFPolicy() {} |
| 2232 virtual ~AllowAllPolicy() {} |
| 2233 |
| 2234 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
| 2235 int sysno) const OVERRIDE { |
| 2236 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 2237 } |
| 2238 |
| 2239 private: |
| 2240 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy); |
| 2241 }; |
| 2242 |
| 2243 SANDBOX_DEATH_TEST(SandboxBPF, StartMultiThreadedAsSingleThreaded, |
| 2244 DEATH_MESSAGE("Cannot start sandbox; process is already multi-threaded")) { |
| 2245 base::Thread thread("sandbox.linux.StartMultiThreadedAsSingleThreaded"); |
| 2246 BPF_ASSERT(thread.Start()); |
| 2247 |
| 2248 SandboxBPF sandbox; |
| 2249 sandbox.SetSandboxPolicy(new AllowAllPolicy()); |
| 2250 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); |
| 2251 } |
| 2252 |
| 2253 SANDBOX_DEATH_TEST(SandboxBPF, StartSingleThreadedAsMultiThreaded, |
| 2254 DEATH_MESSAGE("Cannot start sandbox; process may be single-threaded when " |
| 2255 "reported as not")) { |
| 2256 SandboxBPF sandbox; |
| 2257 sandbox.SetSandboxPolicy(new AllowAllPolicy()); |
| 2258 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::PROCESS_MULTI_THREADED)); |
| 2259 } |
| 2260 |
2177 } // namespace | 2261 } // namespace |
2178 | 2262 |
2179 } // namespace sandbox | 2263 } // namespace sandbox |
OLD | NEW |