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 "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
6 | 6 |
7 // Some headers on Android are missing cdefs: crbug.com/172337. | 7 // Some headers on Android are missing cdefs: crbug.com/172337. |
8 // (We can't use OS_ANDROID here since build_config.h is not included). | 8 // (We can't use OS_ANDROID here since build_config.h is not included). |
9 #if defined(ANDROID) | 9 #if defined(ANDROID) |
10 #include <sys/cdefs.h> | 10 #include <sys/cdefs.h> |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include <sys/wait.h> | 22 #include <sys/wait.h> |
23 #include <time.h> | 23 #include <time.h> |
24 #include <unistd.h> | 24 #include <unistd.h> |
25 | 25 |
26 #include "base/compiler_specific.h" | 26 #include "base/compiler_specific.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 "sandbox/linux/bpf_dsl/bpf_dsl.h" | 31 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" |
| 32 #include "sandbox/linux/bpf_dsl/policy.h" |
32 #include "sandbox/linux/bpf_dsl/policy_compiler.h" | 33 #include "sandbox/linux/bpf_dsl/policy_compiler.h" |
33 #include "sandbox/linux/seccomp-bpf/codegen.h" | 34 #include "sandbox/linux/seccomp-bpf/codegen.h" |
34 #include "sandbox/linux/seccomp-bpf/die.h" | 35 #include "sandbox/linux/seccomp-bpf/die.h" |
35 #include "sandbox/linux/seccomp-bpf/errorcode.h" | 36 #include "sandbox/linux/seccomp-bpf/errorcode.h" |
36 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" | 37 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" |
37 #include "sandbox/linux/seccomp-bpf/syscall.h" | 38 #include "sandbox/linux/seccomp-bpf/syscall.h" |
38 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" | 39 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" |
39 #include "sandbox/linux/seccomp-bpf/trap.h" | 40 #include "sandbox/linux/seccomp-bpf/trap.h" |
40 #include "sandbox/linux/seccomp-bpf/verifier.h" | 41 #include "sandbox/linux/seccomp-bpf/verifier.h" |
41 #include "sandbox/linux/services/linux_syscalls.h" | 42 #include "sandbox/linux/services/linux_syscalls.h" |
42 | 43 |
43 using sandbox::bpf_dsl::Allow; | 44 using sandbox::bpf_dsl::Allow; |
44 using sandbox::bpf_dsl::Error; | 45 using sandbox::bpf_dsl::Error; |
45 using sandbox::bpf_dsl::ResultExpr; | 46 using sandbox::bpf_dsl::ResultExpr; |
46 using sandbox::bpf_dsl::SandboxBPFDSLPolicy; | |
47 | 47 |
48 namespace sandbox { | 48 namespace sandbox { |
49 | 49 |
50 namespace { | 50 namespace { |
51 | 51 |
52 const int kExpectedExitCode = 100; | 52 const int kExpectedExitCode = 100; |
53 | 53 |
54 #if !defined(NDEBUG) | 54 #if !defined(NDEBUG) |
55 void WriteFailedStderrSetupMessage(int out_fd) { | 55 void WriteFailedStderrSetupMessage(int out_fd) { |
56 const char* error_string = strerror(errno); | 56 const char* error_string = strerror(errno); |
57 static const char msg[] = | 57 static const char msg[] = |
58 "You have reproduced a puzzling issue.\n" | 58 "You have reproduced a puzzling issue.\n" |
59 "Please, report to crbug.com/152530!\n" | 59 "Please, report to crbug.com/152530!\n" |
60 "Failed to set up stderr: "; | 60 "Failed to set up stderr: "; |
61 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string && | 61 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string && |
62 HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 && | 62 HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 && |
63 HANDLE_EINTR(write(out_fd, "\n", 1))) { | 63 HANDLE_EINTR(write(out_fd, "\n", 1))) { |
64 } | 64 } |
65 } | 65 } |
66 #endif // !defined(NDEBUG) | 66 #endif // !defined(NDEBUG) |
67 | 67 |
68 // We define a really simple sandbox policy. It is just good enough for us | 68 // We define a really simple sandbox policy. It is just good enough for us |
69 // to tell that the sandbox has actually been activated. | 69 // to tell that the sandbox has actually been activated. |
70 class ProbePolicy : public SandboxBPFDSLPolicy { | 70 class ProbePolicy : public bpf_dsl::Policy { |
71 public: | 71 public: |
72 ProbePolicy() {} | 72 ProbePolicy() {} |
73 virtual ~ProbePolicy() {} | 73 virtual ~ProbePolicy() {} |
74 | 74 |
75 virtual ResultExpr EvaluateSyscall(int sysnum) const override { | 75 virtual ResultExpr EvaluateSyscall(int sysnum) const override { |
76 switch (sysnum) { | 76 switch (sysnum) { |
77 case __NR_getpid: | 77 case __NR_getpid: |
78 // Return EPERM so that we can check that the filter actually ran. | 78 // Return EPERM so that we can check that the filter actually ran. |
79 return Error(EPERM); | 79 return Error(EPERM); |
80 case __NR_exit_group: | 80 case __NR_exit_group: |
81 // Allow exit() with a non-default return code. | 81 // Allow exit() with a non-default return code. |
82 return Allow(); | 82 return Allow(); |
83 default: | 83 default: |
84 // Make everything else fail in an easily recognizable way. | 84 // Make everything else fail in an easily recognizable way. |
85 return Error(EINVAL); | 85 return Error(EINVAL); |
86 } | 86 } |
87 } | 87 } |
88 | 88 |
89 private: | 89 private: |
90 DISALLOW_COPY_AND_ASSIGN(ProbePolicy); | 90 DISALLOW_COPY_AND_ASSIGN(ProbePolicy); |
91 }; | 91 }; |
92 | 92 |
93 void ProbeProcess(void) { | 93 void ProbeProcess(void) { |
94 if (syscall(__NR_getpid) < 0 && errno == EPERM) { | 94 if (syscall(__NR_getpid) < 0 && errno == EPERM) { |
95 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); | 95 syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); |
96 } | 96 } |
97 } | 97 } |
98 | 98 |
99 class AllowAllPolicy : public SandboxBPFDSLPolicy { | 99 class AllowAllPolicy : public bpf_dsl::Policy { |
100 public: | 100 public: |
101 AllowAllPolicy() {} | 101 AllowAllPolicy() {} |
102 virtual ~AllowAllPolicy() {} | 102 virtual ~AllowAllPolicy() {} |
103 | 103 |
104 virtual ResultExpr EvaluateSyscall(int sysnum) const override { | 104 virtual ResultExpr EvaluateSyscall(int sysnum) const override { |
105 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum)); | 105 DCHECK(SandboxBPF::IsValidSyscallNumber(sysnum)); |
106 return Allow(); | 106 return Allow(); |
107 } | 107 } |
108 | 108 |
109 private: | 109 private: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 : quiet_(false), proc_fd_(-1), sandbox_has_started_(false), policy_() { | 146 : quiet_(false), proc_fd_(-1), sandbox_has_started_(false), policy_() { |
147 } | 147 } |
148 | 148 |
149 SandboxBPF::~SandboxBPF() { | 149 SandboxBPF::~SandboxBPF() { |
150 } | 150 } |
151 | 151 |
152 bool SandboxBPF::IsValidSyscallNumber(int sysnum) { | 152 bool SandboxBPF::IsValidSyscallNumber(int sysnum) { |
153 return SyscallSet::IsValid(sysnum); | 153 return SyscallSet::IsValid(sysnum); |
154 } | 154 } |
155 | 155 |
156 bool SandboxBPF::RunFunctionInPolicy( | 156 bool SandboxBPF::RunFunctionInPolicy(void (*code_in_sandbox)(), |
157 void (*code_in_sandbox)(), | 157 scoped_ptr<bpf_dsl::Policy> policy) { |
158 scoped_ptr<bpf_dsl::SandboxBPFDSLPolicy> policy) { | |
159 // Block all signals before forking a child process. This prevents an | 158 // Block all signals before forking a child process. This prevents an |
160 // attacker from manipulating our test by sending us an unexpected signal. | 159 // attacker from manipulating our test by sending us an unexpected signal. |
161 sigset_t old_mask, new_mask; | 160 sigset_t old_mask, new_mask; |
162 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) { | 161 if (sigfillset(&new_mask) || sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) { |
163 SANDBOX_DIE("sigprocmask() failed"); | 162 SANDBOX_DIE("sigprocmask() failed"); |
164 } | 163 } |
165 int fds[2]; | 164 int fds[2]; |
166 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) { | 165 if (pipe2(fds, O_NONBLOCK | O_CLOEXEC)) { |
167 SANDBOX_DIE("pipe() failed"); | 166 SANDBOX_DIE("pipe() failed"); |
168 } | 167 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 } | 266 } |
268 } | 267 } |
269 if (IGNORE_EINTR(close(fds[0]))) { | 268 if (IGNORE_EINTR(close(fds[0]))) { |
270 SANDBOX_DIE("close() failed"); | 269 SANDBOX_DIE("close() failed"); |
271 } | 270 } |
272 | 271 |
273 return rc; | 272 return rc; |
274 } | 273 } |
275 | 274 |
276 bool SandboxBPF::KernelSupportSeccompBPF() { | 275 bool SandboxBPF::KernelSupportSeccompBPF() { |
277 return RunFunctionInPolicy( | 276 return RunFunctionInPolicy(ProbeProcess, |
278 ProbeProcess, | 277 scoped_ptr<bpf_dsl::Policy>(new ProbePolicy())) && |
279 scoped_ptr<bpf_dsl::SandboxBPFDSLPolicy>(new ProbePolicy())) && | 278 RunFunctionInPolicy(TryVsyscallProcess, |
280 RunFunctionInPolicy( | 279 scoped_ptr<bpf_dsl::Policy>(new AllowAllPolicy())); |
281 TryVsyscallProcess, | |
282 scoped_ptr<bpf_dsl::SandboxBPFDSLPolicy>(new AllowAllPolicy())); | |
283 } | 280 } |
284 | 281 |
285 // static | 282 // static |
286 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { | 283 SandboxBPF::SandboxStatus SandboxBPF::SupportsSeccompSandbox(int proc_fd) { |
287 // It the sandbox is currently active, we clearly must have support for | 284 // It the sandbox is currently active, we clearly must have support for |
288 // sandboxing. | 285 // sandboxing. |
289 if (status_ == STATUS_ENABLED) { | 286 if (status_ == STATUS_ENABLED) { |
290 return status_; | 287 return status_; |
291 } | 288 } |
292 | 289 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 // Install the filters. | 413 // Install the filters. |
417 InstallFilter(supports_tsync || thread_state == PROCESS_MULTI_THREADED); | 414 InstallFilter(supports_tsync || thread_state == PROCESS_MULTI_THREADED); |
418 | 415 |
419 // We are now inside the sandbox. | 416 // We are now inside the sandbox. |
420 status_ = STATUS_ENABLED; | 417 status_ = STATUS_ENABLED; |
421 | 418 |
422 return true; | 419 return true; |
423 } | 420 } |
424 | 421 |
425 // Don't take a scoped_ptr here, polymorphism make their use awkward. | 422 // Don't take a scoped_ptr here, polymorphism make their use awkward. |
426 void SandboxBPF::SetSandboxPolicy(bpf_dsl::SandboxBPFDSLPolicy* policy) { | 423 void SandboxBPF::SetSandboxPolicy(bpf_dsl::Policy* policy) { |
427 DCHECK(!policy_); | 424 DCHECK(!policy_); |
428 if (sandbox_has_started_) { | 425 if (sandbox_has_started_) { |
429 SANDBOX_DIE("Cannot change policy after sandbox has started"); | 426 SANDBOX_DIE("Cannot change policy after sandbox has started"); |
430 } | 427 } |
431 policy_.reset(policy); | 428 policy_.reset(policy); |
432 } | 429 } |
433 | 430 |
434 void SandboxBPF::InstallFilter(bool must_sync_threads) { | 431 void SandboxBPF::InstallFilter(bool must_sync_threads) { |
435 // We want to be very careful in not imposing any requirements on the | 432 // We want to be very careful in not imposing any requirements on the |
436 // policies that are set with SetSandboxPolicy(). This means, as soon as | 433 // policies that are set with SetSandboxPolicy(). This means, as soon as |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 static_cast<intptr_t>(args.args[1]), | 513 static_cast<intptr_t>(args.args[1]), |
517 static_cast<intptr_t>(args.args[2]), | 514 static_cast<intptr_t>(args.args[2]), |
518 static_cast<intptr_t>(args.args[3]), | 515 static_cast<intptr_t>(args.args[3]), |
519 static_cast<intptr_t>(args.args[4]), | 516 static_cast<intptr_t>(args.args[4]), |
520 static_cast<intptr_t>(args.args[5])); | 517 static_cast<intptr_t>(args.args[5])); |
521 } | 518 } |
522 | 519 |
523 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; | 520 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; |
524 | 521 |
525 } // namespace sandbox | 522 } // namespace sandbox |
OLD | NEW |