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
)
225 ipc_entry_num_t tsize
;
226 mach_port_index_t index
;
227 ipc_entry_num_t actual
; /* this many names */
228 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
229 mach_port_name_t
*names
;
230 mach_port_type_t
*types
;
233 vm_size_t size
; /* size of allocated memory */
234 vm_offset_t addr1
; /* allocated memory, for names */
235 vm_offset_t addr2
; /* allocated memory, for types */
236 vm_map_copy_t memory1
; /* copied-in memory, for names */
237 vm_map_copy_t memory2
; /* copied-in memory, for types */
239 /* safe simplifying assumption */
240 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
242 if (space
== IS_NULL
)
243 return KERN_INVALID_TASK
;
248 ipc_entry_num_t bound
;
249 vm_size_t size_needed
;
252 if (!is_active(space
)) {
253 is_read_unlock(space
);
255 kmem_free(ipc_kernel_map
, addr1
, size
);
256 kmem_free(ipc_kernel_map
, addr2
, size
);
258 return KERN_INVALID_TASK
;
261 /* upper bound on number of names in the space */
262 bound
= space
->is_table_size
;
263 size_needed
= round_page(bound
* sizeof(mach_port_name_t
));
265 if (size_needed
<= size
)
268 is_read_unlock(space
);
271 kmem_free(ipc_kernel_map
, addr1
, size
);
272 kmem_free(ipc_kernel_map
, addr2
, size
);
276 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, VM_FLAGS_ANYWHERE
);
277 if (kr
!= KERN_SUCCESS
)
278 return KERN_RESOURCE_SHORTAGE
;
280 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, VM_FLAGS_ANYWHERE
);
281 if (kr
!= KERN_SUCCESS
) {
282 kmem_free(ipc_kernel_map
, addr1
, size
);
283 return KERN_RESOURCE_SHORTAGE
;
286 /* can't fault while we hold locks */
288 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
289 vm_map_round_page(addr1
+ size
),
290 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
291 if (kr
!= KERN_SUCCESS
) {
292 kmem_free(ipc_kernel_map
, addr1
, size
);
293 kmem_free(ipc_kernel_map
, addr2
, size
);
294 return KERN_RESOURCE_SHORTAGE
;
297 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
298 vm_map_round_page(addr2
+ size
),
299 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
300 if (kr
!= KERN_SUCCESS
) {
301 kmem_free(ipc_kernel_map
, addr1
, size
);
302 kmem_free(ipc_kernel_map
, addr2
, size
);
303 return KERN_RESOURCE_SHORTAGE
;
307 /* space is read-locked and active */
309 names
= (mach_port_name_t
*) addr1
;
310 types
= (mach_port_type_t
*) addr2
;
313 timestamp
= ipc_port_timestamp();
315 table
= space
->is_table
;
316 tsize
= space
->is_table_size
;
318 for (index
= 0; index
< tsize
; index
++) {
319 ipc_entry_t entry
= &table
[index
];
320 ipc_entry_bits_t bits
= entry
->ie_bits
;
322 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
323 mach_port_name_t name
;
325 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
326 mach_port_names_helper(timestamp
, entry
, name
, names
,
331 is_read_unlock(space
);
334 memory1
= VM_MAP_COPY_NULL
;
335 memory2
= VM_MAP_COPY_NULL
;
338 kmem_free(ipc_kernel_map
, addr1
, size
);
339 kmem_free(ipc_kernel_map
, addr2
, size
);
343 vm_size_t vm_size_used
;
345 size_used
= actual
* sizeof(mach_port_name_t
);
346 vm_size_used
= round_page(size_used
);
349 * Make used memory pageable and get it into
350 * copied-in form. Free any unused memory.
353 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
354 vm_map_round_page(addr1
+ vm_size_used
), FALSE
);
355 assert(kr
== KERN_SUCCESS
);
357 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
358 vm_map_round_page(addr2
+ vm_size_used
), FALSE
);
359 assert(kr
== KERN_SUCCESS
);
361 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr1
,
362 (vm_map_size_t
)size_used
, TRUE
, &memory1
);
363 assert(kr
== KERN_SUCCESS
);
365 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr2
,
366 (vm_map_size_t
)size_used
, TRUE
, &memory2
);
367 assert(kr
== KERN_SUCCESS
);
369 if (vm_size_used
!= size
) {
370 kmem_free(ipc_kernel_map
,
371 addr1
+ vm_size_used
, size
- vm_size_used
);
372 kmem_free(ipc_kernel_map
,
373 addr2
+ vm_size_used
, size
- vm_size_used
);
377 *namesp
= (mach_port_name_t
*) memory1
;
379 *typesp
= (mach_port_type_t
*) memory2
;
385 * Routine: mach_port_type [kernel call]
387 * Retrieves the type of a right in the space.
388 * The type is a bitwise combination of one or more
389 * of the following type bits:
390 * MACH_PORT_TYPE_SEND
391 * MACH_PORT_TYPE_RECEIVE
392 * MACH_PORT_TYPE_SEND_ONCE
393 * MACH_PORT_TYPE_PORT_SET
394 * MACH_PORT_TYPE_DEAD_NAME
395 * In addition, the following pseudo-type bits may be present:
396 * MACH_PORT_TYPE_DNREQUEST
397 * A dead-name notification is requested.
401 * KERN_SUCCESS Type is returned.
402 * KERN_INVALID_TASK The space is null.
403 * KERN_INVALID_TASK The space is dead.
404 * KERN_INVALID_NAME The name doesn't denote a right.
410 mach_port_name_t name
,
411 mach_port_type_t
*typep
)
413 mach_port_urefs_t urefs
;
417 if (space
== IS_NULL
)
418 return KERN_INVALID_TASK
;
420 if (name
== MACH_PORT_NULL
)
421 return KERN_INVALID_NAME
;
423 if (name
== MACH_PORT_DEAD
) {
424 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
428 kr
= ipc_right_lookup_write(space
, name
, &entry
);
429 if (kr
!= KERN_SUCCESS
)
432 /* space is write-locked and active */
433 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
434 /* space is unlocked */
437 /* JMM - workaround rdar://problem/9121297 (CF being too picky on these bits). */
438 *typep
&= ~(MACH_PORT_TYPE_SPREQUEST
| MACH_PORT_TYPE_SPREQUEST_DELAYED
);
445 * Routine: mach_port_rename [kernel call]
447 * Changes the name denoting a right,
448 * from oname to nname.
452 * KERN_SUCCESS The right is renamed.
453 * KERN_INVALID_TASK The space is null.
454 * KERN_INVALID_TASK The space is dead.
455 * KERN_INVALID_NAME The oname doesn't denote a right.
456 * KERN_INVALID_VALUE The nname isn't a legal name.
457 * KERN_NAME_EXISTS The nname already denotes a right.
458 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
460 * This interface is obsolete and always returns
461 * KERN_NOT_SUPPORTED.
466 __unused ipc_space_t space
,
467 __unused mach_port_name_t oname
,
468 __unused mach_port_name_t nname
)
470 return KERN_NOT_SUPPORTED
;
475 * Routine: mach_port_allocate_name [kernel call]
477 * Allocates a right in a space, using a specific name
478 * for the new right. Possible rights:
479 * MACH_PORT_RIGHT_RECEIVE
480 * MACH_PORT_RIGHT_PORT_SET
481 * MACH_PORT_RIGHT_DEAD_NAME
483 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
484 * has no extant send or send-once rights and no queued
485 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
486 * and its make-send count is 0. It is not a member of
487 * a port set. It has no registered no-senders or
488 * port-destroyed notification requests.
490 * A new port set has no members.
492 * A new dead name has one user reference.
496 * KERN_SUCCESS The right is allocated.
497 * KERN_INVALID_TASK The space is null.
498 * KERN_INVALID_TASK The space is dead.
499 * KERN_INVALID_VALUE The name isn't a legal name.
500 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
501 * KERN_NAME_EXISTS The name already denotes a right.
502 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
504 * Restrictions on name allocation: NT bits are reserved by kernel,
505 * must be set on any chosen name. Can't do this at all in kernel
510 mach_port_allocate_name(
512 mach_port_right_t right
,
513 mach_port_name_t name
)
516 mach_port_qos_t qos
= qos_template
;
520 if (!MACH_PORT_VALID(name
))
521 return KERN_INVALID_VALUE
;
523 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
529 * Routine: mach_port_allocate [kernel call]
531 * Allocates a right in a space. Like mach_port_allocate_name,
532 * except that the implementation picks a name for the right.
533 * The name may be any legal name in the space that doesn't
534 * currently denote a right.
538 * KERN_SUCCESS The right is allocated.
539 * KERN_INVALID_TASK The space is null.
540 * KERN_INVALID_TASK The space is dead.
541 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
542 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
543 * KERN_NO_SPACE No room in space for another right.
549 mach_port_right_t right
,
550 mach_port_name_t
*namep
)
553 mach_port_qos_t qos
= qos_template
;
555 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
561 * Routine: mach_port_allocate_qos [kernel call]
563 * Allocates a right, with qos options, in a space. Like
564 * mach_port_allocate_name, except that the implementation
565 * picks a name for the right. The name may be any legal name
566 * in the space that doesn't currently denote a right.
570 * KERN_SUCCESS The right is allocated.
571 * KERN_INVALID_TASK The space is null.
572 * KERN_INVALID_TASK The space is dead.
573 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
574 * KERN_INVALID_ARGUMENT The qos request was invalid.
575 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
576 * KERN_NO_SPACE No room in space for another right.
580 mach_port_allocate_qos(
582 mach_port_right_t right
,
583 mach_port_qos_t
*qosp
,
584 mach_port_name_t
*namep
)
589 return KERN_INVALID_ARGUMENT
;
590 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
596 * Routine: mach_port_allocate_full [kernel call]
598 * Allocates a right in a space. Supports all of the
599 * special cases, such as specifying a subsystem,
600 * a specific name, a real-time port, etc.
601 * The name may be any legal name in the space that doesn't
602 * currently denote a right.
606 * KERN_SUCCESS The right is allocated.
607 * KERN_INVALID_TASK The space is null.
608 * KERN_INVALID_TASK The space is dead.
609 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
610 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
611 * KERN_NO_SPACE No room in space for another right.
615 mach_port_allocate_full(
617 mach_port_right_t right
,
619 mach_port_qos_t
*qosp
,
620 mach_port_name_t
*namep
)
622 ipc_kmsg_t kmsg
= IKM_NULL
;
625 if (space
== IS_NULL
)
626 return (KERN_INVALID_TASK
);
628 if (proto
!= MACH_PORT_NULL
)
629 return (KERN_INVALID_VALUE
);
632 if (!MACH_PORT_VALID (*namep
))
633 return (KERN_INVALID_VALUE
);
636 if (qosp
->prealloc
) {
637 if (qosp
->len
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
) {
638 return KERN_RESOURCE_SHORTAGE
;
640 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
642 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
643 return (KERN_INVALID_VALUE
);
645 kmsg
= (ipc_kmsg_t
)ipc_kmsg_prealloc(size
);
646 if (kmsg
== IKM_NULL
)
647 return (KERN_RESOURCE_SHORTAGE
);
652 case MACH_PORT_RIGHT_RECEIVE
:
657 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
659 kr
= ipc_port_alloc(space
, namep
, &port
);
660 if (kr
== KERN_SUCCESS
) {
661 if (kmsg
!= IKM_NULL
)
662 ipc_kmsg_set_prealloc(kmsg
, port
);
666 } else if (kmsg
!= IKM_NULL
)
671 case MACH_PORT_RIGHT_PORT_SET
:
676 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
678 kr
= ipc_pset_alloc(space
, namep
, &pset
);
679 if (kr
== KERN_SUCCESS
)
684 case MACH_PORT_RIGHT_DEAD_NAME
:
685 kr
= ipc_object_alloc_dead(space
, namep
);
689 kr
= KERN_INVALID_VALUE
;
697 * Routine: mach_port_destroy [kernel call]
699 * Cleans up and destroys all rights denoted by a name
700 * in a space. The destruction of a receive right
701 * destroys the port, unless a port-destroyed request
702 * has been made for it; the destruction of a port-set right
703 * destroys the port set.
707 * KERN_SUCCESS The name is destroyed.
708 * KERN_INVALID_TASK The space is null.
709 * KERN_INVALID_TASK The space is dead.
710 * KERN_INVALID_NAME The name doesn't denote a right.
716 mach_port_name_t name
)
721 if (space
== IS_NULL
)
722 return KERN_INVALID_TASK
;
724 if (!MACH_PORT_VALID(name
))
727 kr
= ipc_right_lookup_write(space
, name
, &entry
);
728 if (kr
!= KERN_SUCCESS
)
730 /* space is write-locked and active */
732 kr
= ipc_right_destroy(space
, name
, entry
); /* unlocks space */
737 * Routine: mach_port_deallocate [kernel call]
739 * Deallocates a user reference from a send right,
740 * send-once right, or a dead-name right. May
741 * deallocate the right, if this is the last uref,
742 * and destroy the name, if it doesn't denote
747 * KERN_SUCCESS The uref is deallocated.
748 * KERN_INVALID_TASK The space is null.
749 * KERN_INVALID_TASK The space is dead.
750 * KERN_INVALID_NAME The name doesn't denote a right.
751 * KERN_INVALID_RIGHT The right isn't correct.
755 mach_port_deallocate(
757 mach_port_name_t name
)
762 if (space
== IS_NULL
)
763 return KERN_INVALID_TASK
;
765 if (!MACH_PORT_VALID(name
))
768 kr
= ipc_right_lookup_write(space
, name
, &entry
);
769 if (kr
!= KERN_SUCCESS
)
771 /* space is write-locked */
773 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
778 * Routine: mach_port_get_refs [kernel call]
780 * Retrieves the number of user references held by a right.
781 * Receive rights, port-set rights, and send-once rights
782 * always have one user reference. Returns zero if the
783 * name denotes a right, but not the queried right.
787 * KERN_SUCCESS Number of urefs returned.
788 * KERN_INVALID_TASK The space is null.
789 * KERN_INVALID_TASK The space is dead.
790 * KERN_INVALID_VALUE "right" isn't a legal value.
791 * KERN_INVALID_NAME The name doesn't denote a right.
797 mach_port_name_t name
,
798 mach_port_right_t right
,
799 mach_port_urefs_t
*urefsp
)
801 mach_port_type_t type
;
802 mach_port_urefs_t urefs
;
806 if (space
== IS_NULL
)
807 return KERN_INVALID_TASK
;
809 if (right
>= MACH_PORT_RIGHT_NUMBER
)
810 return KERN_INVALID_VALUE
;
812 if (!MACH_PORT_VALID(name
)) {
813 if (right
== MACH_PORT_RIGHT_SEND
||
814 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
818 return KERN_INVALID_NAME
;
821 kr
= ipc_right_lookup_write(space
, name
, &entry
);
822 if (kr
!= KERN_SUCCESS
)
825 /* space is write-locked and active */
826 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
);
827 /* space is unlocked */
829 if (kr
!= KERN_SUCCESS
)
832 if (type
& MACH_PORT_TYPE(right
))
834 case MACH_PORT_RIGHT_SEND_ONCE
:
838 case MACH_PORT_RIGHT_PORT_SET
:
839 case MACH_PORT_RIGHT_RECEIVE
:
843 case MACH_PORT_RIGHT_DEAD_NAME
:
844 case MACH_PORT_RIGHT_SEND
:
850 panic("mach_port_get_refs: strange rights");
859 * Routine: mach_port_mod_refs
861 * Modifies the number of user references held by a right.
862 * The resulting number of user references must be non-negative.
863 * If it is zero, the right is deallocated. If the name
864 * doesn't denote other rights, it is destroyed.
868 * KERN_SUCCESS Modified number of urefs.
869 * KERN_INVALID_TASK The space is null.
870 * KERN_INVALID_TASK The space is dead.
871 * KERN_INVALID_VALUE "right" isn't a legal value.
872 * KERN_INVALID_NAME The name doesn't denote a right.
873 * KERN_INVALID_RIGHT Name doesn't denote specified right.
874 * KERN_INVALID_VALUE Impossible modification to urefs.
875 * KERN_UREFS_OVERFLOW Urefs would overflow.
881 mach_port_name_t name
,
882 mach_port_right_t right
,
883 mach_port_delta_t delta
)
888 if (space
== IS_NULL
)
889 return KERN_INVALID_TASK
;
891 if (right
>= MACH_PORT_RIGHT_NUMBER
)
892 return KERN_INVALID_VALUE
;
894 if (!MACH_PORT_VALID(name
)) {
895 if (right
== MACH_PORT_RIGHT_SEND
||
896 right
== MACH_PORT_RIGHT_SEND_ONCE
)
898 return KERN_INVALID_NAME
;
901 kr
= ipc_right_lookup_write(space
, name
, &entry
);
902 if (kr
!= KERN_SUCCESS
)
904 /* space is write-locked and active */
906 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
912 * Routine: mach_port_set_mscount [kernel call]
914 * Changes a receive right's make-send count.
918 * KERN_SUCCESS Set make-send count.
919 * KERN_INVALID_TASK The space is null.
920 * KERN_INVALID_TASK The space is dead.
921 * KERN_INVALID_NAME The name doesn't denote a right.
922 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
926 mach_port_set_mscount(
928 mach_port_name_t name
,
929 mach_port_mscount_t mscount
)
934 if (space
== IS_NULL
)
935 return KERN_INVALID_TASK
;
937 if (!MACH_PORT_VALID(name
))
938 return KERN_INVALID_RIGHT
;
940 kr
= ipc_port_translate_receive(space
, name
, &port
);
941 if (kr
!= KERN_SUCCESS
)
943 /* port is locked and active */
945 ipc_port_set_mscount(port
, mscount
);
952 * Routine: mach_port_set_seqno [kernel call]
954 * Changes a receive right's sequence number.
958 * KERN_SUCCESS Set sequence number.
959 * KERN_INVALID_TASK The space is null.
960 * KERN_INVALID_TASK The space is dead.
961 * KERN_INVALID_NAME The name doesn't denote a right.
962 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
968 mach_port_name_t name
,
969 mach_port_seqno_t seqno
)
974 if (space
== IS_NULL
)
975 return KERN_INVALID_TASK
;
977 if (!MACH_PORT_VALID(name
))
978 return KERN_INVALID_RIGHT
;
980 kr
= ipc_port_translate_receive(space
, name
, &port
);
981 if (kr
!= KERN_SUCCESS
)
983 /* port is locked and active */
985 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
992 * Routine: mach_port_get_context [kernel call]
994 * Returns a receive right's context pointer.
998 * KERN_SUCCESS Set context pointer.
999 * KERN_INVALID_TASK The space is null.
1000 * KERN_INVALID_TASK The space is dead.
1001 * KERN_INVALID_NAME The name doesn't denote a right.
1002 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1006 mach_port_get_context(
1008 mach_port_name_t name
,
1009 mach_vm_address_t
*context
)
1014 if (space
== IS_NULL
)
1015 return KERN_INVALID_TASK
;
1017 if (!MACH_PORT_VALID(name
))
1018 return KERN_INVALID_RIGHT
;
1020 kr
= ipc_port_translate_receive(space
, name
, &port
);
1021 if (kr
!= KERN_SUCCESS
)
1024 /* port is locked and active */
1025 *context
= port
->ip_context
;
1028 return KERN_SUCCESS
;
1033 * Routine: mach_port_set_context [kernel call]
1035 * Changes a receive right's context pointer.
1039 * KERN_SUCCESS Set context pointer.
1040 * KERN_INVALID_TASK The space is null.
1041 * KERN_INVALID_TASK The space is dead.
1042 * KERN_INVALID_NAME The name doesn't denote a right.
1043 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1047 mach_port_set_context(
1049 mach_port_name_t name
,
1050 mach_vm_address_t context
)
1055 if (space
== IS_NULL
)
1056 return KERN_INVALID_TASK
;
1058 if (!MACH_PORT_VALID(name
))
1059 return KERN_INVALID_RIGHT
;
1061 kr
= ipc_port_translate_receive(space
, name
, &port
);
1062 if (kr
!= KERN_SUCCESS
)
1065 /* port is locked and active */
1066 port
->ip_context
= context
;
1069 return KERN_SUCCESS
;
1074 * Routine: mach_port_gst_helper
1076 * portspace is locked for both the recieve right and pset
1077 * under observation.
1079 * A helper function for mach_port_get_set_status.
1083 mach_port_gst_helper(
1086 ipc_entry_num_t maxnames
,
1087 mach_port_name_t
*names
,
1088 ipc_entry_num_t
*actualp
)
1090 mach_port_name_t name
;
1092 assert(port
!= IP_NULL
);
1094 * The space lock is held by the calling function,
1095 * hence it is OK to read name without the port lock.
1097 assert(ip_active(port
));
1098 name
= port
->ip_receiver_name
;
1099 assert(name
!= MACH_PORT_NULL
);
1101 if (ipc_pset_member(pset
, port
)) {
1102 ipc_entry_num_t actual
= *actualp
;
1104 if (actual
< maxnames
)
1105 names
[actual
] = name
;
1107 *actualp
= actual
+1;
1112 * Routine: mach_port_get_set_status [kernel call]
1114 * Retrieves a list of members in a port set.
1115 * Returns the space's name for each receive right member.
1119 * KERN_SUCCESS Retrieved list of members.
1120 * KERN_INVALID_TASK The space is null.
1121 * KERN_INVALID_TASK The space is dead.
1122 * KERN_INVALID_NAME The name doesn't denote a right.
1123 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1124 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1128 mach_port_get_set_status(
1130 mach_port_name_t name
,
1131 mach_port_name_t
**members
,
1132 mach_msg_type_number_t
*membersCnt
)
1134 ipc_entry_num_t actual
; /* this many members */
1135 ipc_entry_num_t maxnames
; /* space for this many members */
1138 vm_size_t size
; /* size of allocated memory */
1139 vm_offset_t addr
; /* allocated memory */
1140 vm_map_copy_t memory
; /* copied-in memory */
1142 if (space
== IS_NULL
)
1143 return KERN_INVALID_TASK
;
1145 if (!MACH_PORT_VALID(name
))
1146 return KERN_INVALID_RIGHT
;
1148 size
= PAGE_SIZE
; /* initial guess */
1151 ipc_entry_t entry
, table
;
1152 ipc_entry_num_t tsize
;
1153 mach_port_index_t index
;
1154 mach_port_name_t
*names
;
1157 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, VM_FLAGS_ANYWHERE
);
1158 if (kr
!= KERN_SUCCESS
)
1159 return KERN_RESOURCE_SHORTAGE
;
1161 /* can't fault while we hold locks */
1163 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1164 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1165 assert(kr
== KERN_SUCCESS
);
1167 kr
= ipc_right_lookup_read(space
, name
, &entry
);
1168 if (kr
!= KERN_SUCCESS
) {
1169 kmem_free(ipc_kernel_map
, addr
, size
);
1172 /* space is read-locked and active */
1174 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_PORT_SET
) {
1175 is_read_unlock(space
);
1176 kmem_free(ipc_kernel_map
, addr
, size
);
1177 return KERN_INVALID_RIGHT
;
1180 pset
= (ipc_pset_t
) entry
->ie_object
;
1181 assert(pset
!= IPS_NULL
);
1182 /* the port set must be active */
1184 names
= (mach_port_name_t
*) addr
;
1185 maxnames
= (ipc_entry_num_t
)(size
/ sizeof(mach_port_name_t
));
1188 table
= space
->is_table
;
1189 tsize
= space
->is_table_size
;
1191 for (index
= 0; index
< tsize
; index
++) {
1192 ipc_entry_t ientry
= &table
[index
];
1194 if (ientry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) {
1196 (ipc_port_t
) ientry
->ie_object
;
1198 mach_port_gst_helper(pset
, port
,
1199 maxnames
, names
, &actual
);
1203 is_read_unlock(space
);
1205 if (actual
<= maxnames
)
1208 /* didn't have enough memory; allocate more */
1210 kmem_free(ipc_kernel_map
, addr
, size
);
1211 size
= round_page(actual
* sizeof(mach_port_name_t
)) + PAGE_SIZE
;
1215 memory
= VM_MAP_COPY_NULL
;
1217 kmem_free(ipc_kernel_map
, addr
, size
);
1219 vm_size_t size_used
;
1220 vm_size_t vm_size_used
;
1222 size_used
= actual
* sizeof(mach_port_name_t
);
1223 vm_size_used
= round_page(size_used
);
1226 * Make used memory pageable and get it into
1227 * copied-in form. Free any unused memory.
1230 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr
),
1231 vm_map_round_page(addr
+ vm_size_used
), FALSE
);
1232 assert(kr
== KERN_SUCCESS
);
1234 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr
,
1235 (vm_map_size_t
)size_used
, TRUE
, &memory
);
1236 assert(kr
== KERN_SUCCESS
);
1238 if (vm_size_used
!= size
)
1239 kmem_free(ipc_kernel_map
,
1240 addr
+ vm_size_used
, size
- vm_size_used
);
1243 *members
= (mach_port_name_t
*) memory
;
1244 *membersCnt
= actual
;
1245 return KERN_SUCCESS
;
1249 * Routine: mach_port_move_member [kernel call]
1251 * If after is MACH_PORT_NULL, removes member
1252 * from the port set it is in. Otherwise, adds
1253 * member to after, removing it from any set
1254 * it might already be in.
1258 * KERN_SUCCESS Moved the port.
1259 * KERN_INVALID_TASK The space is null.
1260 * KERN_INVALID_TASK The space is dead.
1261 * KERN_INVALID_NAME Member didn't denote a right.
1262 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1263 * KERN_INVALID_NAME After didn't denote a right.
1264 * KERN_INVALID_RIGHT After didn't denote a port set right.
1266 * After is MACH_PORT_NULL and Member isn't in a port set.
1270 mach_port_move_member(
1272 mach_port_name_t member
,
1273 mach_port_name_t after
)
1279 wait_queue_link_t wql
;
1280 queue_head_t links_data
;
1281 queue_t links
= &links_data
;
1283 if (space
== IS_NULL
)
1284 return KERN_INVALID_TASK
;
1286 if (!MACH_PORT_VALID(member
))
1287 return KERN_INVALID_RIGHT
;
1289 if (after
== MACH_PORT_DEAD
)
1290 return KERN_INVALID_RIGHT
;
1291 else if (after
== MACH_PORT_NULL
)
1292 wql
= WAIT_QUEUE_LINK_NULL
;
1294 wql
= wait_queue_link_allocate();
1298 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1299 if (kr
!= KERN_SUCCESS
)
1301 /* space is read-locked and active */
1303 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1304 is_read_unlock(space
);
1305 kr
= KERN_INVALID_RIGHT
;
1309 port
= (ipc_port_t
) entry
->ie_object
;
1310 assert(port
!= IP_NULL
);
1312 if (after
== MACH_PORT_NULL
)
1315 entry
= ipc_entry_lookup(space
, after
);
1316 if (entry
== IE_NULL
) {
1317 is_read_unlock(space
);
1318 kr
= KERN_INVALID_NAME
;
1322 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1323 is_read_unlock(space
);
1324 kr
= KERN_INVALID_RIGHT
;
1328 nset
= (ipc_pset_t
) entry
->ie_object
;
1329 assert(nset
!= IPS_NULL
);
1332 ipc_pset_remove_from_all(port
, links
);
1334 if (nset
!= IPS_NULL
) {
1336 kr
= ipc_pset_add(nset
, port
, wql
);
1340 is_read_unlock(space
);
1343 if (kr
!= KERN_SUCCESS
&& wql
!= WAIT_QUEUE_LINK_NULL
)
1344 wait_queue_link_free(wql
);
1345 while(!queue_empty(links
)) {
1346 wql
= (wait_queue_link_t
) dequeue(links
);
1347 wait_queue_link_free(wql
);
1354 * Routine: mach_port_request_notification [kernel call]
1356 * Requests a notification. The caller supplies
1357 * a send-once right for the notification to use,
1358 * and the call returns the previously registered
1359 * send-once right, if any. Possible types:
1361 * MACH_NOTIFY_PORT_DESTROYED
1362 * Requests a port-destroyed notification
1363 * for a receive right. Sync should be zero.
1364 * MACH_NOTIFY_NO_SENDERS
1365 * Requests a no-senders notification for a
1366 * receive right. If there are currently no
1367 * senders, sync is less than or equal to the
1368 * current make-send count, and a send-once right
1369 * is supplied, then an immediate no-senders
1370 * notification is generated.
1371 * MACH_NOTIFY_DEAD_NAME
1372 * Requests a dead-name notification for a send
1373 * or receive right. If the name is already a
1374 * dead name, sync is non-zero, and a send-once
1375 * right is supplied, then an immediate dead-name
1376 * notification is generated.
1380 * KERN_SUCCESS Requested a notification.
1381 * KERN_INVALID_TASK The space is null.
1382 * KERN_INVALID_TASK The space is dead.
1383 * KERN_INVALID_VALUE Bad id value.
1384 * KERN_INVALID_NAME Name doesn't denote a right.
1385 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1386 * KERN_INVALID_CAPABILITY The notify port is dead.
1387 * MACH_NOTIFY_PORT_DESTROYED:
1388 * KERN_INVALID_VALUE Sync isn't zero.
1389 * MACH_NOTIFY_DEAD_NAME:
1390 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1391 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1392 * sync is zero or notify is IP_NULL.
1393 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1394 * generating immediate notif. would overflow urefs.
1398 mach_port_request_notification(
1400 mach_port_name_t name
,
1402 mach_port_mscount_t sync
,
1404 ipc_port_t
*previousp
)
1408 if (space
== IS_NULL
)
1409 return KERN_INVALID_TASK
;
1411 if (notify
== IP_DEAD
)
1412 return KERN_INVALID_CAPABILITY
;
1416 * Requesting notifications on RPC ports is an error.
1422 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1423 if (kr
!= KERN_SUCCESS
)
1426 port
= (ipc_port_t
) entry
->ie_object
;
1428 if (port
->ip_subsystem
!= NULL
) {
1429 is_write_unlock(space
);
1430 panic("mach_port_request_notification: on RPC port!!");
1431 return KERN_INVALID_CAPABILITY
;
1433 is_write_unlock(space
);
1439 case MACH_NOTIFY_PORT_DESTROYED
: {
1440 ipc_port_t port
, previous
;
1443 return KERN_INVALID_VALUE
;
1445 if (!MACH_PORT_VALID(name
))
1446 return KERN_INVALID_RIGHT
;
1448 kr
= ipc_port_translate_receive(space
, name
, &port
);
1449 if (kr
!= KERN_SUCCESS
)
1451 /* port is locked and active */
1453 ipc_port_pdrequest(port
, notify
, &previous
);
1454 /* port is unlocked */
1456 *previousp
= previous
;
1460 case MACH_NOTIFY_NO_SENDERS
: {
1463 if (!MACH_PORT_VALID(name
))
1464 return KERN_INVALID_RIGHT
;
1466 kr
= ipc_port_translate_receive(space
, name
, &port
);
1467 if (kr
!= KERN_SUCCESS
)
1469 /* port is locked and active */
1471 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1472 /* port is unlocked */
1476 case MACH_NOTIFY_SEND_POSSIBLE
:
1478 if (!MACH_PORT_VALID(name
)) {
1479 return KERN_INVALID_ARGUMENT
;
1482 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1483 TRUE
, notify
, previousp
);
1484 if (kr
!= KERN_SUCCESS
)
1488 case MACH_NOTIFY_DEAD_NAME
:
1490 if (!MACH_PORT_VALID(name
)) {
1493 * Should do immediate delivery check -
1494 * will do that in the near future.
1496 return KERN_INVALID_ARGUMENT
;
1499 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1500 FALSE
, notify
, previousp
);
1501 if (kr
!= KERN_SUCCESS
)
1506 return KERN_INVALID_VALUE
;
1509 return KERN_SUCCESS
;
1513 * Routine: mach_port_insert_right [kernel call]
1515 * Inserts a right into a space, as if the space
1516 * voluntarily received the right in a message,
1517 * except that the right gets the specified name.
1521 * KERN_SUCCESS Inserted the right.
1522 * KERN_INVALID_TASK The space is null.
1523 * KERN_INVALID_TASK The space is dead.
1524 * KERN_INVALID_VALUE The name isn't a legal name.
1525 * KERN_NAME_EXISTS The name already denotes a right.
1526 * KERN_INVALID_VALUE Message doesn't carry a port right.
1527 * KERN_INVALID_CAPABILITY Port is null or dead.
1528 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1529 * KERN_RIGHT_EXISTS Space has rights under another name.
1530 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1534 mach_port_insert_right(
1536 mach_port_name_t name
,
1538 mach_msg_type_name_t polyPoly
)
1540 if (space
== IS_NULL
)
1541 return KERN_INVALID_TASK
;
1543 if (!MACH_PORT_VALID(name
) ||
1544 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1545 return KERN_INVALID_VALUE
;
1547 if (!IO_VALID((ipc_object_t
) poly
))
1548 return KERN_INVALID_CAPABILITY
;
1550 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1551 polyPoly
, FALSE
, name
);
1555 * Routine: mach_port_extract_right [kernel call]
1557 * Extracts a right from a space, as if the space
1558 * voluntarily sent the right to the caller.
1562 * KERN_SUCCESS Extracted the right.
1563 * KERN_INVALID_TASK The space is null.
1564 * KERN_INVALID_TASK The space is dead.
1565 * KERN_INVALID_VALUE Requested type isn't a port right.
1566 * KERN_INVALID_NAME Name doesn't denote a right.
1567 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1571 mach_port_extract_right(
1573 mach_port_name_t name
,
1574 mach_msg_type_name_t msgt_name
,
1576 mach_msg_type_name_t
*polyPoly
)
1580 if (space
== IS_NULL
)
1581 return KERN_INVALID_TASK
;
1583 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1584 return KERN_INVALID_VALUE
;
1586 if (!MACH_PORT_VALID(name
)) {
1588 * really should copy out a dead name, if it is a send or
1589 * send-once right being copied, but instead return an
1592 return KERN_INVALID_RIGHT
;
1595 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1597 if (kr
== KERN_SUCCESS
)
1598 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1604 mach_port_get_attributes(
1606 mach_port_name_t name
,
1608 mach_port_info_t info
,
1609 mach_msg_type_number_t
*count
)
1614 if (space
== IS_NULL
)
1615 return KERN_INVALID_TASK
;
1618 case MACH_PORT_LIMITS_INFO
: {
1619 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1621 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1622 return KERN_FAILURE
;
1624 if (!MACH_PORT_VALID(name
)) {
1629 kr
= ipc_port_translate_receive(space
, name
, &port
);
1630 if (kr
!= KERN_SUCCESS
)
1632 /* port is locked and active */
1634 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1635 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1640 case MACH_PORT_RECEIVE_STATUS
: {
1641 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1644 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1645 return KERN_FAILURE
;
1647 if (!MACH_PORT_VALID(name
))
1648 return KERN_INVALID_RIGHT
;
1650 kr
= ipc_port_translate_receive(space
, name
, &port
);
1651 if (kr
!= KERN_SUCCESS
)
1653 /* port is locked and active */
1655 statusp
->mps_pset
= port
->ip_pset_count
;
1658 imq_lock(&port
->ip_messages
);
1659 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1660 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1661 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1662 imq_unlock(&port
->ip_messages
);
1665 statusp
->mps_mscount
= port
->ip_mscount
;
1666 statusp
->mps_sorights
= port
->ip_sorights
;
1667 statusp
->mps_srights
= port
->ip_srights
> 0;
1668 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1669 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1670 statusp
->mps_flags
= 0;
1672 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1677 case MACH_PORT_DNREQUESTS_SIZE
: {
1678 ipc_port_request_t table
;
1680 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1681 return KERN_FAILURE
;
1683 if (!MACH_PORT_VALID(name
)) {
1688 kr
= ipc_port_translate_receive(space
, name
, &port
);
1689 if (kr
!= KERN_SUCCESS
)
1691 /* port is locked and active */
1693 table
= port
->ip_requests
;
1694 if (table
== IPR_NULL
)
1697 *(int *)info
= table
->ipr_size
->its_size
;
1698 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1704 return KERN_INVALID_ARGUMENT
;
1708 return KERN_SUCCESS
;
1712 mach_port_set_attributes(
1714 mach_port_name_t name
,
1716 mach_port_info_t info
,
1717 mach_msg_type_number_t count
)
1722 if (space
== IS_NULL
)
1723 return KERN_INVALID_TASK
;
1727 case MACH_PORT_LIMITS_INFO
: {
1728 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1730 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1731 return KERN_FAILURE
;
1733 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1734 return KERN_INVALID_VALUE
;
1736 if (!MACH_PORT_VALID(name
))
1737 return KERN_INVALID_RIGHT
;
1739 kr
= ipc_port_translate_receive(space
, name
, &port
);
1740 if (kr
!= KERN_SUCCESS
)
1742 /* port is locked and active */
1744 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1748 case MACH_PORT_DNREQUESTS_SIZE
: {
1749 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1750 return KERN_FAILURE
;
1752 if (!MACH_PORT_VALID(name
))
1753 return KERN_INVALID_RIGHT
;
1755 kr
= ipc_port_translate_receive(space
, name
, &port
);
1756 if (kr
!= KERN_SUCCESS
)
1758 /* port is locked and active */
1760 kr
= ipc_port_request_grow(port
, *(int *)info
);
1761 if (kr
!= KERN_SUCCESS
)
1766 return KERN_INVALID_ARGUMENT
;
1769 return KERN_SUCCESS
;
1773 * Routine: mach_port_insert_member [kernel call]
1775 * Add the receive right, specified by name, to
1777 * The port cannot already be a member of the set.
1781 * KERN_SUCCESS Moved the port.
1782 * KERN_INVALID_TASK The space is null.
1783 * KERN_INVALID_TASK The space is dead.
1784 * KERN_INVALID_NAME name didn't denote a right.
1785 * KERN_INVALID_RIGHT name didn't denote a receive right.
1786 * KERN_INVALID_NAME pset_name didn't denote a right.
1787 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1788 * KERN_ALREADY_IN_SET name was already a member of pset.
1792 mach_port_insert_member(
1794 mach_port_name_t name
,
1795 mach_port_name_t psname
)
1800 wait_queue_link_t wql
;
1802 if (space
== IS_NULL
)
1803 return KERN_INVALID_TASK
;
1805 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1806 return KERN_INVALID_RIGHT
;
1808 wql
= wait_queue_link_allocate();
1810 kr
= ipc_object_translate_two(space
,
1811 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1812 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1813 if (kr
!= KERN_SUCCESS
)
1816 /* obj and psobj are locked (and were locked in that order) */
1817 assert(psobj
!= IO_NULL
);
1818 assert(obj
!= IO_NULL
);
1820 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
, wql
);
1825 if (kr
!= KERN_SUCCESS
)
1826 wait_queue_link_free(wql
);
1832 * Routine: mach_port_extract_member [kernel call]
1834 * Remove a port from one portset that it is a member of.
1838 * KERN_SUCCESS Moved the port.
1839 * KERN_INVALID_TASK The space is null.
1840 * KERN_INVALID_TASK The space is dead.
1841 * KERN_INVALID_NAME Member didn't denote a right.
1842 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1843 * KERN_INVALID_NAME After didn't denote a right.
1844 * KERN_INVALID_RIGHT After didn't denote a port set right.
1846 * After is MACH_PORT_NULL and Member isn't in a port set.
1850 mach_port_extract_member(
1852 mach_port_name_t name
,
1853 mach_port_name_t psname
)
1858 wait_queue_link_t wql
= WAIT_QUEUE_LINK_NULL
;
1860 if (space
== IS_NULL
)
1861 return KERN_INVALID_TASK
;
1863 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1864 return KERN_INVALID_RIGHT
;
1866 kr
= ipc_object_translate_two(space
,
1867 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1868 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1869 if (kr
!= KERN_SUCCESS
)
1872 /* obj and psobj are both locked (and were locked in that order) */
1873 assert(psobj
!= IO_NULL
);
1874 assert(obj
!= IO_NULL
);
1876 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
, &wql
);
1880 if (wql
!= WAIT_QUEUE_LINK_NULL
)
1881 wait_queue_link_free(wql
);
1887 * task_set_port_space:
1889 * Set port name space of task to specified size.
1892 task_set_port_space(
1898 is_write_lock(space
);
1900 if (!is_active(space
)) {
1901 is_write_unlock(space
);
1902 return KERN_INVALID_TASK
;
1905 kr
= ipc_entry_grow_table(space
, table_entries
);
1906 if (kr
== KERN_SUCCESS
)
1907 is_write_unlock(space
);
1912 * Get a (new) label handle representing the given port's port label.
1914 #if CONFIG_MACF_MACH
1918 mach_port_name_t name
,
1919 mach_port_name_t
*outlabel
)
1927 if (!MACH_PORT_VALID(name
))
1928 return KERN_INVALID_NAME
;
1930 /* Lookup the port name in the task's space. */
1931 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1932 if (kr
!= KERN_SUCCESS
)
1935 port
= (ipc_port_t
) entry
->ie_object
;
1936 dead
= ipc_right_check(space
, port
, name
, entry
);
1938 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
)
1988 if (space
== IS_NULL
|| space
->is_task
== NULL
)
1989 return KERN_INVALID_TASK
;
1991 if (!MACH_PORT_VALID(name
))
1992 return KERN_INVALID_NAME
;
1994 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1995 if (kr
!= KERN_SUCCESS
)
1998 port
= (ipc_port_t
)entry
->ie_object
;
1999 dead
= ipc_right_check(space
, port
, name
, entry
);
2001 is_write_unlock(space
);
2003 return KERN_INVALID_RIGHT
;
2005 /* object (port) is now locked */
2007 is_write_unlock (space
);
2008 l
= io_getlabel(entry
->ie_object
);
2010 mac_port_label_externalize(l
, policies
, outlabel
, 512, 0);
2012 io_unlocklabel(entry
->ie_object
);
2013 io_unlock(entry
->ie_object
);
2014 return KERN_SUCCESS
;
2018 mach_get_label_text(
2019 __unused ipc_space_t space
,
2020 __unused mach_port_name_t name
,
2021 __unused labelstr_t policies
,
2022 __unused labelstr_t outlabel
)
2024 return KERN_INVALID_ARGUMENT
;
2029 #if CONFIG_MACF_MACH
2031 mach_set_port_label(
2033 mach_port_name_t name
,
2034 labelstr_t labelstr
)
2042 if (space
== IS_NULL
|| space
->is_task
== NULL
)
2043 return KERN_INVALID_TASK
;
2045 if (!MACH_PORT_VALID(name
))
2046 return KERN_INVALID_NAME
;
2048 mac_port_label_init(&inl
);
2049 rc
= mac_port_label_internalize(&inl
, labelstr
);
2051 return KERN_INVALID_ARGUMENT
;
2053 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2054 if (kr
!= KERN_SUCCESS
)
2057 if (io_otype(entMACry
->ie_object
) != IOT_PORT
) {
2058 is_write_unlock(space
);
2059 return KERN_INVALID_RIGHT
;
2062 port
= (ipc_port_t
) entry
->ie_object
;
2065 tasklabel_lock(space
->is_task
);
2066 rc
= mac_port_check_label_update(&space
->is_task
->maclabel
,
2067 &port
->ip_label
, &inl
);
2068 tasklabel_unlock(space
->is_task
);
2070 kr
= KERN_NO_ACCESS
;
2072 mac_port_label_copy(&inl
, &port
->ip_label
);
2075 is_write_unlock(space
);
2080 mach_set_port_label(
2081 ipc_space_t space __unused
,
2082 mach_port_name_t name __unused
,
2083 labelstr_t labelstr __unused
)
2085 return KERN_INVALID_ARGUMENT
;