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

Side by Side Diff: sandbox/mac/bootstrap_sandbox.cc

Issue 264923003: Initial implementation of the Mac Bootstrap Sandbox. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase for sandbox_export.h Created 6 years, 7 months 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 | Annotate | Revision Log
« no previous file with comments | « sandbox/mac/bootstrap_sandbox.h ('k') | sandbox/mac/bootstrap_sandbox_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sandbox/mac/bootstrap_sandbox.h"
6
7 #include "base/logging.h"
8 #include "base/mac/mach_logging.h"
9
10 #include "sandbox/mac/launchd_interception_server.h"
11
12 namespace sandbox {
13
14 const int kNotAPolicy = -1;
15
16 // static
17 scoped_ptr<BootstrapSandbox> BootstrapSandbox::Create() {
18 scoped_ptr<BootstrapSandbox> sandbox(new BootstrapSandbox());
19 sandbox->server_.reset(new LaunchdInterceptionServer(sandbox.get()));
20
21 if (!sandbox->server_->Initialize()) {
22 sandbox.reset();
23 } else {
24 // Note that the extern global bootstrap_port (in bootstrap.h) will not
25 // be changed here. The parent only has its bootstrap port replaced
26 // permanently because changing it repeatedly in a multi-threaded program
27 // could lead to unsafe access patterns. In a single-threaded program,
28 // the port would be restored after fork(). See the design document for
29 // a larger discussion.
30 //
31 // By not changing the global bootstrap_port, users of the bootstrap port
32 // in the parent can potentially skip an unnecessary indirection through
33 // the sandbox server.
34 kern_return_t kr = task_set_special_port(mach_task_self(),
35 TASK_BOOTSTRAP_PORT, sandbox->server_->server_port());
36 if (kr != KERN_SUCCESS)
37 sandbox.reset();
38 }
39
40 return sandbox.Pass();
41 }
42
43 BootstrapSandbox::~BootstrapSandbox() {
44 kern_return_t kr = task_set_special_port(mach_task_self(),
45 TASK_BOOTSTRAP_PORT, real_bootstrap_port_);
46 MACH_CHECK(kr == KERN_SUCCESS, kr);
47 }
48
49 void BootstrapSandbox::RegisterSandboxPolicy(
50 int sandbox_policy_id,
51 const BootstrapSandboxPolicy& policy) {
52 CHECK(IsPolicyValid(policy));
53 CHECK_GT(sandbox_policy_id, 0);
54 base::AutoLock lock(lock_);
55 DCHECK(policies_.find(sandbox_policy_id) == policies_.end());
56 policies_.insert(std::make_pair(sandbox_policy_id, policy));
57 }
58
59 void BootstrapSandbox::PrepareToForkWithPolicy(int sandbox_policy_id) {
60 base::AutoLock lock(lock_);
61
62 CHECK(policies_.find(sandbox_policy_id) != policies_.end());
63 CHECK_EQ(kNotAPolicy, effective_policy_id_)
64 << "Cannot nest calls to PrepareToForkWithPolicy()";
65
66 // Store the policy for the process we're about to create.
67 effective_policy_id_ = sandbox_policy_id;
68 }
69
70 // TODO(rsesek): The |lock_| needs to be taken twice because
71 // base::LaunchProcess handles both fork+exec, and holding the lock for the
72 // duration would block servicing of other bootstrap messages. If a better
73 // LaunchProcess existed (do arbitrary work without layering violations), this
74 // could be avoided.
75
76 void BootstrapSandbox::FinishedFork(base::ProcessHandle handle) {
77 base::AutoLock lock(lock_);
78
79 CHECK_NE(kNotAPolicy, effective_policy_id_)
80 << "Must PrepareToForkWithPolicy() before FinishedFork()";
81
82 if (handle != base::kNullProcessHandle) {
83 const auto& existing_process = sandboxed_processes_.find(handle);
84 CHECK(existing_process == sandboxed_processes_.end());
85 sandboxed_processes_.insert(std::make_pair(handle, effective_policy_id_));
86 VLOG(3) << "Bootstrap sandbox enforced for pid " << handle;
87 }
88
89 effective_policy_id_ = kNotAPolicy;
90 }
91
92 void BootstrapSandbox::ChildDied(base::ProcessHandle handle) {
93 base::AutoLock lock(lock_);
94 const auto& it = sandboxed_processes_.find(handle);
95 CHECK(it != sandboxed_processes_.end());
96 sandboxed_processes_.erase(it);
97 }
98
99 const BootstrapSandboxPolicy* BootstrapSandbox::PolicyForProcess(
100 pid_t pid) const {
101 base::AutoLock lock(lock_);
102 const auto& process = sandboxed_processes_.find(pid);
103
104 // The new child could send bootstrap requests before the parent calls
105 // FinishedFork().
106 int policy_id = effective_policy_id_;
107 if (process != sandboxed_processes_.end()) {
108 policy_id = process->second;
109 }
110
111 if (policy_id == kNotAPolicy)
112 return NULL;
113
114 return &policies_.find(policy_id)->second;
115 }
116
117 BootstrapSandbox::BootstrapSandbox()
118 : real_bootstrap_port_(MACH_PORT_NULL),
119 effective_policy_id_(kNotAPolicy) {
120 mach_port_t port = MACH_PORT_NULL;
121 kern_return_t kr = task_get_special_port(
122 mach_task_self(), TASK_BOOTSTRAP_PORT, &port);
123 MACH_CHECK(kr == KERN_SUCCESS, kr);
124 real_bootstrap_port_.reset(port);
125 }
126
127 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/mac/bootstrap_sandbox.h ('k') | sandbox/mac/bootstrap_sandbox_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698