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