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 <ipc/ipc_labelh.h>
99 #include <kern/misc_protos.h>
100 #include <security/mac_mach_internal.h>
102 #include <mach/security_server.h>
105 * Forward declarations
107 void mach_port_names_helper(
108 ipc_port_timestamp_t timestamp
,
110 mach_port_name_t name
,
111 mach_port_name_t
*names
,
112 mach_port_type_t
*types
,
113 ipc_entry_num_t
*actualp
);
115 void mach_port_gst_helper(
118 ipc_entry_num_t maxnames
,
119 mach_port_name_t
*names
,
120 ipc_entry_num_t
*actualp
);
123 /* Zeroed template of qos flags */
125 static mach_port_qos_t qos_template
;
128 * Routine: mach_port_names_helper
130 * A helper function for mach_port_names.
133 * Space containing entry is [at least] read-locked.
137 mach_port_names_helper(
138 ipc_port_timestamp_t timestamp
,
140 mach_port_name_t name
,
141 mach_port_name_t
*names
,
142 mach_port_type_t
*types
,
143 ipc_entry_num_t
*actualp
)
145 ipc_entry_bits_t bits
;
146 ipc_port_request_index_t request
;
147 mach_port_type_t type
= 0;
148 ipc_entry_num_t actual
;
151 bits
= entry
->ie_bits
;
152 request
= entry
->ie_request
;
153 port
= (ipc_port_t
) entry
->ie_object
;
155 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
156 assert(IP_VALID(port
));
158 if (request
!= IE_REQ_NONE
) {
160 assert(ip_active(port
));
161 type
|= ipc_port_request_type(port
, name
, request
);
165 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
166 mach_port_type_t reqtype
;
168 assert(IP_VALID(port
));
171 reqtype
= (request
!= IE_REQ_NONE
) ?
172 ipc_port_request_type(port
, name
, request
) : 0;
175 * If the port is alive, or was alive when the mach_port_names
176 * started, then return that fact. Otherwise, pretend we found
179 if (ip_active(port
) || IP_TIMESTAMP_ORDER(timestamp
, port
->ip_timestamp
)) {
182 bits
&= ~(IE_BITS_TYPE_MASK
);
183 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
184 /* account for additional reference for dead-name notification */
191 type
|= IE_BITS_TYPE(bits
);
194 names
[actual
] = name
;
195 types
[actual
] = type
;
200 * Routine: mach_port_names [kernel call]
202 * Retrieves a list of the rights present in the space,
203 * along with type information. (Same as returned
204 * by mach_port_type.) The names are returned in
205 * no particular order, but they (and the type info)
206 * are an accurate snapshot of the space.
210 * KERN_SUCCESS Arrays of names and types returned.
211 * KERN_INVALID_TASK The space is null.
212 * KERN_INVALID_TASK The space is dead.
213 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
219 mach_port_name_t
**namesp
,
220 mach_msg_type_number_t
*namesCnt
,
221 mach_port_type_t
**typesp
,
222 mach_msg_type_number_t
*typesCnt
)
224 ipc_tree_entry_t tentry
;
226 ipc_entry_num_t tsize
;
227 mach_port_index_t index
;
228 ipc_entry_num_t actual
; /* this many names */
229 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
230 mach_port_name_t
*names
;
231 mach_port_type_t
*types
;
234 vm_size_t size
; /* size of allocated memory */
235 vm_offset_t addr1
; /* allocated memory, for names */
236 vm_offset_t addr2
; /* allocated memory, for types */
237 vm_map_copy_t memory1
; /* copied-in memory, for names */
238 vm_map_copy_t memory2
; /* copied-in memory, for types */
240 /* safe simplifying assumption */
241 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
243 if (space
== IS_NULL
)
244 return KERN_INVALID_TASK
;
249 ipc_entry_num_t bound
;
250 vm_size_t size_needed
;
253 if (!space
->is_active
) {
254 is_read_unlock(space
);
256 kmem_free(ipc_kernel_map
, addr1
, size
);
257 kmem_free(ipc_kernel_map
, addr2
, size
);
259 return KERN_INVALID_TASK
;
262 /* upper bound on number of names in the space */
264 bound
= space
->is_table_size
+ space
->is_tree_total
;
265 size_needed
= round_page(bound
* sizeof(mach_port_name_t
));
267 if (size_needed
<= size
)
270 is_read_unlock(space
);
273 kmem_free(ipc_kernel_map
, addr1
, size
);
274 kmem_free(ipc_kernel_map
, addr2
, size
);
278 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, VM_FLAGS_ANYWHERE
);
279 if (kr
!= KERN_SUCCESS
)
280 return KERN_RESOURCE_SHORTAGE
;
282 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, VM_FLAGS_ANYWHERE
);
283 if (kr
!= KERN_SUCCESS
) {
284 kmem_free(ipc_kernel_map
, addr1
, size
);
285 return KERN_RESOURCE_SHORTAGE
;
288 /* can't fault while we hold locks */
290 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
291 vm_map_round_page(addr1
+ size
),
292 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
293 if (kr
!= KERN_SUCCESS
) {
294 kmem_free(ipc_kernel_map
, addr1
, size
);
295 kmem_free(ipc_kernel_map
, addr2
, size
);
296 return KERN_RESOURCE_SHORTAGE
;
299 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
300 vm_map_round_page(addr2
+ size
),
301 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
302 if (kr
!= KERN_SUCCESS
) {
303 kmem_free(ipc_kernel_map
, addr1
, size
);
304 kmem_free(ipc_kernel_map
, addr2
, size
);
305 return KERN_RESOURCE_SHORTAGE
;
309 /* space is read-locked and active */
311 names
= (mach_port_name_t
*) addr1
;
312 types
= (mach_port_type_t
*) addr2
;
315 timestamp
= ipc_port_timestamp();
317 table
= space
->is_table
;
318 tsize
= space
->is_table_size
;
320 for (index
= 0; index
< tsize
; index
++) {
321 ipc_entry_t entry
= &table
[index
];
322 ipc_entry_bits_t bits
= entry
->ie_bits
;
324 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
325 mach_port_name_t name
;
327 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
328 mach_port_names_helper(timestamp
, entry
, name
, names
,
333 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
335 tentry
= ipc_splay_traverse_next(&space
->is_tree
, FALSE
)) {
336 ipc_entry_t entry
= &tentry
->ite_entry
;
337 mach_port_name_t name
= tentry
->ite_name
;
339 assert(IE_BITS_TYPE(tentry
->ite_bits
) != MACH_PORT_TYPE_NONE
);
340 mach_port_names_helper(timestamp
, entry
, name
, names
,
343 ipc_splay_traverse_finish(&space
->is_tree
);
344 is_read_unlock(space
);
347 memory1
= VM_MAP_COPY_NULL
;
348 memory2
= VM_MAP_COPY_NULL
;
351 kmem_free(ipc_kernel_map
, addr1
, size
);
352 kmem_free(ipc_kernel_map
, addr2
, size
);
356 vm_size_t vm_size_used
;
358 size_used
= actual
* sizeof(mach_port_name_t
);
359 vm_size_used
= round_page(size_used
);
362 * Make used memory pageable and get it into
363 * copied-in form. Free any unused memory.
366 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
367 vm_map_round_page(addr1
+ vm_size_used
), FALSE
);
368 assert(kr
== KERN_SUCCESS
);
370 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
371 vm_map_round_page(addr2
+ vm_size_used
), FALSE
);
372 assert(kr
== KERN_SUCCESS
);
374 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr1
,
375 (vm_map_size_t
)size_used
, TRUE
, &memory1
);
376 assert(kr
== KERN_SUCCESS
);
378 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr2
,
379 (vm_map_size_t
)size_used
, TRUE
, &memory2
);
380 assert(kr
== KERN_SUCCESS
);
382 if (vm_size_used
!= size
) {
383 kmem_free(ipc_kernel_map
,
384 addr1
+ vm_size_used
, size
- vm_size_used
);
385 kmem_free(ipc_kernel_map
,
386 addr2
+ vm_size_used
, size
- vm_size_used
);
390 *namesp
= (mach_port_name_t
*) memory1
;
392 *typesp
= (mach_port_type_t
*) memory2
;
398 * Routine: mach_port_type [kernel call]
400 * Retrieves the type of a right in the space.
401 * The type is a bitwise combination of one or more
402 * of the following type bits:
403 * MACH_PORT_TYPE_SEND
404 * MACH_PORT_TYPE_RECEIVE
405 * MACH_PORT_TYPE_SEND_ONCE
406 * MACH_PORT_TYPE_PORT_SET
407 * MACH_PORT_TYPE_DEAD_NAME
408 * In addition, the following pseudo-type bits may be present:
409 * MACH_PORT_TYPE_DNREQUEST
410 * A dead-name notification is requested.
414 * KERN_SUCCESS Type is returned.
415 * KERN_INVALID_TASK The space is null.
416 * KERN_INVALID_TASK The space is dead.
417 * KERN_INVALID_NAME The name doesn't denote a right.
423 mach_port_name_t name
,
424 mach_port_type_t
*typep
)
426 mach_port_urefs_t urefs
;
430 if (space
== IS_NULL
)
431 return KERN_INVALID_TASK
;
433 if (name
== MACH_PORT_NULL
)
434 return KERN_INVALID_NAME
;
436 if (name
== MACH_PORT_DEAD
) {
437 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
441 kr
= ipc_right_lookup_write(space
, name
, &entry
);
442 if (kr
!= KERN_SUCCESS
)
444 /* space is write-locked and active */
446 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
447 if (kr
== KERN_SUCCESS
)
448 is_write_unlock(space
);
450 /* JMM - workaround rdar://problem/9121297 (CF being too picky on these bits). */
451 *typep
&= ~(MACH_PORT_TYPE_SPREQUEST
| MACH_PORT_TYPE_SPREQUEST_DELAYED
);
454 /* space is unlocked */
459 * Routine: mach_port_rename [kernel call]
461 * Changes the name denoting a right,
462 * from oname to nname.
466 * KERN_SUCCESS The right is renamed.
467 * KERN_INVALID_TASK The space is null.
468 * KERN_INVALID_TASK The space is dead.
469 * KERN_INVALID_NAME The oname doesn't denote a right.
470 * KERN_INVALID_VALUE The nname isn't a legal name.
471 * KERN_NAME_EXISTS The nname already denotes a right.
472 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
478 mach_port_name_t oname
,
479 mach_port_name_t nname
)
481 if (space
== IS_NULL
)
482 return KERN_INVALID_TASK
;
484 if (!MACH_PORT_VALID(oname
))
485 return KERN_INVALID_NAME
;
487 if (!MACH_PORT_VALID(nname
))
488 return KERN_INVALID_VALUE
;
490 return ipc_object_rename(space
, oname
, nname
);
494 * Routine: mach_port_allocate_name [kernel call]
496 * Allocates a right in a space, using a specific name
497 * for the new right. Possible rights:
498 * MACH_PORT_RIGHT_RECEIVE
499 * MACH_PORT_RIGHT_PORT_SET
500 * MACH_PORT_RIGHT_DEAD_NAME
502 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
503 * has no extant send or send-once rights and no queued
504 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
505 * and its make-send count is 0. It is not a member of
506 * a port set. It has no registered no-senders or
507 * port-destroyed notification requests.
509 * A new port set has no members.
511 * A new dead name has one user reference.
515 * KERN_SUCCESS The right is allocated.
516 * KERN_INVALID_TASK The space is null.
517 * KERN_INVALID_TASK The space is dead.
518 * KERN_INVALID_VALUE The name isn't a legal name.
519 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
520 * KERN_NAME_EXISTS The name already denotes a right.
521 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
523 * Restrictions on name allocation: NT bits are reserved by kernel,
524 * must be set on any chosen name. Can't do this at all in kernel
529 mach_port_allocate_name(
531 mach_port_right_t right
,
532 mach_port_name_t name
)
535 mach_port_qos_t qos
= qos_template
;
539 if (!MACH_PORT_VALID(name
))
540 return KERN_INVALID_VALUE
;
542 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
548 * Routine: mach_port_allocate [kernel call]
550 * Allocates a right in a space. Like mach_port_allocate_name,
551 * except that the implementation picks a name for the right.
552 * The name may be any legal name in the space that doesn't
553 * currently denote a right.
557 * KERN_SUCCESS The right is allocated.
558 * KERN_INVALID_TASK The space is null.
559 * KERN_INVALID_TASK The space is dead.
560 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
561 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
562 * KERN_NO_SPACE No room in space for another right.
568 mach_port_right_t right
,
569 mach_port_name_t
*namep
)
572 mach_port_qos_t qos
= qos_template
;
574 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
580 * Routine: mach_port_allocate_qos [kernel call]
582 * Allocates a right, with qos options, in a space. Like
583 * mach_port_allocate_name, except that the implementation
584 * picks a name for the right. The name may be any legal name
585 * in the space that doesn't currently denote a right.
589 * KERN_SUCCESS The right is allocated.
590 * KERN_INVALID_TASK The space is null.
591 * KERN_INVALID_TASK The space is dead.
592 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
593 * KERN_INVALID_ARGUMENT The qos request was invalid.
594 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
595 * KERN_NO_SPACE No room in space for another right.
599 mach_port_allocate_qos(
601 mach_port_right_t right
,
602 mach_port_qos_t
*qosp
,
603 mach_port_name_t
*namep
)
608 return KERN_INVALID_ARGUMENT
;
609 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
615 * Routine: mach_port_allocate_full [kernel call]
617 * Allocates a right in a space. Supports all of the
618 * special cases, such as specifying a subsystem,
619 * a specific name, a real-time port, etc.
620 * The name may be any legal name in the space that doesn't
621 * currently denote a right.
625 * KERN_SUCCESS The right is allocated.
626 * KERN_INVALID_TASK The space is null.
627 * KERN_INVALID_TASK The space is dead.
628 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
629 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
630 * KERN_NO_SPACE No room in space for another right.
634 mach_port_allocate_full(
636 mach_port_right_t right
,
638 mach_port_qos_t
*qosp
,
639 mach_port_name_t
*namep
)
641 ipc_kmsg_t kmsg
= IKM_NULL
;
644 if (space
== IS_NULL
)
645 return (KERN_INVALID_TASK
);
647 if (proto
!= MACH_PORT_NULL
)
648 return (KERN_INVALID_VALUE
);
651 if (!MACH_PORT_VALID (*namep
))
652 return (KERN_INVALID_VALUE
);
653 if (is_fast_space (space
))
654 return (KERN_FAILURE
);
657 if (qosp
->prealloc
) {
658 if (qosp
->len
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
) {
659 return KERN_RESOURCE_SHORTAGE
;
661 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
663 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
664 return (KERN_INVALID_VALUE
);
666 kmsg
= (ipc_kmsg_t
)ipc_kmsg_prealloc(size
);
667 if (kmsg
== IKM_NULL
)
668 return (KERN_RESOURCE_SHORTAGE
);
673 case MACH_PORT_RIGHT_RECEIVE
:
678 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
680 kr
= ipc_port_alloc(space
, namep
, &port
);
681 if (kr
== KERN_SUCCESS
) {
682 if (kmsg
!= IKM_NULL
)
683 ipc_kmsg_set_prealloc(kmsg
, port
);
687 } else if (kmsg
!= IKM_NULL
)
692 case MACH_PORT_RIGHT_PORT_SET
:
697 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
699 kr
= ipc_pset_alloc(space
, namep
, &pset
);
700 if (kr
== KERN_SUCCESS
)
705 case MACH_PORT_RIGHT_DEAD_NAME
:
706 kr
= ipc_object_alloc_dead(space
, namep
);
710 kr
= KERN_INVALID_VALUE
;
718 * Routine: mach_port_destroy [kernel call]
720 * Cleans up and destroys all rights denoted by a name
721 * in a space. The destruction of a receive right
722 * destroys the port, unless a port-destroyed request
723 * has been made for it; the destruction of a port-set right
724 * destroys the port set.
728 * KERN_SUCCESS The name is destroyed.
729 * KERN_INVALID_TASK The space is null.
730 * KERN_INVALID_TASK The space is dead.
731 * KERN_INVALID_NAME The name doesn't denote a right.
737 mach_port_name_t name
)
742 if (space
== IS_NULL
)
743 return KERN_INVALID_TASK
;
745 if (!MACH_PORT_VALID(name
))
748 kr
= ipc_right_lookup_write(space
, name
, &entry
);
749 if (kr
!= KERN_SUCCESS
)
751 /* space is write-locked and active */
753 kr
= ipc_right_destroy(space
, name
, entry
);
754 is_write_unlock(space
);
759 * Routine: mach_port_deallocate [kernel call]
761 * Deallocates a user reference from a send right,
762 * send-once right, or a dead-name right. May
763 * deallocate the right, if this is the last uref,
764 * and destroy the name, if it doesn't denote
769 * KERN_SUCCESS The uref is deallocated.
770 * KERN_INVALID_TASK The space is null.
771 * KERN_INVALID_TASK The space is dead.
772 * KERN_INVALID_NAME The name doesn't denote a right.
773 * KERN_INVALID_RIGHT The right isn't correct.
777 mach_port_deallocate(
779 mach_port_name_t name
)
784 if (space
== IS_NULL
)
785 return KERN_INVALID_TASK
;
787 if (!MACH_PORT_VALID(name
))
790 kr
= ipc_right_lookup_write(space
, name
, &entry
);
791 if (kr
!= KERN_SUCCESS
)
793 /* space is write-locked */
795 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
800 * Routine: mach_port_get_refs [kernel call]
802 * Retrieves the number of user references held by a right.
803 * Receive rights, port-set rights, and send-once rights
804 * always have one user reference. Returns zero if the
805 * name denotes a right, but not the queried right.
809 * KERN_SUCCESS Number of urefs returned.
810 * KERN_INVALID_TASK The space is null.
811 * KERN_INVALID_TASK The space is dead.
812 * KERN_INVALID_VALUE "right" isn't a legal value.
813 * KERN_INVALID_NAME The name doesn't denote a right.
819 mach_port_name_t name
,
820 mach_port_right_t right
,
821 mach_port_urefs_t
*urefsp
)
823 mach_port_type_t type
;
824 mach_port_urefs_t urefs
;
828 if (space
== IS_NULL
)
829 return KERN_INVALID_TASK
;
831 if (right
>= MACH_PORT_RIGHT_NUMBER
)
832 return KERN_INVALID_VALUE
;
834 if (!MACH_PORT_VALID(name
)) {
835 if (right
== MACH_PORT_RIGHT_SEND
||
836 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
840 return KERN_INVALID_NAME
;
843 kr
= ipc_right_lookup_write(space
, name
, &entry
);
844 if (kr
!= KERN_SUCCESS
)
846 /* space is write-locked and active */
848 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
); /* unlocks */
849 if (kr
!= KERN_SUCCESS
)
850 return kr
; /* space is unlocked */
851 is_write_unlock(space
);
853 if (type
& MACH_PORT_TYPE(right
))
855 case MACH_PORT_RIGHT_SEND_ONCE
:
859 case MACH_PORT_RIGHT_PORT_SET
:
860 case MACH_PORT_RIGHT_RECEIVE
:
864 case MACH_PORT_RIGHT_DEAD_NAME
:
865 case MACH_PORT_RIGHT_SEND
:
871 panic("mach_port_get_refs: strange rights");
880 * Routine: mach_port_mod_refs
882 * Modifies the number of user references held by a right.
883 * The resulting number of user references must be non-negative.
884 * If it is zero, the right is deallocated. If the name
885 * doesn't denote other rights, it is destroyed.
889 * KERN_SUCCESS Modified number of urefs.
890 * KERN_INVALID_TASK The space is null.
891 * KERN_INVALID_TASK The space is dead.
892 * KERN_INVALID_VALUE "right" isn't a legal value.
893 * KERN_INVALID_NAME The name doesn't denote a right.
894 * KERN_INVALID_RIGHT Name doesn't denote specified right.
895 * KERN_INVALID_VALUE Impossible modification to urefs.
896 * KERN_UREFS_OVERFLOW Urefs would overflow.
902 mach_port_name_t name
,
903 mach_port_right_t right
,
904 mach_port_delta_t delta
)
909 if (space
== IS_NULL
)
910 return KERN_INVALID_TASK
;
912 if (right
>= MACH_PORT_RIGHT_NUMBER
)
913 return KERN_INVALID_VALUE
;
915 if (!MACH_PORT_VALID(name
)) {
916 if (right
== MACH_PORT_RIGHT_SEND
||
917 right
== MACH_PORT_RIGHT_SEND_ONCE
)
919 return KERN_INVALID_NAME
;
922 kr
= ipc_right_lookup_write(space
, name
, &entry
);
923 if (kr
!= KERN_SUCCESS
)
925 /* space is write-locked and active */
927 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
933 * Routine: mach_port_set_mscount [kernel call]
935 * Changes a receive right's make-send count.
939 * KERN_SUCCESS Set make-send count.
940 * KERN_INVALID_TASK The space is null.
941 * KERN_INVALID_TASK The space is dead.
942 * KERN_INVALID_NAME The name doesn't denote a right.
943 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
947 mach_port_set_mscount(
949 mach_port_name_t name
,
950 mach_port_mscount_t mscount
)
955 if (space
== IS_NULL
)
956 return KERN_INVALID_TASK
;
958 if (!MACH_PORT_VALID(name
))
959 return KERN_INVALID_RIGHT
;
961 kr
= ipc_port_translate_receive(space
, name
, &port
);
962 if (kr
!= KERN_SUCCESS
)
964 /* port is locked and active */
966 ipc_port_set_mscount(port
, mscount
);
973 * Routine: mach_port_set_seqno [kernel call]
975 * Changes a receive right's sequence number.
979 * KERN_SUCCESS Set sequence number.
980 * KERN_INVALID_TASK The space is null.
981 * KERN_INVALID_TASK The space is dead.
982 * KERN_INVALID_NAME The name doesn't denote a right.
983 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
989 mach_port_name_t name
,
990 mach_port_seqno_t seqno
)
995 if (space
== IS_NULL
)
996 return KERN_INVALID_TASK
;
998 if (!MACH_PORT_VALID(name
))
999 return KERN_INVALID_RIGHT
;
1001 kr
= ipc_port_translate_receive(space
, name
, &port
);
1002 if (kr
!= KERN_SUCCESS
)
1004 /* port is locked and active */
1006 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
1009 return KERN_SUCCESS
;
1013 * Routine: mach_port_get_context [kernel call]
1015 * Returns a receive right's context pointer.
1019 * KERN_SUCCESS Set context pointer.
1020 * KERN_INVALID_TASK The space is null.
1021 * KERN_INVALID_TASK The space is dead.
1022 * KERN_INVALID_NAME The name doesn't denote a right.
1023 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1027 mach_port_get_context(
1029 mach_port_name_t name
,
1030 mach_vm_address_t
*context
)
1035 if (space
== IS_NULL
)
1036 return KERN_INVALID_TASK
;
1038 if (!MACH_PORT_VALID(name
))
1039 return KERN_INVALID_RIGHT
;
1041 kr
= ipc_port_translate_receive(space
, name
, &port
);
1042 if (kr
!= KERN_SUCCESS
)
1045 /* port is locked and active */
1046 *context
= port
->ip_context
;
1049 return KERN_SUCCESS
;
1054 * Routine: mach_port_set_context [kernel call]
1056 * Changes a receive right's context pointer.
1060 * KERN_SUCCESS Set context pointer.
1061 * KERN_INVALID_TASK The space is null.
1062 * KERN_INVALID_TASK The space is dead.
1063 * KERN_INVALID_NAME The name doesn't denote a right.
1064 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1068 mach_port_set_context(
1070 mach_port_name_t name
,
1071 mach_vm_address_t context
)
1076 if (space
== IS_NULL
)
1077 return KERN_INVALID_TASK
;
1079 if (!MACH_PORT_VALID(name
))
1080 return KERN_INVALID_RIGHT
;
1082 kr
= ipc_port_translate_receive(space
, name
, &port
);
1083 if (kr
!= KERN_SUCCESS
)
1086 /* port is locked and active */
1087 port
->ip_context
= context
;
1090 return KERN_SUCCESS
;
1095 * Routine: mach_port_gst_helper
1097 * A helper function for mach_port_get_set_status.
1101 mach_port_gst_helper(
1104 ipc_entry_num_t maxnames
,
1105 mach_port_name_t
*names
,
1106 ipc_entry_num_t
*actualp
)
1108 mach_port_name_t name
;
1110 assert(port
!= IP_NULL
);
1113 assert(ip_active(port
));
1115 name
= port
->ip_receiver_name
;
1116 assert(name
!= MACH_PORT_NULL
);
1120 if (ipc_pset_member(pset
, port
)) {
1121 ipc_entry_num_t actual
= *actualp
;
1123 if (actual
< maxnames
)
1124 names
[actual
] = name
;
1126 *actualp
= actual
+1;
1131 * Routine: mach_port_get_set_status [kernel call]
1133 * Retrieves a list of members in a port set.
1134 * Returns the space's name for each receive right member.
1138 * KERN_SUCCESS Retrieved list of members.
1139 * KERN_INVALID_TASK The space is null.
1140 * KERN_INVALID_TASK The space is dead.
1141 * KERN_INVALID_NAME The name doesn't denote a right.
1142 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1143 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1147 mach_port_get_set_status(
1149 mach_port_name_t name
,
1150 mach_port_name_t
**members
,
1151 mach_msg_type_number_t
*membersCnt
)
1153 ipc_entry_num_t actual
; /* this many members */
1154 ipc_entry_num_t maxnames
; /* space for this many members */
1157 vm_size_t size
; /* size of allocated memory */
1158 vm_offset_t addr
; /* allocated memory */
1159 vm_map_copy_t memory
; /* copied-in memory */
1161 if (space
== IS_NULL
)
1162 return KERN_INVALID_TASK
;
1164 if (!MACH_PORT_VALID(name
))
1165 return KERN_INVALID_RIGHT
;
1167 size
= PAGE_SIZE
; /* initial guess */
1170 ipc_tree_entry_t tentry
;
1171 ipc_entry_t entry
, table
;
1172 ipc_entry_num_t tsize
;
1173 mach_port_index_t index
;
1174 mach_port_name_t
*names
;
1177 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, VM_FLAGS_ANYWHERE
);
1178 if (kr
!= KERN_SUCCESS
)
1179 return KERN_RESOURCE_SHORTAGE
;
1181 /* can't fault while we hold locks */
1183 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1184 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1185 assert(kr
== KERN_SUCCESS
);
1187 kr
= ipc_right_lookup_read(space
, name
, &entry
);
1188 if (kr
!= KERN_SUCCESS
) {
1189 kmem_free(ipc_kernel_map
, addr
, size
);
1192 /* space is read-locked and active */
1194 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_PORT_SET
) {
1195 is_read_unlock(space
);
1196 kmem_free(ipc_kernel_map
, addr
, size
);
1197 return KERN_INVALID_RIGHT
;
1200 pset
= (ipc_pset_t
) entry
->ie_object
;
1201 assert(pset
!= IPS_NULL
);
1202 /* the port set must be active */
1204 names
= (mach_port_name_t
*) addr
;
1205 maxnames
= (ipc_entry_num_t
)(size
/ sizeof(mach_port_name_t
));
1208 table
= space
->is_table
;
1209 tsize
= space
->is_table_size
;
1211 for (index
= 0; index
< tsize
; index
++) {
1212 ipc_entry_t ientry
= &table
[index
];
1214 if (ientry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) {
1216 (ipc_port_t
) ientry
->ie_object
;
1218 mach_port_gst_helper(pset
, port
,
1219 maxnames
, names
, &actual
);
1223 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
1225 tentry
= ipc_splay_traverse_next(&space
->is_tree
,FALSE
)) {
1226 ipc_entry_bits_t bits
= tentry
->ite_bits
;
1228 assert(IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
);
1230 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1231 ipc_port_t port
= (ipc_port_t
) tentry
->ite_object
;
1233 mach_port_gst_helper(pset
, port
, maxnames
,
1237 ipc_splay_traverse_finish(&space
->is_tree
);
1238 is_read_unlock(space
);
1240 if (actual
<= maxnames
)
1243 /* didn't have enough memory; allocate more */
1245 kmem_free(ipc_kernel_map
, addr
, size
);
1246 size
= round_page(actual
* sizeof(mach_port_name_t
)) + PAGE_SIZE
;
1250 memory
= VM_MAP_COPY_NULL
;
1252 kmem_free(ipc_kernel_map
, addr
, size
);
1254 vm_size_t size_used
;
1255 vm_size_t vm_size_used
;
1257 size_used
= actual
* sizeof(mach_port_name_t
);
1258 vm_size_used
= round_page(size_used
);
1261 * Make used memory pageable and get it into
1262 * copied-in form. Free any unused memory.
1265 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr
),
1266 vm_map_round_page(addr
+ vm_size_used
), FALSE
);
1267 assert(kr
== KERN_SUCCESS
);
1269 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr
,
1270 (vm_map_size_t
)size_used
, TRUE
, &memory
);
1271 assert(kr
== KERN_SUCCESS
);
1273 if (vm_size_used
!= size
)
1274 kmem_free(ipc_kernel_map
,
1275 addr
+ vm_size_used
, size
- vm_size_used
);
1278 *members
= (mach_port_name_t
*) memory
;
1279 *membersCnt
= actual
;
1280 return KERN_SUCCESS
;
1284 * Routine: mach_port_move_member [kernel call]
1286 * If after is MACH_PORT_NULL, removes member
1287 * from the port set it is in. Otherwise, adds
1288 * member to after, removing it from any set
1289 * it might already be in.
1293 * KERN_SUCCESS Moved the port.
1294 * KERN_INVALID_TASK The space is null.
1295 * KERN_INVALID_TASK The space is dead.
1296 * KERN_INVALID_NAME Member didn't denote a right.
1297 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1298 * KERN_INVALID_NAME After didn't denote a right.
1299 * KERN_INVALID_RIGHT After didn't denote a port set right.
1301 * After is MACH_PORT_NULL and Member isn't in a port set.
1305 mach_port_move_member(
1307 mach_port_name_t member
,
1308 mach_port_name_t after
)
1315 if (space
== IS_NULL
)
1316 return KERN_INVALID_TASK
;
1318 if (!MACH_PORT_VALID(member
))
1319 return KERN_INVALID_RIGHT
;
1321 if (after
== MACH_PORT_DEAD
)
1322 return KERN_INVALID_RIGHT
;
1324 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1325 if (kr
!= KERN_SUCCESS
)
1327 /* space is read-locked and active */
1329 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1330 is_read_unlock(space
);
1331 return KERN_INVALID_RIGHT
;
1334 port
= (ipc_port_t
) entry
->ie_object
;
1335 assert(port
!= IP_NULL
);
1337 if (after
== MACH_PORT_NULL
)
1340 entry
= ipc_entry_lookup(space
, after
);
1341 if (entry
== IE_NULL
) {
1342 is_read_unlock(space
);
1343 return KERN_INVALID_NAME
;
1346 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1347 is_read_unlock(space
);
1348 return KERN_INVALID_RIGHT
;
1351 nset
= (ipc_pset_t
) entry
->ie_object
;
1352 assert(nset
!= IPS_NULL
);
1355 ipc_pset_remove_from_all(port
);
1357 if (nset
!= IPS_NULL
) {
1359 kr
= ipc_pset_add(nset
, port
);
1363 is_read_unlock(space
);
1368 * Routine: mach_port_request_notification [kernel call]
1370 * Requests a notification. The caller supplies
1371 * a send-once right for the notification to use,
1372 * and the call returns the previously registered
1373 * send-once right, if any. Possible types:
1375 * MACH_NOTIFY_PORT_DESTROYED
1376 * Requests a port-destroyed notification
1377 * for a receive right. Sync should be zero.
1378 * MACH_NOTIFY_NO_SENDERS
1379 * Requests a no-senders notification for a
1380 * receive right. If there are currently no
1381 * senders, sync is less than or equal to the
1382 * current make-send count, and a send-once right
1383 * is supplied, then an immediate no-senders
1384 * notification is generated.
1385 * MACH_NOTIFY_DEAD_NAME
1386 * Requests a dead-name notification for a send
1387 * or receive right. If the name is already a
1388 * dead name, sync is non-zero, and a send-once
1389 * right is supplied, then an immediate dead-name
1390 * notification is generated.
1394 * KERN_SUCCESS Requested a notification.
1395 * KERN_INVALID_TASK The space is null.
1396 * KERN_INVALID_TASK The space is dead.
1397 * KERN_INVALID_VALUE Bad id value.
1398 * KERN_INVALID_NAME Name doesn't denote a right.
1399 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1400 * KERN_INVALID_CAPABILITY The notify port is dead.
1401 * MACH_NOTIFY_PORT_DESTROYED:
1402 * KERN_INVALID_VALUE Sync isn't zero.
1403 * MACH_NOTIFY_DEAD_NAME:
1404 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1405 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1406 * sync is zero or notify is IP_NULL.
1407 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1408 * generating immediate notif. would overflow urefs.
1412 mach_port_request_notification(
1414 mach_port_name_t name
,
1416 mach_port_mscount_t sync
,
1418 ipc_port_t
*previousp
)
1422 if (space
== IS_NULL
)
1423 return KERN_INVALID_TASK
;
1425 if (notify
== IP_DEAD
)
1426 return KERN_INVALID_CAPABILITY
;
1430 * Requesting notifications on RPC ports is an error.
1436 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1437 if (kr
!= KERN_SUCCESS
)
1440 port
= (ipc_port_t
) entry
->ie_object
;
1442 if (port
->ip_subsystem
!= NULL
) {
1443 is_write_unlock(space
);
1444 panic("mach_port_request_notification: on RPC port!!");
1445 return KERN_INVALID_CAPABILITY
;
1447 is_write_unlock(space
);
1453 case MACH_NOTIFY_PORT_DESTROYED
: {
1454 ipc_port_t port
, previous
;
1457 return KERN_INVALID_VALUE
;
1459 if (!MACH_PORT_VALID(name
))
1460 return KERN_INVALID_RIGHT
;
1462 kr
= ipc_port_translate_receive(space
, name
, &port
);
1463 if (kr
!= KERN_SUCCESS
)
1465 /* port is locked and active */
1467 ipc_port_pdrequest(port
, notify
, &previous
);
1468 /* port is unlocked */
1470 *previousp
= previous
;
1474 case MACH_NOTIFY_NO_SENDERS
: {
1477 if (!MACH_PORT_VALID(name
))
1478 return KERN_INVALID_RIGHT
;
1480 kr
= ipc_port_translate_receive(space
, name
, &port
);
1481 if (kr
!= KERN_SUCCESS
)
1483 /* port is locked and active */
1485 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1486 /* port is unlocked */
1490 case MACH_NOTIFY_SEND_POSSIBLE
:
1492 if (!MACH_PORT_VALID(name
)) {
1493 return KERN_INVALID_ARGUMENT
;
1496 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1497 TRUE
, notify
, previousp
);
1498 if (kr
!= KERN_SUCCESS
)
1502 case MACH_NOTIFY_DEAD_NAME
:
1504 if (!MACH_PORT_VALID(name
)) {
1507 * Should do immediate delivery check -
1508 * will do that in the near future.
1510 return KERN_INVALID_ARGUMENT
;
1513 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1514 FALSE
, notify
, previousp
);
1515 if (kr
!= KERN_SUCCESS
)
1520 return KERN_INVALID_VALUE
;
1523 return KERN_SUCCESS
;
1527 * Routine: mach_port_insert_right [kernel call]
1529 * Inserts a right into a space, as if the space
1530 * voluntarily received the right in a message,
1531 * except that the right gets the specified name.
1535 * KERN_SUCCESS Inserted the right.
1536 * KERN_INVALID_TASK The space is null.
1537 * KERN_INVALID_TASK The space is dead.
1538 * KERN_INVALID_VALUE The name isn't a legal name.
1539 * KERN_NAME_EXISTS The name already denotes a right.
1540 * KERN_INVALID_VALUE Message doesn't carry a port right.
1541 * KERN_INVALID_CAPABILITY Port is null or dead.
1542 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1543 * KERN_RIGHT_EXISTS Space has rights under another name.
1544 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1548 mach_port_insert_right(
1550 mach_port_name_t name
,
1552 mach_msg_type_name_t polyPoly
)
1554 if (space
== IS_NULL
)
1555 return KERN_INVALID_TASK
;
1557 if (!MACH_PORT_VALID(name
) ||
1558 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1559 return KERN_INVALID_VALUE
;
1561 if (!IO_VALID((ipc_object_t
) poly
))
1562 return KERN_INVALID_CAPABILITY
;
1564 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1565 polyPoly
, FALSE
, name
);
1569 * Routine: mach_port_extract_right [kernel call]
1571 * Extracts a right from a space, as if the space
1572 * voluntarily sent the right to the caller.
1576 * KERN_SUCCESS Extracted the right.
1577 * KERN_INVALID_TASK The space is null.
1578 * KERN_INVALID_TASK The space is dead.
1579 * KERN_INVALID_VALUE Requested type isn't a port right.
1580 * KERN_INVALID_NAME Name doesn't denote a right.
1581 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1585 mach_port_extract_right(
1587 mach_port_name_t name
,
1588 mach_msg_type_name_t msgt_name
,
1590 mach_msg_type_name_t
*polyPoly
)
1594 if (space
== IS_NULL
)
1595 return KERN_INVALID_TASK
;
1597 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1598 return KERN_INVALID_VALUE
;
1600 if (!MACH_PORT_VALID(name
)) {
1602 * really should copy out a dead name, if it is a send or
1603 * send-once right being copied, but instead return an
1606 return KERN_INVALID_RIGHT
;
1609 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1611 if (kr
== KERN_SUCCESS
)
1612 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1618 mach_port_get_attributes(
1620 mach_port_name_t name
,
1622 mach_port_info_t info
,
1623 mach_msg_type_number_t
*count
)
1628 if (space
== IS_NULL
)
1629 return KERN_INVALID_TASK
;
1632 case MACH_PORT_LIMITS_INFO
: {
1633 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1635 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1636 return KERN_FAILURE
;
1638 if (!MACH_PORT_VALID(name
)) {
1643 kr
= ipc_port_translate_receive(space
, name
, &port
);
1644 if (kr
!= KERN_SUCCESS
)
1646 /* port is locked and active */
1648 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1649 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1654 case MACH_PORT_RECEIVE_STATUS
: {
1655 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1658 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1659 return KERN_FAILURE
;
1661 if (!MACH_PORT_VALID(name
))
1662 return KERN_INVALID_RIGHT
;
1664 kr
= ipc_port_translate_receive(space
, name
, &port
);
1665 if (kr
!= KERN_SUCCESS
)
1667 /* port is locked and active */
1669 statusp
->mps_pset
= port
->ip_pset_count
;
1672 imq_lock(&port
->ip_messages
);
1673 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1674 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1675 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1676 imq_unlock(&port
->ip_messages
);
1679 statusp
->mps_mscount
= port
->ip_mscount
;
1680 statusp
->mps_sorights
= port
->ip_sorights
;
1681 statusp
->mps_srights
= port
->ip_srights
> 0;
1682 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1683 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1684 statusp
->mps_flags
= 0;
1686 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1691 case MACH_PORT_DNREQUESTS_SIZE
: {
1692 ipc_port_request_t table
;
1694 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1695 return KERN_FAILURE
;
1697 if (!MACH_PORT_VALID(name
)) {
1702 kr
= ipc_port_translate_receive(space
, name
, &port
);
1703 if (kr
!= KERN_SUCCESS
)
1705 /* port is locked and active */
1707 table
= port
->ip_requests
;
1708 if (table
== IPR_NULL
)
1711 *(int *)info
= table
->ipr_size
->its_size
;
1712 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1718 return KERN_INVALID_ARGUMENT
;
1722 return KERN_SUCCESS
;
1726 mach_port_set_attributes(
1728 mach_port_name_t name
,
1730 mach_port_info_t info
,
1731 mach_msg_type_number_t count
)
1736 if (space
== IS_NULL
)
1737 return KERN_INVALID_TASK
;
1741 case MACH_PORT_LIMITS_INFO
: {
1742 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1744 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1745 return KERN_FAILURE
;
1747 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1748 return KERN_INVALID_VALUE
;
1750 if (!MACH_PORT_VALID(name
))
1751 return KERN_INVALID_RIGHT
;
1753 kr
= ipc_port_translate_receive(space
, name
, &port
);
1754 if (kr
!= KERN_SUCCESS
)
1756 /* port is locked and active */
1758 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1762 case MACH_PORT_DNREQUESTS_SIZE
: {
1763 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1764 return KERN_FAILURE
;
1766 if (!MACH_PORT_VALID(name
))
1767 return KERN_INVALID_RIGHT
;
1769 kr
= ipc_port_translate_receive(space
, name
, &port
);
1770 if (kr
!= KERN_SUCCESS
)
1772 /* port is locked and active */
1774 kr
= ipc_port_request_grow(port
, *(int *)info
);
1775 if (kr
!= KERN_SUCCESS
)
1780 return KERN_INVALID_ARGUMENT
;
1783 return KERN_SUCCESS
;
1787 * Routine: mach_port_insert_member [kernel call]
1789 * Add the receive right, specified by name, to
1791 * The port cannot already be a member of the set.
1795 * KERN_SUCCESS Moved the port.
1796 * KERN_INVALID_TASK The space is null.
1797 * KERN_INVALID_TASK The space is dead.
1798 * KERN_INVALID_NAME name didn't denote a right.
1799 * KERN_INVALID_RIGHT name didn't denote a receive right.
1800 * KERN_INVALID_NAME pset_name didn't denote a right.
1801 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1802 * KERN_ALREADY_IN_SET name was already a member of pset.
1806 mach_port_insert_member(
1808 mach_port_name_t name
,
1809 mach_port_name_t psname
)
1815 if (space
== IS_NULL
)
1816 return KERN_INVALID_TASK
;
1818 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1819 return KERN_INVALID_RIGHT
;
1821 kr
= ipc_object_translate_two(space
,
1822 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1823 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1824 if (kr
!= KERN_SUCCESS
)
1827 /* obj and psobj are locked (and were locked in that order) */
1828 assert(psobj
!= IO_NULL
);
1829 assert(obj
!= IO_NULL
);
1831 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1838 * Routine: mach_port_extract_member [kernel call]
1840 * Remove a port from one portset that it is a member of.
1844 * KERN_SUCCESS Moved the port.
1845 * KERN_INVALID_TASK The space is null.
1846 * KERN_INVALID_TASK The space is dead.
1847 * KERN_INVALID_NAME Member didn't denote a right.
1848 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1849 * KERN_INVALID_NAME After didn't denote a right.
1850 * KERN_INVALID_RIGHT After didn't denote a port set right.
1852 * After is MACH_PORT_NULL and Member isn't in a port set.
1856 mach_port_extract_member(
1858 mach_port_name_t name
,
1859 mach_port_name_t psname
)
1865 if (space
== IS_NULL
)
1866 return KERN_INVALID_TASK
;
1868 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1869 return KERN_INVALID_RIGHT
;
1871 kr
= ipc_object_translate_two(space
,
1872 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1873 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1874 if (kr
!= KERN_SUCCESS
)
1877 /* obj and psobj are both locked (and were locked in that order) */
1878 assert(psobj
!= IO_NULL
);
1879 assert(obj
!= IO_NULL
);
1881 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1888 * task_set_port_space:
1890 * Set port name space of task to specified size.
1893 task_set_port_space(
1899 is_write_lock(space
);
1901 if (!space
->is_active
) {
1902 is_write_unlock(space
);
1903 return KERN_INVALID_TASK
;
1906 kr
= ipc_entry_grow_table(space
, table_entries
);
1907 if (kr
== KERN_SUCCESS
)
1908 is_write_unlock(space
);
1913 * Get a (new) label handle representing the given port's port label.
1915 #if CONFIG_MACF_MACH
1919 mach_port_name_t name
,
1920 mach_port_name_t
*outlabel
)
1928 if (!MACH_PORT_VALID(name
))
1929 return KERN_INVALID_NAME
;
1931 /* Lookup the port name in the task's space. */
1932 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1933 if (kr
!= KERN_SUCCESS
)
1936 port
= (ipc_port_t
) entry
->ie_object
;
1937 dead
= ipc_right_check(space
, port
, name
, entry
);
1939 is_write_unlock(space
);
1940 return KERN_INVALID_RIGHT
;
1942 /* port is now locked */
1944 is_write_unlock(space
);
1945 /* Make sure we are not dealing with a label handle. */
1946 if (ip_kotype(port
) == IKOT_LABELH
) {
1947 /* already is a label handle! */
1949 return KERN_INVALID_ARGUMENT
;
1952 /* Copy the port label and stash it in a new label handle. */
1953 mac_port_label_init(&outl
);
1954 mac_port_label_copy(&port
->ip_label
, &outl
);
1955 kr
= labelh_new_user(space
, &outl
, outlabel
);
1958 return KERN_SUCCESS
;
1963 __unused ipc_space_t space
,
1964 __unused mach_port_name_t name
,
1965 __unused mach_port_name_t
*outlabel
)
1967 return KERN_INVALID_ARGUMENT
;
1972 * also works on label handles
1974 #if CONFIG_MACF_MACH
1976 mach_get_label_text(
1978 mach_port_name_t name
,
1979 labelstr_t policies
,
1980 labelstr_t outlabel
)
1987 if (space
== IS_NULL
|| space
->is_task
== NULL
)
1988 return KERN_INVALID_TASK
;
1990 if (!MACH_PORT_VALID(name
))
1991 return KERN_INVALID_NAME
;
1993 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1994 if (kr
!= KERN_SUCCESS
)
1997 dead
= ipc_right_check(space
, (ipc_port_t
) entry
->ie_object
, name
,
2000 is_write_unlock(space
);
2001 return KERN_INVALID_RIGHT
;
2003 /* object (port) is now locked */
2005 is_write_unlock (space
);
2006 l
= io_getlabel(entry
->ie_object
);
2008 mac_port_label_externalize(l
, policies
, outlabel
, 512, 0);
2010 io_unlocklabel(entry
->ie_object
);
2011 io_unlock(entry
->ie_object
);
2012 return KERN_SUCCESS
;
2016 mach_get_label_text(
2017 __unused ipc_space_t space
,
2018 __unused mach_port_name_t name
,
2019 __unused labelstr_t policies
,
2020 __unused labelstr_t outlabel
)
2022 return KERN_INVALID_ARGUMENT
;
2027 #if CONFIG_MACF_MACH
2029 mach_set_port_label(
2031 mach_port_name_t name
,
2032 labelstr_t labelstr
)
2040 if (space
== IS_NULL
|| space
->is_task
== NULL
)
2041 return KERN_INVALID_TASK
;
2043 if (!MACH_PORT_VALID(name
))
2044 return KERN_INVALID_NAME
;
2046 mac_port_label_init(&inl
);
2047 rc
= mac_port_label_internalize(&inl
, labelstr
);
2049 return KERN_INVALID_ARGUMENT
;
2051 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2052 if (kr
!= KERN_SUCCESS
)
2055 if (io_otype(entMACry
->ie_object
) != IOT_PORT
) {
2056 is_write_unlock(space
);
2057 return KERN_INVALID_RIGHT
;
2060 port
= (ipc_port_t
) entry
->ie_object
;
2063 tasklabel_lock(space
->is_task
);
2064 rc
= mac_port_check_label_update(&space
->is_task
->maclabel
,
2065 &port
->ip_label
, &inl
);
2066 tasklabel_unlock(space
->is_task
);
2068 kr
= KERN_NO_ACCESS
;
2070 mac_port_label_copy(&inl
, &port
->ip_label
);
2073 is_write_unlock(space
);
2078 mach_set_port_label(
2079 ipc_space_t space __unused
,
2080 mach_port_name_t name __unused
,
2081 labelstr_t labelstr __unused
)
2083 return KERN_INVALID_ARGUMENT
;