]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ipc/mach_debug.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / ipc / mach_debug.c
index c97e27bcf89205c57ee8f4bbe94f4a7c518f3eec..6ad851ac5ed8f3dfb2a62232a606b8b838db9bbc 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2000-2004 Apple Computer, 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,
  * 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@
  */
 /*
  * @OSF_COPYRIGHT@
  */
-/* 
+/*
  * Mach Operating System
  * Copyright (c) 1991,1990 Carnegie Mellon University
  * All Rights Reserved.
- * 
+ *
  * Permission to use, copy, modify and distribute this software and its
  * documentation is hereby granted, provided that both the copyright
  * notice and this permission notice appear in all copies of the
  * software, derivative works or modified versions, and any portions
  * thereof, and that both notices appear in supporting documentation.
- * 
+ *
  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- * 
+ *
  * Carnegie Mellon requests users of this software to return to
- * 
+ *
  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  *  School of Computer Science
  *  Carnegie Mellon University
  *  Pittsburgh PA 15213-3890
- * 
+ *
  * any improvements or extensions that they make and grant Carnegie Mellon
  * the rights to redistribute these changes.
  */
@@ -84,6 +84,9 @@
 #include <ipc/ipc_hash.h>
 #include <ipc/ipc_table.h>
 #include <ipc/ipc_right.h>
+
+#include <security/mac_mach_internal.h>
+#include <device/device_types.h>
 #endif
 
 /*
 #if !MACH_IPC_DEBUG
 kern_return_t
 mach_port_get_srights(
-       __unused ipc_space_t            space,
-       __unused mach_port_name_t       name,
-       __unused mach_port_rights_t     *srightsp)
+       __unused ipc_space_t            space,
+       __unused mach_port_name_t       name,
+       __unused mach_port_rights_t     *srightsp)
 {
-        return KERN_FAILURE;
+       return KERN_FAILURE;
 }
 #else
 kern_return_t
 mach_port_get_srights(
-       ipc_space_t             space,
-       mach_port_name_t        name,
-       mach_port_rights_t      *srightsp)
+       ipc_space_t             space,
+       mach_port_name_t        name,
+       mach_port_rights_t      *srightsp)
 {
        ipc_port_t port;
        kern_return_t kr;
        mach_port_rights_t srights;
 
-       if (space == IS_NULL)
+       if (space == IS_NULL) {
                return KERN_INVALID_TASK;
+       }
 
        kr = ipc_port_translate_receive(space, name, &port);
-       if (kr != KERN_SUCCESS)
+       if (kr != KERN_SUCCESS) {
                return kr;
+       }
        /* port is locked and active */
 
        srights = port->ip_srights;
