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 const uint32_t BATCH_SIZE = 4 << 10;
192 ipc_info_name_t *table_info;
193 vm_offset_t table_addr = 0;
194 vm_size_t table_size, table_size_needed;
195 ipc_entry_t table;
196 ipc_entry_num_t tsize;
197 kern_return_t kr;
198 vm_map_copy_t copy;
199
200 if (space == IS_NULL) {
201 return KERN_INVALID_TASK;
202 }
203
204 #if !(DEVELOPMENT || DEBUG) && CONFIG_MACF
205 const boolean_t dbg_ok = (mac_task_check_expose_task(kernel_task, TASK_FLAVOR_CONTROL) == 0);
206 #else
207 const boolean_t dbg_ok = TRUE;
208 #endif
209
210 /* start with in-line memory */
211
212 table_size = 0;
213
214 is_read_lock(space);
215
216 allocate_loop:
217 for (;;) {
218 if (!is_active(space)) {
219 is_read_unlock(space);
220 if (table_size != 0) {
221 kmem_free(ipc_kernel_map,
222 table_addr, table_size);
223 }
224 return KERN_INVALID_TASK;
225 }
226
227 table = is_active_table(space);
228 tsize = table->ie_size;
229
230 table_size_needed =
231 vm_map_round_page(tsize * sizeof(ipc_info_name_t),
232 VM_MAP_PAGE_MASK(ipc_kernel_map));
233
234 if (table_size_needed <= table_size) {
235 break;
236 }
237
238 is_read_unlock(space);
239
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,
244 KMA_DATA, VM_KERN_MEMORY_IPC);
245 if (kr != KERN_SUCCESS) {
246 return KERN_RESOURCE_SHORTAGE;
247 }
248 table_size = table_size_needed;
249
250 is_read_lock(space);
251 }
252 /* space is read-locked and active; we have enough wired memory */
253
254 /* walk the table for this space */
255 table_info = (ipc_info_name_array_t)table_addr;
256 for (mach_port_index_t index = 0; index < tsize; index++) {
257 ipc_info_name_t *iin = &table_info[index];
258 ipc_entry_t entry = &table[index];
259 ipc_entry_bits_t bits;
260
261 if (index == 0) {
262 bits = IE_BITS_GEN_MASK;
263 } else {
264 bits = entry->ie_bits;
265 }
266 iin->iin_name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits));
267 iin->iin_collision = 0;
268 iin->iin_type = IE_BITS_TYPE(bits);
269 if ((bits & MACH_PORT_TYPE_PORT_RIGHTS) != MACH_PORT_TYPE_NONE &&
270 entry->ie_request != IE_REQ_NONE) {
271 ipc_port_t port = ip_object_to_port(entry->ie_object);
272
273 assert(IP_VALID(port));
274 ip_mq_lock(port);
275 iin->iin_type |= ipc_port_request_type(port, iin->iin_name, entry->ie_request);
276 ip_mq_unlock(port);
277 }
278
279 iin->iin_urefs = IE_BITS_UREFS(bits);
280 iin->iin_object = (dbg_ok) ? (natural_t)VM_KERNEL_ADDRPERM((uintptr_t)entry->ie_object) : 0;
281 iin->iin_next = entry->ie_next;
282 iin->iin_hash = entry->ie_index;
283
284 if (index + 1 < tsize && (index + 1) % BATCH_SIZE == 0) {
285 /*
286 * Give the system some breathing room,
287 * and check if anything changed,
288 * if yes start over.
289 */
290 is_read_unlock(space);
291 is_read_lock(space);
292 if (!is_active(space)) {
293 goto allocate_loop;
294 }
295 table = is_active_table(space);
296 if (tsize < table->ie_size) {
297 goto allocate_loop;
298 }
299 tsize = table->ie_size;
300 }
301 }
302
303 /* get the overall space info */
304 infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD);
305 infop->iis_table_size = tsize;
306 infop->iis_table_next = space->is_table_next->its_size;
307
308 is_read_unlock(space);
309
310 /* prepare the table out-of-line data for return */
311 if (table_size > 0) {
312 vm_map_size_t used = tsize * sizeof(ipc_info_name_t);
313 vm_map_size_t keep = vm_map_round_page(used,
314 VM_MAP_PAGE_MASK(ipc_kernel_map));
315
316 if (keep < table_size) {
317 kmem_free(ipc_kernel_map, table_addr + keep,
318 table_size - keep);
319 table_size = keep;
320 }
321 if (table_size > used) {
322 bzero(&table_info[infop->iis_table_size],
323 table_size - used);
324 }
325
326 kr = vm_map_unwire(ipc_kernel_map, table_addr,
327 table_addr + table_size, FALSE);
328 assert(kr == KERN_SUCCESS);
329 kr = vm_map_copyin(ipc_kernel_map, table_addr, used, TRUE, ©);
330 assert(kr == KERN_SUCCESS);
331 *tablep = (ipc_info_name_t *)copy;
332 *tableCntp = infop->iis_table_size;
333 } else {
334 *tablep = (ipc_info_name_t *)0;
335 *tableCntp = 0;
336 }
337
338 /* splay tree is obsolete, no work to do... */
339 *treep = (ipc_info_tree_name_t *)0;
340 *treeCntp = 0;
341 return KERN_SUCCESS;
342 }
343
344 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)345 mach_port_space_info_from_user(
346 mach_port_t port,
347 ipc_info_space_t *infop,
348 ipc_info_name_array_t *tablep,
349 mach_msg_type_number_t *tableCntp,
350 __unused ipc_info_tree_name_array_t *treep,
351 __unused mach_msg_type_number_t *treeCntp)
352 {
353 kern_return_t kr;
354
355 ipc_space_t space = convert_port_to_space_read_no_eval(port);
356
357 if (space == IPC_SPACE_NULL) {
358 return KERN_INVALID_ARGUMENT;
359 }
360
361 kr = mach_port_space_info(space, infop, tablep, tableCntp, treep, treeCntp);
362
363 ipc_space_release(space);
364 return kr;
365 }
366 #endif /* MACH_IPC_DEBUG */
367
368 /*
369 * Routine: mach_port_space_basic_info
370 * Purpose:
371 * Returns basic information about an IPC space.
372 * Conditions:
373 * Nothing locked.
374 * Returns:
375 * KERN_SUCCESS Returned information.
376 * KERN_FAILURE The call is not supported.
377 * KERN_INVALID_TASK The space is dead.
378 */
379
380 #if !MACH_IPC_DEBUG
381 kern_return_t
mach_port_space_basic_info(__unused ipc_space_t space,__unused ipc_info_space_basic_t * infop)382 mach_port_space_basic_info(
383 __unused ipc_space_t space,
384 __unused ipc_info_space_basic_t *infop)
385 {
386 return KERN_FAILURE;
387 }
388 #else
389 kern_return_t
mach_port_space_basic_info(ipc_space_t space,ipc_info_space_basic_t * infop)390 mach_port_space_basic_info(
391 ipc_space_t space,
392 ipc_info_space_basic_t *infop)
393 {
394 ipc_entry_num_t tsize;
395
396 if (space == IS_NULL) {
397 return KERN_INVALID_TASK;
398 }
399
400 is_read_lock(space);
401 if (!is_active(space)) {
402 is_read_unlock(space);
403 return KERN_INVALID_TASK;
404 }
405
406 tsize = is_active_table(space)->ie_size;
407
408 /* get the basic space info */
409 infop->iisb_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD);
410 infop->iisb_table_size = tsize;
411 infop->iisb_table_next = space->is_table_next->its_size;
412 infop->iisb_table_inuse = tsize - space->is_table_free - 1;
413 infop->iisb_reserved[0] = 0;
414 infop->iisb_reserved[1] = 0;
415
416 is_read_unlock(space);
417
418 return KERN_SUCCESS;
419 }
420 #endif /* MACH_IPC_DEBUG */
421
422 /*
423 * Routine: mach_port_dnrequest_info
424 * Purpose:
425 * Returns information about the dead-name requests
426 * registered with the named receive right.
427 * Conditions:
428 * Nothing locked.
429 * Returns:
430 * KERN_SUCCESS Retrieved information.
431 * KERN_INVALID_TASK The space is null.
432 * KERN_INVALID_TASK The space is dead.
433 * KERN_INVALID_NAME The name doesn't denote a right.
434 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
435 */
436
437 #if !MACH_IPC_DEBUG
438 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)439 mach_port_dnrequest_info(
440 __unused ipc_space_t space,
441 __unused mach_port_name_t name,
442 __unused unsigned int *totalp,
443 __unused unsigned int *usedp)
444 {
445 return KERN_FAILURE;
446 }
447 #else
448 kern_return_t
mach_port_dnrequest_info(ipc_space_t space,mach_port_name_t name,unsigned int * totalp,unsigned int * usedp)449 mach_port_dnrequest_info(
450 ipc_space_t space,
451 mach_port_name_t name,
452 unsigned int *totalp,
453 unsigned int *usedp)
454 {
455 unsigned int total, used;
456 ipc_port_t port;
457 kern_return_t kr;
458
459 if (space == IS_NULL) {
460 return KERN_INVALID_TASK;
461 }
462
463 kr = ipc_port_translate_receive(space, name, &port);
464 if (kr != KERN_SUCCESS) {
465 return kr;
466 }
467 /* port is locked and active */
468
469 if (port->ip_requests == IPR_NULL) {
470 total = 0;
471 used = 0;
472 } else {
473 ipc_port_request_t requests = port->ip_requests;
474 ipc_port_request_index_t index;
475
476 total = requests->ipr_size->its_size;
477
478 for (index = 1, used = 0;
479 index < total; index++) {
480 ipc_port_request_t ipr = &requests[index];
481
482 if (ipr->ipr_name != MACH_PORT_NULL) {
483 used++;
484 }
485 }
486 }
487 ip_mq_unlock(port);
488
489 *totalp = total;
490 *usedp = used;
491 return KERN_SUCCESS;
492 }
493 #endif /* MACH_IPC_DEBUG */
494
495 /*
496 * Routine: mach_port_kobject [kernel call]
497 * Purpose:
498 * Retrieve the type and address of the kernel object
499 * represented by a send or receive right. Returns
500 * the kernel address in a mach_vm_address_t to
501 * mask potential differences in kernel address space
502 * size.
503 * Conditions:
504 * Nothing locked.
505 * Returns:
506 * KERN_SUCCESS Retrieved kernel object info.
507 * KERN_INVALID_TASK The space is null.
508 * KERN_INVALID_TASK The space is dead.
509 * KERN_INVALID_NAME The name doesn't denote a right.
510 * KERN_INVALID_RIGHT Name doesn't denote
511 * send or receive rights.
512 */
513
514 #if !MACH_IPC_DEBUG
515 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)516 mach_port_kobject_from_user(
517 __unused mach_port_t port,
518 __unused mach_port_name_t name,
519 __unused natural_t *typep,
520 __unused mach_vm_address_t *addrp)
521 {
522 return KERN_FAILURE;
523 }
524
525 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)526 mach_port_kobject_description_from_user(
527 __unused mach_port_t port,
528 __unused mach_port_name_t name,
529 __unused natural_t *typep,
530 __unused mach_vm_address_t *addrp,
531 __unused kobject_description_t des)
532 {
533 return KERN_FAILURE;
534 }
535 #else
536 kern_return_t
537 mach_port_kobject_description(
538 ipc_space_t space,
539 mach_port_name_t name,
540 natural_t *typep,
541 mach_vm_address_t *addrp,
542 kobject_description_t desc);
543
544 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)545 mach_port_kobject_description(
546 ipc_space_t space,
547 mach_port_name_t name,
548 natural_t *typep,
549 mach_vm_address_t *addrp,
550 kobject_description_t desc)
551 {
552 ipc_entry_bits_t bits;
553 ipc_object_t object;
554 kern_return_t kr;
555 mach_vm_address_t kaddr = 0;
556 io_object_t obj = NULL;
557
558 if (space == IS_NULL) {
559 return KERN_INVALID_TASK;
560 }
561
562 kr = ipc_right_lookup_read(space, name, &bits, &object);
563 if (kr != KERN_SUCCESS) {
564 return kr;
565 }
566 /* object is locked and active */
567
568 if ((bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) {
569 io_unlock(object);
570 return KERN_INVALID_RIGHT;
571 }
572
573 *typep = (unsigned int)io_kotype(object);
574 if (io_is_kobject(object)) {
575 ipc_port_t port = ip_object_to_port(object);
576 kaddr = (mach_vm_address_t)ipc_kobject_get_raw(port, io_kotype(object));
577 }
578 *addrp = 0;
579
580 if (desc) {
581 *desc = '\0';
582 switch (io_kotype(object)) {
583 case IKOT_IOKIT_OBJECT:
584 case IKOT_IOKIT_CONNECT:
585 case IKOT_IOKIT_IDENT:
586 case IKOT_UEXT_OBJECT:
587 obj = (io_object_t) kaddr;
588 iokit_add_reference(obj, IKOT_IOKIT_OBJECT);
589 break;
590
591 default:
592 break;
593 }
594 }
595 #if (DEVELOPMENT || DEBUG)
596 *addrp = VM_KERNEL_UNSLIDE_OR_PERM(kaddr);
597 #endif
598
599 io_unlock(object);
600
601 if (obj) {
602 iokit_port_object_description(obj, desc);
603 iokit_remove_reference(obj);
604 }
605
606 return KERN_SUCCESS;
607 }
608
609 kern_return_t
610 mach_port_kobject(
611 ipc_space_t space,
612 mach_port_name_t name,
613 natural_t *typep,
614 mach_vm_address_t *addrp);
615
616 kern_return_t
mach_port_kobject(ipc_space_t space,mach_port_name_t name,natural_t * typep,mach_vm_address_t * addrp)617 mach_port_kobject(
618 ipc_space_t space,
619 mach_port_name_t name,
620 natural_t *typep,
621 mach_vm_address_t *addrp)
622 {
623 return mach_port_kobject_description(space, name, typep, addrp, NULL);
624 }
625
626 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)627 mach_port_kobject_description_from_user(
628 mach_port_t port,
629 mach_port_name_t name,
630 natural_t *typep,
631 mach_vm_address_t *addrp,
632 kobject_description_t desc)
633 {
634 kern_return_t kr;
635
636 ipc_space_t space = convert_port_to_space_read_no_eval(port);
637
638 if (space == IPC_SPACE_NULL) {
639 return KERN_INVALID_ARGUMENT;
640 }
641
642 kr = mach_port_kobject_description(space, name, typep, addrp, desc);
643
644 ipc_space_release(space);
645 return kr;
646 }
647
648 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)649 mach_port_kobject_from_user(
650 mach_port_t port,
651 mach_port_name_t name,
652 natural_t *typep,
653 mach_vm_address_t *addrp)
654 {
655 return mach_port_kobject_description_from_user(port, name, typep, addrp, NULL);
656 }
657
658 #endif /* MACH_IPC_DEBUG */
659
660 /*
661 * Routine: mach_port_kernel_object [Legacy kernel call]
662 * Purpose:
663 * Retrieve the type and address of the kernel object
664 * represented by a send or receive right. Hard-coded
665 * to return only the low-order 32-bits of the kernel
666 * object.
667 * Conditions:
668 * Nothing locked.
669 * Returns:
670 * KERN_SUCCESS Retrieved kernel object info.
671 * KERN_INVALID_TASK The space is null.
672 * KERN_INVALID_TASK The space is dead.
673 * KERN_INVALID_NAME The name doesn't denote a right.
674 * KERN_INVALID_RIGHT Name doesn't denote
675 * send or receive rights.
676 */
677
678 #if !MACH_IPC_DEBUG
679 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)680 mach_port_kernel_object_from_user(
681 __unused mach_port_t port,
682 __unused mach_port_name_t name,
683 __unused unsigned int *typep,
684 __unused unsigned int *addrp)
685 {
686 return KERN_FAILURE;
687 }
688 #else
689 kern_return_t
690 mach_port_kernel_object(
691 ipc_space_t space,
692 mach_port_name_t name,
693 unsigned int *typep,
694 unsigned int *addrp);
695
696 kern_return_t
mach_port_kernel_object(ipc_space_t space,mach_port_name_t name,unsigned int * typep,unsigned int * addrp)697 mach_port_kernel_object(
698 ipc_space_t space,
699 mach_port_name_t name,
700 unsigned int *typep,
701 unsigned int *addrp)
702 {
703 mach_vm_address_t addr = 0;
704 kern_return_t kr;
705
706 kr = mach_port_kobject(space, name, typep, &addr);
707 *addrp = (unsigned int) addr;
708 return kr;
709 }
710
711 kern_return_t
mach_port_kernel_object_from_user(mach_port_t port,mach_port_name_t name,unsigned int * typep,unsigned int * addrp)712 mach_port_kernel_object_from_user(
713 mach_port_t port,
714 mach_port_name_t name,
715 unsigned int *typep,
716 unsigned int *addrp)
717 {
718 kern_return_t kr;
719
720 ipc_space_t space = convert_port_to_space_read_no_eval(port);
721
722 if (space == IPC_SPACE_NULL) {
723 return KERN_INVALID_ARGUMENT;
724 }
725
726 kr = mach_port_kernel_object(space, name, typep, addrp);
727
728 ipc_space_release(space);
729 return kr;
730 }
731 #endif /* MACH_IPC_DEBUG */
732
733 #if (DEVELOPMENT || DEBUG)
734 kern_return_t
mach_port_special_reply_port_reset_link(ipc_space_t space,mach_port_name_t name,boolean_t * srp_lost_link)735 mach_port_special_reply_port_reset_link(
736 ipc_space_t space,
737 mach_port_name_t name,
738 boolean_t *srp_lost_link)
739 {
740 ipc_port_t port;
741 kern_return_t kr;
742 thread_t thread = current_thread();
743
744 if (space != current_space()) {
745 return KERN_INVALID_TASK;
746 }
747
748 if (!MACH_PORT_VALID(name)) {
749 return KERN_INVALID_NAME;
750 }
751
752 if (!IP_VALID(thread->ith_special_reply_port)) {
753 return KERN_INVALID_VALUE;
754 }
755
756 kr = ipc_port_translate_receive(space, name, &port);
757 if (kr != KERN_SUCCESS) {
758 return kr;
759 }
760
761 if (thread->ith_special_reply_port != port) {
762 ip_mq_unlock(port);
763 return KERN_INVALID_ARGUMENT;
764 }
765
766 *srp_lost_link = (port->ip_srp_lost_link == 1)? TRUE : FALSE;
767 port->ip_srp_lost_link = 0;
768
769 ip_mq_unlock(port);
770 return KERN_SUCCESS;
771 }
772 #else
773 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)774 mach_port_special_reply_port_reset_link(
775 __unused ipc_space_t space,
776 __unused mach_port_name_t name,
777 __unused boolean_t *srp_lost_link)
778 {
779 return KERN_NOT_SUPPORTED;
780 }
781 #endif
782