blob: 1aac68be87ed8761bbaf19b8f69509bd1d73b1e3 [file] [log] [blame]
rsesek408d2ee52015-09-18 01:18:041// Copyright 2015 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/pre_exec_delegate.h"
6
7#include <mach/mach.h>
8#include <servers/bootstrap.h>
avi74a1875f2015-12-22 02:10:039#include <stdint.h>
rsesek408d2ee52015-09-18 01:18:0410
11#include "base/logging.h"
12#include "base/mac/mac_util.h"
13#include "sandbox/mac/bootstrap_sandbox.h"
rseseke624db42015-09-30 18:18:0814#include "sandbox/mac/xpc.h"
rsesek408d2ee52015-09-18 01:18:0415
16namespace sandbox {
17
18PreExecDelegate::PreExecDelegate(
19 const std::string& sandbox_server_bootstrap_name,
20 uint64_t sandbox_token)
21 : sandbox_server_bootstrap_name_(sandbox_server_bootstrap_name),
22 sandbox_server_bootstrap_name_ptr_(
23 sandbox_server_bootstrap_name_.c_str()),
24 sandbox_token_(sandbox_token),
sdy07171a42016-08-30 18:22:0425 is_yosemite_or_later_(base::mac::IsAtLeastOS10_10()),
26 look_up_message_(CreateBootstrapLookUpMessage()) {}
rsesek408d2ee52015-09-18 01:18:0427
28PreExecDelegate::~PreExecDelegate() {}
29
30void PreExecDelegate::RunAsyncSafe() {
31 mach_port_t sandbox_server_port = MACH_PORT_NULL;
rseseke624db42015-09-30 18:18:0832 kern_return_t kr = DoBootstrapLookUp(&sandbox_server_port);
rsesek408d2ee52015-09-18 01:18:0433 if (kr != KERN_SUCCESS)
34 RAW_LOG(FATAL, "Failed to look up bootstrap sandbox server port.");
35
36 mach_port_t new_bootstrap_port = MACH_PORT_NULL;
37 if (!BootstrapSandbox::ClientCheckIn(sandbox_server_port,
38 sandbox_token_,
39 &new_bootstrap_port)) {
40 RAW_LOG(FATAL, "Failed to check in with sandbox server.");
41 }
42
43 kr = task_set_bootstrap_port(mach_task_self(), new_bootstrap_port);
44 if (kr != KERN_SUCCESS)
45 RAW_LOG(FATAL, "Failed to replace bootstrap port.");
46
47 // On OS X 10.10 and higher, libxpc uses the port stash to transfer the
48 // XPC root port. This is effectively the same connection as the Mach
49 // bootstrap port, but not transferred using the task special port.
50 // Therefore, stash the replacement bootstrap port, so that on 10.10 it
51 // will be retrieved by the XPC code and used as a replacement for the
52 // XPC root port as well.
53 if (is_yosemite_or_later_) {
54 kr = mach_ports_register(mach_task_self(), &new_bootstrap_port, 1);
55 if (kr != KERN_SUCCESS)
56 RAW_LOG(ERROR, "Failed to register replacement bootstrap port.");
57 }
58}
59
rseseke624db42015-09-30 18:18:0860xpc_object_t PreExecDelegate::CreateBootstrapLookUpMessage() {
61 if (is_yosemite_or_later_) {
62 xpc_object_t dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
63 xpc_dictionary_set_uint64(dictionary, "type", 7);
64 xpc_dictionary_set_uint64(dictionary, "handle", 0);
65 xpc_dictionary_set_string(dictionary, "name",
66 sandbox_server_bootstrap_name_ptr_);
67 xpc_dictionary_set_int64(dictionary, "targetpid", 0);
68 xpc_dictionary_set_uint64(dictionary, "flags", 0);
69 xpc_dictionary_set_uint64(dictionary, "subsystem", 5);
70 xpc_dictionary_set_uint64(dictionary, "routine", 207);
71 // Add a NULL port so that the slot in the dictionary is already
72 // allocated.
73 xpc_dictionary_set_mach_send(dictionary, "domain-port", MACH_PORT_NULL);
74 return dictionary;
75 }
76
77 return nullptr;
78}
79
80kern_return_t PreExecDelegate::DoBootstrapLookUp(mach_port_t* out_port) {
81 if (is_yosemite_or_later_) {
82 xpc_dictionary_set_mach_send(look_up_message_, "domain-port",
83 bootstrap_port);
84
85 // |pipe| cannot be created pre-fork() since the |bootstrap_port| will
86 // be invalidated. Deliberately leak |pipe| as well.
87 xpc_pipe_t pipe = xpc_pipe_create_from_port(bootstrap_port, 0);
88 xpc_object_t reply;
89 int rv = xpc_pipe_routine(pipe, look_up_message_, &reply);
90 if (rv != 0) {
91 return xpc_dictionary_get_int64(reply, "error");
92 } else {
93 xpc_object_t port_value = xpc_dictionary_get_value(reply, "port");
94 *out_port = xpc_mach_send_get_right(port_value);
95 return *out_port != MACH_PORT_NULL ? KERN_SUCCESS : KERN_INVALID_RIGHT;
96 }
97 } else {
98 // On non-XPC launchd systems, bootstrap_look_up() is MIG-based and
99 // generally safe.
100 return bootstrap_look_up(bootstrap_port,
101 sandbox_server_bootstrap_name_ptr_, out_port);
102 }
103}
104
rsesek408d2ee52015-09-18 01:18:04105} // namespace sandbox