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 <bsm/libbsm.h> | 7 #include <bsm/libbsm.h> |
8 #include <servers/bootstrap.h> | 8 #include <servers/bootstrap.h> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 } | 69 } |
70 reply_buffer_.reset(buffer, kBufferSize); | 70 reply_buffer_.reset(buffer, kBufferSize); |
71 | 71 |
72 // Allocate the dummy sandbox port. | 72 // Allocate the dummy sandbox port. |
73 if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) != | 73 if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) != |
74 KERN_SUCCESS) { | 74 KERN_SUCCESS) { |
75 MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port."; | 75 MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port."; |
76 return false; | 76 return false; |
77 } | 77 } |
78 sandbox_port_.reset(port); | 78 sandbox_port_.reset(port); |
| 79 if ((kr = mach_port_insert_right(task, sandbox_port_, sandbox_port_, |
| 80 MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)) { |
| 81 MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port send right."; |
| 82 return false; |
| 83 } |
| 84 sandbox_send_port_.reset(sandbox_port_); |
79 | 85 |
80 // Set up the dispatch queue to service the bootstrap port. | 86 // Set up the dispatch queue to service the bootstrap port. |
81 // TODO(rsesek): Specify DISPATCH_QUEUE_SERIAL, in the 10.7 SDK. NULL means | 87 // TODO(rsesek): Specify DISPATCH_QUEUE_SERIAL, in the 10.7 SDK. NULL means |
82 // the same thing but is not symbolically clear. | 88 // the same thing but is not symbolically clear. |
83 server_queue_ = dispatch_queue_create( | 89 server_queue_ = dispatch_queue_create( |
84 "org.chromium.sandbox.LaunchdInterceptionServer", NULL); | 90 "org.chromium.sandbox.LaunchdInterceptionServer", NULL); |
85 server_source_ = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, | 91 server_source_ = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, |
86 server_port_.get(), 0, server_queue_); | 92 server_port_.get(), 0, server_queue_); |
87 dispatch_source_set_event_handler(server_source_, ^{ ReceiveMessage(); }); | 93 dispatch_source_set_event_handler(server_source_, ^{ ReceiveMessage(); }); |
88 dispatch_resume(server_source_); | 94 dispatch_resume(server_source_); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 // or the one specified in the policy. | 215 // or the one specified in the policy. |
210 VLOG(1) << "Intercepting look_up2 with a sandboxed service port: " | 216 VLOG(1) << "Intercepting look_up2 with a sandboxed service port: " |
211 << request_service_name; | 217 << request_service_name; |
212 | 218 |
213 mach_port_t result_port; | 219 mach_port_t result_port; |
214 if (rule.result == POLICY_DENY_DUMMY_PORT) | 220 if (rule.result == POLICY_DENY_DUMMY_PORT) |
215 result_port = sandbox_port_.get(); | 221 result_port = sandbox_port_.get(); |
216 else | 222 else |
217 result_port = rule.substitute_port; | 223 result_port = rule.substitute_port; |
218 | 224 |
219 // Grant an additional send right on the result_port so that it can be | |
220 // sent to the sandboxed child process. | |
221 kern_return_t kr = mach_port_insert_right(mach_task_self(), | |
222 result_port, result_port, MACH_MSG_TYPE_MAKE_SEND); | |
223 if (kr != KERN_SUCCESS) { | |
224 MACH_LOG(ERROR, kr) << "Unable to insert right on result_port."; | |
225 } | |
226 | |
227 compat_shim_.look_up2_fill_reply(reply, result_port); | 225 compat_shim_.look_up2_fill_reply(reply, result_port); |
228 SendReply(reply); | 226 // If the message was sent successfully, clear the result_port out of the |
| 227 // message so that it is not destroyed at the end of ReceiveMessage. The |
| 228 // above-inserted right has been moved out of the process, and destroying |
| 229 // the message will unref yet another right. |
| 230 if (SendReply(reply)) |
| 231 compat_shim_.look_up2_fill_reply(reply, MACH_PORT_NULL); |
229 } else { | 232 } else { |
230 NOTREACHED(); | 233 NOTREACHED(); |
231 } | 234 } |
232 } | 235 } |
233 | 236 |
234 void LaunchdInterceptionServer::HandleSwapInteger(mach_msg_header_t* request, | 237 void LaunchdInterceptionServer::HandleSwapInteger(mach_msg_header_t* request, |
235 mach_msg_header_t* reply, | 238 mach_msg_header_t* reply, |
236 pid_t sender_pid) { | 239 pid_t sender_pid) { |
237 // Only allow getting information out of launchd. Do not allow setting | 240 // Only allow getting information out of launchd. Do not allow setting |
238 // values. Two commonly observed values that are retrieved are | 241 // values. Two commonly observed values that are retrieved are |
239 // VPROC_GSK_MGR_PID and VPROC_GSK_TRANSACTIONS_ENABLED. | 242 // VPROC_GSK_MGR_PID and VPROC_GSK_TRANSACTIONS_ENABLED. |
240 if (compat_shim_.swap_integer_is_get_only(request)) { | 243 if (compat_shim_.swap_integer_is_get_only(request)) { |
241 VLOG(2) << "Forwarding vproc swap_integer message."; | 244 VLOG(2) << "Forwarding vproc swap_integer message."; |
242 ForwardMessage(request, reply); | 245 ForwardMessage(request, reply); |
243 } else { | 246 } else { |
244 VLOG(2) << "Rejecting non-read-only swap_integer message."; | 247 VLOG(2) << "Rejecting non-read-only swap_integer message."; |
245 RejectMessage(request, reply, BOOTSTRAP_NOT_PRIVILEGED); | 248 RejectMessage(request, reply, BOOTSTRAP_NOT_PRIVILEGED); |
246 } | 249 } |
247 } | 250 } |
248 | 251 |
249 void LaunchdInterceptionServer::SendReply(mach_msg_header_t* reply) { | 252 bool LaunchdInterceptionServer::SendReply(mach_msg_header_t* reply) { |
250 kern_return_t kr = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, | 253 kern_return_t kr = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, |
251 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | 254 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); |
252 if (kr != KERN_SUCCESS) { | 255 MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) |
253 MACH_LOG(ERROR, kr) << "Unable to send intercepted reply message."; | 256 << "Unable to send intercepted reply message."; |
254 } | 257 return kr == KERN_SUCCESS; |
255 } | 258 } |
256 | 259 |
257 void LaunchdInterceptionServer::ForwardMessage(mach_msg_header_t* request, | 260 void LaunchdInterceptionServer::ForwardMessage(mach_msg_header_t* request, |
258 mach_msg_header_t* reply) { | 261 mach_msg_header_t* reply) { |
259 request->msgh_local_port = request->msgh_remote_port; | 262 request->msgh_local_port = request->msgh_remote_port; |
260 request->msgh_remote_port = sandbox_->real_bootstrap_port(); | 263 request->msgh_remote_port = sandbox_->real_bootstrap_port(); |
261 // Preserve the msgh_bits that do not deal with the local and remote ports. | 264 // Preserve the msgh_bits that do not deal with the local and remote ports. |
262 request->msgh_bits = (request->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) | | 265 request->msgh_bits = (request->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) | |
263 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE); | 266 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE); |
264 kern_return_t kr = mach_msg_send(request); | 267 kern_return_t kr = mach_msg_send(request); |
(...skipping 10 matching lines...) Expand all Loading... |
275 mig_reply_error_t* error_reply = reinterpret_cast<mig_reply_error_t*>(reply); | 278 mig_reply_error_t* error_reply = reinterpret_cast<mig_reply_error_t*>(reply); |
276 error_reply->Head.msgh_size = sizeof(mig_reply_error_t); | 279 error_reply->Head.msgh_size = sizeof(mig_reply_error_t); |
277 error_reply->Head.msgh_bits = | 280 error_reply->Head.msgh_bits = |
278 MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE); | 281 MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE); |
279 error_reply->NDR = NDR_record; | 282 error_reply->NDR = NDR_record; |
280 error_reply->RetCode = error_code; | 283 error_reply->RetCode = error_code; |
281 SendReply(&error_reply->Head); | 284 SendReply(&error_reply->Head); |
282 } | 285 } |
283 | 286 |
284 } // namespace sandbox | 287 } // namespace sandbox |
OLD | NEW |