2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
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.
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.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
58 * support for mandatory and extensible security protections. This notice
59 * is included in support of clause 2.2 (b) of the Apple Public License,
61 * Copyright (c) 2005-2006 SPARTA, Inc.
66 * File: ipc/mach_port.c
70 * Exported kernel calls. See mach/mach_port.defs.
73 #include <mach_debug.h>
76 #include <mach/port.h>
77 #include <mach/kern_return.h>
78 #include <mach/notify.h>
79 #include <mach/mach_param.h>
80 #include <mach/vm_param.h>
81 #include <mach/vm_prot.h>
82 #include <mach/vm_map.h>
83 #include <kern/task.h>
84 #include <kern/counters.h>
85 #include <kern/thread.h>
86 #include <kern/kalloc.h>
87 #include <mach/mach_port_server.h>
88 #include <vm/vm_map.h>
89 #include <vm/vm_kern.h>
90 #include <ipc/ipc_entry.h>
91 #include <ipc/ipc_space.h>
92 #include <ipc/ipc_object.h>
93 #include <ipc/ipc_notify.h>
94 #include <ipc/ipc_port.h>
95 #include <ipc/ipc_pset.h>
96 #include <ipc/ipc_right.h>
97 #include <ipc/ipc_kmsg.h>
98 #include <kern/misc_protos.h>
99 #include <security/mac_mach_internal.h>
101 #if IMPORTANCE_INHERITANCE
102 #include <ipc/ipc_importance.h>
107 * Forward declarations
109 void mach_port_names_helper(
110 ipc_port_timestamp_t timestamp
,
112 mach_port_name_t name
,
113 mach_port_name_t
*names
,
114 mach_port_type_t
*types
,
115 ipc_entry_num_t
*actualp
);
117 void mach_port_gst_helper(
119 ipc_entry_num_t maxnames
,
120 mach_port_name_t
*names
,
121 ipc_entry_num_t
*actualp
);
125 mach_port_guard_exception(
126 mach_port_name_t name
,
131 /* Needs port locked */
132 void mach_port_get_status_helper(
134 mach_port_status_t
*status
);
136 /* Zeroed template of qos flags */
138 static mach_port_qos_t qos_template
;
141 * Routine: mach_port_names_helper
143 * A helper function for mach_port_names.
146 * Space containing entry is [at least] read-locked.
150 mach_port_names_helper(
151 ipc_port_timestamp_t timestamp
,
153 mach_port_name_t name
,
154 mach_port_name_t
*names
,
155 mach_port_type_t
*types
,
156 ipc_entry_num_t
*actualp
)
158 ipc_entry_bits_t bits
;
159 ipc_port_request_index_t request
;
160 mach_port_type_t type
= 0;
161 ipc_entry_num_t actual
;
164 bits
= entry
->ie_bits
;
165 request
= entry
->ie_request
;
166 __IGNORE_WCASTALIGN(port
= (ipc_port_t
) entry
->ie_object
);
168 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
169 assert(IP_VALID(port
));
171 if (request
!= IE_REQ_NONE
) {
173 assert(ip_active(port
));
174 type
|= ipc_port_request_type(port
, name
, request
);
178 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
179 mach_port_type_t reqtype
;
181 assert(IP_VALID(port
));
184 reqtype
= (request
!= IE_REQ_NONE
) ?
185 ipc_port_request_type(port
, name
, request
) : 0;
188 * If the port is alive, or was alive when the mach_port_names
189 * started, then return that fact. Otherwise, pretend we found
192 if (ip_active(port
) || IP_TIMESTAMP_ORDER(timestamp
, port
->ip_timestamp
)) {
195 bits
&= ~(IE_BITS_TYPE_MASK
);
196 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
197 /* account for additional reference for dead-name notification */
204 type
|= IE_BITS_TYPE(bits
);
207 names
[actual
] = name
;
208 types
[actual
] = type
;
213 * Routine: mach_port_names [kernel call]
215 * Retrieves a list of the rights present in the space,
216 * along with type information. (Same as returned
217 * by mach_port_type.) The names are returned in
218 * no particular order, but they (and the type info)
219 * are an accurate snapshot of the space.
223 * KERN_SUCCESS Arrays of names and types returned.
224 * KERN_INVALID_TASK The space is null.
225 * KERN_INVALID_TASK The space is dead.
226 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
232 mach_port_name_t
**namesp
,
233 mach_msg_type_number_t
*namesCnt
,
234 mach_port_type_t
**typesp
,
235 mach_msg_type_number_t
*typesCnt
)
238 ipc_entry_num_t tsize
;
239 mach_port_index_t index
;
240 ipc_entry_num_t actual
; /* this many names */
241 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
242 mach_port_name_t
*names
;
243 mach_port_type_t
*types
;
246 vm_size_t size
; /* size of allocated memory */
247 vm_offset_t addr1
; /* allocated memory, for names */
248 vm_offset_t addr2
; /* allocated memory, for types */
249 vm_map_copy_t memory1
; /* copied-in memory, for names */
250 vm_map_copy_t memory2
; /* copied-in memory, for types */
252 /* safe simplifying assumption */
253 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
255 if (space
== IS_NULL
)
256 return KERN_INVALID_TASK
;
261 ipc_entry_num_t bound
;
262 vm_size_t size_needed
;
265 if (!is_active(space
)) {
266 is_read_unlock(space
);
268 kmem_free(ipc_kernel_map
, addr1
, size
);
269 kmem_free(ipc_kernel_map
, addr2
, size
);
271 return KERN_INVALID_TASK
;
274 /* upper bound on number of names in the space */
275 bound
= space
->is_table_size
;
276 size_needed
= vm_map_round_page(
277 (bound
* sizeof(mach_port_name_t
)),
278 VM_MAP_PAGE_MASK(ipc_kernel_map
));
280 if (size_needed
<= size
)
283 is_read_unlock(space
);
286 kmem_free(ipc_kernel_map
, addr1
, size
);
287 kmem_free(ipc_kernel_map
, addr2
, size
);
291 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_KERN_MEMORY_IPC
));
292 if (kr
!= KERN_SUCCESS
)
293 return KERN_RESOURCE_SHORTAGE
;
295 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_KERN_MEMORY_IPC
));
296 if (kr
!= KERN_SUCCESS
) {
297 kmem_free(ipc_kernel_map
, addr1
, size
);
298 return KERN_RESOURCE_SHORTAGE
;
301 /* can't fault while we hold locks */
305 vm_map_trunc_page(addr1
,
306 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
307 vm_map_round_page(addr1
+ size
,
308 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
309 VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_IPC
),
311 if (kr
!= KERN_SUCCESS
) {
312 kmem_free(ipc_kernel_map
, addr1
, size
);
313 kmem_free(ipc_kernel_map
, addr2
, size
);
314 return KERN_RESOURCE_SHORTAGE
;
319 vm_map_trunc_page(addr2
,
320 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
321 vm_map_round_page(addr2
+ size
,
322 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
323 VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_IPC
),
325 if (kr
!= KERN_SUCCESS
) {
326 kmem_free(ipc_kernel_map
, addr1
, size
);
327 kmem_free(ipc_kernel_map
, addr2
, size
);
328 return KERN_RESOURCE_SHORTAGE
;
332 /* space is read-locked and active */
334 names
= (mach_port_name_t
*) addr1
;
335 types
= (mach_port_type_t
*) addr2
;
338 timestamp
= ipc_port_timestamp();
340 table
= space
->is_table
;
341 tsize
= space
->is_table_size
;
343 for (index
= 0; index
< tsize
; index
++) {
344 ipc_entry_t entry
= &table
[index
];
345 ipc_entry_bits_t bits
= entry
->ie_bits
;
347 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
348 mach_port_name_t name
;
350 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
351 mach_port_names_helper(timestamp
, entry
, name
, names
,
356 is_read_unlock(space
);
359 memory1
= VM_MAP_COPY_NULL
;
360 memory2
= VM_MAP_COPY_NULL
;
363 kmem_free(ipc_kernel_map
, addr1
, size
);
364 kmem_free(ipc_kernel_map
, addr2
, size
);
368 vm_size_t vm_size_used
;
370 size_used
= actual
* sizeof(mach_port_name_t
);
372 vm_map_round_page(size_used
,
373 VM_MAP_PAGE_MASK(ipc_kernel_map
));
376 * Make used memory pageable and get it into
377 * copied-in form. Free any unused memory.
382 vm_map_trunc_page(addr1
,
383 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
384 vm_map_round_page(addr1
+ vm_size_used
,
385 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
387 assert(kr
== KERN_SUCCESS
);
391 vm_map_trunc_page(addr2
,
392 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
393 vm_map_round_page(addr2
+ vm_size_used
,
394 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
396 assert(kr
== KERN_SUCCESS
);
398 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr1
,
399 (vm_map_size_t
)size_used
, TRUE
, &memory1
);
400 assert(kr
== KERN_SUCCESS
);
402 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr2
,
403 (vm_map_size_t
)size_used
, TRUE
, &memory2
);
404 assert(kr
== KERN_SUCCESS
);
406 if (vm_size_used
!= size
) {
407 kmem_free(ipc_kernel_map
,
408 addr1
+ vm_size_used
, size
- vm_size_used
);
409 kmem_free(ipc_kernel_map
,
410 addr2
+ vm_size_used
, size
- vm_size_used
);
414 *namesp
= (mach_port_name_t
*) memory1
;
416 *typesp
= (mach_port_type_t
*) memory2
;
422 * Routine: mach_port_type [kernel call]
424 * Retrieves the type of a right in the space.
425 * The type is a bitwise combination of one or more
426 * of the following type bits:
427 * MACH_PORT_TYPE_SEND
428 * MACH_PORT_TYPE_RECEIVE
429 * MACH_PORT_TYPE_SEND_ONCE
430 * MACH_PORT_TYPE_PORT_SET
431 * MACH_PORT_TYPE_DEAD_NAME
432 * In addition, the following pseudo-type bits may be present:
433 * MACH_PORT_TYPE_DNREQUEST
434 * A dead-name notification is requested.
438 * KERN_SUCCESS Type is returned.
439 * KERN_INVALID_TASK The space is null.
440 * KERN_INVALID_TASK The space is dead.
441 * KERN_INVALID_NAME The name doesn't denote a right.
447 mach_port_name_t name
,
448 mach_port_type_t
*typep
)
450 mach_port_urefs_t urefs
;
454 if (space
== IS_NULL
)
455 return KERN_INVALID_TASK
;
457 if (name
== MACH_PORT_NULL
)
458 return KERN_INVALID_NAME
;
460 if (name
== MACH_PORT_DEAD
) {
461 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
465 kr
= ipc_right_lookup_write(space
, name
, &entry
);
466 if (kr
!= KERN_SUCCESS
)
469 /* space is write-locked and active */
470 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
471 /* space is unlocked */
474 /* JMM - workaround rdar://problem/9121297 (CF being too picky on these bits). */
475 *typep
&= ~(MACH_PORT_TYPE_SPREQUEST
| MACH_PORT_TYPE_SPREQUEST_DELAYED
);
482 * Routine: mach_port_rename [kernel call]
484 * Changes the name denoting a right,
485 * from oname to nname.
489 * KERN_SUCCESS The right is renamed.
490 * KERN_INVALID_TASK The space is null.
491 * KERN_INVALID_TASK The space is dead.
492 * KERN_INVALID_NAME The oname doesn't denote a right.
493 * KERN_INVALID_VALUE The nname isn't a legal name.
494 * KERN_NAME_EXISTS The nname already denotes a right.
495 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
497 * This interface is obsolete and always returns
498 * KERN_NOT_SUPPORTED.
503 __unused ipc_space_t space
,
504 __unused mach_port_name_t oname
,
505 __unused mach_port_name_t nname
)
507 return KERN_NOT_SUPPORTED
;
512 * Routine: mach_port_allocate_name [kernel call]
514 * Allocates a right in a space, using a specific name
515 * for the new right. Possible rights:
516 * MACH_PORT_RIGHT_RECEIVE
517 * MACH_PORT_RIGHT_PORT_SET
518 * MACH_PORT_RIGHT_DEAD_NAME
520 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
521 * has no extant send or send-once rights and no queued
522 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
523 * and its make-send count is 0. It is not a member of
524 * a port set. It has no registered no-senders or
525 * port-destroyed notification requests.
527 * A new port set has no members.
529 * A new dead name has one user reference.
533 * KERN_SUCCESS The right is allocated.
534 * KERN_INVALID_TASK The space is null.
535 * KERN_INVALID_TASK The space is dead.
536 * KERN_INVALID_VALUE The name isn't a legal name.
537 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
538 * KERN_NAME_EXISTS The name already denotes a right.
539 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
541 * Restrictions on name allocation: NT bits are reserved by kernel,
542 * must be set on any chosen name. Can't do this at all in kernel
547 mach_port_allocate_name(
549 mach_port_right_t right
,
550 mach_port_name_t name
)
553 mach_port_qos_t qos
= qos_template
;
557 if (!MACH_PORT_VALID(name
))
558 return KERN_INVALID_VALUE
;
560 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
566 * Routine: mach_port_allocate [kernel call]
568 * Allocates a right in a space. Like mach_port_allocate_name,
569 * except that the implementation picks a name for the right.
570 * The name may be any legal name in the space that doesn't
571 * currently denote a right.
575 * KERN_SUCCESS The right is allocated.
576 * KERN_INVALID_TASK The space is null.
577 * KERN_INVALID_TASK The space is dead.
578 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
579 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
580 * KERN_NO_SPACE No room in space for another right.
586 mach_port_right_t right
,
587 mach_port_name_t
*namep
)
590 mach_port_qos_t qos
= qos_template
;
592 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
598 * Routine: mach_port_allocate_qos [kernel call]
600 * Allocates a right, with qos options, in a space. Like
601 * mach_port_allocate_name, except that the implementation
602 * picks a name for the right. The name may be any legal name
603 * in the space that doesn't currently denote a right.
607 * KERN_SUCCESS The right is allocated.
608 * KERN_INVALID_TASK The space is null.
609 * KERN_INVALID_TASK The space is dead.
610 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
611 * KERN_INVALID_ARGUMENT The qos request was invalid.
612 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
613 * KERN_NO_SPACE No room in space for another right.
617 mach_port_allocate_qos(
619 mach_port_right_t right
,
620 mach_port_qos_t
*qosp
,
621 mach_port_name_t
*namep
)
626 return KERN_INVALID_ARGUMENT
;
627 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
633 * Routine: mach_port_allocate_full [kernel call]
635 * Allocates a right in a space. Supports all of the
636 * special cases, such as specifying a subsystem,
637 * a specific name, a real-time port, etc.
638 * The name may be any legal name in the space that doesn't
639 * currently denote a right.
643 * KERN_SUCCESS The right is allocated.
644 * KERN_INVALID_TASK The space is null.
645 * KERN_INVALID_TASK The space is dead.
646 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
647 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
648 * KERN_NO_SPACE No room in space for another right.
652 mach_port_allocate_full(
654 mach_port_right_t right
,
656 mach_port_qos_t
*qosp
,
657 mach_port_name_t
*namep
)
659 ipc_kmsg_t kmsg
= IKM_NULL
;
662 if (space
== IS_NULL
)
663 return (KERN_INVALID_TASK
);
665 if (proto
!= MACH_PORT_NULL
)
666 return (KERN_INVALID_VALUE
);
669 if (!MACH_PORT_VALID (*namep
))
670 return (KERN_INVALID_VALUE
);
673 if (qosp
->prealloc
) {
674 if (qosp
->len
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
) {
675 return KERN_RESOURCE_SHORTAGE
;
677 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
679 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
680 return (KERN_INVALID_VALUE
);
682 kmsg
= (ipc_kmsg_t
)ipc_kmsg_prealloc(size
);
683 if (kmsg
== IKM_NULL
)
684 return (KERN_RESOURCE_SHORTAGE
);
689 case MACH_PORT_RIGHT_RECEIVE
:
694 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
696 kr
= ipc_port_alloc(space
, namep
, &port
);
697 if (kr
== KERN_SUCCESS
) {
698 if (kmsg
!= IKM_NULL
)
699 ipc_kmsg_set_prealloc(kmsg
, port
);
703 } else if (kmsg
!= IKM_NULL
)
708 case MACH_PORT_RIGHT_PORT_SET
:
713 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
715 kr
= ipc_pset_alloc(space
, namep
, &pset
);
716 if (kr
== KERN_SUCCESS
)
721 case MACH_PORT_RIGHT_DEAD_NAME
:
722 kr
= ipc_object_alloc_dead(space
, namep
);
726 kr
= KERN_INVALID_VALUE
;
734 * Routine: mach_port_destroy [kernel call]
736 * Cleans up and destroys all rights denoted by a name
737 * in a space. The destruction of a receive right
738 * destroys the port, unless a port-destroyed request
739 * has been made for it; the destruction of a port-set right
740 * destroys the port set.
744 * KERN_SUCCESS The name is destroyed.
745 * KERN_INVALID_TASK The space is null.
746 * KERN_INVALID_TASK The space is dead.
747 * KERN_INVALID_NAME The name doesn't denote a right.
753 mach_port_name_t name
)
758 if (space
== IS_NULL
)
759 return KERN_INVALID_TASK
;
761 if (!MACH_PORT_VALID(name
))
764 kr
= ipc_right_lookup_write(space
, name
, &entry
);
765 if (kr
!= KERN_SUCCESS
)
767 /* space is write-locked and active */
769 kr
= ipc_right_destroy(space
, name
, entry
, TRUE
, 0); /* unlocks space */
774 * Routine: mach_port_deallocate [kernel call]
776 * Deallocates a user reference from a send right,
777 * send-once right, or a dead-name right. May
778 * deallocate the right, if this is the last uref,
779 * and destroy the name, if it doesn't denote
784 * KERN_SUCCESS The uref is deallocated.
785 * KERN_INVALID_TASK The space is null.
786 * KERN_INVALID_TASK The space is dead.
787 * KERN_INVALID_NAME The name doesn't denote a right.
788 * KERN_INVALID_RIGHT The right isn't correct.
792 mach_port_deallocate(
794 mach_port_name_t name
)
799 if (space
== IS_NULL
)
800 return KERN_INVALID_TASK
;
802 if (!MACH_PORT_VALID(name
))
805 kr
= ipc_right_lookup_write(space
, name
, &entry
);
806 if (kr
!= KERN_SUCCESS
)
808 /* space is write-locked */
810 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
815 * Routine: mach_port_get_refs [kernel call]
817 * Retrieves the number of user references held by a right.
818 * Receive rights, port-set rights, and send-once rights
819 * always have one user reference. Returns zero if the
820 * name denotes a right, but not the queried right.
824 * KERN_SUCCESS Number of urefs returned.
825 * KERN_INVALID_TASK The space is null.
826 * KERN_INVALID_TASK The space is dead.
827 * KERN_INVALID_VALUE "right" isn't a legal value.
828 * KERN_INVALID_NAME The name doesn't denote a right.
834 mach_port_name_t name
,
835 mach_port_right_t right
,
836 mach_port_urefs_t
*urefsp
)
838 mach_port_type_t type
;
839 mach_port_urefs_t urefs
;
843 if (space
== IS_NULL
)
844 return KERN_INVALID_TASK
;
846 if (right
>= MACH_PORT_RIGHT_NUMBER
)
847 return KERN_INVALID_VALUE
;
849 if (!MACH_PORT_VALID(name
)) {
850 if (right
== MACH_PORT_RIGHT_SEND
||
851 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
855 return KERN_INVALID_NAME
;
858 kr
= ipc_right_lookup_write(space
, name
, &entry
);
859 if (kr
!= KERN_SUCCESS
)
862 /* space is write-locked and active */
863 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
);
864 /* space is unlocked */
866 if (kr
!= KERN_SUCCESS
)
869 if (type
& MACH_PORT_TYPE(right
))
871 case MACH_PORT_RIGHT_SEND_ONCE
:
875 case MACH_PORT_RIGHT_PORT_SET
:
876 case MACH_PORT_RIGHT_RECEIVE
:
880 case MACH_PORT_RIGHT_DEAD_NAME
:
881 case MACH_PORT_RIGHT_SEND
:
887 panic("mach_port_get_refs: strange rights");
896 * Routine: mach_port_mod_refs
898 * Modifies the number of user references held by a right.
899 * The resulting number of user references must be non-negative.
900 * If it is zero, the right is deallocated. If the name
901 * doesn't denote other rights, it is destroyed.
905 * KERN_SUCCESS Modified number of urefs.
906 * KERN_INVALID_TASK The space is null.
907 * KERN_INVALID_TASK The space is dead.
908 * KERN_INVALID_VALUE "right" isn't a legal value.
909 * KERN_INVALID_NAME The name doesn't denote a right.
910 * KERN_INVALID_RIGHT Name doesn't denote specified right.
911 * KERN_INVALID_VALUE Impossible modification to urefs.
912 * KERN_UREFS_OVERFLOW Urefs would overflow.
918 mach_port_name_t name
,
919 mach_port_right_t right
,
920 mach_port_delta_t delta
)
925 if (space
== IS_NULL
)
926 return KERN_INVALID_TASK
;
928 if (right
>= MACH_PORT_RIGHT_NUMBER
)
929 return KERN_INVALID_VALUE
;
931 if (!MACH_PORT_VALID(name
)) {
932 if (right
== MACH_PORT_RIGHT_SEND
||
933 right
== MACH_PORT_RIGHT_SEND_ONCE
)
935 return KERN_INVALID_NAME
;
938 kr
= ipc_right_lookup_write(space
, name
, &entry
);
939 if (kr
!= KERN_SUCCESS
)
941 /* space is write-locked and active */
943 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
949 * Routine: mach_port_peek [kernel call]
951 * Peek at the message queue for the specified receive
952 * right and return info about a message in the queue.
954 * On input, seqnop points to a sequence number value
955 * to match the message being peeked. If zero is specified
956 * as the seqno, the first message in the queue will be
959 * Only the following trailer types are currently supported:
960 * MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)
962 * or'ed with one of these element types:
963 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_NULL)
964 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SEQNO)
965 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER)
966 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT)
968 * On input, the value pointed to by trailer_sizep must be
969 * large enough to hold the requested trailer size.
971 * The message sequence number, id, size, requested trailer info
972 * and requested trailer size are returned in their respective
973 * output parameters upon success.
978 * KERN_SUCCESS Matching message found, out parameters set.
979 * KERN_INVALID_TASK The space is null or dead.
980 * KERN_INVALID_NAME The name doesn't denote a right.
981 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
982 * KERN_INVALID_VALUE The input parameter values are out of bounds.
983 * KERN_FAILURE The requested message was not found.
989 mach_port_name_t name
,
990 mach_msg_trailer_type_t trailer_type
,
991 mach_port_seqno_t
*seqnop
,
992 mach_msg_size_t
*msg_sizep
,
993 mach_msg_id_t
*msg_idp
,
994 mach_msg_trailer_info_t trailer_infop
,
995 mach_msg_type_number_t
*trailer_sizep
)
1000 mach_msg_max_trailer_t max_trailer
;
1002 if (space
== IS_NULL
)
1003 return KERN_INVALID_TASK
;
1005 if (!MACH_PORT_VALID(name
))
1006 return KERN_INVALID_RIGHT
;
1009 * We don't allow anything greater than the audit trailer - to avoid
1010 * leaking the context pointer and to avoid variable-sized context issues.
1012 if (GET_RCV_ELEMENTS(trailer_type
) > MACH_RCV_TRAILER_AUDIT
||
1013 REQUESTED_TRAILER_SIZE(TRUE
, trailer_type
) > *trailer_sizep
)
1014 return KERN_INVALID_VALUE
;
1016 *trailer_sizep
= REQUESTED_TRAILER_SIZE(TRUE
, trailer_type
);
1018 kr
= ipc_port_translate_receive(space
, name
, &port
);
1019 if (kr
!= KERN_SUCCESS
)
1022 /* Port locked and active */
1024 found
= ipc_mqueue_peek(&port
->ip_messages
, seqnop
,
1025 msg_sizep
, msg_idp
, &max_trailer
);
1029 return KERN_FAILURE
;
1031 max_trailer
.msgh_seqno
= *seqnop
;
1032 memcpy(trailer_infop
, &max_trailer
, *trailer_sizep
);
1034 return KERN_SUCCESS
;
1038 * Routine: mach_port_set_mscount [kernel call]
1040 * Changes a receive right's make-send count.
1044 * KERN_SUCCESS Set make-send count.
1045 * KERN_INVALID_TASK The space is null.
1046 * KERN_INVALID_TASK The space is dead.
1047 * KERN_INVALID_NAME The name doesn't denote a right.
1048 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1052 mach_port_set_mscount(
1054 mach_port_name_t name
,
1055 mach_port_mscount_t mscount
)
1060 if (space
== IS_NULL
)
1061 return KERN_INVALID_TASK
;
1063 if (!MACH_PORT_VALID(name
))
1064 return KERN_INVALID_RIGHT
;
1066 kr
= ipc_port_translate_receive(space
, name
, &port
);
1067 if (kr
!= KERN_SUCCESS
)
1069 /* port is locked and active */
1071 ipc_port_set_mscount(port
, mscount
);
1074 return KERN_SUCCESS
;
1078 * Routine: mach_port_set_seqno [kernel call]
1080 * Changes a receive right's sequence number.
1084 * KERN_SUCCESS Set sequence number.
1085 * KERN_INVALID_TASK The space is null.
1086 * KERN_INVALID_TASK The space is dead.
1087 * KERN_INVALID_NAME The name doesn't denote a right.
1088 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1092 mach_port_set_seqno(
1094 mach_port_name_t name
,
1095 mach_port_seqno_t seqno
)
1100 if (space
== IS_NULL
)
1101 return KERN_INVALID_TASK
;
1103 if (!MACH_PORT_VALID(name
))
1104 return KERN_INVALID_RIGHT
;
1106 kr
= ipc_port_translate_receive(space
, name
, &port
);
1107 if (kr
!= KERN_SUCCESS
)
1109 /* port is locked and active */
1111 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
1114 return KERN_SUCCESS
;
1118 * Routine: mach_port_get_context [kernel call]
1120 * Returns a receive right's context pointer.
1124 * KERN_SUCCESS Set context pointer.
1125 * KERN_INVALID_TASK The space is null.
1126 * KERN_INVALID_TASK The space is dead.
1127 * KERN_INVALID_NAME The name doesn't denote a right.
1128 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1132 mach_port_get_context(
1134 mach_port_name_t name
,
1135 mach_vm_address_t
*context
)
1140 if (space
== IS_NULL
)
1141 return KERN_INVALID_TASK
;
1143 if (!MACH_PORT_VALID(name
))
1144 return KERN_INVALID_RIGHT
;
1146 kr
= ipc_port_translate_receive(space
, name
, &port
);
1147 if (kr
!= KERN_SUCCESS
)
1150 /* Port locked and active */
1152 /* For strictly guarded ports, return empty context (which acts as guard) */
1153 if (port
->ip_strict_guard
)
1156 *context
= port
->ip_context
;
1159 return KERN_SUCCESS
;
1164 * Routine: mach_port_set_context [kernel call]
1166 * Changes a receive right's context pointer.
1170 * KERN_SUCCESS Set context pointer.
1171 * KERN_INVALID_TASK The space is null.
1172 * KERN_INVALID_TASK The space is dead.
1173 * KERN_INVALID_NAME The name doesn't denote a right.
1174 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1178 mach_port_set_context(
1180 mach_port_name_t name
,
1181 mach_vm_address_t context
)
1186 if (space
== IS_NULL
)
1187 return KERN_INVALID_TASK
;
1189 if (!MACH_PORT_VALID(name
))
1190 return KERN_INVALID_RIGHT
;
1192 kr
= ipc_port_translate_receive(space
, name
, &port
);
1193 if (kr
!= KERN_SUCCESS
)
1196 /* port is locked and active */
1197 if(port
->ip_strict_guard
) {
1198 uint64_t portguard
= port
->ip_context
;
1200 /* For strictly guarded ports, disallow overwriting context; Raise Exception */
1201 mach_port_guard_exception(name
, context
, portguard
, kGUARD_EXC_SET_CONTEXT
);
1202 return KERN_INVALID_ARGUMENT
;
1205 port
->ip_context
= context
;
1208 return KERN_SUCCESS
;
1213 * Routine: mach_port_get_set_status [kernel call]
1215 * Retrieves a list of members in a port set.
1216 * Returns the space's name for each receive right member.
1220 * KERN_SUCCESS Retrieved list of members.
1221 * KERN_INVALID_TASK The space is null.
1222 * KERN_INVALID_TASK The space is dead.
1223 * KERN_INVALID_NAME The name doesn't denote a right.
1224 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1225 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1229 mach_port_get_set_status(
1231 mach_port_name_t name
,
1232 mach_port_name_t
**members
,
1233 mach_msg_type_number_t
*membersCnt
)
1235 ipc_entry_num_t actual
; /* this many members */
1236 ipc_entry_num_t maxnames
; /* space for this many members */
1239 vm_size_t size
; /* size of allocated memory */
1240 vm_offset_t addr
; /* allocated memory */
1241 vm_map_copy_t memory
; /* copied-in memory */
1243 if (space
== IS_NULL
)
1244 return KERN_INVALID_TASK
;
1246 if (!MACH_PORT_VALID(name
))
1247 return KERN_INVALID_RIGHT
;
1249 size
= VM_MAP_PAGE_SIZE(ipc_kernel_map
); /* initial guess */
1252 mach_port_name_t
*names
;
1256 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_KERN_MEMORY_IPC
));
1257 if (kr
!= KERN_SUCCESS
)
1258 return KERN_RESOURCE_SHORTAGE
;
1260 /* can't fault while we hold locks */
1262 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1263 VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_IPC
), FALSE
);
1264 assert(kr
== KERN_SUCCESS
);
1266 kr
= ipc_object_translate(space
, name
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1267 if (kr
!= KERN_SUCCESS
) {
1268 kmem_free(ipc_kernel_map
, addr
, size
);
1272 /* just use a portset reference from here on out */
1273 __IGNORE_WCASTALIGN(pset
= (ipc_pset_t
) psobj
);
1274 ips_reference(pset
);
1277 names
= (mach_port_name_t
*) addr
;
1278 maxnames
= (ipc_entry_num_t
)(size
/ sizeof(mach_port_name_t
));
1280 ipc_mqueue_set_gather_member_names(space
, &pset
->ips_messages
, maxnames
, names
, &actual
);
1282 /* release the portset reference */
1285 if (actual
<= maxnames
)
1288 /* didn't have enough memory; allocate more */
1289 kmem_free(ipc_kernel_map
, addr
, size
);
1290 size
= vm_map_round_page(
1291 (actual
* sizeof(mach_port_name_t
)),
1292 VM_MAP_PAGE_MASK(ipc_kernel_map
)) +
1293 VM_MAP_PAGE_SIZE(ipc_kernel_map
);
1297 memory
= VM_MAP_COPY_NULL
;
1299 kmem_free(ipc_kernel_map
, addr
, size
);
1301 vm_size_t size_used
;
1302 vm_size_t vm_size_used
;
1304 size_used
= actual
* sizeof(mach_port_name_t
);
1305 vm_size_used
= vm_map_round_page(
1307 VM_MAP_PAGE_MASK(ipc_kernel_map
));
1310 * Make used memory pageable and get it into
1311 * copied-in form. Free any unused memory.
1316 vm_map_trunc_page(addr
,
1317 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
1318 vm_map_round_page(addr
+ vm_size_used
,
1319 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
1321 assert(kr
== KERN_SUCCESS
);
1323 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr
,
1324 (vm_map_size_t
)size_used
, TRUE
, &memory
);
1325 assert(kr
== KERN_SUCCESS
);
1327 if (vm_size_used
!= size
)
1328 kmem_free(ipc_kernel_map
,
1329 addr
+ vm_size_used
, size
- vm_size_used
);
1332 *members
= (mach_port_name_t
*) memory
;
1333 *membersCnt
= actual
;
1334 return KERN_SUCCESS
;
1338 * Routine: mach_port_move_member [kernel call]
1340 * If after is MACH_PORT_NULL, removes member
1341 * from the port set it is in. Otherwise, adds
1342 * member to after, removing it from any set
1343 * it might already be in.
1347 * KERN_SUCCESS Moved the port.
1348 * KERN_INVALID_TASK The space is null.
1349 * KERN_INVALID_TASK The space is dead.
1350 * KERN_INVALID_NAME Member didn't denote a right.
1351 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1352 * KERN_INVALID_NAME After didn't denote a right.
1353 * KERN_INVALID_RIGHT After didn't denote a port set right.
1355 * After is MACH_PORT_NULL and Member isn't in a port set.
1359 mach_port_move_member(
1361 mach_port_name_t member
,
1362 mach_port_name_t after
)
1368 uint64_t wq_link_id
= 0;
1369 uint64_t wq_reserved_prepost
= 0;
1371 if (space
== IS_NULL
)
1372 return KERN_INVALID_TASK
;
1374 if (!MACH_PORT_VALID(member
))
1375 return KERN_INVALID_RIGHT
;
1377 if (after
== MACH_PORT_DEAD
) {
1378 return KERN_INVALID_RIGHT
;
1379 } else if (after
== MACH_PORT_NULL
) {
1383 * We reserve both a link, and
1384 * enough prepost objects to complete
1385 * the set move atomically - we can't block
1386 * while we're holding the space lock, and
1387 * the ipc_pset_add calls ipc_mqueue_add
1388 * which may have to prepost this port onto
1391 wq_link_id
= waitq_link_reserve(NULL
);
1392 wq_reserved_prepost
= waitq_prepost_reserve(NULL
, 10,
1397 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1398 if (kr
!= KERN_SUCCESS
)
1400 /* space is read-locked and active */
1402 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1403 is_read_unlock(space
);
1404 kr
= KERN_INVALID_RIGHT
;
1408 __IGNORE_WCASTALIGN(port
= (ipc_port_t
) entry
->ie_object
);
1409 assert(port
!= IP_NULL
);
1411 if (after
== MACH_PORT_NULL
)
1414 entry
= ipc_entry_lookup(space
, after
);
1415 if (entry
== IE_NULL
) {
1416 is_read_unlock(space
);
1417 kr
= KERN_INVALID_NAME
;
1421 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1422 is_read_unlock(space
);
1423 kr
= KERN_INVALID_RIGHT
;
1427 __IGNORE_WCASTALIGN(nset
= (ipc_pset_t
) entry
->ie_object
);
1428 assert(nset
!= IPS_NULL
);
1431 ipc_pset_remove_from_all(port
);
1433 if (nset
!= IPS_NULL
) {
1435 kr
= ipc_pset_add(nset
, port
, &wq_link_id
, &wq_reserved_prepost
);
1439 is_read_unlock(space
);
1444 * on success the ipc_pset_add() will consume the wq_link_id
1445 * value (resetting it to 0), so this function is always safe to call.
1447 waitq_link_release(wq_link_id
);
1448 waitq_prepost_release_reserve(wq_reserved_prepost
);
1454 * Routine: mach_port_request_notification [kernel call]
1456 * Requests a notification. The caller supplies
1457 * a send-once right for the notification to use,
1458 * and the call returns the previously registered
1459 * send-once right, if any. Possible types:
1461 * MACH_NOTIFY_PORT_DESTROYED
1462 * Requests a port-destroyed notification
1463 * for a receive right. Sync should be zero.
1464 * MACH_NOTIFY_NO_SENDERS
1465 * Requests a no-senders notification for a
1466 * receive right. If there are currently no
1467 * senders, sync is less than or equal to the
1468 * current make-send count, and a send-once right
1469 * is supplied, then an immediate no-senders
1470 * notification is generated.
1471 * MACH_NOTIFY_DEAD_NAME
1472 * Requests a dead-name notification for a send
1473 * or receive right. If the name is already a
1474 * dead name, sync is non-zero, and a send-once
1475 * right is supplied, then an immediate dead-name
1476 * notification is generated.
1480 * KERN_SUCCESS Requested a notification.
1481 * KERN_INVALID_TASK The space is null.
1482 * KERN_INVALID_TASK The space is dead.
1483 * KERN_INVALID_VALUE Bad id value.
1484 * KERN_INVALID_NAME Name doesn't denote a right.
1485 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1486 * KERN_INVALID_CAPABILITY The notify port is dead.
1487 * MACH_NOTIFY_PORT_DESTROYED:
1488 * KERN_INVALID_VALUE Sync isn't zero.
1489 * MACH_NOTIFY_DEAD_NAME:
1490 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1491 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1492 * sync is zero or notify is IP_NULL.
1493 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1494 * generating immediate notif. would overflow urefs.
1498 mach_port_request_notification(
1500 mach_port_name_t name
,
1502 mach_port_mscount_t sync
,
1504 ipc_port_t
*previousp
)
1508 if (space
== IS_NULL
)
1509 return KERN_INVALID_TASK
;
1511 if (notify
== IP_DEAD
)
1512 return KERN_INVALID_CAPABILITY
;
1516 * Requesting notifications on RPC ports is an error.
1522 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1523 if (kr
!= KERN_SUCCESS
)
1526 port
= (ipc_port_t
) entry
->ie_object
;
1528 if (port
->ip_subsystem
!= NULL
) {
1529 is_write_unlock(space
);
1530 panic("mach_port_request_notification: on RPC port!!");
1531 return KERN_INVALID_CAPABILITY
;
1533 is_write_unlock(space
);
1539 case MACH_NOTIFY_PORT_DESTROYED
: {
1540 ipc_port_t port
, previous
;
1543 return KERN_INVALID_VALUE
;
1545 if (!MACH_PORT_VALID(name
))
1546 return KERN_INVALID_RIGHT
;
1548 kr
= ipc_port_translate_receive(space
, name
, &port
);
1549 if (kr
!= KERN_SUCCESS
)
1551 /* port is locked and active */
1553 ipc_port_pdrequest(port
, notify
, &previous
);
1554 /* port is unlocked */
1556 *previousp
= previous
;
1560 case MACH_NOTIFY_NO_SENDERS
: {
1563 if (!MACH_PORT_VALID(name
))
1564 return KERN_INVALID_RIGHT
;
1566 kr
= ipc_port_translate_receive(space
, name
, &port
);
1567 if (kr
!= KERN_SUCCESS
)
1569 /* port is locked and active */
1571 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1572 /* port is unlocked */
1576 case MACH_NOTIFY_SEND_POSSIBLE
:
1578 if (!MACH_PORT_VALID(name
)) {
1579 return KERN_INVALID_ARGUMENT
;
1582 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1583 TRUE
, notify
, previousp
);
1584 if (kr
!= KERN_SUCCESS
)
1588 case MACH_NOTIFY_DEAD_NAME
:
1590 if (!MACH_PORT_VALID(name
)) {
1593 * Should do immediate delivery check -
1594 * will do that in the near future.
1596 return KERN_INVALID_ARGUMENT
;
1599 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1600 FALSE
, notify
, previousp
);
1601 if (kr
!= KERN_SUCCESS
)
1606 return KERN_INVALID_VALUE
;
1609 return KERN_SUCCESS
;
1613 * Routine: mach_port_insert_right [kernel call]
1615 * Inserts a right into a space, as if the space
1616 * voluntarily received the right in a message,
1617 * except that the right gets the specified name.
1621 * KERN_SUCCESS Inserted the right.
1622 * KERN_INVALID_TASK The space is null.
1623 * KERN_INVALID_TASK The space is dead.
1624 * KERN_INVALID_VALUE The name isn't a legal name.
1625 * KERN_NAME_EXISTS The name already denotes a right.
1626 * KERN_INVALID_VALUE Message doesn't carry a port right.
1627 * KERN_INVALID_CAPABILITY Port is null or dead.
1628 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1629 * KERN_RIGHT_EXISTS Space has rights under another name.
1630 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1634 mach_port_insert_right(
1636 mach_port_name_t name
,
1638 mach_msg_type_name_t polyPoly
)
1640 if (space
== IS_NULL
)
1641 return KERN_INVALID_TASK
;
1643 if (!MACH_PORT_VALID(name
) ||
1644 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1645 return KERN_INVALID_VALUE
;
1647 if (!IO_VALID((ipc_object_t
) poly
))
1648 return KERN_INVALID_CAPABILITY
;
1650 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1651 polyPoly
, FALSE
, name
);
1655 * Routine: mach_port_extract_right [kernel call]
1657 * Extracts a right from a space, as if the space
1658 * voluntarily sent the right to the caller.
1662 * KERN_SUCCESS Extracted the right.
1663 * KERN_INVALID_TASK The space is null.
1664 * KERN_INVALID_TASK The space is dead.
1665 * KERN_INVALID_VALUE Requested type isn't a port right.
1666 * KERN_INVALID_NAME Name doesn't denote a right.
1667 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1671 mach_port_extract_right(
1673 mach_port_name_t name
,
1674 mach_msg_type_name_t msgt_name
,
1676 mach_msg_type_name_t
*polyPoly
)
1680 if (space
== IS_NULL
)
1681 return KERN_INVALID_TASK
;
1683 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1684 return KERN_INVALID_VALUE
;
1686 if (!MACH_PORT_VALID(name
)) {
1688 * really should copy out a dead name, if it is a send or
1689 * send-once right being copied, but instead return an
1692 return KERN_INVALID_RIGHT
;
1695 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1697 if (kr
== KERN_SUCCESS
)
1698 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1703 * Routine: mach_port_get_status_helper [helper]
1705 * Populates a mach_port_status_t structure with
1708 * Port needs to be locked
1712 void mach_port_get_status_helper(
1714 mach_port_status_t
*statusp
)
1719 imq_lock(&port
->ip_messages
);
1720 /* don't leak set IDs, just indicate that the port is in one or not */
1721 statusp
->mps_pset
= !!(port
->ip_in_pset
);
1722 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1723 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1724 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1725 imq_unlock(&port
->ip_messages
);
1728 statusp
->mps_mscount
= port
->ip_mscount
;
1729 statusp
->mps_sorights
= port
->ip_sorights
;
1730 statusp
->mps_srights
= port
->ip_srights
> 0;
1731 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1732 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1733 statusp
->mps_flags
= 0;
1734 if (port
->ip_impdonation
) {
1735 statusp
->mps_flags
|= MACH_PORT_STATUS_FLAG_IMP_DONATION
;
1736 if (port
->ip_tempowner
) {
1737 statusp
->mps_flags
|= MACH_PORT_STATUS_FLAG_TEMPOWNER
;
1738 if (IIT_NULL
!= port
->ip_imp_task
) {
1739 statusp
->mps_flags
|= MACH_PORT_STATUS_FLAG_TASKPTR
;
1743 if (port
->ip_guarded
) {
1744 statusp
->mps_flags
|= MACH_PORT_STATUS_FLAG_GUARDED
;
1745 if (port
->ip_strict_guard
) {
1746 statusp
->mps_flags
|= MACH_PORT_STATUS_FLAG_STRICT_GUARD
;
1755 mach_port_get_attributes(
1757 mach_port_name_t name
,
1759 mach_port_info_t info
,
1760 mach_msg_type_number_t
*count
)
1765 if (space
== IS_NULL
)
1766 return KERN_INVALID_TASK
;
1769 case MACH_PORT_LIMITS_INFO
: {
1770 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1772 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1773 return KERN_FAILURE
;
1775 if (!MACH_PORT_VALID(name
)) {
1780 kr
= ipc_port_translate_receive(space
, name
, &port
);
1781 if (kr
!= KERN_SUCCESS
)
1783 /* port is locked and active */
1785 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1786 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1791 case MACH_PORT_RECEIVE_STATUS
: {
1792 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1794 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1795 return KERN_FAILURE
;
1797 if (!MACH_PORT_VALID(name
))
1798 return KERN_INVALID_RIGHT
;
1800 kr
= ipc_port_translate_receive(space
, name
, &port
);
1801 if (kr
!= KERN_SUCCESS
)
1803 /* port is locked and active */
1804 mach_port_get_status_helper(port
, statusp
);
1805 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1810 case MACH_PORT_DNREQUESTS_SIZE
: {
1811 ipc_port_request_t table
;
1813 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1814 return KERN_FAILURE
;
1816 if (!MACH_PORT_VALID(name
)) {
1821 kr
= ipc_port_translate_receive(space
, name
, &port
);
1822 if (kr
!= KERN_SUCCESS
)
1824 /* port is locked and active */
1826 table
= port
->ip_requests
;
1827 if (table
== IPR_NULL
)
1830 *(int *)info
= table
->ipr_size
->its_size
;
1831 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1836 case MACH_PORT_INFO_EXT
: {
1837 mach_port_info_ext_t
*mp_info
= (mach_port_info_ext_t
*)info
;
1838 if (*count
< MACH_PORT_INFO_EXT_COUNT
)
1839 return KERN_FAILURE
;
1841 if (!MACH_PORT_VALID(name
))
1842 return KERN_INVALID_RIGHT
;
1844 kr
= ipc_port_translate_receive(space
, name
, &port
);
1845 if (kr
!= KERN_SUCCESS
)
1847 /* port is locked and active */
1848 mach_port_get_status_helper(port
, &mp_info
->mpie_status
);
1849 mp_info
->mpie_boost_cnt
= port
->ip_impcount
;
1850 *count
= MACH_PORT_INFO_EXT_COUNT
;
1856 return KERN_INVALID_ARGUMENT
;
1860 return KERN_SUCCESS
;
1864 mach_port_set_attributes(
1866 mach_port_name_t name
,
1868 mach_port_info_t info
,
1869 mach_msg_type_number_t count
)
1874 if (space
== IS_NULL
)
1875 return KERN_INVALID_TASK
;
1879 case MACH_PORT_LIMITS_INFO
: {
1880 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1882 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1883 return KERN_FAILURE
;
1885 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1886 return KERN_INVALID_VALUE
;
1888 if (!MACH_PORT_VALID(name
))
1889 return KERN_INVALID_RIGHT
;
1891 kr
= ipc_port_translate_receive(space
, name
, &port
);
1892 if (kr
!= KERN_SUCCESS
)
1894 /* port is locked and active */
1896 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1900 case MACH_PORT_DNREQUESTS_SIZE
: {
1901 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1902 return KERN_FAILURE
;
1904 if (!MACH_PORT_VALID(name
))
1905 return KERN_INVALID_RIGHT
;
1907 kr
= ipc_port_translate_receive(space
, name
, &port
);
1908 if (kr
!= KERN_SUCCESS
)
1910 /* port is locked and active */
1912 kr
= ipc_port_request_grow(port
, *(int *)info
);
1913 if (kr
!= KERN_SUCCESS
)
1917 case MACH_PORT_TEMPOWNER
:
1918 if (!MACH_PORT_VALID(name
))
1919 return KERN_INVALID_RIGHT
;
1921 ipc_importance_task_t release_imp_task
= IIT_NULL
;
1922 natural_t assertcnt
= 0;
1924 kr
= ipc_port_translate_receive(space
, name
, &port
);
1925 if (kr
!= KERN_SUCCESS
)
1927 /* port is locked and active */
1930 * don't allow temp-owner importance donation if user
1931 * associated it with a kobject already (timer, host_notify target).
1933 if (is_ipc_kobject(ip_kotype(port
))) {
1935 return KERN_INVALID_ARGUMENT
;
1938 if (port
->ip_tempowner
!= 0) {
1939 if (IIT_NULL
!= port
->ip_imp_task
) {
1940 release_imp_task
= port
->ip_imp_task
;
1941 port
->ip_imp_task
= IIT_NULL
;
1942 assertcnt
= port
->ip_impcount
;
1945 assertcnt
= port
->ip_impcount
;
1948 port
->ip_impdonation
= 1;
1949 port
->ip_tempowner
= 1;
1952 #if IMPORTANCE_INHERITANCE
1953 /* drop assertions from previous destination task */
1954 if (release_imp_task
!= IIT_NULL
) {
1955 assert(ipc_importance_task_is_any_receiver_type(release_imp_task
));
1957 ipc_importance_task_drop_internal_assertion(release_imp_task
, assertcnt
);
1958 ipc_importance_task_release(release_imp_task
);
1959 } else if (assertcnt
> 0) {
1960 release_imp_task
= current_task()->task_imp_base
;
1961 if (release_imp_task
!= IIT_NULL
&&
1962 ipc_importance_task_is_any_receiver_type(release_imp_task
)) {
1963 ipc_importance_task_drop_internal_assertion(release_imp_task
, assertcnt
);
1967 if (release_imp_task
!= IIT_NULL
)
1968 ipc_importance_task_release(release_imp_task
);
1969 #endif /* IMPORTANCE_INHERITANCE */
1973 #if IMPORTANCE_INHERITANCE
1974 case MACH_PORT_DENAP_RECEIVER
:
1975 case MACH_PORT_IMPORTANCE_RECEIVER
:
1976 if (!MACH_PORT_VALID(name
))
1977 return KERN_INVALID_RIGHT
;
1979 kr
= ipc_port_translate_receive(space
, name
, &port
);
1980 if (kr
!= KERN_SUCCESS
)
1984 * don't allow importance donation if user associated
1985 * it with a kobject already (timer, host_notify target).
1987 if (is_ipc_kobject(ip_kotype(port
))) {
1989 return KERN_INVALID_ARGUMENT
;
1992 /* port is locked and active */
1993 port
->ip_impdonation
= 1;
1997 #endif /* IMPORTANCE_INHERITANCE */
2000 return KERN_INVALID_ARGUMENT
;
2003 return KERN_SUCCESS
;
2007 * Routine: mach_port_insert_member [kernel call]
2009 * Add the receive right, specified by name, to
2011 * The port cannot already be a member of the set.
2015 * KERN_SUCCESS Moved the port.
2016 * KERN_INVALID_TASK The space is null.
2017 * KERN_INVALID_TASK The space is dead.
2018 * KERN_INVALID_NAME name didn't denote a right.
2019 * KERN_INVALID_RIGHT name didn't denote a receive right.
2020 * KERN_INVALID_NAME pset_name didn't denote a right.
2021 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
2022 * KERN_ALREADY_IN_SET name was already a member of pset.
2026 mach_port_insert_member(
2028 mach_port_name_t name
,
2029 mach_port_name_t psname
)
2034 uint64_t wq_link_id
;
2035 uint64_t wq_reserved_prepost
;
2037 if (space
== IS_NULL
)
2038 return KERN_INVALID_TASK
;
2040 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
2041 return KERN_INVALID_RIGHT
;
2043 wq_link_id
= waitq_link_reserve(NULL
);
2044 wq_reserved_prepost
= waitq_prepost_reserve(NULL
, 10,
2045 WAITQ_DONT_LOCK
, NULL
);
2047 kr
= ipc_object_translate_two(space
,
2048 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
2049 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
2050 if (kr
!= KERN_SUCCESS
)
2053 /* obj and psobj are locked (and were locked in that order) */
2054 assert(psobj
!= IO_NULL
);
2055 assert(obj
!= IO_NULL
);
2057 __IGNORE_WCASTALIGN(kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
,
2058 &wq_link_id
, &wq_reserved_prepost
));
2064 /* on success, wq_link_id is reset to 0, so this is always safe */
2065 waitq_link_release(wq_link_id
);
2066 waitq_prepost_release_reserve(wq_reserved_prepost
);
2072 * Routine: mach_port_extract_member [kernel call]
2074 * Remove a port from one portset that it is a member of.
2078 * KERN_SUCCESS Moved the port.
2079 * KERN_INVALID_TASK The space is null.
2080 * KERN_INVALID_TASK The space is dead.
2081 * KERN_INVALID_NAME Member didn't denote a right.
2082 * KERN_INVALID_RIGHT Member didn't denote a receive right.
2083 * KERN_INVALID_NAME After didn't denote a right.
2084 * KERN_INVALID_RIGHT After didn't denote a port set right.
2086 * After is MACH_PORT_NULL and Member isn't in a port set.
2090 mach_port_extract_member(
2092 mach_port_name_t name
,
2093 mach_port_name_t psname
)
2099 if (space
== IS_NULL
)
2100 return KERN_INVALID_TASK
;
2102 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
2103 return KERN_INVALID_RIGHT
;
2105 kr
= ipc_object_translate_two(space
,
2106 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
2107 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
2108 if (kr
!= KERN_SUCCESS
)
2111 /* obj and psobj are both locked (and were locked in that order) */
2112 assert(psobj
!= IO_NULL
);
2113 assert(obj
!= IO_NULL
);
2115 __IGNORE_WCASTALIGN(kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
));
2124 * task_set_port_space:
2126 * Set port name space of task to specified size.
2129 task_set_port_space(
2135 if (space
== IS_NULL
)
2136 return KERN_INVALID_TASK
;
2138 is_write_lock(space
);
2140 if (!is_active(space
)) {
2141 is_write_unlock(space
);
2142 return KERN_INVALID_TASK
;
2145 kr
= ipc_entry_grow_table(space
, table_entries
);
2146 if (kr
== KERN_SUCCESS
)
2147 is_write_unlock(space
);
2152 * Routine: mach_port_guard_locked [helper routine]
2154 * Sets a new guard for a locked port.
2158 * KERN_SUCCESS Port Guarded.
2159 * KERN_INVALID_ARGUMENT Port already contains a context/guard.
2161 static kern_return_t
2162 mach_port_guard_locked(
2167 if (port
->ip_context
)
2168 return KERN_INVALID_ARGUMENT
;
2170 port
->ip_context
= guard
;
2171 port
->ip_guarded
= 1;
2172 port
->ip_strict_guard
= (strict
)?1:0;
2173 return KERN_SUCCESS
;
2177 * Routine: mach_port_unguard_locked [helper routine]
2179 * Removes guard for a locked port.
2183 * KERN_SUCCESS Port Unguarded.
2184 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
2185 * This also raises a EXC_GUARD exception.
2187 static kern_return_t
2188 mach_port_unguard_locked(
2190 mach_port_name_t name
,
2193 /* Port locked and active */
2194 if (!port
->ip_guarded
) {
2195 /* Port already unguarded; Raise exception */
2196 mach_port_guard_exception(name
, guard
, 0, kGUARD_EXC_UNGUARDED
);
2197 return KERN_INVALID_ARGUMENT
;
2200 if (port
->ip_context
!= guard
) {
2201 /* Incorrect guard; Raise exception */
2202 mach_port_guard_exception(name
, guard
, port
->ip_context
, kGUARD_EXC_INCORRECT_GUARD
);
2203 return KERN_INVALID_ARGUMENT
;
2206 port
->ip_context
= 0;
2207 port
->ip_guarded
= port
->ip_strict_guard
= 0;
2208 return KERN_SUCCESS
;
2213 * Routine: mach_port_guard_exception [helper routine]
2215 * Marks the thread with AST_GUARD for mach port guard violation.
2216 * Also saves exception info in thread structure.
2220 * KERN_FAILURE Thread marked with AST_GUARD.
2223 mach_port_guard_exception(
2224 mach_port_name_t name
,
2229 thread_t t
= current_thread();
2230 uint64_t code
, subcode
;
2232 /* Log exception info to syslog */
2233 printf( "Mach Port Guard Exception - "
2236 "Expected Guard: 0x%x, "
2237 "Received Guard: 0x%x\n",
2238 (unsigned)VM_KERNEL_UNSLIDE_OR_PERM(t
),
2240 (unsigned)portguard
,
2244 * EXC_GUARD namespace for mach ports
2247 * Mach Port guards use the exception codes like
2250 * +----------------------------------------------------------------+
2251 * |[63:61] GUARD_TYPE_MACH_PORT | [60:32] flavor | [31:0] port name|
2252 * +----------------------------------------------------------------+
2255 * +----------------------------------------------------------------+
2256 * | [63:0] guard value |
2257 * +----------------------------------------------------------------+
2260 code
= (((uint64_t)GUARD_TYPE_MACH_PORT
) << 61) |
2261 (((uint64_t)reason
) << 32) |
2263 subcode
= (uint64_t)(portguard
);
2265 t
->guard_exc_info
.code
= code
;
2266 t
->guard_exc_info
.subcode
= subcode
;
2268 /* Mark thread with AST_GUARD */
2269 thread_guard_violation(t
, GUARD_TYPE_MACH_PORT
);
2270 return KERN_FAILURE
;
2275 * Routine: mach_port_guard_ast
2277 * Raises an exception for mach port guard violation.
2285 mach_port_guard_ast(thread_t t
)
2287 /* Raise an EXC_GUARD exception */
2288 task_exception_notify(EXC_GUARD
, t
->guard_exc_info
.code
, t
->guard_exc_info
.subcode
);
2290 /* Terminate task which caused the exception */
2291 task_bsdtask_kill(current_task());
2296 * Routine: mach_port_construct [kernel call]
2298 * Constructs a mach port with the provided set of options.
2302 * KERN_SUCCESS The right is allocated.
2303 * KERN_INVALID_TASK The space is null.
2304 * KERN_INVALID_TASK The space is dead.
2305 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
2306 * KERN_NO_SPACE No room in space for another right.
2307 * KERN_FAILURE Illegal option values requested.
2311 mach_port_construct(
2313 mach_port_options_t
*options
,
2315 mach_port_name_t
*name
)
2320 if (space
== IS_NULL
)
2321 return (KERN_INVALID_TASK
);
2323 /* Allocate a new port in the IPC space */
2324 kr
= ipc_port_alloc(space
, name
, &port
);
2325 if (kr
!= KERN_SUCCESS
)
2328 /* Port locked and active */
2329 if (options
->flags
& MPO_CONTEXT_AS_GUARD
) {
2330 kr
= mach_port_guard_locked(port
, (uint64_t) context
, (options
->flags
& MPO_STRICT
));
2331 /* A newly allocated and locked port should always be guarded successfully */
2332 assert(kr
== KERN_SUCCESS
);
2334 port
->ip_context
= context
;
2340 /* Set port attributes as requested */
2342 if (options
->flags
& MPO_QLIMIT
) {
2343 kr
= mach_port_set_attributes(space
, *name
, MACH_PORT_LIMITS_INFO
,
2344 (mach_port_info_t
)&options
->mpl
, sizeof(options
->mpl
)/sizeof(int));
2345 if (kr
!= KERN_SUCCESS
)
2349 if (options
->flags
& MPO_TEMPOWNER
) {
2350 kr
= mach_port_set_attributes(space
, *name
, MACH_PORT_TEMPOWNER
, NULL
, 0);
2351 if (kr
!= KERN_SUCCESS
)
2355 if (options
->flags
& MPO_IMPORTANCE_RECEIVER
) {
2356 kr
= mach_port_set_attributes(space
, *name
, MACH_PORT_IMPORTANCE_RECEIVER
, NULL
, 0);
2357 if (kr
!= KERN_SUCCESS
)
2361 if (options
->flags
& MPO_DENAP_RECEIVER
) {
2362 kr
= mach_port_set_attributes(space
, *name
, MACH_PORT_DENAP_RECEIVER
, NULL
, 0);
2363 if (kr
!= KERN_SUCCESS
)
2367 if (options
->flags
& MPO_INSERT_SEND_RIGHT
) {
2368 kr
= ipc_object_copyin(space
, *name
, MACH_MSG_TYPE_MAKE_SEND
, (ipc_object_t
*)&port
);
2369 if (kr
!= KERN_SUCCESS
)
2372 kr
= mach_port_insert_right(space
, *name
, port
, MACH_MSG_TYPE_PORT_SEND
);
2373 if (kr
!= KERN_SUCCESS
)
2377 return KERN_SUCCESS
;
2380 /* Attempt to destroy port. If its already destroyed by some other thread, we're done */
2381 (void) mach_port_destruct(space
, *name
, 0, context
);
2386 * Routine: mach_port_destruct [kernel call]
2388 * Destroys a mach port with appropriate guard
2392 * KERN_SUCCESS The name is destroyed.
2393 * KERN_INVALID_TASK The space is null.
2394 * KERN_INVALID_TASK The space is dead.
2395 * KERN_INVALID_NAME The name doesn't denote a right.
2396 * KERN_INVALID_RIGHT The right isn't correct.
2397 * KERN_INVALID_VALUE The delta for send right is incorrect.
2398 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
2399 * This also raises a EXC_GUARD exception.
2405 mach_port_name_t name
,
2406 mach_port_delta_t srdelta
,
2412 if (space
== IS_NULL
)
2413 return KERN_INVALID_TASK
;
2415 if (!MACH_PORT_VALID(name
))
2416 return KERN_INVALID_NAME
;
2418 /* Remove reference for receive right */
2419 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2420 if (kr
!= KERN_SUCCESS
)
2422 /* space is write-locked and active */
2423 kr
= ipc_right_destruct(space
, name
, entry
, srdelta
, guard
); /* unlocks */
2429 * Routine: mach_port_guard [kernel call]
2431 * Guard a mach port with specified guard value.
2432 * The context field of the port is used as the guard.
2436 * KERN_SUCCESS The name is destroyed.
2437 * KERN_INVALID_TASK The space is null.
2438 * KERN_INVALID_TASK The space is dead.
2439 * KERN_INVALID_NAME The name doesn't denote a right.
2440 * KERN_INVALID_RIGHT The right isn't correct.
2441 * KERN_INVALID_ARGUMENT Port already contains a context/guard.
2446 mach_port_name_t name
,
2453 if (space
== IS_NULL
)
2454 return KERN_INVALID_TASK
;
2456 if (!MACH_PORT_VALID(name
))
2457 return KERN_INVALID_NAME
;
2459 /* Guard can be applied only to receive rights */
2460 kr
= ipc_port_translate_receive(space
, name
, &port
);
2461 if (kr
!= KERN_SUCCESS
)
2464 /* Port locked and active */
2465 kr
= mach_port_guard_locked(port
, guard
, strict
);
2473 * Routine: mach_port_unguard [kernel call]
2475 * Unguard a mach port with specified guard value.
2479 * KERN_SUCCESS The name is destroyed.
2480 * KERN_INVALID_TASK The space is null.
2481 * KERN_INVALID_TASK The space is dead.
2482 * KERN_INVALID_NAME The name doesn't denote a right.
2483 * KERN_INVALID_RIGHT The right isn't correct.
2484 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
2485 * This also raises a EXC_GUARD exception.
2490 mach_port_name_t name
,
2497 if (space
== IS_NULL
)
2498 return KERN_INVALID_TASK
;
2500 if (!MACH_PORT_VALID(name
))
2501 return KERN_INVALID_NAME
;
2503 kr
= ipc_port_translate_receive(space
, name
, &port
);
2504 if (kr
!= KERN_SUCCESS
)
2507 /* Port locked and active */
2508 kr
= mach_port_unguard_locked(port
, name
, guard
);