xref: /xnu-8019.80.24/osfmk/ipc/mach_debug.c (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*
2  * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
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.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
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.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * @OSF_COPYRIGHT@
30  */
31 /*
32  * Mach Operating System
33  * Copyright (c) 1991,1990 Carnegie Mellon University
34  * All Rights Reserved.
35  *
36  * Permission to use, copy, modify and distribute this software and its
37  * documentation is hereby granted, provided that both the copyright
38  * notice and this permission notice appear in all copies of the
39  * software, derivative works or modified versions, and any portions
40  * thereof, and that both notices appear in supporting documentation.
41  *
42  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45  *
46  * Carnegie Mellon requests users of this software to return to
47  *
48  *  Software Distribution Coordinator  or  [email protected]
49  *  School of Computer Science
50  *  Carnegie Mellon University
51  *  Pittsburgh PA 15213-3890
52  *
53  * any improvements or extensions that they make and grant Carnegie Mellon
54  * the rights to redistribute these changes.
55  */
56 /*
57  */
58 /*
59  *	File:	ipc/mach_debug.c
60  *	Author:	Rich Draves
61  *	Date:	1989
62  *
63  *	Exported IPC debug calls.
64  */
65 #include <mach_ipc_debug.h>
66 
67 #include <mach/vm_param.h>
68 #include <mach/kern_return.h>
69 #include <mach/machine/vm_types.h>
70 #include <mach/mach_host_server.h>
71 #include <mach/mach_port_server.h>
72 #include <mach_debug/ipc_info.h>
73 #include <mach_debug/hash_info.h>
74 
75 #if MACH_IPC_DEBUG
76 #include <kern/host.h>
77 #include <kern/misc_protos.h>
78 #include <vm/vm_map.h>
79 #include <vm/vm_kern.h>
80 #include <ipc/port.h>
81 #include <ipc/ipc_types.h>
82 #include <ipc/ipc_space.h>
83 #include <ipc/ipc_port.h>
84 #include <ipc/ipc_hash.h>
85 #include <ipc/ipc_table.h>
86 #include <ipc/ipc_right.h>
87 
88 #include <security/mac_mach_internal.h>
89 #include <device/device_types.h>
90 #endif
91 
92 /*
93  *	Routine:	mach_port_get_srights [kernel call]
94  *	Purpose:
95  *		Retrieve the number of extant send rights
96  *		that a receive right has.
97  *	Conditions:
98  *		Nothing locked.
99  *	Returns:
100  *		KERN_SUCCESS		Retrieved number of send rights.
101  *		KERN_INVALID_TASK	The space is null.
102  *		KERN_INVALID_TASK	The space is dead.
103  *		KERN_INVALID_NAME	The name doesn't denote a right.
104  *		KERN_INVALID_RIGHT	Name doesn't denote receive rights.
105  */
106 
107 #if !MACH_IPC_DEBUG
108 kern_return_t
mach_port_get_srights(__unused ipc_space_t space,__unused mach_port_name_t name,__unused mach_port_rights_t * srightsp)109 mach_port_get_srights(
110 	__unused ipc_space_t            space,
111 	__unused mach_port_name_t       name,
112 	__unused mach_port_rights_t     *srightsp)
113 {
114 	return KERN_FAILURE;
115 }
116 #else
117 kern_return_t
mach_port_get_srights(ipc_space_t space,mach_port_name_t name,mach_port_rights_t * srightsp)118 mach_port_get_srights(
119 	ipc_space_t             space,
120 	mach_port_name_t        name,
121 	mach_port_rights_t      *srightsp)
122 {
123 	ipc_port_t port;
124 	kern_return_t kr;
125 	mach_port_rights_t srights;
126 
127 	if (space == IS_NULL) {
128 		return KERN_INVALID_TASK;
129 	}
130 
131 	kr = ipc_port_translate_receive(space, name, &port);
132 	if (kr != KERN_SUCCESS) {
133 		return kr;
134 	}
135 	/* port is locked and active */
136 
137 	srights = port->ip_srights;
138 	ip_mq_unlock(port);
139 
140 	*srightsp = srights;
141 	return KERN_SUCCESS;
142 }
143 #endif /* MACH_IPC_DEBUG */
144 
145 
146 /*
147  *	Routine:	mach_port_space_info
148  *	Purpose:
149  *		Returns information about an IPC space.
150  *	Conditions:
151  *		Nothing locked.  Obeys CountInOut protocol.
152  *	Returns:
153  *		KERN_SUCCESS		Returned information.
154  *		KERN_INVALID_TASK	The space is null.
155  *		KERN_INVALID_TASK	The space is dead.
156  *		KERN_RESOURCE_SHORTAGE	Couldn't allocate memory.
157  */
158 
159 #if !MACH_IPC_DEBUG
160 kern_return_t
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)161 mach_port_space_info_from_user(
162 	__unused mach_port_t                    port,
163 	__unused ipc_info_space_t               *infop,
164 	__unused ipc_info_name_array_t  *tablep,
165 	__unused mach_msg_type_number_t         *tableCntp,
166 	__unused ipc_info_tree_name_array_t *treep,
167 	__unused mach_msg_type_number_t         *treeCntp)
168 {
169 	return KERN_FAILURE;
170 }
171 
172 #else
173 kern_return_t
174 mach_port_space_info(
175 	ipc_space_t                     space,
176 	ipc_info_space_t                *infop,
177 	ipc_info_name_array_t           *tablep,
178 	mach_msg_type_number_t          *tableCntp,
179 	__unused ipc_info_tree_name_array_t     *treep,
180 	__unused mach_msg_type_number_t         *treeCntp);
181 
182 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)183 mach_port_space_info(
184 	ipc_space_t                     space,
185 	ipc_info_space_t                *infop,
186 	ipc_info_name_array_t           *tablep,
187 	mach_msg_type_number_t          *tableCntp,
188 	__unused ipc_info_tree_name_array_t     *treep,
189 	__unused mach_msg_type_number_t         *treeCntp)
190 {
191 	ipc_info_name_t *table_info;
192 	vm_offset_t table_addr;
193 	vm_size_t table_size, table_size_needed;
194 	ipc_entry_t table;
195 	ipc_entry_num_t tsize;
196 	mach_port_index_t index;
197 	kern_return_t kr;
198 	vm_map_copy_t copy;
199 
200 
201 	if (space == IS_NULL) {
202 		return KERN_INVALID_TASK;
203 	}
204 
205 #if !(DEVELOPMENT || DEBUG) && CONFIG_MACF
206 	const boolean_t dbg_ok = (mac_task_check_expose_task(kernel_task, TASK_FLAVOR_CONTROL) == 0);
207 #else
208 	const boolean_t dbg_ok = TRUE;
209 #endif
210 
211 	/* start with in-line memory */
212 
213 	table_size = 0;
214 
215 	for (;;) {
216 		is_read_lock(space);
217 		if (!is_active(space)) {
218 			is_read_unlock(space);
219 			if (table_size != 0) {
220 				kmem_free(ipc_kernel_map,
221 				    table_addr, table_size);
222 			}
223 			return KERN_INVALID_TASK;
224 		}
225 
226 		table = is_active_table(space);
227 		tsize = table->ie_size;
228 
229 		table_size_needed =
230 		    vm_map_round_page(tsize * sizeof(ipc_info_name_t),
231 		    VM_MAP_PAGE_MASK(ipc_kernel_map));
232 
233 		if (table_size_needed == table_size) {
234 			break;
235 		}
236 
237 		is_read_unlock(space);
238 
239 		if (table_size != table_size_needed) {
240 			if (table_size != 0) {
241 				kmem_free(ipc_kernel_map, table_addr, table_size);
242 			}
243 			kr = kmem_alloc(ipc_kernel_map, &table_addr, table_size_needed, VM_KERN_MEMORY_IPC);
244 			if (kr != KERN_SUCCESS) {
245 				return KERN_RESOURCE_SHORTAGE;
246 			}
247 			table_size = table_size_needed;
248 		}
249 	}
250 	/* space is read-locked and active; we have enough wired memory */
251 
252 	/* get the overall space info */
253 	infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD);
254 	infop->iis_table_size = tsize;
255 	infop->iis_table_next = space->is_table_next->its_size;
256 
257 	/* walk the table for this space */
258 	table_info = (ipc_info_name_array_t)table_addr;
259 	for (index = 0; index < tsize; index++) {
260 		ipc_info_name_t *iin = &table_info[index];
261 		ipc_entry_t entry = &table[index];
262 		ipc_entry_bits_t bits;
263 
264 		if (index == 0) {
265 			bits = IE_BITS_GEN_MASK;
266 		} else {
267 			bits = entry->ie_bits;
268 		}
269 		iin->iin_name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits));
270 		iin->iin_collision = 0;
271 		iin->iin_type = IE_BITS_TYPE(bits);
272 		if ((bits & MACH_PORT_TYPE_PORT_RIGHTS) != MACH_PORT_TYPE_NONE &&
273 		    entry->ie_request != IE_REQ_NONE) {
274 			ipc_port_t port = ip_object_to_port(entry->ie_object);
275 
276 			assert(IP_VALID(port));
277 			ip_mq_lock(port);
278 			iin->iin_type |= ipc_port_request_type(port, iin->iin_name, entry->ie_request);
279 			ip_mq_unlock(port);
280 		}
281 
282 		iin->iin_urefs = IE_BITS_UREFS(bits);
283 		iin->iin_object = (dbg_ok) ? (natural_t)VM_KERNEL_ADDRPERM((uintptr_t)entry->ie_object) : 0;
284 		iin->iin_next = entry->ie_next;
285 		iin->iin_hash = entry->ie_index;
286 	}
287 
288 	is_read_unlock(space);
289 
290 	/* prepare the table out-of-line data for return */
291 	if (table_size > 0) {
292 		vm_size_t used_table_size;
293 
294 		used_table_size = infop->iis_table_size * sizeof(ipc_info_name_t);
295 		if (table_size > used_table_size) {
296 			bzero((char *)&table_info[infop->iis_table_size],
297 			    table_size - used_table_size);
298 		}
299 
300 		kr = vm_map_unwire(
301 			ipc_kernel_map,
302 			vm_map_trunc_page(table_addr,
303 			VM_MAP_PAGE_MASK(ipc_kernel_map)),
304 			vm_map_round_page(table_addr + table_size,
305 			VM_MAP_PAGE_MASK(ipc_kernel_map)),
306 			FALSE);
307 		assert(kr == KERN_SUCCESS);
308 		kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)table_addr,
309 		    (vm_map_size_t)used_table_size, TRUE, &copy);
310 		assert(kr == KERN_SUCCESS);
311 		*tablep = (ipc_info_name_t *)copy;
312 		*tableCntp = infop->iis_table_size;
313 	} else {
314 		*tablep = (ipc_info_name_t *)0;
315 		*tableCntp = 0;
316 	}
317 
318 	/* splay tree is obsolete, no work to do... */
319 	*treep = (ipc_info_tree_name_t *)0;
320 	*treeCntp = 0;
321 	return KERN_SUCCESS;
322 }
323 
324 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)325 mach_port_space_info_from_user(
326 	mach_port_t                     port,
327 	ipc_info_space_t                *infop,
328 	ipc_info_name_array_t           *tablep,
329 	mach_msg_type_number_t          *tableCntp,
330 	__unused ipc_info_tree_name_array_t     *treep,
331 	__unused mach_msg_type_number_t         *treeCntp)
332 {
333 	kern_return_t kr;
334 
335 	ipc_space_t space = convert_port_to_space_read_no_eval(port);
336 
337 	if (space == IPC_SPACE_NULL) {
338 		return KERN_INVALID_ARGUMENT;
339 	}
340 
341 	kr = mach_port_space_info(space, infop, tablep, tableCntp, treep, treeCntp);
342 
343 	ipc_space_release(space);
344 	return kr;
345 }
346 #endif /* MACH_IPC_DEBUG */
347 
348 /*
349  *	Routine:	mach_port_space_basic_info
350  *	Purpose:
351  *		Returns basic information about an IPC space.
352  *	Conditions:
353  *		Nothing locked.
354  *	Returns:
355  *		KERN_SUCCESS		Returned information.
356  *		KERN_FAILURE		The call is not supported.
357  *		KERN_INVALID_TASK	The space is dead.
358  */
359 
360 #if !MACH_IPC_DEBUG
361 kern_return_t
mach_port_space_basic_info(__unused ipc_space_t space,__unused ipc_info_space_basic_t * infop)362 mach_port_space_basic_info(
363 	__unused ipc_space_t                    space,
364 	__unused ipc_info_space_basic_t         *infop)
365 {
366 	return KERN_FAILURE;
367 }
368 #else
369 kern_return_t
mach_port_space_basic_info(ipc_space_t space,ipc_info_space_basic_t * infop)370 mach_port_space_basic_info(
371 	ipc_space_t                     space,
372 	ipc_info_space_basic_t          *infop)
373 {
374 	ipc_entry_num_t tsize;
375 
376 	if (space == IS_NULL) {
377 		return KERN_INVALID_TASK;
378 	}
379 
380 	is_read_lock(space);
381 	if (!is_active(space)) {
382 		is_read_unlock(space);
383 		return KERN_INVALID_TASK;
384 	}
385 
386 	tsize = is_active_table(space)->ie_size;
387 
388 	/* get the basic space info */
389 	infop->iisb_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD);
390 	infop->iisb_table_size = tsize;
391 	infop->iisb_table_next = space->is_table_next->its_size;
392 	infop->iisb_table_inuse = tsize - space->is_table_free - 1;
393 	infop->iisb_reserved[0] = 0;
394 	infop->iisb_reserved[1] = 0;
395 
396 	is_read_unlock(space);
397 
398 	return KERN_SUCCESS;
399 }
400 #endif /* MACH_IPC_DEBUG */
401 
402 /*
403  *	Routine:	mach_port_dnrequest_info
404  *	Purpose:
405  *		Returns information about the dead-name requests
406  *		registered with the named receive right.
407  *	Conditions:
408  *		Nothing locked.
409  *	Returns:
410  *		KERN_SUCCESS		Retrieved information.
411  *		KERN_INVALID_TASK	The space is null.
412  *		KERN_INVALID_TASK	The space is dead.
413  *		KERN_INVALID_NAME	The name doesn't denote a right.
414  *		KERN_INVALID_RIGHT	Name doesn't denote receive rights.
415  */
416 
417 #if !MACH_IPC_DEBUG
418 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)419 mach_port_dnrequest_info(
420 	__unused ipc_space_t            space,
421 	__unused mach_port_name_t       name,
422 	__unused unsigned int   *totalp,
423 	__unused unsigned int   *usedp)
424 {
425 	return KERN_FAILURE;
426 }
427 #else
428 kern_return_t
mach_port_dnrequest_info(ipc_space_t space,mach_port_name_t name,unsigned int * totalp,unsigned int * usedp)429 mach_port_dnrequest_info(
430 	ipc_space_t                     space,
431 	mach_port_name_t                name,
432 	unsigned int                    *totalp,
433 	unsigned int                    *usedp)
434 {
435 	unsigned int total, used;
436 	ipc_port_t port;
437 	kern_return_t kr;
438 
439 	if (space == IS_NULL) {
440 		return KERN_INVALID_TASK;
441 	}
442 
443 	kr = ipc_port_translate_receive(space, name, &port);
444 	if (kr != KERN_SUCCESS) {
445 		return kr;
446 	}
447 	/* port is locked and active */
448 
449 	if (port->ip_requests == IPR_NULL) {
450 		total = 0;
451 		used = 0;
452 	} else {
453 		ipc_port_request_t requests = port->ip_requests;
454 		ipc_port_request_index_t index;
455 
456 		total = requests->ipr_size->its_size;
457 
458 		for (index = 1, used = 0;
459 		    index < total; index++) {
460 			ipc_port_request_t ipr = &requests[index];
461 
462 			if (ipr->ipr_name != MACH_PORT_NULL) {
463 				used++;
464 			}
465 		}
466 	}
467 	ip_mq_unlock(port);
468 
469 	*totalp = total;
470 	*usedp = used;
471 	return KERN_SUCCESS;
472 }
473 #endif /* MACH_IPC_DEBUG */
474 
475 /*
476  *	Routine:	mach_port_kobject [kernel call]
477  *	Purpose:
478  *		Retrieve the type and address of the kernel object
479  *		represented by a send or receive right. Returns
480  *		the kernel address in a mach_vm_address_t to
481  *		mask potential differences in kernel address space
482  *		size.
483  *	Conditions:
484  *		Nothing locked.
485  *	Returns:
486  *		KERN_SUCCESS		Retrieved kernel object info.
487  *		KERN_INVALID_TASK	The space is null.
488  *		KERN_INVALID_TASK	The space is dead.
489  *		KERN_INVALID_NAME	The name doesn't denote a right.
490  *		KERN_INVALID_RIGHT	Name doesn't denote
491  *					send or receive rights.
492  */
493 
494 #if !MACH_IPC_DEBUG
495 kern_return_t
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)496 mach_port_kobject_from_user(
497 	__unused mach_port_t            port,
498 	__unused mach_port_name_t       name,
499 	__unused natural_t              *typep,
500 	__unused mach_vm_address_t      *addrp)
501 {
502 	return KERN_FAILURE;
503 }
504 
505 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)506 mach_port_kobject_description_from_user(
507 	__unused mach_port_t            port,
508 	__unused mach_port_name_t       name,
509 	__unused natural_t              *typep,
510 	__unused mach_vm_address_t      *addrp,
511 	__unused kobject_description_t  des)
512 {
513 	return KERN_FAILURE;
514 }
515 #else
516 kern_return_t
517 mach_port_kobject_description(
518 	ipc_space_t                     space,
519 	mach_port_name_t                name,
520 	natural_t                       *typep,
521 	mach_vm_address_t               *addrp,
522 	kobject_description_t           desc);
523 
524 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)525 mach_port_kobject_description(
526 	ipc_space_t                     space,
527 	mach_port_name_t                name,
528 	natural_t                       *typep,
529 	mach_vm_address_t               *addrp,
530 	kobject_description_t           desc)
531 {
532 	ipc_entry_bits_t bits;
533 	ipc_object_t object;
534 	kern_return_t kr;
535 	mach_vm_address_t kaddr = 0;
536 	io_object_t obj = NULL;
537 
538 	if (space == IS_NULL) {
539 		return KERN_INVALID_TASK;
540 	}
541 
542 	kr = ipc_right_lookup_read(space, name, &bits, &object);
543 	if (kr != KERN_SUCCESS) {
544 		return kr;
545 	}
546 	/* object is locked and active */
547 
548 	if ((bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) {
549 		io_unlock(object);
550 		return KERN_INVALID_RIGHT;
551 	}
552 
553 	*typep = (unsigned int)io_kotype(object);
554 	if (io_is_kobject(object)) {
555 		ipc_port_t port = ip_object_to_port(object);
556 		kaddr = (mach_vm_address_t)ipc_kobject_get_raw(port, io_kotype(object));
557 	}
558 	*addrp = 0;
559 
560 	if (desc) {
561 		*desc = '\0';
562 		switch (io_kotype(object)) {
563 		case IKOT_IOKIT_OBJECT:
564 		case IKOT_IOKIT_CONNECT:
565 		case IKOT_IOKIT_IDENT:
566 		case IKOT_UEXT_OBJECT:
567 			obj = (io_object_t) kaddr;
568 			iokit_add_reference(obj, IKOT_IOKIT_OBJECT);
569 			break;
570 
571 		default:
572 			break;
573 		}
574 	}
575 #if (DEVELOPMENT || DEBUG)
576 	*addrp = VM_KERNEL_UNSLIDE_OR_PERM(kaddr);
577 #endif
578 
579 	io_unlock(object);
580 
581 	if (obj) {
582 		iokit_port_object_description(obj, desc);
583 		iokit_remove_reference(obj);
584 	}
585 
586 	return KERN_SUCCESS;
587 }
588 
589 kern_return_t
590 mach_port_kobject(
591 	ipc_space_t                     space,
592 	mach_port_name_t                name,
593 	natural_t                       *typep,
594 	mach_vm_address_t               *addrp);
595 
596 kern_return_t
mach_port_kobject(ipc_space_t space,mach_port_name_t name,natural_t * typep,mach_vm_address_t * addrp)597 mach_port_kobject(
598 	ipc_space_t                     space,
599 	mach_port_name_t                name,
600 	natural_t                       *typep,
601 	mach_vm_address_t               *addrp)
602 {
603 	return mach_port_kobject_description(space, name, typep, addrp, NULL);
604 }
605 
606 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)607 mach_port_kobject_description_from_user(
608 	mach_port_t                     port,
609 	mach_port_name_t                name,
610 	natural_t                       *typep,
611 	mach_vm_address_t               *addrp,
612 	kobject_description_t           desc)
613 {
614 	kern_return_t kr;
615 
616 	ipc_space_t space = convert_port_to_space_read_no_eval(port);
617 
618 	if (space == IPC_SPACE_NULL) {
619 		return KERN_INVALID_ARGUMENT;
620 	}
621 
622 	kr = mach_port_kobject_description(space, name, typep, addrp, desc);
623 
624 	ipc_space_release(space);
625 	return kr;
626 }
627 
628 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)629 mach_port_kobject_from_user(
630 	mach_port_t                     port,
631 	mach_port_name_t                name,
632 	natural_t                       *typep,
633 	mach_vm_address_t               *addrp)
634 {
635 	return mach_port_kobject_description_from_user(port, name, typep, addrp, NULL);
636 }
637 
638 #endif /* MACH_IPC_DEBUG */
639 
640 /*
641  *	Routine:	mach_port_kernel_object [Legacy kernel call]
642  *	Purpose:
643  *		Retrieve the type and address of the kernel object
644  *		represented by a send or receive right. Hard-coded
645  *		to return only the low-order 32-bits of the kernel
646  *		object.
647  *	Conditions:
648  *		Nothing locked.
649  *	Returns:
650  *		KERN_SUCCESS		Retrieved kernel object info.
651  *		KERN_INVALID_TASK	The space is null.
652  *		KERN_INVALID_TASK	The space is dead.
653  *		KERN_INVALID_NAME	The name doesn't denote a right.
654  *		KERN_INVALID_RIGHT	Name doesn't denote
655  *					send or receive rights.
656  */
657 
658 #if !MACH_IPC_DEBUG
659 kern_return_t
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)660 mach_port_kernel_object_from_user(
661 	__unused mach_port_t            port,
662 	__unused mach_port_name_t       name,
663 	__unused unsigned int           *typep,
664 	__unused unsigned int           *addrp)
665 {
666 	return KERN_FAILURE;
667 }
668 #else
669 kern_return_t
670 mach_port_kernel_object(
671 	ipc_space_t                     space,
672 	mach_port_name_t                name,
673 	unsigned int                    *typep,
674 	unsigned int                    *addrp);
675 
676 kern_return_t
mach_port_kernel_object(ipc_space_t space,mach_port_name_t name,unsigned int * typep,unsigned int * addrp)677 mach_port_kernel_object(
678 	ipc_space_t                     space,
679 	mach_port_name_t                name,
680 	unsigned int                    *typep,
681 	unsigned int                    *addrp)
682 {
683 	mach_vm_address_t addr = 0;
684 	kern_return_t kr;
685 
686 	kr = mach_port_kobject(space, name, typep, &addr);
687 	*addrp = (unsigned int) addr;
688 	return kr;
689 }
690 
691 kern_return_t
mach_port_kernel_object_from_user(mach_port_t port,mach_port_name_t name,unsigned int * typep,unsigned int * addrp)692 mach_port_kernel_object_from_user(
693 	mach_port_t                     port,
694 	mach_port_name_t                name,
695 	unsigned int                    *typep,
696 	unsigned int                    *addrp)
697 {
698 	kern_return_t kr;
699 
700 	ipc_space_t space = convert_port_to_space_read_no_eval(port);
701 
702 	if (space == IPC_SPACE_NULL) {
703 		return KERN_INVALID_ARGUMENT;
704 	}
705 
706 	kr = mach_port_kernel_object(space, name, typep, addrp);
707 
708 	ipc_space_release(space);
709 	return kr;
710 }
711 #endif /* MACH_IPC_DEBUG */
712 
713 #if (DEVELOPMENT || DEBUG)
714 kern_return_t
mach_port_special_reply_port_reset_link(ipc_space_t space,mach_port_name_t name,boolean_t * srp_lost_link)715 mach_port_special_reply_port_reset_link(
716 	ipc_space_t             space,
717 	mach_port_name_t        name,
718 	boolean_t               *srp_lost_link)
719 {
720 	ipc_port_t port;
721 	kern_return_t kr;
722 	thread_t thread = current_thread();
723 
724 	if (space != current_space()) {
725 		return KERN_INVALID_TASK;
726 	}
727 
728 	if (!MACH_PORT_VALID(name)) {
729 		return KERN_INVALID_NAME;
730 	}
731 
732 	if (!IP_VALID(thread->ith_special_reply_port)) {
733 		return KERN_INVALID_VALUE;
734 	}
735 
736 	kr = ipc_port_translate_receive(space, name, &port);
737 	if (kr != KERN_SUCCESS) {
738 		return kr;
739 	}
740 
741 	if (thread->ith_special_reply_port != port) {
742 		ip_mq_unlock(port);
743 		return KERN_INVALID_ARGUMENT;
744 	}
745 
746 	*srp_lost_link = (port->ip_srp_lost_link == 1)? TRUE : FALSE;
747 	port->ip_srp_lost_link = 0;
748 
749 	ip_mq_unlock(port);
750 	return KERN_SUCCESS;
751 }
752 #else
753 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)754 mach_port_special_reply_port_reset_link(
755 	__unused ipc_space_t            space,
756 	__unused mach_port_name_t       name,
757 	__unused boolean_t              *srp_lost_link)
758 {
759 	return KERN_NOT_SUPPORTED;
760 }
761 #endif
762