@@ -153,24 +158,34 @@ mach_port_get_srights(
 
 #if !MACH_IPC_DEBUG
 kern_return_t
-mach_port_space_info(
-       __unused ipc_space_t                    space,
-       __unused ipc_info_space_t               *infop,
-       __unused ipc_info_name_array_t  *tablep,
-       __unused mach_msg_type_number_t         *tableCntp,
+mach_port_space_info_from_user(
+       __unused mach_port_t                    port,
+       __unused ipc_info_space_t               *infop,
+       __unused ipc_info_name_array_t  *tablep,
+       __unused mach_msg_type_number_t         *tableCntp,
        __unused ipc_info_tree_name_array_t *treep,
-       __unused mach_msg_type_number_t         *treeCntp)
+       __unused mach_msg_type_number_t         *treeCntp)
 {
-        return KERN_FAILURE;
+       return KERN_FAILURE;
 }
+
 #else
 kern_return_t
 mach_port_space_info(
-       ipc_space_t                     space,
-       ipc_info_space_t                *infop,
-       ipc_info_name_array_t           *tablep,
-       mach_msg_type_number_t          *tableCntp,
-       __unused ipc_info_tree_name_array_t     *treep,
+       ipc_space_t                     space,
+       ipc_info_space_t                *infop,
+       ipc_info_name_array_t           *tablep,
+       mach_msg_type_number_t          *tableCntp,
+       __unused ipc_info_tree_name_array_t     *treep,
+       __unused mach_msg_type_number_t         *treeCntp);
+
+kern_return_t
+mach_port_space_info(
+       ipc_space_t                     space,
+       ipc_info_space_t                *infop,
+       ipc_info_name_array_t           *tablep,
+       mach_msg_type_number_t          *tableCntp,
+       __unused ipc_info_tree_name_array_t     *treep,
        __unused mach_msg_type_number_t         *treeCntp)
 {
        ipc_info_name_t *table_info;
@@ -183,8 +198,15 @@ mach_port_space_info(
        vm_map_copy_t copy;
 
 
-       if (space == IS_NULL)
+       if (space == IS_NULL) {
                return KERN_INVALID_TASK;
+       }
+
+#if !(DEVELOPMENT || DEBUG) && CONFIG_MACF
+       const boolean_t dbg_ok = (mac_task_check_expose_task(kernel_task, TASK_FLAVOR_CONTROL) == 0);
+#else
+       const boolean_t dbg_ok = TRUE;
+#endif
 
        /* start with in-line memory */
 
@@ -194,32 +216,34 @@ mach_port_space_info(
                is_read_lock(space);
                if (!is_active(space)) {
                        is_read_unlock(space);
-                       if (table_size != 0)
+                       if (table_size != 0) {
                                kmem_free(ipc_kernel_map,
-                                         table_addr, table_size);
+                                   table_addr, table_size);
+                       }
                        return KERN_INVALID_TASK;
                }
 
                table_size_needed =
-                       vm_map_round_page((space->is_table_size
-                                          * sizeof(ipc_info_name_t)),
-                                         VM_MAP_PAGE_MASK(ipc_kernel_map));
+                   vm_map_round_page((space->is_table_size
+                   * sizeof(ipc_info_name_t)),
+                   VM_MAP_PAGE_MASK(ipc_kernel_map));
 
-               if (table_size_needed == table_size)
+               if (table_size_needed == table_size) {
                        break;
+               }
 
                is_read_unlock(space);
 
                if (table_size != table_size_needed) {
-                       if (table_size != 0)
+                       if (table_size != 0) {
                                kmem_free(ipc_kernel_map, table_addr, table_size);
-                       kr = kmem_alloc(ipc_kernel_map, &table_addr, table_size_needed);
+                       }
+                       kr = kmem_alloc(ipc_kernel_map, &table_addr, table_size_needed, VM_KERN_MEMORY_IPC);
                        if (kr != KERN_SUCCESS) {
                                return KERN_RESOURCE_SHORTAGE;
                        }
                        table_size = table_size_needed;
                }
-
        }
        /* space is read-locked and active; we have enough wired memory */
 
@@ -243,7 +267,7 @@ mach_port_space_info(
                iin->iin_type = IE_BITS_TYPE(bits);
                if ((entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) != MACH_PORT_TYPE_NONE &&
                    entry->ie_request != IE_REQ_NONE) {
-                       ipc_port_t port = (ipc_port_t) entry->ie_object;
+                       ipc_port_t port = ip_object_to_port(entry->ie_object);
 
                        assert(IP_VALID(port));
                        ip_lock(port);
@@ -252,7 +276,7 @@ mach_port_space_info(
                }
 
                iin->iin_urefs = IE_BITS_UREFS(bits);
-               iin->iin_object = (natural_t)VM_KERNEL_ADDRPERM((uintptr_t)entry->ie_object);
+               iin->iin_object = (dbg_ok) ? (natural_t)VM_KERNEL_ADDRPERM((uintptr_t)entry->ie_object) : 0;
                iin->iin_next = entry->ie_next;
                iin->iin_hash = entry->ie_index;
        }
@@ -261,20 +285,24 @@ mach_port_space_info(
 
        /* prepare the table out-of-line data for return */
        if (table_size > 0) {
-               if (table_size > infop->iis_table_size * sizeof(ipc_info_name_t))
+               vm_size_t used_table_size;
+
+               used_table_size = infop->iis_table_size * sizeof(ipc_info_name_t);
+               if (table_size > used_table_size) {
                        bzero((char *)&table_info[infop->iis_table_size],
-                             table_size - infop->iis_table_size * sizeof(ipc_info_name_t));
+                           table_size - used_table_size);
+               }
 
                kr = vm_map_unwire(
                        ipc_kernel_map,
                        vm_map_trunc_page(table_addr,
-                                         VM_MAP_PAGE_MASK(ipc_kernel_map)),
+                       VM_MAP_PAGE_MASK(ipc_kernel_map)),
                        vm_map_round_page(table_addr + table_size,
-                                         VM_MAP_PAGE_MASK(ipc_kernel_map)),
+                       VM_MAP_PAGE_MASK(ipc_kernel_map)),
                        FALSE);
                assert(kr == KERN_SUCCESS);
-               kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)table_addr, 
-                                  (vm_map_size_t)table_size, TRUE, &copy);
+               kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)table_addr,
+                   (vm_map_size_t)used_table_size, TRUE, &copy);
                assert(kr == KERN_SUCCESS);
                *tablep = (ipc_info_name_t *)copy;
                *tableCntp = infop->iis_table_size;
