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

Side by Side Diff: sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc

Issue 759473002: Linux sandbox: change seccomp detection and initialization. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor_startsandbox
Patch Set: Get rid of SeccompLevel::INVALID Created 6 years 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 (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 "sandbox/linux/bpf_dsl/bpf_dsl.h" 5 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <pthread.h> 9 #include <pthread.h>
10 #include <sched.h> 10 #include <sched.h>
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 // function has completed. 73 // function has completed.
74 setenv(kSandboxDebuggingEnv, "t", 0); 74 setenv(kSandboxDebuggingEnv, "t", 0);
75 Die::SuppressInfoMessages(true); 75 Die::SuppressInfoMessages(true);
76 } 76 }
77 77
78 // This test should execute no matter whether we have kernel support. So, 78 // This test should execute no matter whether we have kernel support. So,
79 // we make it a TEST() instead of a BPF_TEST(). 79 // we make it a TEST() instead of a BPF_TEST().
80 TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupports)) { 80 TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupports)) {
81 // We check that we don't crash, but it's ok if the kernel doesn't 81 // We check that we don't crash, but it's ok if the kernel doesn't
82 // support it. 82 // support it.
83 bool seccomp_bpf_supported = 83 bool seccomp_bpf_supported = SandboxBPF::SupportsSeccompSandbox(
84 SandboxBPF::SupportsSeccompSandbox() == SandboxBPF::STATUS_AVAILABLE; 84 SandboxBPF::SeccompLevel::SINGLE_THREADED);
85 bool seccomp_bpf_tsync_supported = SandboxBPF::SupportsSeccompSandbox(
86 SandboxBPF::SeccompLevel::MULTI_THREADED);
85 // We want to log whether or not seccomp BPF is actually supported 87 // We want to log whether or not seccomp BPF is actually supported
86 // since actual test coverage depends on it. 88 // since actual test coverage depends on it.
87 RecordProperty("SeccompBPFSupported", 89 std::cout << "Seccomp BPF supported (single thread): "
88 seccomp_bpf_supported ? "true." : "false.");
89 std::cout << "Seccomp BPF supported: "
90 << (seccomp_bpf_supported ? "true." : "false.") << "\n"; 90 << (seccomp_bpf_supported ? "true." : "false.") << "\n";
91 RecordProperty("PointerSize", sizeof(void*)); 91 std::cout << "Seccomp BPF supported (multi thread): "
92 << (seccomp_bpf_tsync_supported ? "true." : "false.") << "\n";
92 std::cout << "Pointer size: " << sizeof(void*) << "\n"; 93 std::cout << "Pointer size: " << sizeof(void*) << "\n";
93 } 94 }
94 95
95 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupportsTwice)) { 96 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupportsTwice)) {
96 SandboxBPF::SupportsSeccompSandbox(); 97 bool single1 = SandboxBPF::SupportsSeccompSandbox(
97 SandboxBPF::SupportsSeccompSandbox(); 98 SandboxBPF::SeccompLevel::SINGLE_THREADED);
99 bool single2 = SandboxBPF::SupportsSeccompSandbox(
100 SandboxBPF::SeccompLevel::SINGLE_THREADED);
101 ASSERT_EQ(single1, single2);
102 bool multi1 = SandboxBPF::SupportsSeccompSandbox(
103 SandboxBPF::SeccompLevel::MULTI_THREADED);
104 bool multi2 = SandboxBPF::SupportsSeccompSandbox(
105 SandboxBPF::SeccompLevel::MULTI_THREADED);
106 ASSERT_EQ(multi1, multi2);
107
108 // Multi threaded support implies single threaded support.
109 if (multi1) {
110 ASSERT_TRUE(single1);
111 }
98 } 112 }
99 113
100 // BPF_TEST does a lot of the boiler-plate code around setting up a 114 // BPF_TEST does a lot of the boiler-plate code around setting up a
101 // policy and optional passing data between the caller, the policy and 115 // policy and optional passing data between the caller, the policy and
102 // any Trap() handlers. This is great for writing short and concise tests, 116 // any Trap() handlers. This is great for writing short and concise tests,
103 // and it helps us accidentally forgetting any of the crucial steps in 117 // and it helps us accidentally forgetting any of the crucial steps in
104 // setting up the sandbox. But it wouldn't hurt to have at least one test 118 // setting up the sandbox. But it wouldn't hurt to have at least one test
105 // that explicitly walks through all these steps. 119 // that explicitly walks through all these steps.
106 120
107 intptr_t IncreaseCounter(const struct arch_seccomp_data& args, void* aux) { 121 intptr_t IncreaseCounter(const struct arch_seccomp_data& args, void* aux) {
(...skipping 16 matching lines...) Expand all
124 return Allow(); 138 return Allow();
125 } 139 }
126 140
127 private: 141 private:
128 int* counter_ptr_; 142 int* counter_ptr_;
129 143
130 DISALLOW_COPY_AND_ASSIGN(VerboseAPITestingPolicy); 144 DISALLOW_COPY_AND_ASSIGN(VerboseAPITestingPolicy);
131 }; 145 };
132 146
133 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) { 147 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) {
134 if (SandboxBPF::SupportsSeccompSandbox() == 148 if (SandboxBPF::SupportsSeccompSandbox(
135 sandbox::SandboxBPF::STATUS_AVAILABLE) { 149 SandboxBPF::SeccompLevel::SINGLE_THREADED)) {
136 static int counter = 0; 150 static int counter = 0;
137 151
138 SandboxBPF sandbox; 152 SandboxBPF sandbox;
139 sandbox.SetSandboxPolicy(new VerboseAPITestingPolicy(&counter)); 153 sandbox.SetSandboxPolicy(new VerboseAPITestingPolicy(&counter));
140 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); 154 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED));
141 155
142 BPF_ASSERT_EQ(0, counter); 156 BPF_ASSERT_EQ(0, counter);
143 BPF_ASSERT_EQ(0, syscall(__NR_uname, 0)); 157 BPF_ASSERT_EQ(0, syscall(__NR_uname, 0));
144 BPF_ASSERT_EQ(1, counter); 158 BPF_ASSERT_EQ(1, counter);
145 BPF_ASSERT_EQ(1, syscall(__NR_uname, 0)); 159 BPF_ASSERT_EQ(1, syscall(__NR_uname, 0));
146 BPF_ASSERT_EQ(2, counter); 160 BPF_ASSERT_EQ(2, counter);
147 } 161 }
148 } 162 }
149 163
150 // A simple blacklist test 164 // A simple blacklist test
(...skipping 21 matching lines...) Expand all
172 } 186 }
173 187
174 private: 188 private:
175 DISALLOW_COPY_AND_ASSIGN(BlacklistNanosleepPolicy); 189 DISALLOW_COPY_AND_ASSIGN(BlacklistNanosleepPolicy);
176 }; 190 };
177 191
178 BPF_TEST_C(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { 192 BPF_TEST_C(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) {
179 BlacklistNanosleepPolicy::AssertNanosleepFails(); 193 BlacklistNanosleepPolicy::AssertNanosleepFails();
180 } 194 }
181 195
196 BPF_TEST_C(SandboxBPF, UseVsyscall, BlacklistNanosleepPolicy) {
197 time_t current_time;
198 // time() is implemented as a vsyscall. With an older glibc, with
199 // vsyscall=emulate and some versions of the seccomp BPF patch
200 // we may get SIGKILL-ed. Detect this!
201 BPF_ASSERT_NE(static_cast<time_t>(-1), time(&current_time));
202 }
203
182 // Now do a simple whitelist test 204 // Now do a simple whitelist test
183 205
184 class WhitelistGetpidPolicy : public Policy { 206 class WhitelistGetpidPolicy : public Policy {
185 public: 207 public:
186 WhitelistGetpidPolicy() {} 208 WhitelistGetpidPolicy() {}
187 ~WhitelistGetpidPolicy() override {} 209 ~WhitelistGetpidPolicy() override {}
188 210
189 ResultExpr EvaluateSyscall(int sysno) const override { 211 ResultExpr EvaluateSyscall(int sysno) const override {
190 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); 212 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
191 switch (sysno) { 213 switch (sysno) {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 BPF_ASSERT(syscall(__NR_getppid, 0) > 0); 413 BPF_ASSERT(syscall(__NR_getppid, 0) > 0);
392 BPF_ASSERT(errno == 0); 414 BPF_ASSERT(errno == 0);
393 415
394 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); 416 BPF_ASSERT(syscall(__NR_getppid, 1) == -1);
395 BPF_ASSERT(errno == EPERM); 417 BPF_ASSERT(errno == EPERM);
396 418
397 // Stack a second sandbox with its own policy. Verify that we can further 419 // Stack a second sandbox with its own policy. Verify that we can further
398 // restrict filters, but we cannot relax existing filters. 420 // restrict filters, but we cannot relax existing filters.
399 SandboxBPF sandbox; 421 SandboxBPF sandbox;
400 sandbox.SetSandboxPolicy(new StackingPolicyPartTwo()); 422 sandbox.SetSandboxPolicy(new StackingPolicyPartTwo());
401 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); 423 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED));
402 424
403 errno = 0; 425 errno = 0;
404 BPF_ASSERT(syscall(__NR_getppid, 0) == -1); 426 BPF_ASSERT(syscall(__NR_getppid, 0) == -1);
405 BPF_ASSERT(errno == EINVAL); 427 BPF_ASSERT(errno == EINVAL);
406 428
407 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); 429 BPF_ASSERT(syscall(__NR_getppid, 1) == -1);
408 BPF_ASSERT(errno == EPERM); 430 BPF_ASSERT(errno == EPERM);
409 } 431 }
410 432
411 // A more complex, but synthetic policy. This tests the correctness of the BPF 433 // A more complex, but synthetic policy. This tests the correctness of the BPF
(...skipping 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after
2062 2084
2063 ResultExpr EvaluateSyscall(int system_call_number) const override { 2085 ResultExpr EvaluateSyscall(int system_call_number) const override {
2064 return Trace(kTraceData); 2086 return Trace(kTraceData);
2065 } 2087 }
2066 2088
2067 private: 2089 private:
2068 DISALLOW_COPY_AND_ASSIGN(TraceAllPolicy); 2090 DISALLOW_COPY_AND_ASSIGN(TraceAllPolicy);
2069 }; 2091 };
2070 2092
2071 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) { 2093 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) {
2072 if (SandboxBPF::SupportsSeccompSandbox() != 2094 if (!SandboxBPF::SupportsSeccompSandbox(
2073 sandbox::SandboxBPF::STATUS_AVAILABLE) { 2095 SandboxBPF::SeccompLevel::SINGLE_THREADED)) {
2074 return; 2096 return;
2075 } 2097 }
2076 2098
2077 // This test is disabled on arm due to a kernel bug. 2099 // This test is disabled on arm due to a kernel bug.
2078 // See https://code.google.com/p/chromium/issues/detail?id=383977 2100 // See https://code.google.com/p/chromium/issues/detail?id=383977
2079 #if defined(__arm__) || defined(__aarch64__) 2101 #if defined(__arm__) || defined(__aarch64__)
2080 printf("This test is currently disabled on ARM32/64 due to a kernel bug."); 2102 printf("This test is currently disabled on ARM32/64 due to a kernel bug.");
2081 return; 2103 return;
2082 #endif 2104 #endif
2083 2105
2084 #if defined(__mips__) 2106 #if defined(__mips__)
2085 // TODO: Figure out how to support specificity of handling indirect syscalls 2107 // TODO: Figure out how to support specificity of handling indirect syscalls
2086 // in this test and enable it. 2108 // in this test and enable it.
2087 printf("This test is currently disabled on MIPS."); 2109 printf("This test is currently disabled on MIPS.");
2088 return; 2110 return;
2089 #endif 2111 #endif
2090 2112
2091 pid_t pid = fork(); 2113 pid_t pid = fork();
2092 BPF_ASSERT_NE(-1, pid); 2114 BPF_ASSERT_NE(-1, pid);
2093 if (pid == 0) { 2115 if (pid == 0) {
2094 pid_t my_pid = getpid(); 2116 pid_t my_pid = getpid();
2095 BPF_ASSERT_NE(-1, ptrace(PTRACE_TRACEME, -1, NULL, NULL)); 2117 BPF_ASSERT_NE(-1, ptrace(PTRACE_TRACEME, -1, NULL, NULL));
2096 BPF_ASSERT_EQ(0, raise(SIGSTOP)); 2118 BPF_ASSERT_EQ(0, raise(SIGSTOP));
2097 SandboxBPF sandbox; 2119 SandboxBPF sandbox;
2098 sandbox.SetSandboxPolicy(new TraceAllPolicy); 2120 sandbox.SetSandboxPolicy(new TraceAllPolicy);
2099 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); 2121 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED));
2100 2122
2101 // getpid is allowed. 2123 // getpid is allowed.
2102 BPF_ASSERT_EQ(my_pid, sys_getpid()); 2124 BPF_ASSERT_EQ(my_pid, sys_getpid());
2103 2125
2104 // write to stdout is skipped and returns a fake value. 2126 // write to stdout is skipped and returns a fake value.
2105 BPF_ASSERT_EQ(kExpectedReturnValue, 2127 BPF_ASSERT_EQ(kExpectedReturnValue,
2106 syscall(__NR_write, STDOUT_FILENO, "A", 1)); 2128 syscall(__NR_write, STDOUT_FILENO, "A", 1));
2107 2129
2108 // kill is rewritten to exit(kExpectedReturnValue). 2130 // kill is rewritten to exit(kExpectedReturnValue).
2109 syscall(__NR_kill, my_pid, SIGKILL); 2131 syscall(__NR_kill, my_pid, SIGKILL);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2260 } 2282 }
2261 2283
2262 BPF_ASSERT(event->IsSignaled()); 2284 BPF_ASSERT(event->IsSignaled());
2263 2285
2264 BlacklistNanosleepPolicy::AssertNanosleepFails(); 2286 BlacklistNanosleepPolicy::AssertNanosleepFails();
2265 2287
2266 return NULL; 2288 return NULL;
2267 } 2289 }
2268 2290
2269 SANDBOX_TEST(SandboxBPF, Tsync) { 2291 SANDBOX_TEST(SandboxBPF, Tsync) {
2270 if (SandboxBPF::SupportsSeccompThreadFilterSynchronization() != 2292 if (!(SandboxBPF::SupportsSeccompSandbox(
2271 SandboxBPF::STATUS_AVAILABLE) { 2293 SandboxBPF::SeccompLevel::MULTI_THREADED))) {
2272 return; 2294 return;
2273 } 2295 }
2274 2296
2275 base::WaitableEvent event(true, false); 2297 base::WaitableEvent event(true, false);
2276 2298
2277 // Create a thread on which to invoke the blocked syscall. 2299 // Create a thread on which to invoke the blocked syscall.
2278 pthread_t thread; 2300 pthread_t thread;
2279 BPF_ASSERT_EQ( 2301 BPF_ASSERT_EQ(
2280 0, pthread_create(&thread, NULL, &TsyncApplyToTwoThreadsFunc, &event)); 2302 0, pthread_create(&thread, NULL, &TsyncApplyToTwoThreadsFunc, &event));
2281 2303
2282 // Test that nanoseelp success. 2304 // Test that nanoseelp success.
2283 const struct timespec ts = {0, 0}; 2305 const struct timespec ts = {0, 0};
2284 BPF_ASSERT_EQ(0, HANDLE_EINTR(syscall(__NR_nanosleep, &ts, NULL))); 2306 BPF_ASSERT_EQ(0, HANDLE_EINTR(syscall(__NR_nanosleep, &ts, NULL)));
2285 2307
2286 // Engage the sandbox. 2308 // Engage the sandbox.
2287 SandboxBPF sandbox; 2309 SandboxBPF sandbox;
2288 sandbox.SetSandboxPolicy(new BlacklistNanosleepPolicy()); 2310 sandbox.SetSandboxPolicy(new BlacklistNanosleepPolicy());
2289 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_MULTI_THREADED)); 2311 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::SeccompLevel::MULTI_THREADED));
2290 2312
2291 // This thread should have the filter applied as well. 2313 // This thread should have the filter applied as well.
2292 BlacklistNanosleepPolicy::AssertNanosleepFails(); 2314 BlacklistNanosleepPolicy::AssertNanosleepFails();
2293 2315
2294 // Signal the condition to invoke the system call. 2316 // Signal the condition to invoke the system call.
2295 event.Signal(); 2317 event.Signal();
2296 2318
2297 // Wait for the thread to finish. 2319 // Wait for the thread to finish.
2298 BPF_ASSERT_EQ(0, pthread_join(thread, NULL)); 2320 BPF_ASSERT_EQ(0, pthread_join(thread, NULL));
2299 } 2321 }
(...skipping 11 matching lines...) Expand all
2311 2333
2312 SANDBOX_DEATH_TEST( 2334 SANDBOX_DEATH_TEST(
2313 SandboxBPF, 2335 SandboxBPF,
2314 StartMultiThreadedAsSingleThreaded, 2336 StartMultiThreadedAsSingleThreaded,
2315 DEATH_MESSAGE("Cannot start sandbox; process is already multi-threaded")) { 2337 DEATH_MESSAGE("Cannot start sandbox; process is already multi-threaded")) {
2316 base::Thread thread("sandbox.linux.StartMultiThreadedAsSingleThreaded"); 2338 base::Thread thread("sandbox.linux.StartMultiThreadedAsSingleThreaded");
2317 BPF_ASSERT(thread.Start()); 2339 BPF_ASSERT(thread.Start());
2318 2340
2319 SandboxBPF sandbox; 2341 SandboxBPF sandbox;
2320 sandbox.SetSandboxPolicy(new AllowAllPolicy()); 2342 sandbox.SetSandboxPolicy(new AllowAllPolicy());
2321 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); 2343 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED));
2322 } 2344 }
2323 2345
2324 // http://crbug.com/407357 2346 // http://crbug.com/407357
2325 #if !defined(THREAD_SANITIZER) 2347 #if !defined(THREAD_SANITIZER)
2326 SANDBOX_DEATH_TEST( 2348 SANDBOX_DEATH_TEST(
2327 SandboxBPF, 2349 SandboxBPF,
2328 StartSingleThreadedAsMultiThreaded, 2350 StartSingleThreadedAsMultiThreaded,
2329 DEATH_MESSAGE( 2351 DEATH_MESSAGE(
2330 "Cannot start sandbox; process may be single-threaded when " 2352 "Cannot start sandbox; process may be single-threaded when "
2331 "reported as not")) { 2353 "reported as not")) {
2332 SandboxBPF sandbox; 2354 SandboxBPF sandbox;
2333 sandbox.SetSandboxPolicy(new AllowAllPolicy()); 2355 sandbox.SetSandboxPolicy(new AllowAllPolicy());
2334 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::PROCESS_MULTI_THREADED)); 2356 BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::SeccompLevel::MULTI_THREADED));
2335 } 2357 }
2336 #endif // !defined(THREAD_SANITIZER) 2358 #endif // !defined(THREAD_SANITIZER)
2337 2359
2338 // A stub handler for the UnsafeTrap. Never called. 2360 // A stub handler for the UnsafeTrap. Never called.
2339 intptr_t NoOpHandler(const struct arch_seccomp_data& args, void*) { 2361 intptr_t NoOpHandler(const struct arch_seccomp_data& args, void*) {
2340 return -1; 2362 return -1;
2341 } 2363 }
2342 2364
2343 class UnsafeTrapWithCondPolicy : public Policy { 2365 class UnsafeTrapWithCondPolicy : public Policy {
2344 public: 2366 public:
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2394 BPF_ASSERT_EQ(ENOSYS, errno); 2416 BPF_ASSERT_EQ(ENOSYS, errno);
2395 2417
2396 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300)); 2418 BPF_ASSERT_EQ(-1, syscall(__NR_setgid, 300));
2397 BPF_ASSERT_EQ(EPERM, errno); 2419 BPF_ASSERT_EQ(EPERM, errno);
2398 } 2420 }
2399 2421
2400 } // namespace 2422 } // namespace
2401 2423
2402 } // namespace bpf_dsl 2424 } // namespace bpf_dsl
2403 } // namespace sandbox 2425 } // namespace sandbox
OLDNEW
« no previous file with comments | « content/renderer/renderer_main_platform_delegate_android.cc ('k') | sandbox/linux/seccomp-bpf/sandbox_bpf.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698