X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/fe8ab488e9161c46dd9885d58fc52996dc0249ff..c6bf4f310a33a9262d455ea4d3f0630b1255e3fe:/libsyscall/mach/mach_port.c diff --git a/libsyscall/mach/mach_port.c b/libsyscall/mach/mach_port.c index 428ada4f2..57d675094 100644 --- a/libsyscall/mach/mach_port.c +++ b/libsyscall/mach/mach_port.c @@ -2,7 +2,7 @@ * Copyright (c) 2011 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ @@ -30,6 +30,9 @@ #include #include #include +#include +#include "tsd.h" + kern_return_t mach_port_names( @@ -42,9 +45,9 @@ mach_port_names( kern_return_t rv; rv = _kernelrpc_mach_port_names(task, names, namesCnt, types, - typesCnt); + typesCnt); - return (rv); + return rv; } kern_return_t @@ -55,9 +58,13 @@ mach_port_type( { kern_return_t rv; - rv = _kernelrpc_mach_port_type(task, name, ptype); + rv = _kernelrpc_mach_port_type_trap(task, name, ptype); + + if (rv == MACH_SEND_INVALID_DEST) { + rv = _kernelrpc_mach_port_type(task, name, ptype); + } - return (rv); + return rv; } kern_return_t @@ -70,7 +77,7 @@ mach_port_rename( rv = _kernelrpc_mach_port_rename(task, old_name, new_name); - return (rv); + return rv; } kern_return_t @@ -83,7 +90,7 @@ mach_port_allocate_name( rv = _kernelrpc_mach_port_allocate_name(task, right, name); - return (rv); + return rv; } kern_return_t @@ -96,10 +103,11 @@ mach_port_allocate( rv = _kernelrpc_mach_port_allocate_trap(task, right, name); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_allocate(task, right, name); + } - return (rv); + return rv; } kern_return_t @@ -111,10 +119,11 @@ mach_port_destroy( rv = _kernelrpc_mach_port_destroy_trap(task, name); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_destroy(task, name); + } - return (rv); + return rv; } kern_return_t @@ -124,12 +133,13 @@ mach_port_deallocate( { kern_return_t rv; - rv = _kernelrpc_mach_port_deallocate_trap(task, name); + rv = _kernelrpc_mach_port_deallocate_trap(task, name); - if (rv == MACH_SEND_INVALID_DEST) - rv = _kernelrpc_mach_port_deallocate(task,name); + if (rv == MACH_SEND_INVALID_DEST) { + rv = _kernelrpc_mach_port_deallocate(task, name); + } - return (rv); + return rv; } kern_return_t @@ -143,7 +153,7 @@ mach_port_get_refs( rv = _kernelrpc_mach_port_get_refs(task, name, right, refs); - return (rv); + return rv; } kern_return_t @@ -155,32 +165,33 @@ mach_port_mod_refs( { kern_return_t rv; - rv = _kernelrpc_mach_port_mod_refs_trap(task, name, right, delta); + rv = _kernelrpc_mach_port_mod_refs_trap(task, name, right, delta); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_mod_refs(task, name, right, delta); + } - return (rv); + return rv; } kern_return_t mach_port_peek( - ipc_space_t task, - mach_port_name_t name, + ipc_space_t task, + mach_port_name_t name, mach_msg_trailer_type_t trailer_type, - mach_port_seqno_t *seqnop, - mach_msg_size_t *msg_sizep, - mach_msg_id_t *msg_idp, + mach_port_seqno_t *seqnop, + mach_msg_size_t *msg_sizep, + mach_msg_id_t *msg_idp, mach_msg_trailer_info_t trailer_infop, - mach_msg_type_number_t *trailer_sizep) + mach_msg_type_number_t *trailer_sizep) { kern_return_t rv; - rv = _kernelrpc_mach_port_peek(task, name, trailer_type, - seqnop, msg_sizep, msg_idp, - trailer_infop, trailer_sizep); + rv = _kernelrpc_mach_port_peek(task, name, trailer_type, + seqnop, msg_sizep, msg_idp, + trailer_infop, trailer_sizep); - return (rv); + return rv; } kern_return_t @@ -193,7 +204,7 @@ mach_port_set_mscount( rv = _kernelrpc_mach_port_set_mscount(task, name, mscount); - return (rv); + return rv; } kern_return_t @@ -206,9 +217,9 @@ mach_port_get_set_status( kern_return_t rv; rv = _kernelrpc_mach_port_get_set_status(task, name, members, - membersCnt); + membersCnt); - return (rv); + return rv; } kern_return_t @@ -221,10 +232,11 @@ mach_port_move_member( rv = _kernelrpc_mach_port_move_member_trap(task, member, after); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_move_member(task, member, after); + } - return (rv); + return rv; } kern_return_t @@ -239,10 +251,15 @@ mach_port_request_notification( { kern_return_t rv; - rv = _kernelrpc_mach_port_request_notification(task, name, msgid, - sync, notify, notifyPoly, previous); + rv = _kernelrpc_mach_port_request_notification_trap(task, name, msgid, + sync, notify, notifyPoly, previous); - return (rv); + if (rv == MACH_SEND_INVALID_DEST) { + rv = _kernelrpc_mach_port_request_notification(task, name, msgid, + sync, notify, notifyPoly, previous); + } + + return rv; } kern_return_t @@ -254,13 +271,14 @@ mach_port_insert_right( { kern_return_t rv; - rv = _kernelrpc_mach_port_insert_right_trap(task, name, poly, polyPoly); + rv = _kernelrpc_mach_port_insert_right_trap(task, name, poly, polyPoly); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_insert_right(task, name, poly, polyPoly); + } - return (rv); + return rv; } kern_return_t @@ -274,9 +292,9 @@ mach_port_extract_right( kern_return_t rv; rv = _kernelrpc_mach_port_extract_right(task, name, msgt_name, - poly, polyPoly); + poly, polyPoly); - return (rv); + return rv; } kern_return_t @@ -289,7 +307,7 @@ mach_port_set_seqno( rv = _kernelrpc_mach_port_set_seqno(task, name, seqno); - return (rv); + return rv; } kern_return_t @@ -302,10 +320,27 @@ mach_port_get_attributes( { kern_return_t rv; - rv = _kernelrpc_mach_port_get_attributes(task, name, flavor, - port_info_out, port_info_outCnt); + rv = _kernelrpc_mach_port_get_attributes_trap(task, name, flavor, + port_info_out, port_info_outCnt); + +#ifdef __x86_64__ + /* REMOVE once XBS kernel has new trap */ + if (rv == ((1 << 24) | 40)) { /* see mach/i386/syscall_sw.h */ + rv = MACH_SEND_INVALID_DEST; + } +#elif defined(__i386__) + /* REMOVE once XBS kernel has new trap */ + if (rv == (kern_return_t)(-40)) { + rv = MACH_SEND_INVALID_DEST; + } +#endif + + if (rv == MACH_SEND_INVALID_DEST) { + rv = _kernelrpc_mach_port_get_attributes(task, name, flavor, + port_info_out, port_info_outCnt); + } - return (rv); + return rv; } kern_return_t @@ -319,9 +354,9 @@ mach_port_set_attributes( kern_return_t rv; rv = _kernelrpc_mach_port_set_attributes(task, name, flavor, - port_info, port_infoCnt); + port_info, port_infoCnt); - return (rv); + return rv; } kern_return_t @@ -335,7 +370,7 @@ mach_port_allocate_qos( rv = _kernelrpc_mach_port_allocate_qos(task, right, qos, name); - return (rv); + return rv; } kern_return_t @@ -350,7 +385,7 @@ mach_port_allocate_full( rv = _kernelrpc_mach_port_allocate_full(task, right, proto, qos, name); - return (rv); + return rv; } kern_return_t @@ -362,7 +397,7 @@ task_set_port_space( rv = _kernelrpc_task_set_port_space(task, table_entries); - return (rv); + return rv; } kern_return_t @@ -375,7 +410,7 @@ mach_port_get_srights( rv = _kernelrpc_mach_port_get_srights(task, name, srights); - return (rv); + return rv; } kern_return_t @@ -390,9 +425,9 @@ mach_port_space_info( kern_return_t rv; rv = _kernelrpc_mach_port_space_info(task, space_info, table_info, - table_infoCnt, tree_info, tree_infoCnt); + table_infoCnt, tree_info, tree_infoCnt); - return (rv); + return rv; } kern_return_t @@ -404,7 +439,94 @@ mach_port_space_basic_info( rv = _kernelrpc_mach_port_space_basic_info(task, space_basic_info); - return (rv); + return rv; +} + +static inline mach_port_t +_tsd_get_special_reply_port() +{ + return (mach_port_t)(uintptr_t)_os_tsd_get_direct(__TSD_MACH_SPECIAL_REPLY); +} + +static inline void +_tsd_set_special_reply_port(mach_port_t port) +{ + _os_tsd_set_direct(__TSD_MACH_SPECIAL_REPLY, (void *)(uintptr_t)port); +} + +mach_port_t +mig_get_special_reply_port(void) +{ + mach_port_t srp; + + srp = _tsd_get_special_reply_port(); + if (!MACH_PORT_VALID(srp)) { + srp = thread_get_special_reply_port(); + _tsd_set_special_reply_port(srp); + } + + return srp; +} + +void +mig_dealloc_special_reply_port(mach_port_t migport) +{ + mach_port_t srp = _tsd_get_special_reply_port(); + if (MACH_PORT_VALID(srp)) { + thread_destruct_special_reply_port(srp, THREAD_SPECIAL_REPLY_PORT_ALL); + if (migport != srp) { + mach_port_deallocate(mach_task_self(), migport); + } + _tsd_set_special_reply_port(MACH_PORT_NULL); + } +} + +kern_return_t +mach_sync_ipc_link_monitoring_start(mach_port_t *special_reply_port) +{ + mach_port_t srp; + boolean_t link_broken; + kern_return_t kr; + + *special_reply_port = MACH_PORT_DEAD; + + srp = mig_get_special_reply_port(); + + kr = mach_port_mod_refs(mach_task_self(), srp, MACH_PORT_RIGHT_SEND, 1); + + if (kr != KERN_SUCCESS) { + return kr; + } + + kr = _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp, &link_broken); + if (kr != KERN_SUCCESS) { + mach_port_deallocate(mach_task_self(), srp); + return kr; + } + + *special_reply_port = srp; + + return kr; +} + +kern_return_t +mach_sync_ipc_link_monitoring_stop(mach_port_t srp, boolean_t* in_effect) +{ + kern_return_t kr; + boolean_t link_broken = TRUE; + + kr = _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp, &link_broken); + + /* + * We return if the sync IPC priority inversion avoidance facility took + * effect, so if the link was broken it didn't take effect. + * Flip the return. + */ + *in_effect = !link_broken; + + mach_port_deallocate(mach_task_self(), srp); + + return kr; } kern_return_t @@ -417,9 +539,9 @@ mach_port_dnrequest_info( kern_return_t rv; rv = _kernelrpc_mach_port_dnrequest_info(task, name, dnr_total, - dnr_used); + dnr_used); - return (rv); + return rv; } kern_return_t @@ -432,9 +554,9 @@ mach_port_kernel_object( kern_return_t rv; rv = _kernelrpc_mach_port_kernel_object(task, name, - object_type, object_addr); + object_type, object_addr); - return (rv); + return rv; } kern_return_t @@ -447,10 +569,11 @@ mach_port_insert_member( rv = _kernelrpc_mach_port_insert_member_trap(task, name, pset); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_insert_member(task, name, pset); + } - return (rv); + return rv; } kern_return_t @@ -461,12 +584,13 @@ mach_port_extract_member( { kern_return_t rv; - rv = _kernelrpc_mach_port_extract_member_trap(task, name, pset); + rv = _kernelrpc_mach_port_extract_member_trap(task, name, pset); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_extract_member(task, name, pset); + } - return (rv); + return rv; } kern_return_t @@ -484,7 +608,7 @@ mach_port_get_context( *context = (mach_port_context_t)wide_context; } - return (rv); + return rv; } kern_return_t @@ -497,7 +621,7 @@ mach_port_set_context( rv = _kernelrpc_mach_port_set_context(task, name, context); - return (rv); + return rv; } kern_return_t @@ -511,76 +635,150 @@ mach_port_kobject( rv = _kernelrpc_mach_port_kobject(task, name, object_type, object_addr); - return (rv); + return rv; } kern_return_t mach_port_construct( - ipc_space_t task, - mach_port_options_t *options, - mach_port_context_t context, - mach_port_name_t *name) + ipc_space_t task, + mach_port_options_t *options, + mach_port_context_t context, + mach_port_name_t *name) { kern_return_t rv; rv = _kernelrpc_mach_port_construct_trap(task, options, (uint64_t) context, name); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_construct(task, options, (uint64_t) context, name); + } - return (rv); + return rv; } kern_return_t mach_port_destruct( - ipc_space_t task, - mach_port_name_t name, - mach_port_delta_t srdelta, - mach_port_context_t guard) + ipc_space_t task, + mach_port_name_t name, + mach_port_delta_t srdelta, + mach_port_context_t guard) { kern_return_t rv; rv = _kernelrpc_mach_port_destruct_trap(task, name, srdelta, (uint64_t) guard); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_destruct(task, name, srdelta, (uint64_t) guard); + } - return (rv); - + return rv; } kern_return_t mach_port_guard( - ipc_space_t task, - mach_port_name_t name, - mach_port_context_t guard, - boolean_t strict) + ipc_space_t task, + mach_port_name_t name, + mach_port_context_t guard, + boolean_t strict) { kern_return_t rv; rv = _kernelrpc_mach_port_guard_trap(task, name, (uint64_t) guard, strict); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_guard(task, name, (uint64_t) guard, strict); + } - return (rv); - + return rv; } kern_return_t mach_port_unguard( - ipc_space_t task, - mach_port_name_t name, - mach_port_context_t guard) + ipc_space_t task, + mach_port_name_t name, + mach_port_context_t guard) { kern_return_t rv; rv = _kernelrpc_mach_port_unguard_trap(task, name, (uint64_t) guard); - if (rv == MACH_SEND_INVALID_DEST) + if (rv == MACH_SEND_INVALID_DEST) { rv = _kernelrpc_mach_port_unguard(task, name, (uint64_t) guard); + } + + return rv; +} + +extern kern_return_t +_kernelrpc_mach_voucher_extract_attr_recipe( + mach_port_name_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_raw_recipe_t recipe, + mach_msg_type_number_t *recipe_size); + +kern_return_t +mach_voucher_extract_attr_recipe( + mach_port_name_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_raw_recipe_t recipe, + mach_msg_type_number_t *recipe_size) +{ + kern_return_t rv; - return (rv); + rv = mach_voucher_extract_attr_recipe_trap(voucher, key, recipe, recipe_size); + if (rv == MACH_SEND_INVALID_DEST) { + rv = _kernelrpc_mach_voucher_extract_attr_recipe(voucher, key, recipe, recipe_size); + } + + return rv; +} + + +kern_return_t +thread_destruct_special_reply_port( + mach_port_name_t port, + thread_destruct_special_reply_port_rights_t rights) +{ + switch (rights) { + case THREAD_SPECIAL_REPLY_PORT_ALL: + return mach_port_destruct(mach_task_self(), port, -1, 0); + + case THREAD_SPECIAL_REPLY_PORT_RECEIVE_ONLY: + return mach_port_destruct(mach_task_self(), port, 0, 0); + + case THREAD_SPECIAL_REPLY_PORT_SEND_ONLY: + return mach_port_deallocate(mach_task_self(), port); + + default: + return KERN_INVALID_ARGUMENT; + } +} + +kern_return_t +mach_port_guard_with_flags( + ipc_space_t task, + mach_port_name_t name, + mach_port_context_t guard, + uint64_t flags) +{ + kern_return_t rv; + + rv = _kernelrpc_mach_port_guard_with_flags(task, name, (uint64_t) guard, flags); + + return rv; } +kern_return_t +mach_port_swap_guard( + ipc_space_t task, + mach_port_name_t name, + mach_port_context_t old_guard, + mach_port_context_t new_guard) +{ + kern_return_t rv; + + rv = _kernelrpc_mach_port_swap_guard(task, name, (uint64_t)old_guard, (uint64_t)new_guard); + + return rv; +}