@@ -288,6 +316,80 @@ mach_port_space_info(
        *treeCntp = 0;
        return KERN_SUCCESS;
 }
+
+kern_return_t
+mach_port_space_info_from_user(
+       mach_port_t                     port,
+       ipc_info_space_t                *infop,
+       ipc_info_name_array_t           *tablep,
+       mach_msg_type_number_t          *tableCntp,
+       __unused ipc_info_tree_name_array_t     *treep,
+       __unused mach_msg_type_number_t         *treeCntp)
+{
+       kern_return_t kr;
+
+       ipc_space_t space = convert_port_to_space_check_type(port, NULL, TASK_FLAVOR_READ, FALSE);
+
+       if (space == IPC_SPACE_NULL) {
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       kr = mach_port_space_info(space, infop, tablep, tableCntp, treep, treeCntp);
+
+       ipc_space_release(space);
+       return kr;
+}
+#endif /* MACH_IPC_DEBUG */
+
+/*
+ *     Routine:        mach_port_space_basic_info
+ *     Purpose:
+ *             Returns basic information about an IPC space.
+ *     Conditions:
+ *             Nothing locked.
+ *     Returns:
+ *             KERN_SUCCESS            Returned information.
+ *             KERN_FAILURE            The call is not supported.
+ *             KERN_INVALID_TASK       The space is dead.
+ */
+
+#if !MACH_IPC_DEBUG
+kern_return_t
+mach_port_space_basic_info(
+       __unused ipc_space_t                    space,
+       __unused ipc_info_space_basic_t         *infop)
+{
+       return KERN_FAILURE;
+}
+#else
+kern_return_t
+mach_port_space_basic_info(
+       ipc_space_t                     space,
+       ipc_info_space_basic_t          *infop)
+{
+       if (space == IS_NULL) {
+               return KERN_INVALID_TASK;
+       }
+
+
+       is_read_lock(space);
+       if (!is_active(space)) {
+               is_read_unlock(space);
+               return KERN_INVALID_TASK;
+       }
+
+       /* get the basic space info */
+       infop->iisb_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD);
+       infop->iisb_table_size = space->is_table_size;
+       infop->iisb_table_next = space->is_table_next->its_size;
+       infop->iisb_table_inuse = space->is_table_size - space->is_table_free - 1;
+       infop->iisb_reserved[0] = 0;
+       infop->iisb_reserved[1] = 0;
+
+       is_read_unlock(space);
+
+       return KERN_SUCCESS;
+}
 #endif /* MACH_IPC_DEBUG */
 
 /*
@@ -308,31 +410,33 @@ mach_port_space_info(
 #if !MACH_IPC_DEBUG
 kern_return_t
 mach_port_dnrequest_info(
-       __unused ipc_space_t            space,
-       __unused mach_port_name_t       name,
-       __unused unsigned int   *totalp,
-       __unused unsigned int   *usedp)
+       __unused ipc_space_t            space,
+       __unused mach_port_name_t       name,
+       __unused unsigned int   *totalp,
+       __unused unsigned int   *usedp)
 {
-        return KERN_FAILURE;
+       return KERN_FAILURE;
 }
 #else
 kern_return_t
 mach_port_dnrequest_info(
-       ipc_space_t                     space,
-       mach_port_name_t                name,
-       unsigned int                    *totalp,
-       unsigned int                    *usedp)
+       ipc_space_t                     space,
+       mach_port_name_t                name,
+       unsigned int                    *totalp,
+       unsigned int                    *usedp)
 {
        unsigned int total, used;
        ipc_port_t port;
        kern_return_t kr;
 
-       if (space == IS_NULL)
+       if (space == IS_NULL) {
                return KERN_INVALID_TASK;
+       }
 
        kr = ipc_port_translate_receive(space, name, &port);
-       if (kr != KERN_SUCCESS)
+       if (kr != KERN_SUCCESS) {
                return kr;
+       }
        /* port is locked and active */
 
        if (port->ip_requests == IPR_NULL) {
@@ -345,11 +449,12 @@ mach_port_dnrequest_info(
                total = requests->ipr_size->its_size;
 
                for (index = 1, used = 0;
-                    index < total; index++) {
+                   index < total; index++) {
                        ipc_port_request_t ipr = &requests[index];
 
-                       if (ipr->ipr_name != MACH_PORT_NULL)
+                       if (ipr->ipr_name != MACH_PORT_NULL) {
                                used++;
+                       }
                }
        }
        ip_unlock(port);
@@ -381,33 +486,56 @@ mach_port_dnrequest_info(
 
 #if !MACH_IPC_DEBUG
 kern_return_t
-mach_port_kobject(
-       __unused ipc_space_t            space,
-       __unused mach_port_name_t       name,
-       __unused natural_t              *typep,
-       __unused mach_vm_address_t      *addrp)
+mach_port_kobject_from_user(
+       __unused mach_port_t            port,
+       __unused mach_port_name_t       name,
+       __unused natural_t              *typep,
+       __unused mach_vm_address_t      *addrp)
 {
-        return KERN_FAILURE;
+       return KERN_FAILURE;
+}
+
+kern_return_t
+mach_port_kobject_description_from_user(
+       __unused mach_port_t            port,
+       __unused mach_port_name_t       name,
+       __unused natural_t              *typep,
+       __unused mach_vm_address_t      *addrp,
+       __unused kobject_description_t  des)
+{
+       return KERN_FAILURE;
 }
 #else
 kern_return_t
-mach_port_kobject(
-       ipc_space_t                     space,
-       mach_port_name_t                name,
-       natural_t                       *typep,
-       mach_vm_address_t               *addrp)
+mach_port_kobject_description(
+       ipc_space_t                     space,
+       mach_port_name_t                name,
+       natural_t                       *typep,
+       mach_vm_address_t               *addrp,
+       kobject_description_t           desc);
+
+kern_return_t
+mach_port_kobject_description(
+       ipc_space_t                     space,
+       mach_port_name_t                name,
+       natural_t                       *typep,
+       mach_vm_address_t               *addrp,
+       kobject_description_t           desc)
 {
        ipc_entry_t entry;
        ipc_port_t port;
        kern_return_t kr;
        mach_vm_address_t kaddr;
+       io_object_t obj = NULL;
 
-       if (space == IS_NULL)
+       if (space == IS_NULL) {
                return KERN_INVALID_TASK;
+       }
 
        kr = ipc_right_lookup_read(space, name, &entry);
-       if (kr != KERN_SUCCESS)
+       if (kr != KERN_SUCCESS) {
                return kr;
+       }
        /* space is read-locked and active */
 
        if ((entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) {
@@ -415,7 +543,7 @@ mach_port_kobject(
                return KERN_INVALID_RIGHT;
        }
 
-       port = (ipc_port_t) entry->ie_object;
+       port = ip_object_to_port(entry->ie_object);
        assert(port != IP_NULL);
 
        ip_lock(port);
@@ -427,17 +555,89 @@ mach_port_kobject(
        }
 
        *typep = (unsigned int) ip_kotype(port);
-       kaddr = (mach_vm_address_t)port->ip_kobject;
+       kaddr = (mach_vm_address_t)ip_get_kobject(port);
+       *addrp = 0;
+
+       if (desc) {
+               *desc = '\0';
+               switch (ip_kotype(port)) {
+               case IKOT_IOKIT_OBJECT:
+               case IKOT_IOKIT_CONNECT:
+               case IKOT_IOKIT_IDENT:
+               case IKOT_UEXT_OBJECT:
+                       obj = (io_object_t) kaddr;
+                       iokit_add_reference(obj, IKOT_IOKIT_OBJECT);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+#if (DEVELOPMENT || DEBUG)
+       *addrp = VM_KERNEL_UNSLIDE_OR_PERM(kaddr);
+#endif
+
        ip_unlock(port);
 
-       if (0 != kaddr && is_ipc_kobject(*typep))
-               *addrp = VM_KERNEL_ADDRPERM(VM_KERNEL_UNSLIDE(kaddr));
-       else
-               *addrp = 0;
+       if (obj) {
+               iokit_port_object_description(obj, desc);
+               iokit_remove_reference(obj);
+       }
 
        return KERN_SUCCESS;
 }
+
+kern_return_t
+mach_port_kobject(
+       ipc_space_t                     space,
+       mach_port_name_t                name,
+       natural_t                       *typep,
+       mach_vm_address_t               *addrp);
+
+kern_return_t
+mach_port_kobject(
+       ipc_space_t                     space,
+       mach_port_name_t                name,
+       natural_t                       *typep,
+       mach_vm_address_t               *addrp)
+{
+       return mach_port_kobject_description(space, name, typep, addrp, NULL);
+}
+
+kern_return_t
+mach_port_kobject_description_from_user(
+       mach_port_t                     port,
+       mach_port_name_t                name,
+       natural_t                       *typep,
+       mach_vm_address_t               *addrp,
+       kobject_description_t           desc)
+{
+       kern_return_t kr;
+
+       ipc_space_t space = convert_port_to_space_check_type(port, NULL, TASK_FLAVOR_READ, FALSE);
+
+       if (space == IPC_SPACE_NULL) {
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       kr = mach_port_kobject_description(space, name, typep, addrp, desc);
+
+       ipc_space_release(space);
+       return kr;
+}
+
+kern_return_t
+mach_port_kobject_from_user(
+       mach_port_t                     port,
+       mach_port_name_t                name,
+       natural_t                       *typep,
+       mach_vm_address_t               *addrp)
+{
+       return mach_port_kobject_description_from_user(port, name, typep, addrp, NULL);
+}
+
 #endif /* MACH_IPC_DEBUG */
+
 /*
  *     Routine:        mach_port_kernel_object [Legacy kernel call]
  *     Purpose:
@@ -458,21 +658,28 @@ mach_port_kobject(
 
 #if !MACH_IPC_DEBUG
 kern_return_t
-mach_port_kernel_object(
-       __unused ipc_space_t            space,
-       __unused mach_port_name_t       name,
-       __unused unsigned int           *typep,
-       __unused unsigned int           *addrp)
+mach_port_kernel_object_from_user(
+       __unused mach_port_t            port,
+       __unused mach_port_name_t       name,
+       __unused unsigned int           *typep,
+       __unused unsigned int           *addrp)
 {
-        return KERN_FAILURE;
+       return KERN_FAILURE;
 }
 #else
 kern_return_t
 mach_port_kernel_object(
-       ipc_space_t                     space,
-       mach_port_name_t                name,
-       unsigned int                    *typep,
-       unsigned int                    *addrp)
+       ipc_space_t                     space,
+       mach_port_name_t                name,
+       unsigned int                    *typep,
+       unsigned int                    *addrp);
+
+kern_return_t
+mach_port_kernel_object(
+       ipc_space_t                     space,
+       mach_port_name_t                name,
+       unsigned int                    *typep,
+       unsigned int                    *addrp)
 {
        mach_vm_address_t addr = 0;
        kern_return_t kr;
@@ -481,4 +688,77 @@ mach_port_kernel_object(
        *addrp = (unsigned int) addr;
        return kr;
 }
+
+kern_return_t
+mach_port_kernel_object_from_user(
+       mach_port_t                     port,
+       mach_port_name_t                name,
+       unsigned int                    *typep,
+       unsigned int                    *addrp)
+{
+       kern_return_t kr;
+
+       ipc_space_t space = convert_port_to_space_check_type(port, NULL, TASK_FLAVOR_READ, FALSE);
+
+       if (space == IPC_SPACE_NULL) {
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       kr = mach_port_kernel_object(space, name, typep, addrp);
+
+       ipc_space_release(space);
+       return kr;
+}
 #endif /* MACH_IPC_DEBUG */
+
+#if (DEVELOPMENT || DEBUG)
+kern_return_t
+mach_port_special_reply_port_reset_link(
+       ipc_space_t             space,
+       mach_port_name_t        name,
+       boolean_t               *srp_lost_link)
+{
+       ipc_port_t port;
+       kern_return_t kr;
+       thread_t thread = current_thread();
+
+       if (space != current_space()) {
+               return KERN_INVALID_TASK;
+       }
+
+       if (!MACH_PORT_VALID(name)) {
+               return KERN_INVALID_NAME;
+       }
+
+       if (!IP_VALID(thread->ith_special_reply_port)) {
+               return KERN_INVALID_VALUE;
+       }
+
+       kr = ipc_port_translate_receive(space, name, &port);
+       if (kr != KERN_SUCCESS) {
+               return kr;
+       }
+
+       if (thread->ith_special_reply_port != port) {
+               ip_unlock(port);
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       imq_lock(&port->ip_messages);
+       *srp_lost_link = (port->ip_srp_lost_link == 1)? TRUE : FALSE;
+       port->ip_srp_lost_link = 0;
+       imq_unlock(&port->ip_messages);
+
+       ip_unlock(port);
+       return KERN_SUCCESS;
+}
+#else
+kern_return_t
+mach_port_special_reply_port_reset_link(
+       __unused ipc_space_t            space,
+       __unused mach_port_name_t       name,
+       __unused boolean_t              *srp_lost_link)
+{
+       return KERN_NOT_SUPPORTED;
+}
+#endif