X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..4ba76501152d51ccb5647018f3192c6096367d48:/osfmk/ipc/mach_debug.c?ds=sidebyside diff --git a/osfmk/ipc/mach_debug.c b/osfmk/ipc/mach_debug.c index f255df6f5..cf1d90c0b 100644 --- a/osfmk/ipc/mach_debug.c +++ b/osfmk/ipc/mach_debug.c @@ -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 @@ -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,34 +22,34 @@ * 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,8 @@ #include #include #include + +#include #endif /* @@ -104,29 +106,31 @@ #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; @@ -137,67 +141,6 @@ mach_port_get_srights( } #endif /* MACH_IPC_DEBUG */ -/* - * Routine: host_ipc_hash_info - * Purpose: - * Return information about the global reverse hash table. - * Conditions: - * Nothing locked. Obeys CountInOut protocol. - * Returns: - * KERN_SUCCESS Returned information. - * KERN_INVALID_HOST The host is null. - * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. - */ - -#if !MACH_IPC_DEBUG -kern_return_t -host_ipc_hash_info( - __unused host_t host, - __unused hash_info_bucket_array_t *infop, - __unused mach_msg_type_number_t *countp) -{ - return KERN_FAILURE; -} -#else -kern_return_t -host_ipc_hash_info( - host_t host, - hash_info_bucket_array_t *infop, - mach_msg_type_number_t *countp) -{ - vm_map_copy_t copy; - vm_offset_t addr; - vm_size_t size; - hash_info_bucket_t *info; - natural_t count; - kern_return_t kr; - - if (host == HOST_NULL) - return KERN_INVALID_HOST; - - /* start with in-line data */ - - count = ipc_hash_size(); - size = round_page(count * sizeof(hash_info_bucket_t)); - kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size); - if (kr != KERN_SUCCESS) - return KERN_RESOURCE_SHORTAGE; - - info = (hash_info_bucket_t *) addr; - count = ipc_hash_info(info, count); - - if (size > count * sizeof(hash_info_bucket_t)) - bzero((char *)&info[count], size - count * sizeof(hash_info_bucket_t)); - - kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr, - (vm_map_size_t)size, TRUE, ©); - assert(kr == KERN_SUCCESS); - - *infop = (hash_info_bucket_t *) copy; - *countp = count; - return KERN_SUCCESS; -} -#endif /* MACH_IPC_DEBUG */ /* * Routine: mach_port_space_info @@ -215,32 +158,28 @@ host_ipc_hash_info( #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, + __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, __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, - ipc_info_tree_name_array_t *treep, - mach_msg_type_number_t *treeCntp) + 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; vm_offset_t table_addr; vm_size_t table_size, table_size_needed; - ipc_info_tree_name_t *tree_info; - vm_offset_t tree_addr; - vm_size_t tree_size, tree_size_needed; - ipc_tree_entry_t tentry; ipc_entry_t table; ipc_entry_num_t tsize; mach_port_index_t index; @@ -248,59 +187,51 @@ 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) == 0); +#else + const boolean_t dbg_ok = TRUE; +#endif /* start with in-line memory */ table_size = 0; - tree_size = 0; for (;;) { is_read_lock(space); - if (!space->is_active) { + if (!is_active(space)) { is_read_unlock(space); - if (table_size != 0) - kmem_free(ipc_kernel_map, - table_addr, table_size); - if (tree_size != 0) + if (table_size != 0) { kmem_free(ipc_kernel_map, - tree_addr, tree_size); + table_addr, table_size); + } return KERN_INVALID_TASK; } - table_size_needed = round_page(space->is_table_size - * sizeof(ipc_info_name_t)); - tree_size_needed = round_page(space->is_tree_total - * sizeof(ipc_info_tree_name_t)); + table_size_needed = + 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) && - (tree_size_needed == tree_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); - if (kr != KERN_SUCCESS) { - if (tree_size != 0) - kmem_free(ipc_kernel_map, tree_addr, tree_size); - return KERN_RESOURCE_SHORTAGE; } - table_size = table_size_needed; - } - if (tree_size != tree_size_needed) { - if (tree_size != 0) - kmem_free(ipc_kernel_map, tree_addr, tree_size); - kr = kmem_alloc(ipc_kernel_map, &tree_addr, tree_size_needed); + kr = kmem_alloc(ipc_kernel_map, &table_addr, table_size_needed, VM_KERN_MEMORY_IPC); if (kr != KERN_SUCCESS) { - if (table_size != 0) - kmem_free(ipc_kernel_map, table_addr, table_size); return KERN_RESOURCE_SHORTAGE; } - tree_size = tree_size_needed; + table_size = table_size_needed; } } /* space is read-locked and active; we have enough wired memory */ @@ -309,9 +240,6 @@ mach_port_space_info( infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD); infop->iis_table_size = space->is_table_size; infop->iis_table_next = space->is_table_next->its_size; - infop->iis_tree_size = space->is_tree_total; - infop->iis_tree_small = space->is_tree_small; - infop->iis_tree_hash = space->is_tree_hash; /* walk the table for this space */ table = space->is_table; @@ -324,11 +252,11 @@ mach_port_space_info( bits = entry->ie_bits; iin->iin_name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits)); - iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; + iin->iin_collision = 0; 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); @@ -337,66 +265,33 @@ mach_port_space_info( } iin->iin_urefs = IE_BITS_UREFS(bits); - iin->iin_object = (natural_t)(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; } - /* walk the splay tree for this space */ - tree_info = (ipc_info_tree_name_array_t)tree_addr; - for (tentry = ipc_splay_traverse_start(&space->is_tree), index = 0; - tentry != ITE_NULL; - tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { - ipc_info_tree_name_t *iitn = &tree_info[index++]; - ipc_info_name_t *iin = &iitn->iitn_name; - ipc_entry_t entry = &tentry->ite_entry; - ipc_entry_bits_t bits = entry->ie_bits; - - assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE); - - iin->iin_name = tentry->ite_name; - iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; - 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; - - assert(IP_VALID(port)); - ip_lock(port); - iin->iin_type |= ipc_port_request_type(port, iin->iin_name, entry->ie_request); - ip_unlock(port); - } - - iin->iin_urefs = IE_BITS_UREFS(bits); - iin->iin_object = (natural_t)(uintptr_t)entry->ie_object; - iin->iin_next = entry->ie_next; - iin->iin_hash = entry->ie_index; - - if (tentry->ite_lchild == ITE_NULL) - iitn->iitn_lchild = MACH_PORT_NULL; - else - iitn->iitn_lchild = tentry->ite_lchild->ite_name; - - if (tentry->ite_rchild == ITE_NULL) - iitn->iitn_rchild = MACH_PORT_NULL; - else - iitn->iitn_rchild = tentry->ite_rchild->ite_name; - - } - ipc_splay_traverse_finish(&space->is_tree); is_read_unlock(space); /* 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_round_page(table_addr + table_size), FALSE); + kr = vm_map_unwire( + ipc_kernel_map, + vm_map_trunc_page(table_addr, + VM_MAP_PAGE_MASK(ipc_kernel_map)), + vm_map_round_page(table_addr + table_size, + 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, ©); + kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)table_addr, + (vm_map_size_t)used_table_size, TRUE, ©); assert(kr == KERN_SUCCESS); *tablep = (ipc_info_name_t *)copy; *tableCntp = infop->iis_table_size; @@ -405,24 +300,60 @@ mach_port_space_info( *tableCntp = 0; } - /* prepare the tree out-of-line data for return */ - if (tree_size > 0) { - if (tree_size > infop->iis_tree_size * sizeof(ipc_info_tree_name_t)) - bzero((char *)&tree_info[infop->iis_tree_size], - tree_size - infop->iis_tree_size * sizeof(ipc_info_tree_name_t)); + /* splay tree is obsolete, no work to do... */ + *treep = (ipc_info_tree_name_t *)0; + *treeCntp = 0; + return KERN_SUCCESS; +} +#endif /* MACH_IPC_DEBUG */ - kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(tree_addr), - vm_map_round_page(tree_addr + tree_size), FALSE); - assert(kr == KERN_SUCCESS); - kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)tree_addr, - (vm_map_size_t)tree_size, TRUE, ©); - assert(kr == KERN_SUCCESS); - *treep = (ipc_info_tree_name_t *)copy; - *treeCntp = infop->iis_tree_size; - } else { - *treep = (ipc_info_tree_name_t *)0; - *treeCntp = 0; +/* + * 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 */ @@ -445,31 +376,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) { @@ -482,11 +415,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); @@ -519,31 +453,34 @@ 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) + __unused ipc_space_t space, + __unused mach_port_name_t name, + __unused natural_t *typep, + __unused mach_vm_address_t *addrp) { - return KERN_FAILURE; + 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) + ipc_space_t space, + mach_port_name_t name, + natural_t *typep, + mach_vm_address_t *addrp) { ipc_entry_t entry; ipc_port_t port; kern_return_t kr; + mach_vm_address_t kaddr; - 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) { @@ -551,7 +488,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); @@ -563,12 +500,19 @@ mach_port_kobject( } *typep = (unsigned int) ip_kotype(port); - *addrp = (mach_vm_address_t)port->ip_kobject; + kaddr = (mach_vm_address_t)port->ip_kobject; + *addrp = 0; +#if (DEVELOPMENT || DEBUG) + if (kaddr && ip_is_kobject(port)) { + *addrp = VM_KERNEL_UNSLIDE_OR_PERM(kaddr); + } +#endif ip_unlock(port); - return KERN_SUCCESS; + return KERN_SUCCESS; } #endif /* MACH_IPC_DEBUG */ + /* * Routine: mach_port_kernel_object [Legacy kernel call] * Purpose: @@ -590,20 +534,20 @@ 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) + __unused ipc_space_t space, + __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) { mach_vm_address_t addr = 0; kern_return_t kr; @@ -613,3 +557,55 @@ mach_port_kernel_object( 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