2 * Copyright (c) 2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/mach_port_internal.h>
30 #include <mach/mach.h>
31 #include <mach/mach_vm.h>
32 #include <mach/mach_traps.h>
33 #include <mach/mach_sync_ipc.h>
40 mach_port_name_array_t
*names
,
41 mach_msg_type_number_t
*namesCnt
,
42 mach_port_type_array_t
*types
,
43 mach_msg_type_number_t
*typesCnt
)
47 rv
= _kernelrpc_mach_port_names(task
, names
, namesCnt
, types
,
56 mach_port_name_t name
,
57 mach_port_type_t
*ptype
)
61 rv
= _kernelrpc_mach_port_type_trap(task
, name
, ptype
);
63 if (rv
== MACH_SEND_INVALID_DEST
) {
64 rv
= _kernelrpc_mach_port_type(task
, name
, ptype
);
73 mach_port_name_t old_name
,
74 mach_port_name_t new_name
)
78 rv
= _kernelrpc_mach_port_rename(task
, old_name
, new_name
);
84 mach_port_allocate_name(
86 mach_port_right_t right
,
87 mach_port_name_t name
)
91 rv
= _kernelrpc_mach_port_allocate_name(task
, right
, name
);
99 mach_port_right_t right
,
100 mach_port_name_t
*name
)
104 rv
= _kernelrpc_mach_port_allocate_trap(task
, right
, name
);
106 if (rv
== MACH_SEND_INVALID_DEST
) {
107 rv
= _kernelrpc_mach_port_allocate(task
, right
, name
);
116 mach_port_name_t name
)
120 rv
= _kernelrpc_mach_port_destroy_trap(task
, name
);
122 if (rv
== MACH_SEND_INVALID_DEST
) {
123 rv
= _kernelrpc_mach_port_destroy(task
, name
);
130 mach_port_deallocate(
132 mach_port_name_t name
)
136 rv
= _kernelrpc_mach_port_deallocate_trap(task
, name
);
138 if (rv
== MACH_SEND_INVALID_DEST
) {
139 rv
= _kernelrpc_mach_port_deallocate(task
, name
);
148 mach_port_name_t name
,
149 mach_port_right_t right
,
150 mach_port_urefs_t
*refs
)
154 rv
= _kernelrpc_mach_port_get_refs(task
, name
, right
, refs
);
162 mach_port_name_t name
,
163 mach_port_right_t right
,
164 mach_port_delta_t delta
)
168 rv
= _kernelrpc_mach_port_mod_refs_trap(task
, name
, right
, delta
);
170 if (rv
== MACH_SEND_INVALID_DEST
) {
171 rv
= _kernelrpc_mach_port_mod_refs(task
, name
, right
, delta
);
180 mach_port_name_t name
,
181 mach_msg_trailer_type_t trailer_type
,
182 mach_port_seqno_t
*seqnop
,
183 mach_msg_size_t
*msg_sizep
,
184 mach_msg_id_t
*msg_idp
,
185 mach_msg_trailer_info_t trailer_infop
,
186 mach_msg_type_number_t
*trailer_sizep
)
190 rv
= _kernelrpc_mach_port_peek(task
, name
, trailer_type
,
191 seqnop
, msg_sizep
, msg_idp
,
192 trailer_infop
, trailer_sizep
);
198 mach_port_set_mscount(
200 mach_port_name_t name
,
201 mach_port_mscount_t mscount
)
205 rv
= _kernelrpc_mach_port_set_mscount(task
, name
, mscount
);
211 mach_port_get_set_status(
213 mach_port_name_t name
,
214 mach_port_name_array_t
*members
,
215 mach_msg_type_number_t
*membersCnt
)
219 rv
= _kernelrpc_mach_port_get_set_status(task
, name
, members
,
226 mach_port_move_member(
228 mach_port_name_t member
,
229 mach_port_name_t after
)
233 rv
= _kernelrpc_mach_port_move_member_trap(task
, member
, after
);
235 if (rv
== MACH_SEND_INVALID_DEST
) {
236 rv
= _kernelrpc_mach_port_move_member(task
, member
, after
);
243 mach_port_request_notification(
245 mach_port_name_t name
,
247 mach_port_mscount_t sync
,
249 mach_msg_type_name_t notifyPoly
,
250 mach_port_t
*previous
)
254 rv
= _kernelrpc_mach_port_request_notification_trap(task
, name
, msgid
,
255 sync
, notify
, notifyPoly
, previous
);
257 if (rv
== MACH_SEND_INVALID_DEST
) {
258 rv
= _kernelrpc_mach_port_request_notification(task
, name
, msgid
,
259 sync
, notify
, notifyPoly
, previous
);
266 mach_port_insert_right(
268 mach_port_name_t name
,
270 mach_msg_type_name_t polyPoly
)
274 rv
= _kernelrpc_mach_port_insert_right_trap(task
, name
, poly
, polyPoly
);
276 if (rv
== MACH_SEND_INVALID_DEST
) {
277 rv
= _kernelrpc_mach_port_insert_right(task
, name
, poly
,
285 mach_port_extract_right(
287 mach_port_name_t name
,
288 mach_msg_type_name_t msgt_name
,
290 mach_msg_type_name_t
*polyPoly
)
294 rv
= _kernelrpc_mach_port_extract_right(task
, name
, msgt_name
,
303 mach_port_name_t name
,
304 mach_port_seqno_t seqno
)
308 rv
= _kernelrpc_mach_port_set_seqno(task
, name
, seqno
);
314 mach_port_get_attributes(
316 mach_port_name_t name
,
317 mach_port_flavor_t flavor
,
318 mach_port_info_t port_info_out
,
319 mach_msg_type_number_t
*port_info_outCnt
)
323 rv
= _kernelrpc_mach_port_get_attributes_trap(task
, name
, flavor
,
324 port_info_out
, port_info_outCnt
);
327 /* REMOVE once XBS kernel has new trap */
328 if (rv
== ((1 << 24) | 40)) { /* see mach/i386/syscall_sw.h */
329 rv
= MACH_SEND_INVALID_DEST
;
331 #elif defined(__i386__)
332 /* REMOVE once XBS kernel has new trap */
333 if (rv
== (kern_return_t
)(-40)) {
334 rv
= MACH_SEND_INVALID_DEST
;
338 if (rv
== MACH_SEND_INVALID_DEST
) {
339 rv
= _kernelrpc_mach_port_get_attributes(task
, name
, flavor
,
340 port_info_out
, port_info_outCnt
);
347 mach_port_set_attributes(
349 mach_port_name_t name
,
350 mach_port_flavor_t flavor
,
351 mach_port_info_t port_info
,
352 mach_msg_type_number_t port_infoCnt
)
356 rv
= _kernelrpc_mach_port_set_attributes(task
, name
, flavor
,
357 port_info
, port_infoCnt
);
363 mach_port_allocate_qos(
365 mach_port_right_t right
,
366 mach_port_qos_t
*qos
,
367 mach_port_name_t
*name
)
371 rv
= _kernelrpc_mach_port_allocate_qos(task
, right
, qos
, name
);
377 mach_port_allocate_full(
379 mach_port_right_t right
,
381 mach_port_qos_t
*qos
,
382 mach_port_name_t
*name
)
386 rv
= _kernelrpc_mach_port_allocate_full(task
, right
, proto
, qos
, name
);
398 rv
= _kernelrpc_task_set_port_space(task
, table_entries
);
404 mach_port_get_srights(
406 mach_port_name_t name
,
407 mach_port_rights_t
*srights
)
411 rv
= _kernelrpc_mach_port_get_srights(task
, name
, srights
);
417 mach_port_space_info(
419 ipc_info_space_t
*space_info
,
420 ipc_info_name_array_t
*table_info
,
421 mach_msg_type_number_t
*table_infoCnt
,
422 ipc_info_tree_name_array_t
*tree_info
,
423 mach_msg_type_number_t
*tree_infoCnt
)
427 rv
= _kernelrpc_mach_port_space_info(task
, space_info
, table_info
,
428 table_infoCnt
, tree_info
, tree_infoCnt
);
434 mach_port_space_basic_info(
436 ipc_info_space_basic_t
*space_basic_info
)
440 rv
= _kernelrpc_mach_port_space_basic_info(task
, space_basic_info
);
445 static inline mach_port_t
446 _tsd_get_special_reply_port()
448 return (mach_port_t
)(uintptr_t)_os_tsd_get_direct(__TSD_MACH_SPECIAL_REPLY
);
452 _tsd_set_special_reply_port(mach_port_t port
)
454 _os_tsd_set_direct(__TSD_MACH_SPECIAL_REPLY
, (void *)(uintptr_t)port
);
458 mig_get_special_reply_port(void)
462 srp
= _tsd_get_special_reply_port();
463 if (!MACH_PORT_VALID(srp
)) {
464 srp
= thread_get_special_reply_port();
465 _tsd_set_special_reply_port(srp
);
472 mig_dealloc_special_reply_port(mach_port_t migport
)
474 mach_port_t srp
= _tsd_get_special_reply_port();
475 if (MACH_PORT_VALID(srp
)) {
476 thread_destruct_special_reply_port(srp
, THREAD_SPECIAL_REPLY_PORT_ALL
);
477 if (migport
!= srp
) {
478 mach_port_deallocate(mach_task_self(), migport
);
480 _tsd_set_special_reply_port(MACH_PORT_NULL
);
485 mach_sync_ipc_link_monitoring_start(mach_port_t
*special_reply_port
)
488 boolean_t link_broken
;
491 *special_reply_port
= MACH_PORT_DEAD
;
493 srp
= mig_get_special_reply_port();
495 kr
= mach_port_mod_refs(mach_task_self(), srp
, MACH_PORT_RIGHT_SEND
, 1);
497 if (kr
!= KERN_SUCCESS
) {
501 kr
= _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp
, &link_broken
);
502 if (kr
!= KERN_SUCCESS
) {
503 mach_port_deallocate(mach_task_self(), srp
);
507 *special_reply_port
= srp
;
513 mach_sync_ipc_link_monitoring_stop(mach_port_t srp
, boolean_t
* in_effect
)
516 boolean_t link_broken
= TRUE
;
518 kr
= _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp
, &link_broken
);
521 * We return if the sync IPC priority inversion avoidance facility took
522 * effect, so if the link was broken it didn't take effect.
525 *in_effect
= !link_broken
;
527 mach_port_deallocate(mach_task_self(), srp
);
533 mach_port_dnrequest_info(
535 mach_port_name_t name
,
541 rv
= _kernelrpc_mach_port_dnrequest_info(task
, name
, dnr_total
,
548 mach_port_kernel_object(
550 mach_port_name_t name
,
551 unsigned *object_type
,
552 unsigned *object_addr
)
556 rv
= _kernelrpc_mach_port_kernel_object(task
, name
,
557 object_type
, object_addr
);
563 mach_port_insert_member(
565 mach_port_name_t name
,
566 mach_port_name_t pset
)
570 rv
= _kernelrpc_mach_port_insert_member_trap(task
, name
, pset
);
572 if (rv
== MACH_SEND_INVALID_DEST
) {
573 rv
= _kernelrpc_mach_port_insert_member(task
, name
, pset
);
580 mach_port_extract_member(
582 mach_port_name_t name
,
583 mach_port_name_t pset
)
587 rv
= _kernelrpc_mach_port_extract_member_trap(task
, name
, pset
);
589 if (rv
== MACH_SEND_INVALID_DEST
) {
590 rv
= _kernelrpc_mach_port_extract_member(task
, name
, pset
);
597 mach_port_get_context(
599 mach_port_name_t name
,
600 mach_port_context_t
*context
)
603 mach_vm_address_t wide_context
;
605 rv
= _kernelrpc_mach_port_get_context(task
, name
, &wide_context
);
607 if (rv
== KERN_SUCCESS
) {
608 *context
= (mach_port_context_t
)wide_context
;
615 mach_port_set_context(
617 mach_port_name_t name
,
618 mach_port_context_t context
)
622 rv
= _kernelrpc_mach_port_set_context(task
, name
, context
);
630 mach_port_name_t name
,
631 natural_t
*object_type
,
632 mach_vm_address_t
*object_addr
)
636 rv
= _kernelrpc_mach_port_kobject(task
, name
, object_type
, object_addr
);
642 mach_port_kobject_description(
644 mach_port_name_t name
,
645 natural_t
*object_type
,
646 mach_vm_address_t
*object_addr
,
647 kobject_description_t desc
)
651 rv
= _kernelrpc_mach_port_kobject_description(task
, name
, object_type
, object_addr
, desc
);
659 mach_port_options_t
*options
,
660 mach_port_context_t context
,
661 mach_port_name_t
*name
)
665 rv
= _kernelrpc_mach_port_construct_trap(task
, options
, (uint64_t) context
, name
);
667 if (rv
== MACH_SEND_INVALID_DEST
) {
668 rv
= _kernelrpc_mach_port_construct(task
, options
, (uint64_t) context
, name
);
677 mach_port_name_t name
,
678 mach_port_delta_t srdelta
,
679 mach_port_context_t guard
)
683 rv
= _kernelrpc_mach_port_destruct_trap(task
, name
, srdelta
, (uint64_t) guard
);
685 if (rv
== MACH_SEND_INVALID_DEST
) {
686 rv
= _kernelrpc_mach_port_destruct(task
, name
, srdelta
, (uint64_t) guard
);
695 mach_port_name_t name
,
696 mach_port_context_t guard
,
701 rv
= _kernelrpc_mach_port_guard_trap(task
, name
, (uint64_t) guard
, strict
);
703 if (rv
== MACH_SEND_INVALID_DEST
) {
704 rv
= _kernelrpc_mach_port_guard(task
, name
, (uint64_t) guard
, strict
);
713 mach_port_name_t name
,
714 mach_port_context_t guard
)
718 rv
= _kernelrpc_mach_port_unguard_trap(task
, name
, (uint64_t) guard
);
720 if (rv
== MACH_SEND_INVALID_DEST
) {
721 rv
= _kernelrpc_mach_port_unguard(task
, name
, (uint64_t) guard
);
728 _kernelrpc_mach_voucher_extract_attr_recipe(
729 mach_port_name_t voucher
,
730 mach_voucher_attr_key_t key
,
731 mach_voucher_attr_raw_recipe_t recipe
,
732 mach_msg_type_number_t
*recipe_size
);
735 mach_voucher_extract_attr_recipe(
736 mach_port_name_t voucher
,
737 mach_voucher_attr_key_t key
,
738 mach_voucher_attr_raw_recipe_t recipe
,
739 mach_msg_type_number_t
*recipe_size
)
743 rv
= mach_voucher_extract_attr_recipe_trap(voucher
, key
, recipe
, recipe_size
);
745 if (rv
== MACH_SEND_INVALID_DEST
) {
746 rv
= _kernelrpc_mach_voucher_extract_attr_recipe(voucher
, key
, recipe
, recipe_size
);
754 thread_destruct_special_reply_port(
755 mach_port_name_t port
,
756 thread_destruct_special_reply_port_rights_t rights
)
759 case THREAD_SPECIAL_REPLY_PORT_ALL
:
760 return mach_port_destruct(mach_task_self(), port
, -1, 0);
762 case THREAD_SPECIAL_REPLY_PORT_RECEIVE_ONLY
:
763 return mach_port_destruct(mach_task_self(), port
, 0, 0);
765 case THREAD_SPECIAL_REPLY_PORT_SEND_ONLY
:
766 return mach_port_deallocate(mach_task_self(), port
);
769 return KERN_INVALID_ARGUMENT
;
774 mach_port_guard_with_flags(
776 mach_port_name_t name
,
777 mach_port_context_t guard
,
782 rv
= _kernelrpc_mach_port_guard_with_flags(task
, name
, (uint64_t) guard
, flags
);
788 mach_port_swap_guard(
790 mach_port_name_t name
,
791 mach_port_context_t old_guard
,
792 mach_port_context_t new_guard
)
796 rv
= _kernelrpc_mach_port_swap_guard(task
, name
, (uint64_t)old_guard
, (uint64_t)new_guard
);