2 * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
23 #include "launch_priv.h"
24 #include "bootstrap.h"
25 #include "bootstrap_priv.h"
27 #include "vproc_priv.h"
29 #include <mach/mach.h>
30 #include <mach/vm_map.h>
31 #include <sys/types.h>
32 #include <sys/syslog.h>
42 kern_return_t kr
= task_get_special_port(task_self_trap(), TASK_BOOTSTRAP_PORT
, &bootstrap_port
);
43 if (kr
!= KERN_SUCCESS
) {
49 bootstrap_create_server(mach_port_t bp
, cmd_t server_cmd
, uid_t server_uid
, boolean_t on_demand
, mach_port_t
*server_port
)
53 kr
= vproc_mig_create_server(bp
, server_cmd
, server_uid
, on_demand
, server_port
);
55 if (kr
== VPROC_ERR_TRY_PER_USER
) {
58 if (vproc_mig_lookup_per_user_context(bp
, 0, &puc
) == 0) {
59 kr
= vproc_mig_create_server(puc
, server_cmd
, server_uid
, on_demand
, server_port
);
60 mach_port_deallocate(mach_task_self(), puc
);
68 bootstrap_subset(mach_port_t bp
, mach_port_t requestor_port
, mach_port_t
*subset_port
)
70 return vproc_mig_subset(bp
, requestor_port
, subset_port
);
74 bootstrap_unprivileged(mach_port_t bp
, mach_port_t
*unpriv_port
)
78 *unpriv_port
= MACH_PORT_NULL
;
80 kr
= mach_port_mod_refs(mach_task_self(), bp
, MACH_PORT_RIGHT_SEND
, 1);
82 if (kr
== KERN_SUCCESS
) {
90 bootstrap_parent(mach_port_t bp
, mach_port_t
*parent_port
)
92 return vproc_mig_parent(bp
, parent_port
);
96 bootstrap_register(mach_port_t bp
, name_t service_name
, mach_port_t sp
)
98 return bootstrap_register2(bp
, service_name
, sp
, 0);
102 bootstrap_register2(mach_port_t bp
, name_t service_name
, mach_port_t sp
, uint64_t flags
)
104 kern_return_t kr
= vproc_mig_register2(bp
, service_name
, sp
, flags
);
106 if (kr
== VPROC_ERR_TRY_PER_USER
) {
109 if (vproc_mig_lookup_per_user_context(bp
, 0, &puc
) == 0) {
110 kr
= vproc_mig_register2(puc
, service_name
, sp
, flags
);
111 mach_port_deallocate(mach_task_self(), puc
);
119 bootstrap_create_service(mach_port_t bp
, name_t service_name
, mach_port_t
*sp
)
123 if ((kr
= bootstrap_check_in(bp
, service_name
, sp
))) {
127 if ((kr
= mach_port_mod_refs(mach_task_self(), *sp
, MACH_PORT_RIGHT_RECEIVE
, -1))) {
131 return bootstrap_look_up(bp
, service_name
, sp
);
135 bootstrap_check_in(mach_port_t bp
, const name_t service_name
, mach_port_t
*sp
)
138 (void)bzero(junk
, sizeof(junk
));
139 return vproc_mig_check_in2(bp
, (char *)service_name
, sp
, junk
, 0);
143 bootstrap_check_in2(mach_port_t bp
, const name_t service_name
, mach_port_t
*sp
, uint64_t flags
)
146 (void)bzero(junk
, sizeof(junk
));
147 return vproc_mig_check_in2(bp
, (char *)service_name
, sp
, junk
, flags
);
151 bootstrap_look_up_per_user(mach_port_t bp
, const name_t service_name
, uid_t target_user
, mach_port_t
*sp
)
153 audit_token_t au_tok
;
157 /* See rdar://problem/4890134. */
159 if ((kr
= vproc_mig_lookup_per_user_context(bp
, target_user
, &puc
)) != 0) {
167 kr
= vproc_mig_look_up2(puc
, (char *)service_name
, sp
, &au_tok
, 0, junk
, 0);
168 mach_port_deallocate(mach_task_self(), puc
);
175 bootstrap_lookup_children(mach_port_t bp
, mach_port_array_t
*children
, name_array_t
*names
, bootstrap_property_array_t
*properties
, mach_msg_type_number_t
*n_children
)
177 mach_msg_type_number_t junk
= 0;
178 return vproc_mig_lookup_children(bp
, children
, &junk
, names
, n_children
, properties
, &junk
);
182 bootstrap_look_up(mach_port_t bp
, const name_t service_name
, mach_port_t
*sp
)
184 return bootstrap_look_up2(bp
, service_name
, sp
, 0, 0);
188 bootstrap_look_up2(mach_port_t bp
, const name_t service_name
, mach_port_t
*sp
, pid_t target_pid
, uint64_t flags
)
191 return bootstrap_look_up3(bp
, service_name
, sp
, target_pid
, instance_id
, flags
);
195 bootstrap_look_up3(mach_port_t bp
, const name_t service_name
, mach_port_t
*sp
, pid_t target_pid
, const uuid_t instance_id
, uint64_t flags
)
197 audit_token_t au_tok
;
198 bool privileged_server_lookup
= flags
& BOOTSTRAP_PRIVILEGED_SERVER
;
199 kern_return_t kr
= 0;
202 // We have to cast instance_id here because the MIG-generated method
203 // doesn't expect a const parameter.
204 if ((kr
= vproc_mig_look_up2(bp
, (char *)service_name
, sp
, &au_tok
, target_pid
, (unsigned char*)instance_id
, flags
)) != VPROC_ERR_TRY_PER_USER
) {
208 if ((kr
= vproc_mig_lookup_per_user_context(bp
, 0, &puc
)) != 0) {
212 kr
= vproc_mig_look_up2(puc
, (char *)service_name
, sp
, &au_tok
, target_pid
, (unsigned char*)instance_id
, flags
);
213 mach_port_deallocate(mach_task_self(), puc
);
216 if ((kr
== 0) && privileged_server_lookup
) {
220 * The audit token magic is dependent on the per-user launchd
221 * forwarding MIG requests to the root launchd when it cannot
222 * find the answer locally.
225 /* This API should be in Libsystem, but is not */
226 //audit_token_to_au32(au_tok, NULL, &server_euid, NULL, NULL, NULL, NULL, NULL, NULL);
228 server_euid
= au_tok
.val
[1];
231 mach_port_deallocate(mach_task_self(), *sp
);
232 *sp
= MACH_PORT_NULL
;
233 kr
= BOOTSTRAP_NOT_PRIVILEGED
;
241 bootstrap_check_in3(mach_port_t bp
, const name_t service_name
, mach_port_t
*sp
, uuid_t instance_id
, uint64_t flags
)
243 return vproc_mig_check_in2(bp
, (char *)service_name
, sp
, instance_id
, flags
);
247 bootstrap_get_root(mach_port_t bp
, mach_port_t
*root
)
249 return vproc_mig_get_root_bootstrap(bp
, root
);
253 bootstrap_status(mach_port_t bp
, name_t service_name
, bootstrap_status_t
*service_active
)
258 if ((kr
= bootstrap_look_up(bp
, service_name
, &p
))) {
262 mach_port_deallocate(mach_task_self(), p
);
263 *service_active
= BOOTSTRAP_STATUS_ACTIVE
;
265 if (bootstrap_check_in(bp
, service_name
, &p
) == BOOTSTRAP_SUCCESS
) {
266 mach_port_mod_refs(mach_task_self(), p
, MACH_PORT_RIGHT_RECEIVE
, -1);
267 *service_active
= BOOTSTRAP_STATUS_ON_DEMAND
;
270 return BOOTSTRAP_SUCCESS
;
274 bootstrap_info(mach_port_t bp
,
275 name_array_t
*service_names
, mach_msg_type_number_t
*service_namesCnt
,
276 name_array_t
*service_jobs
, mach_msg_type_number_t
*service_jobsCnt
,
277 bootstrap_status_array_t
*service_active
, mach_msg_type_number_t
*service_activeCnt
,
280 return vproc_mig_info(bp
, service_names
, service_namesCnt
, service_jobs
, service_jobsCnt
, service_active
, service_activeCnt
, flags
);
284 bootstrap_strerror(kern_return_t r
)
287 case BOOTSTRAP_SUCCESS
:
289 case BOOTSTRAP_NOT_PRIVILEGED
:
290 return "Permission denied";
291 case BOOTSTRAP_NAME_IN_USE
:
292 case BOOTSTRAP_SERVICE_ACTIVE
:
293 return "Service name already exists";
294 case BOOTSTRAP_UNKNOWN_SERVICE
:
295 return "Unknown service name";
296 case BOOTSTRAP_BAD_COUNT
:
297 return "Too many lookups were requested in one request";
298 case BOOTSTRAP_NO_MEMORY
:
299 return "Out of memory";
301 return mach_error_string(r
);