OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/mac/launchd_interception_server.h" | 5 #include "sandbox/mac/launchd_interception_server.h" |
6 | 6 |
7 #include <servers/bootstrap.h> | 7 #include <servers/bootstrap.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
11 #include "base/mac/mach_logging.h" | 11 #include "base/mac/mach_logging.h" |
12 #include "sandbox/mac/bootstrap_sandbox.h" | 12 #include "sandbox/mac/bootstrap_sandbox.h" |
13 #include "sandbox/mac/mach_message_server.h" | 13 #include "sandbox/mac/mach_message_server.h" |
14 #include "sandbox/mac/os_compatibility.h" | 14 #include "sandbox/mac/os_compatibility.h" |
15 #include "sandbox/mac/xpc_message_server.h" | 15 #include "sandbox/mac/xpc_message_server.h" |
16 | 16 |
17 namespace sandbox { | 17 namespace sandbox { |
18 | 18 |
19 // The buffer size for all launchd messages. This comes from | 19 // The buffer size for all launchd messages. This comes from |
20 // sizeof(union __RequestUnion__vproc_mig_job_subsystem) in launchd, and it | 20 // sizeof(union __RequestUnion__vproc_mig_job_subsystem) in launchd, and it |
21 // is larger than the __ReplyUnion. | 21 // is larger than the __ReplyUnion. |
22 const mach_msg_size_t kBufferSize = 2096; | 22 const mach_msg_size_t kBufferSize = 2096; |
23 | 23 |
24 LaunchdInterceptionServer::LaunchdInterceptionServer( | 24 LaunchdInterceptionServer::LaunchdInterceptionServer( |
25 const BootstrapSandbox* sandbox) | 25 const BootstrapSandbox* sandbox) |
26 : sandbox_(sandbox), | 26 : sandbox_(sandbox), |
| 27 xpc_launchd_(false), |
27 sandbox_port_(MACH_PORT_NULL), | 28 sandbox_port_(MACH_PORT_NULL), |
28 compat_shim_(OSCompatibility::CreateForPlatform()) { | 29 compat_shim_(OSCompatibility::CreateForPlatform()) { |
29 } | 30 } |
30 | 31 |
31 LaunchdInterceptionServer::~LaunchdInterceptionServer() { | 32 LaunchdInterceptionServer::~LaunchdInterceptionServer() { |
32 } | 33 } |
33 | 34 |
34 bool LaunchdInterceptionServer::Initialize(mach_port_t server_receive_right) { | 35 bool LaunchdInterceptionServer::Initialize(mach_port_t server_receive_right) { |
35 mach_port_t task = mach_task_self(); | 36 mach_port_t task = mach_task_self(); |
36 kern_return_t kr; | 37 kern_return_t kr; |
37 | 38 |
38 // Allocate the dummy sandbox port. | 39 // Allocate the dummy sandbox port. |
39 mach_port_t port; | 40 mach_port_t port; |
40 if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) != | 41 if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) != |
41 KERN_SUCCESS) { | 42 KERN_SUCCESS) { |
42 MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port."; | 43 MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port."; |
43 return false; | 44 return false; |
44 } | 45 } |
45 sandbox_port_.reset(port); | 46 sandbox_port_.reset(port); |
46 if ((kr = mach_port_insert_right(task, sandbox_port_, sandbox_port_, | 47 if ((kr = mach_port_insert_right(task, sandbox_port_, sandbox_port_, |
47 MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)) { | 48 MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)) { |
48 MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port send right."; | 49 MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port send right."; |
49 return false; | 50 return false; |
50 } | 51 } |
51 sandbox_send_port_.reset(sandbox_port_); | 52 sandbox_send_port_.reset(sandbox_port_); |
52 | 53 |
53 if (base::mac::IsOSYosemiteOrLater()) { | 54 if (base::mac::IsOSYosemiteOrLater()) { |
54 message_server_.reset(new XPCMessageServer(this, server_receive_right)); | 55 message_server_.reset(new XPCMessageServer(this, server_receive_right)); |
| 56 xpc_launchd_ = true; |
55 } else { | 57 } else { |
56 message_server_.reset( | 58 message_server_.reset( |
57 new MachMessageServer(this, server_receive_right, kBufferSize)); | 59 new MachMessageServer(this, server_receive_right, kBufferSize)); |
58 } | 60 } |
59 return message_server_->Initialize(); | 61 return message_server_->Initialize(); |
60 } | 62 } |
61 | 63 |
62 void LaunchdInterceptionServer::DemuxMessage(IPCMessage request) { | 64 void LaunchdInterceptionServer::DemuxMessage(IPCMessage request) { |
63 const uint64_t message_subsystem = | 65 const uint64_t message_subsystem = |
64 compat_shim_->GetMessageSubsystem(request); | 66 compat_shim_->GetMessageSubsystem(request); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 // VPROC_GSK_MGR_PID and VPROC_GSK_TRANSACTIONS_ENABLED. | 154 // VPROC_GSK_MGR_PID and VPROC_GSK_TRANSACTIONS_ENABLED. |
153 if (compat_shim_->IsSwapIntegerReadOnly(request)) { | 155 if (compat_shim_->IsSwapIntegerReadOnly(request)) { |
154 VLOG(2) << "Forwarding vproc swap_integer message."; | 156 VLOG(2) << "Forwarding vproc swap_integer message."; |
155 ForwardMessage(request); | 157 ForwardMessage(request); |
156 } else { | 158 } else { |
157 VLOG(2) << "Rejecting non-read-only swap_integer message."; | 159 VLOG(2) << "Rejecting non-read-only swap_integer message."; |
158 message_server_->RejectMessage(request, BOOTSTRAP_NOT_PRIVILEGED); | 160 message_server_->RejectMessage(request, BOOTSTRAP_NOT_PRIVILEGED); |
159 } | 161 } |
160 } | 162 } |
161 void LaunchdInterceptionServer::ForwardMessage(IPCMessage request) { | 163 void LaunchdInterceptionServer::ForwardMessage(IPCMessage request) { |
| 164 // If launchd is using XPC, then when the request is forwarded, it must |
| 165 // contain a valid domain port. Because the client processes are sandboxed, |
| 166 // they have not had their launchd domains uncorked (and launchd will |
| 167 // reject the message as being from an invalid client). Instead, provide the |
| 168 // original bootstrap as the domain port, so launchd services the request |
| 169 // as if it were coming from the sandbox host process (this). |
| 170 if (xpc_launchd_) { |
| 171 // xpc_dictionary_set_mach_send increments the send right count. |
| 172 xpc_dictionary_set_mach_send(request.xpc, "domain-port", |
| 173 sandbox_->real_bootstrap_port()); |
| 174 } |
| 175 |
162 message_server_->ForwardMessage(request, sandbox_->real_bootstrap_port()); | 176 message_server_->ForwardMessage(request, sandbox_->real_bootstrap_port()); |
163 } | 177 } |
164 | 178 |
165 } // namespace sandbox | 179 } // namespace sandbox |
OLD | NEW |