]> git.saurik.com Git - apple/xnu.git/blobdiff - libsyscall/mach/mach_port.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / libsyscall / mach / mach_port.c
index 2aadae90d8ec09655ddc75d8e6bc4329a0e37d75..57d67509466e616870fe0f203631cc25dbd7ca86 100644 (file)
@@ -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
  * 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 <mach/mach.h>
 #include <mach/mach_vm.h>
 #include <mach/mach_traps.h>
+#include <mach/mach_sync_ipc.h>
+#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);
+
+       if (rv == MACH_SEND_INVALID_DEST) {
+               rv = _kernelrpc_mach_port_request_notification(task, name, msgid,
+                   sync, notify, notifyPoly, previous);
+       }
 
-       return (rv);
+       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,108 @@ 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;
+}
+
+kern_return_t
+mach_port_space_basic_info(
+       ipc_space_t task,
+       ipc_info_space_basic_t *space_basic_info)
+{
+       kern_return_t rv;
+
+       rv = _kernelrpc_mach_port_space_basic_info(task, space_basic_info);
+
+       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);
 
-       return (rv);
+       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
@@ -405,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
@@ -420,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
@@ -435,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
@@ -449,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
@@ -472,7 +608,7 @@ mach_port_get_context(
                *context = (mach_port_context_t)wide_context;
        }
 
-       return (rv);
+       return rv;
 }
 
 kern_return_t
@@ -485,7 +621,7 @@ mach_port_set_context(
 
        rv = _kernelrpc_mach_port_set_context(task, name, context);
 
-       return (rv);
+       return rv;
 }
 
 kern_return_t
@@ -499,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;
+
+       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);
 
-       return (rv);
+       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;
+}