| 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 = 0; |
| 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 |