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 <sys/prctl.h> | 8 #include <sys/prctl.h> |
9 #include <sys/syscall.h> | 9 #include <sys/syscall.h> |
10 #include <sys/time.h> | 10 #include <sys/time.h> |
11 #include <sys/types.h> | 11 #include <sys/types.h> |
12 #include <sys/utsname.h> | 12 #include <sys/utsname.h> |
13 #include <unistd.h> | 13 #include <unistd.h> |
14 | 14 |
15 #if defined(ANDROID) | 15 #if defined(ANDROID) |
16 // Work-around for buggy headers in Android's NDK | 16 // Work-around for buggy headers in Android's NDK |
17 #define __user | 17 #define __user |
18 #endif | 18 #endif |
19 #include <linux/futex.h> | 19 #include <linux/futex.h> |
20 | 20 |
21 #include <ostream> | 21 #include <ostream> |
22 | 22 |
23 #include "base/bind.h" | 23 #include "base/bind.h" |
24 #include "base/logging.h" | 24 #include "base/logging.h" |
| 25 #include "base/macros.h" |
25 #include "base/memory/scoped_ptr.h" | 26 #include "base/memory/scoped_ptr.h" |
26 #include "build/build_config.h" | 27 #include "build/build_config.h" |
27 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" | 28 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
28 #include "sandbox/linux/seccomp-bpf/syscall.h" | 29 #include "sandbox/linux/seccomp-bpf/syscall.h" |
29 #include "sandbox/linux/seccomp-bpf/trap.h" | 30 #include "sandbox/linux/seccomp-bpf/trap.h" |
30 #include "sandbox/linux/seccomp-bpf/verifier.h" | 31 #include "sandbox/linux/seccomp-bpf/verifier.h" |
31 #include "sandbox/linux/services/broker_process.h" | 32 #include "sandbox/linux/services/broker_process.h" |
32 #include "sandbox/linux/services/linux_syscalls.h" | 33 #include "sandbox/linux/services/linux_syscalls.h" |
33 #include "sandbox/linux/tests/unit_tests.h" | 34 #include "sandbox/linux/tests/unit_tests.h" |
34 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 // and it helps us accidentally forgetting any of the crucial steps in | 78 // and it helps us accidentally forgetting any of the crucial steps in |
78 // setting up the sandbox. But it wouldn't hurt to have at least one test | 79 // setting up the sandbox. But it wouldn't hurt to have at least one test |
79 // that explicitly walks through all these steps. | 80 // that explicitly walks through all these steps. |
80 | 81 |
81 intptr_t FakeGetPid(const struct arch_seccomp_data& args, void* aux) { | 82 intptr_t FakeGetPid(const struct arch_seccomp_data& args, void* aux) { |
82 BPF_ASSERT(aux); | 83 BPF_ASSERT(aux); |
83 pid_t* pid_ptr = static_cast<pid_t*>(aux); | 84 pid_t* pid_ptr = static_cast<pid_t*>(aux); |
84 return (*pid_ptr)++; | 85 return (*pid_ptr)++; |
85 } | 86 } |
86 | 87 |
87 ErrorCode VerboseAPITestingPolicy(SandboxBPF* sandbox, int sysno, void* aux) { | 88 class VerboseAPITestingPolicy : public SandboxBPFPolicy { |
88 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { | 89 public: |
89 return ErrorCode(ENOSYS); | 90 VerboseAPITestingPolicy(pid_t* pid_ptr) : pid_ptr_(pid_ptr) {} |
90 } else if (sysno == __NR_getpid) { | 91 |
91 return sandbox->Trap(FakeGetPid, aux); | 92 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
92 } else { | 93 int sysno) const OVERRIDE { |
| 94 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
| 95 if (sysno == __NR_getpid) { |
| 96 return sandbox->Trap(FakeGetPid, pid_ptr_); |
| 97 } |
93 return ErrorCode(ErrorCode::ERR_ALLOWED); | 98 return ErrorCode(ErrorCode::ERR_ALLOWED); |
94 } | 99 } |
95 } | 100 |
| 101 private: |
| 102 pid_t* pid_ptr_; |
| 103 DISALLOW_COPY_AND_ASSIGN(VerboseAPITestingPolicy); |
| 104 }; |
96 | 105 |
97 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) { | 106 SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) { |
98 if (SandboxBPF::SupportsSeccompSandbox(-1) == | 107 if (SandboxBPF::SupportsSeccompSandbox(-1) == |
99 sandbox::SandboxBPF::STATUS_AVAILABLE) { | 108 sandbox::SandboxBPF::STATUS_AVAILABLE) { |
100 pid_t test_var = 0; | 109 pid_t pid; |
| 110 |
101 SandboxBPF sandbox; | 111 SandboxBPF sandbox; |
102 sandbox.SetSandboxPolicyDeprecated(VerboseAPITestingPolicy, &test_var); | 112 sandbox.SetSandboxPolicy(new VerboseAPITestingPolicy(&pid)); |
103 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); | 113 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); |
104 | 114 |
105 BPF_ASSERT(test_var == 0); | 115 BPF_ASSERT_EQ(0, pid); |
106 BPF_ASSERT(syscall(__NR_getpid) == 0); | 116 BPF_ASSERT_EQ(0, syscall(__NR_getpid)); |
107 BPF_ASSERT(test_var == 1); | 117 BPF_ASSERT_EQ(1, pid); |
108 BPF_ASSERT(syscall(__NR_getpid) == 1); | 118 BPF_ASSERT_EQ(1, syscall(__NR_getpid)); |
109 BPF_ASSERT(test_var == 2); | 119 BPF_ASSERT_EQ(2, pid); |
110 | 120 |
111 // N.B.: Any future call to getpid() would corrupt the stack. | 121 // N.B.: Any future call to getpid() would corrupt the stack. |
112 // This is OK. The SANDBOX_TEST() macro is guaranteed to | 122 // This is OK. The SANDBOX_TEST() macro is guaranteed to |
113 // only ever call _exit() after the test completes. | 123 // only ever call _exit() after the test completes. |
114 } | 124 } |
115 } | 125 } |
116 | 126 |
117 // A simple blacklist test | 127 // A simple blacklist test |
118 | 128 |
119 ErrorCode BlacklistNanosleepPolicy(SandboxBPF*, int sysno, void* aux) { | 129 ErrorCode BlacklistNanosleepPolicy(SandboxBPF*, int sysno, void* aux) { |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 | 287 |
278 // Finally, test an errno in between the minimum and maximum. | 288 // Finally, test an errno in between the minimum and maximum. |
279 errno = 0; | 289 errno = 0; |
280 struct utsname uts_buf; | 290 struct utsname uts_buf; |
281 BPF_ASSERT(uname(&uts_buf) == -1); | 291 BPF_ASSERT(uname(&uts_buf) == -1); |
282 BPF_ASSERT(errno == 42); | 292 BPF_ASSERT(errno == 42); |
283 } | 293 } |
284 | 294 |
285 // Testing the stacking of two sandboxes | 295 // Testing the stacking of two sandboxes |
286 | 296 |
287 ErrorCode StackingPolicyPartOne(SandboxBPF* sandbox, int sysno, void*) { | 297 class StackingPolicyPartOne : public SandboxBPFPolicy { |
288 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { | 298 public: |
289 return ErrorCode(ENOSYS); | 299 StackingPolicyPartOne() {} |
| 300 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
| 301 int sysno) const OVERRIDE { |
| 302 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
| 303 switch (sysno) { |
| 304 case __NR_getppid: |
| 305 return sandbox->Cond(0, |
| 306 ErrorCode::TP_32BIT, |
| 307 ErrorCode::OP_EQUAL, |
| 308 0, |
| 309 ErrorCode(ErrorCode::ERR_ALLOWED), |
| 310 ErrorCode(EPERM)); |
| 311 default: |
| 312 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 313 } |
290 } | 314 } |
291 | 315 |
292 switch (sysno) { | 316 private: |
293 case __NR_getppid: | 317 DISALLOW_COPY_AND_ASSIGN(StackingPolicyPartOne); |
294 return sandbox->Cond(0, | 318 }; |
295 ErrorCode::TP_32BIT, | |
296 ErrorCode::OP_EQUAL, | |
297 0, | |
298 ErrorCode(ErrorCode::ERR_ALLOWED), | |
299 ErrorCode(EPERM)); | |
300 default: | |
301 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
302 } | |
303 } | |
304 | 319 |
305 ErrorCode StackingPolicyPartTwo(SandboxBPF* sandbox, int sysno, void*) { | 320 class StackingPolicyPartTwo : public SandboxBPFPolicy { |
306 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { | 321 public: |
307 return ErrorCode(ENOSYS); | 322 StackingPolicyPartTwo() {} |
| 323 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
| 324 int sysno) const OVERRIDE { |
| 325 DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
| 326 switch (sysno) { |
| 327 case __NR_getppid: |
| 328 return sandbox->Cond(0, |
| 329 ErrorCode::TP_32BIT, |
| 330 ErrorCode::OP_EQUAL, |
| 331 0, |
| 332 ErrorCode(EINVAL), |
| 333 ErrorCode(ErrorCode::ERR_ALLOWED)); |
| 334 default: |
| 335 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 336 } |
308 } | 337 } |
309 | 338 |
310 switch (sysno) { | 339 private: |
311 case __NR_getppid: | 340 DISALLOW_COPY_AND_ASSIGN(StackingPolicyPartTwo); |
312 return sandbox->Cond(0, | 341 }; |
313 ErrorCode::TP_32BIT, | |
314 ErrorCode::OP_EQUAL, | |
315 0, | |
316 ErrorCode(EINVAL), | |
317 ErrorCode(ErrorCode::ERR_ALLOWED)); | |
318 default: | |
319 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
320 } | |
321 } | |
322 | 342 |
323 BPF_TEST(SandboxBPF, StackingPolicy, StackingPolicyPartOne) { | 343 BPF_TEST_C(SandboxBPF, StackingPolicy, StackingPolicyPartOne) { |
324 errno = 0; | 344 errno = 0; |
325 BPF_ASSERT(syscall(__NR_getppid, 0) > 0); | 345 BPF_ASSERT(syscall(__NR_getppid, 0) > 0); |
326 BPF_ASSERT(errno == 0); | 346 BPF_ASSERT(errno == 0); |
327 | 347 |
328 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); | 348 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); |
329 BPF_ASSERT(errno == EPERM); | 349 BPF_ASSERT(errno == EPERM); |
330 | 350 |
331 // Stack a second sandbox with its own policy. Verify that we can further | 351 // Stack a second sandbox with its own policy. Verify that we can further |
332 // restrict filters, but we cannot relax existing filters. | 352 // restrict filters, but we cannot relax existing filters. |
333 SandboxBPF sandbox; | 353 SandboxBPF sandbox; |
334 sandbox.SetSandboxPolicyDeprecated(StackingPolicyPartTwo, NULL); | 354 sandbox.SetSandboxPolicy(new StackingPolicyPartTwo()); |
335 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); | 355 BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED)); |
336 | 356 |
337 errno = 0; | 357 errno = 0; |
338 BPF_ASSERT(syscall(__NR_getppid, 0) == -1); | 358 BPF_ASSERT(syscall(__NR_getppid, 0) == -1); |
339 BPF_ASSERT(errno == EINVAL); | 359 BPF_ASSERT(errno == EINVAL); |
340 | 360 |
341 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); | 361 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); |
342 BPF_ASSERT(errno == EPERM); | 362 BPF_ASSERT(errno == EPERM); |
343 } | 363 } |
344 | 364 |
(...skipping 1457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1802 &pid) == -EPERM); | 1822 &pid) == -EPERM); |
1803 } | 1823 } |
1804 | 1824 |
1805 BPF_TEST(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } | 1825 BPF_TEST(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } |
1806 | 1826 |
1807 BPF_TEST(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } | 1827 BPF_TEST(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } |
1808 | 1828 |
1809 } // namespace | 1829 } // namespace |
1810 | 1830 |
1811 } // namespace sandbox | 1831 } // namespace sandbox |
OLD | NEW |