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.
134 mach_port_names_helper(
135 ipc_port_timestamp_t timestamp
,
137 mach_port_name_t name
,
138 mach_port_name_t
*names
,
139 mach_port_type_t
*types
,
140 ipc_entry_num_t
*actualp
)
142 ipc_entry_bits_t bits
;
143 ipc_port_request_index_t request
;
144 mach_port_type_t type
;
145 ipc_entry_num_t actual
;
147 bits
= entry
->ie_bits
;
148 request
= entry
->ie_request
;
149 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
153 port
= (ipc_port_t
) entry
->ie_object
;
154 assert(port
!= IP_NULL
);
157 * The timestamp serializes mach_port_names
158 * with ipc_port_destroy. If the port died,
159 * but after mach_port_names started, pretend
160 * that it isn't dead.
164 died
= (!ip_active(port
) &&
165 IP_TIMESTAMP_ORDER(port
->ip_timestamp
, timestamp
));
169 /* pretend this is a dead-name entry */
171 bits
&= ~(IE_BITS_TYPE_MASK
);
172 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
179 type
= IE_BITS_TYPE(bits
);
181 type
|= MACH_PORT_TYPE_DNREQUEST
;
184 names
[actual
] = name
;
185 types
[actual
] = type
;
190 * Routine: mach_port_names [kernel call]
192 * Retrieves a list of the rights present in the space,
193 * along with type information. (Same as returned
194 * by mach_port_type.) The names are returned in
195 * no particular order, but they (and the type info)
196 * are an accurate snapshot of the space.
200 * KERN_SUCCESS Arrays of names and types returned.
201 * KERN_INVALID_TASK The space is null.
202 * KERN_INVALID_TASK The space is dead.
203 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
209 mach_port_name_t
**namesp
,
210 mach_msg_type_number_t
*namesCnt
,
211 mach_port_type_t
**typesp
,
212 mach_msg_type_number_t
*typesCnt
)
214 ipc_tree_entry_t tentry
;
216 ipc_entry_num_t tsize
;
217 mach_port_index_t index
;
218 ipc_entry_num_t actual
; /* this many names */
219 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
220 mach_port_name_t
*names
;
221 mach_port_type_t
*types
;
224 vm_size_t size
; /* size of allocated memory */
225 vm_offset_t addr1
; /* allocated memory, for names */
226 vm_offset_t addr2
; /* allocated memory, for types */
227 vm_map_copy_t memory1
; /* copied-in memory, for names */
228 vm_map_copy_t memory2
; /* copied-in memory, for types */
230 /* safe simplifying assumption */
231 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
233 if (space
== IS_NULL
)
234 return KERN_INVALID_TASK
;
239 ipc_entry_num_t bound
;
240 vm_size_t size_needed
;
243 if (!space
->is_active
) {
244 is_read_unlock(space
);
246 kmem_free(ipc_kernel_map
, addr1
, size
);
247 kmem_free(ipc_kernel_map
, addr2
, size
);
249 return KERN_INVALID_TASK
;
252 /* upper bound on number of names in the space */
254 bound
= space
->is_table_size
+ space
->is_tree_total
;
255 size_needed
= round_page(bound
* sizeof(mach_port_name_t
));
257 if (size_needed
<= size
)
260 is_read_unlock(space
);
263 kmem_free(ipc_kernel_map
, addr1
, size
);
264 kmem_free(ipc_kernel_map
, addr2
, size
);
268 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, VM_FLAGS_ANYWHERE
);
269 if (kr
!= KERN_SUCCESS
)
270 return KERN_RESOURCE_SHORTAGE
;
272 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, VM_FLAGS_ANYWHERE
);
273 if (kr
!= KERN_SUCCESS
) {
274 kmem_free(ipc_kernel_map
, addr1
, size
);
275 return KERN_RESOURCE_SHORTAGE
;
278 /* can't fault while we hold locks */
280 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
281 vm_map_round_page(addr1
+ size
),
282 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
283 if (kr
!= KERN_SUCCESS
) {
284 kmem_free(ipc_kernel_map
, addr1
, size
);
285 kmem_free(ipc_kernel_map
, addr2
, size
);
286 return KERN_RESOURCE_SHORTAGE
;
289 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
290 vm_map_round_page(addr2
+ size
),
291 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
292 if (kr
!= KERN_SUCCESS
) {
293 kmem_free(ipc_kernel_map
, addr1
, size
);
294 kmem_free(ipc_kernel_map
, addr2
, size
);
295 return KERN_RESOURCE_SHORTAGE
;
299 /* space is read-locked and active */
301 names
= (mach_port_name_t
*) addr1
;
302 types
= (mach_port_type_t
*) addr2
;
305 timestamp
= ipc_port_timestamp();
307 table
= space
->is_table
;
308 tsize
= space
->is_table_size
;
310 for (index
= 0; index
< tsize
; index
++) {
311 ipc_entry_t entry
= &table
[index
];
312 ipc_entry_bits_t bits
= entry
->ie_bits
;
314 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
315 mach_port_name_t name
;
317 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
318 mach_port_names_helper(timestamp
, entry
, name
, names
,
323 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
325 tentry
= ipc_splay_traverse_next(&space
->is_tree
, FALSE
)) {
326 ipc_entry_t entry
= &tentry
->ite_entry
;
327 mach_port_name_t name
= tentry
->ite_name
;
329 assert(IE_BITS_TYPE(tentry
->ite_bits
) != MACH_PORT_TYPE_NONE
);
330 mach_port_names_helper(timestamp
, entry
, name
, names
,
333 ipc_splay_traverse_finish(&space
->is_tree
);
334 is_read_unlock(space
);
337 memory1
= VM_MAP_COPY_NULL
;
338 memory2
= VM_MAP_COPY_NULL
;
341 kmem_free(ipc_kernel_map
, addr1
, size
);
342 kmem_free(ipc_kernel_map
, addr2
, size
);
346 vm_size_t vm_size_used
;
348 size_used
= actual
* sizeof(mach_port_name_t
);
349 vm_size_used
= round_page(size_used
);
352 * Make used memory pageable and get it into
353 * copied-in form. Free any unused memory.
356 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
357 vm_map_round_page(addr1
+ vm_size_used
), FALSE
);
358 assert(kr
== KERN_SUCCESS
);
360 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
361 vm_map_round_page(addr2
+ vm_size_used
), FALSE
);
362 assert(kr
== KERN_SUCCESS
);
364 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr1
,
365 (vm_map_size_t
)size_used
, TRUE
, &memory1
);
366 assert(kr
== KERN_SUCCESS
);
368 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr2
,
369 (vm_map_size_t
)size_used
, TRUE
, &memory2
);
370 assert(kr
== KERN_SUCCESS
);
372 if (vm_size_used
!= size
) {
373 kmem_free(ipc_kernel_map
,
374 addr1
+ vm_size_used
, size
- vm_size_used
);
375 kmem_free(ipc_kernel_map
,
376 addr2
+ vm_size_used
, size
- vm_size_used
);
380 *namesp
= (mach_port_name_t
*) memory1
;
382 *typesp
= (mach_port_type_t
*) memory2
;
388 * Routine: mach_port_type [kernel call]
390 * Retrieves the type of a right in the space.
391 * The type is a bitwise combination of one or more
392 * of the following type bits:
393 * MACH_PORT_TYPE_SEND
394 * MACH_PORT_TYPE_RECEIVE
395 * MACH_PORT_TYPE_SEND_ONCE
396 * MACH_PORT_TYPE_PORT_SET
397 * MACH_PORT_TYPE_DEAD_NAME
398 * In addition, the following pseudo-type bits may be present:
399 * MACH_PORT_TYPE_DNREQUEST
400 * A dead-name notification is requested.
404 * KERN_SUCCESS Type is returned.
405 * KERN_INVALID_TASK The space is null.
406 * KERN_INVALID_TASK The space is dead.
407 * KERN_INVALID_NAME The name doesn't denote a right.
413 mach_port_name_t name
,
414 mach_port_type_t
*typep
)
416 mach_port_urefs_t urefs
;
420 if (space
== IS_NULL
)
421 return KERN_INVALID_TASK
;
423 if (name
== MACH_PORT_NULL
)
424 return KERN_INVALID_NAME
;
426 if (name
== MACH_PORT_DEAD
) {
427 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
431 kr
= ipc_right_lookup_write(space
, name
, &entry
);
432 if (kr
!= KERN_SUCCESS
)
434 /* space is write-locked and active */
436 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
437 if (kr
== KERN_SUCCESS
)
438 is_write_unlock(space
);
439 /* space is unlocked */
444 * Routine: mach_port_rename [kernel call]
446 * Changes the name denoting a right,
447 * from oname to nname.
451 * KERN_SUCCESS The right is renamed.
452 * KERN_INVALID_TASK The space is null.
453 * KERN_INVALID_TASK The space is dead.
454 * KERN_INVALID_NAME The oname doesn't denote a right.
455 * KERN_INVALID_VALUE The nname isn't a legal name.
456 * KERN_NAME_EXISTS The nname already denotes a right.
457 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
463 mach_port_name_t oname
,
464 mach_port_name_t nname
)
466 if (space
== IS_NULL
)
467 return KERN_INVALID_TASK
;
469 if (!MACH_PORT_VALID(oname
))
470 return KERN_INVALID_NAME
;
472 if (!MACH_PORT_VALID(nname
))
473 return KERN_INVALID_VALUE
;
475 return ipc_object_rename(space
, oname
, nname
);
479 * Routine: mach_port_allocate_name [kernel call]
481 * Allocates a right in a space, using a specific name
482 * for the new right. Possible rights:
483 * MACH_PORT_RIGHT_RECEIVE
484 * MACH_PORT_RIGHT_PORT_SET
485 * MACH_PORT_RIGHT_DEAD_NAME
487 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
488 * has no extant send or send-once rights and no queued
489 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
490 * and its make-send count is 0. It is not a member of
491 * a port set. It has no registered no-senders or
492 * port-destroyed notification requests.
494 * A new port set has no members.
496 * A new dead name has one user reference.
500 * KERN_SUCCESS The right is allocated.
501 * KERN_INVALID_TASK The space is null.
502 * KERN_INVALID_TASK The space is dead.
503 * KERN_INVALID_VALUE The name isn't a legal name.
504 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
505 * KERN_NAME_EXISTS The name already denotes a right.
506 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
508 * Restrictions on name allocation: NT bits are reserved by kernel,
509 * must be set on any chosen name. Can't do this at all in kernel
514 mach_port_allocate_name(
516 mach_port_right_t right
,
517 mach_port_name_t name
)
520 mach_port_qos_t qos
= qos_template
;
524 if (!MACH_PORT_VALID(name
))
525 return KERN_INVALID_VALUE
;
527 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
533 * Routine: mach_port_allocate [kernel call]
535 * Allocates a right in a space. Like mach_port_allocate_name,
536 * except that the implementation picks a name for the right.
537 * The name may be any legal name in the space that doesn't
538 * currently denote a right.
542 * KERN_SUCCESS The right is allocated.
543 * KERN_INVALID_TASK The space is null.
544 * KERN_INVALID_TASK The space is dead.
545 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
546 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
547 * KERN_NO_SPACE No room in space for another right.
553 mach_port_right_t right
,
554 mach_port_name_t
*namep
)
557 mach_port_qos_t qos
= qos_template
;
559 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
565 * Routine: mach_port_allocate_qos [kernel call]
567 * Allocates a right, with qos options, in a space. Like
568 * mach_port_allocate_name, except that the implementation
569 * picks a name for the right. The name may be any legal name
570 * in the space that doesn't currently denote a right.
574 * KERN_SUCCESS The right is allocated.
575 * KERN_INVALID_TASK The space is null.
576 * KERN_INVALID_TASK The space is dead.
577 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
578 * KERN_INVALID_ARGUMENT The qos request was invalid.
579 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
580 * KERN_NO_SPACE No room in space for another right.
584 mach_port_allocate_qos(
586 mach_port_right_t right
,
587 mach_port_qos_t
*qosp
,
588 mach_port_name_t
*namep
)
593 return KERN_INVALID_ARGUMENT
;
594 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
600 * Routine: mach_port_allocate_full [kernel call]
602 * Allocates a right in a space. Supports all of the
603 * special cases, such as specifying a subsystem,
604 * a specific name, a real-time port, etc.
605 * The name may be any legal name in the space that doesn't
606 * currently denote a right.
610 * KERN_SUCCESS The right is allocated.
611 * KERN_INVALID_TASK The space is null.
612 * KERN_INVALID_TASK The space is dead.
613 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
614 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
615 * KERN_NO_SPACE No room in space for another right.
619 mach_port_allocate_full(
621 mach_port_right_t right
,
623 mach_port_qos_t
*qosp
,
624 mach_port_name_t
*namep
)
626 ipc_kmsg_t kmsg
= IKM_NULL
;
629 if (space
== IS_NULL
)
630 return (KERN_INVALID_TASK
);
632 if (proto
!= MACH_PORT_NULL
)
633 return (KERN_INVALID_VALUE
);
636 if (!MACH_PORT_VALID (*namep
))
637 return (KERN_INVALID_VALUE
);
638 if (is_fast_space (space
))
639 return (KERN_FAILURE
);
642 if (qosp
->prealloc
) {
643 if (qosp
->len
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
) {
644 return KERN_RESOURCE_SHORTAGE
;
646 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
648 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
649 return (KERN_INVALID_VALUE
);
651 kmsg
= (ipc_kmsg_t
)ipc_kmsg_prealloc(size
);
652 if (kmsg
== IKM_NULL
)
653 return (KERN_RESOURCE_SHORTAGE
);
658 case MACH_PORT_RIGHT_RECEIVE
:
663 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
665 kr
= ipc_port_alloc(space
, namep
, &port
);
666 if (kr
== KERN_SUCCESS
) {
667 if (kmsg
!= IKM_NULL
)
668 ipc_kmsg_set_prealloc(kmsg
, port
);
672 } else if (kmsg
!= IKM_NULL
)
677 case MACH_PORT_RIGHT_PORT_SET
:
682 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
684 kr
= ipc_pset_alloc(space
, namep
, &pset
);
685 if (kr
== KERN_SUCCESS
)
690 case MACH_PORT_RIGHT_DEAD_NAME
:
691 kr
= ipc_object_alloc_dead(space
, namep
);
695 kr
= KERN_INVALID_VALUE
;
703 * Routine: mach_port_destroy [kernel call]
705 * Cleans up and destroys all rights denoted by a name
706 * in a space. The destruction of a receive right
707 * destroys the port, unless a port-destroyed request
708 * has been made for it; the destruction of a port-set right
709 * destroys the port set.
713 * KERN_SUCCESS The name is destroyed.
714 * KERN_INVALID_TASK The space is null.
715 * KERN_INVALID_TASK The space is dead.
716 * KERN_INVALID_NAME The name doesn't denote a right.
722 mach_port_name_t name
)
727 if (space
== IS_NULL
)
728 return KERN_INVALID_TASK
;
730 if (!MACH_PORT_VALID(name
))
733 kr
= ipc_right_lookup_write(space
, name
, &entry
);
734 if (kr
!= KERN_SUCCESS
)
736 /* space is write-locked and active */
738 kr
= ipc_right_destroy(space
, name
, entry
);
739 is_write_unlock(space
);
744 * Routine: mach_port_deallocate [kernel call]
746 * Deallocates a user reference from a send right,
747 * send-once right, or a dead-name right. May
748 * deallocate the right, if this is the last uref,
749 * and destroy the name, if it doesn't denote
754 * KERN_SUCCESS The uref is deallocated.
755 * KERN_INVALID_TASK The space is null.
756 * KERN_INVALID_TASK The space is dead.
757 * KERN_INVALID_NAME The name doesn't denote a right.
758 * KERN_INVALID_RIGHT The right isn't correct.
762 mach_port_deallocate(
764 mach_port_name_t name
)
769 if (space
== IS_NULL
)
770 return KERN_INVALID_TASK
;
772 if (!MACH_PORT_VALID(name
))
775 kr
= ipc_right_lookup_write(space
, name
, &entry
);
776 if (kr
!= KERN_SUCCESS
)
778 /* space is write-locked */
780 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
785 * Routine: mach_port_get_refs [kernel call]
787 * Retrieves the number of user references held by a right.
788 * Receive rights, port-set rights, and send-once rights
789 * always have one user reference. Returns zero if the
790 * name denotes a right, but not the queried right.
794 * KERN_SUCCESS Number of urefs returned.
795 * KERN_INVALID_TASK The space is null.
796 * KERN_INVALID_TASK The space is dead.
797 * KERN_INVALID_VALUE "right" isn't a legal value.
798 * KERN_INVALID_NAME The name doesn't denote a right.
804 mach_port_name_t name
,
805 mach_port_right_t right
,
806 mach_port_urefs_t
*urefsp
)
808 mach_port_type_t type
;
809 mach_port_urefs_t urefs
;
813 if (space
== IS_NULL
)
814 return KERN_INVALID_TASK
;
816 if (right
>= MACH_PORT_RIGHT_NUMBER
)
817 return KERN_INVALID_VALUE
;
819 if (!MACH_PORT_VALID(name
)) {
820 if (right
== MACH_PORT_RIGHT_SEND
||
821 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
825 return KERN_INVALID_NAME
;
828 kr
= ipc_right_lookup_write(space
, name
, &entry
);
829 if (kr
!= KERN_SUCCESS
)
831 /* space is write-locked and active */
833 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
); /* unlocks */
834 if (kr
!= KERN_SUCCESS
)
835 return kr
; /* space is unlocked */
836 is_write_unlock(space
);
838 if (type
& MACH_PORT_TYPE(right
))
840 case MACH_PORT_RIGHT_SEND_ONCE
:
844 case MACH_PORT_RIGHT_PORT_SET
:
845 case MACH_PORT_RIGHT_RECEIVE
:
849 case MACH_PORT_RIGHT_DEAD_NAME
:
850 case MACH_PORT_RIGHT_SEND
:
856 panic("mach_port_get_refs: strange rights");
865 * Routine: mach_port_mod_refs
867 * Modifies the number of user references held by a right.
868 * The resulting number of user references must be non-negative.
869 * If it is zero, the right is deallocated. If the name
870 * doesn't denote other rights, it is destroyed.
874 * KERN_SUCCESS Modified number of urefs.
875 * KERN_INVALID_TASK The space is null.
876 * KERN_INVALID_TASK The space is dead.
877 * KERN_INVALID_VALUE "right" isn't a legal value.
878 * KERN_INVALID_NAME The name doesn't denote a right.
879 * KERN_INVALID_RIGHT Name doesn't denote specified right.
880 * KERN_INVALID_VALUE Impossible modification to urefs.
881 * KERN_UREFS_OVERFLOW Urefs would overflow.
887 mach_port_name_t name
,
888 mach_port_right_t right
,
889 mach_port_delta_t delta
)
894 if (space
== IS_NULL
)
895 return KERN_INVALID_TASK
;
897 if (right
>= MACH_PORT_RIGHT_NUMBER
)
898 return KERN_INVALID_VALUE
;
900 if (!MACH_PORT_VALID(name
)) {
901 if (right
== MACH_PORT_RIGHT_SEND
||
902 right
== MACH_PORT_RIGHT_SEND_ONCE
)
904 return KERN_INVALID_NAME
;
907 kr
= ipc_right_lookup_write(space
, name
, &entry
);
908 if (kr
!= KERN_SUCCESS
)
910 /* space is write-locked and active */
912 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
918 * Routine: mach_port_set_mscount [kernel call]
920 * Changes a receive right's make-send count.
924 * KERN_SUCCESS Set make-send count.
925 * KERN_INVALID_TASK The space is null.
926 * KERN_INVALID_TASK The space is dead.
927 * KERN_INVALID_NAME The name doesn't denote a right.
928 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
932 mach_port_set_mscount(
934 mach_port_name_t name
,
935 mach_port_mscount_t mscount
)
940 if (space
== IS_NULL
)
941 return KERN_INVALID_TASK
;
943 if (!MACH_PORT_VALID(name
))
944 return KERN_INVALID_RIGHT
;
946 kr
= ipc_port_translate_receive(space
, name
, &port
);
947 if (kr
!= KERN_SUCCESS
)
949 /* port is locked and active */
951 ipc_port_set_mscount(port
, mscount
);
958 * Routine: mach_port_set_seqno [kernel call]
960 * Changes a receive right's sequence number.
964 * KERN_SUCCESS Set sequence number.
965 * KERN_INVALID_TASK The space is null.
966 * KERN_INVALID_TASK The space is dead.
967 * KERN_INVALID_NAME The name doesn't denote a right.
968 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
974 mach_port_name_t name
,
975 mach_port_seqno_t seqno
)
980 if (space
== IS_NULL
)
981 return KERN_INVALID_TASK
;
983 if (!MACH_PORT_VALID(name
))
984 return KERN_INVALID_RIGHT
;
986 kr
= ipc_port_translate_receive(space
, name
, &port
);
987 if (kr
!= KERN_SUCCESS
)
989 /* port is locked and active */
991 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
998 * Routine: mach_port_get_context [kernel call]
1000 * Returns a receive right's context pointer.
1004 * KERN_SUCCESS Set context pointer.
1005 * KERN_INVALID_TASK The space is null.
1006 * KERN_INVALID_TASK The space is dead.
1007 * KERN_INVALID_NAME The name doesn't denote a right.
1008 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1012 mach_port_get_context(
1014 mach_port_name_t name
,
1015 mach_vm_address_t
*context
)
1020 if (space
== IS_NULL
)
1021 return KERN_INVALID_TASK
;
1023 if (!MACH_PORT_VALID(name
))
1024 return KERN_INVALID_RIGHT
;
1026 kr
= ipc_port_translate_receive(space
, name
, &port
);
1027 if (kr
!= KERN_SUCCESS
)
1030 /* port is locked and active */
1031 *context
= port
->ip_context
;
1034 return KERN_SUCCESS
;
1039 * Routine: mach_port_set_context [kernel call]
1041 * Changes a receive right's context pointer.
1045 * KERN_SUCCESS Set context pointer.
1046 * KERN_INVALID_TASK The space is null.
1047 * KERN_INVALID_TASK The space is dead.
1048 * KERN_INVALID_NAME The name doesn't denote a right.
1049 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1053 mach_port_set_context(
1055 mach_port_name_t name
,
1056 mach_vm_address_t context
)
1061 if (space
== IS_NULL
)
1062 return KERN_INVALID_TASK
;
1064 if (!MACH_PORT_VALID(name
))
1065 return KERN_INVALID_RIGHT
;
1067 kr
= ipc_port_translate_receive(space
, name
, &port
);
1068 if (kr
!= KERN_SUCCESS
)
1071 /* port is locked and active */
1072 port
->ip_context
= context
;
1075 return KERN_SUCCESS
;
1080 * Routine: mach_port_gst_helper
1082 * A helper function for mach_port_get_set_status.
1086 mach_port_gst_helper(
1089 ipc_entry_num_t maxnames
,
1090 mach_port_name_t
*names
,
1091 ipc_entry_num_t
*actualp
)
1093 mach_port_name_t name
;
1095 assert(port
!= IP_NULL
);
1098 assert(ip_active(port
));
1100 name
= port
->ip_receiver_name
;
1101 assert(name
!= MACH_PORT_NULL
);
1105 if (ipc_pset_member(pset
, port
)) {
1106 ipc_entry_num_t actual
= *actualp
;
1108 if (actual
< maxnames
)
1109 names
[actual
] = name
;
1111 *actualp
= actual
+1;
1116 * Routine: mach_port_get_set_status [kernel call]
1118 * Retrieves a list of members in a port set.
1119 * Returns the space's name for each receive right member.
1123 * KERN_SUCCESS Retrieved list of members.
1124 * KERN_INVALID_TASK The space is null.
1125 * KERN_INVALID_TASK The space is dead.
1126 * KERN_INVALID_NAME The name doesn't denote a right.
1127 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1128 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1132 mach_port_get_set_status(
1134 mach_port_name_t name
,
1135 mach_port_name_t
**members
,
1136 mach_msg_type_number_t
*membersCnt
)
1138 ipc_entry_num_t actual
; /* this many members */
1139 ipc_entry_num_t maxnames
; /* space for this many members */
1142 vm_size_t size
; /* size of allocated memory */
1143 vm_offset_t addr
; /* allocated memory */
1144 vm_map_copy_t memory
; /* copied-in memory */
1146 if (space
== IS_NULL
)
1147 return KERN_INVALID_TASK
;
1149 if (!MACH_PORT_VALID(name
))
1150 return KERN_INVALID_RIGHT
;
1152 size
= PAGE_SIZE
; /* initial guess */
1155 ipc_tree_entry_t tentry
;
1156 ipc_entry_t entry
, table
;
1157 ipc_entry_num_t tsize
;
1158 mach_port_index_t index
;
1159 mach_port_name_t
*names
;
1162 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, VM_FLAGS_ANYWHERE
);
1163 if (kr
!= KERN_SUCCESS
)
1164 return KERN_RESOURCE_SHORTAGE
;
1166 /* can't fault while we hold locks */
1168 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1169 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1170 assert(kr
== KERN_SUCCESS
);
1172 kr
= ipc_right_lookup_read(space
, name
, &entry
);
1173 if (kr
!= KERN_SUCCESS
) {
1174 kmem_free(ipc_kernel_map
, addr
, size
);
1177 /* space is read-locked and active */
1179 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_PORT_SET
) {
1180 is_read_unlock(space
);
1181 kmem_free(ipc_kernel_map
, addr
, size
);
1182 return KERN_INVALID_RIGHT
;
1185 pset
= (ipc_pset_t
) entry
->ie_object
;
1186 assert(pset
!= IPS_NULL
);
1187 /* the port set must be active */
1189 names
= (mach_port_name_t
*) addr
;
1190 maxnames
= (ipc_entry_num_t
)(size
/ sizeof(mach_port_name_t
));
1193 table
= space
->is_table
;
1194 tsize
= space
->is_table_size
;
1196 for (index
= 0; index
< tsize
; index
++) {
1197 ipc_entry_t ientry
= &table
[index
];
1199 if (ientry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) {
1201 (ipc_port_t
) ientry
->ie_object
;
1203 mach_port_gst_helper(pset
, port
,
1204 maxnames
, names
, &actual
);
1208 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
1210 tentry
= ipc_splay_traverse_next(&space
->is_tree
,FALSE
)) {
1211 ipc_entry_bits_t bits
= tentry
->ite_bits
;
1213 assert(IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
);
1215 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1216 ipc_port_t port
= (ipc_port_t
) tentry
->ite_object
;
1218 mach_port_gst_helper(pset
, port
, maxnames
,
1222 ipc_splay_traverse_finish(&space
->is_tree
);
1223 is_read_unlock(space
);
1225 if (actual
<= maxnames
)
1228 /* didn't have enough memory; allocate more */
1230 kmem_free(ipc_kernel_map
, addr
, size
);
1231 size
= round_page(actual
* sizeof(mach_port_name_t
)) + PAGE_SIZE
;
1235 memory
= VM_MAP_COPY_NULL
;
1237 kmem_free(ipc_kernel_map
, addr
, size
);
1239 vm_size_t size_used
;
1240 vm_size_t vm_size_used
;
1242 size_used
= actual
* sizeof(mach_port_name_t
);
1243 vm_size_used
= round_page(size_used
);
1246 * Make used memory pageable and get it into
1247 * copied-in form. Free any unused memory.
1250 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr
),
1251 vm_map_round_page(addr
+ vm_size_used
), FALSE
);
1252 assert(kr
== KERN_SUCCESS
);
1254 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr
,
1255 (vm_map_size_t
)size_used
, TRUE
, &memory
);
1256 assert(kr
== KERN_SUCCESS
);
1258 if (vm_size_used
!= size
)
1259 kmem_free(ipc_kernel_map
,
1260 addr
+ vm_size_used
, size
- vm_size_used
);
1263 *members
= (mach_port_name_t
*) memory
;
1264 *membersCnt
= actual
;
1265 return KERN_SUCCESS
;
1269 * Routine: mach_port_move_member [kernel call]
1271 * If after is MACH_PORT_NULL, removes member
1272 * from the port set it is in. Otherwise, adds
1273 * member to after, removing it from any set
1274 * it might already be in.
1278 * KERN_SUCCESS Moved the port.
1279 * KERN_INVALID_TASK The space is null.
1280 * KERN_INVALID_TASK The space is dead.
1281 * KERN_INVALID_NAME Member didn't denote a right.
1282 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1283 * KERN_INVALID_NAME After didn't denote a right.
1284 * KERN_INVALID_RIGHT After didn't denote a port set right.
1286 * After is MACH_PORT_NULL and Member isn't in a port set.
1290 mach_port_move_member(
1292 mach_port_name_t member
,
1293 mach_port_name_t after
)
1300 if (space
== IS_NULL
)
1301 return KERN_INVALID_TASK
;
1303 if (!MACH_PORT_VALID(member
))
1304 return KERN_INVALID_RIGHT
;
1306 if (after
== MACH_PORT_DEAD
)
1307 return KERN_INVALID_RIGHT
;
1309 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1310 if (kr
!= KERN_SUCCESS
)
1312 /* space is read-locked and active */
1314 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1315 is_read_unlock(space
);
1316 return KERN_INVALID_RIGHT
;
1319 port
= (ipc_port_t
) entry
->ie_object
;
1320 assert(port
!= IP_NULL
);
1322 if (after
== MACH_PORT_NULL
)
1325 entry
= ipc_entry_lookup(space
, after
);
1326 if (entry
== IE_NULL
) {
1327 is_read_unlock(space
);
1328 return KERN_INVALID_NAME
;
1331 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1332 is_read_unlock(space
);
1333 return KERN_INVALID_RIGHT
;
1336 nset
= (ipc_pset_t
) entry
->ie_object
;
1337 assert(nset
!= IPS_NULL
);
1340 ipc_pset_remove_from_all(port
);
1342 if (nset
!= IPS_NULL
) {
1344 kr
= ipc_pset_add(nset
, port
);
1348 is_read_unlock(space
);
1353 * Routine: mach_port_request_notification [kernel call]
1355 * Requests a notification. The caller supplies
1356 * a send-once right for the notification to use,
1357 * and the call returns the previously registered
1358 * send-once right, if any. Possible types:
1360 * MACH_NOTIFY_PORT_DESTROYED
1361 * Requests a port-destroyed notification
1362 * for a receive right. Sync should be zero.
1363 * MACH_NOTIFY_NO_SENDERS
1364 * Requests a no-senders notification for a
1365 * receive right. If there are currently no
1366 * senders, sync is less than or equal to the
1367 * current make-send count, and a send-once right
1368 * is supplied, then an immediate no-senders
1369 * notification is generated.
1370 * MACH_NOTIFY_DEAD_NAME
1371 * Requests a dead-name notification for a send
1372 * or receive right. If the name is already a
1373 * dead name, sync is non-zero, and a send-once
1374 * right is supplied, then an immediate dead-name
1375 * notification is generated.
1379 * KERN_SUCCESS Requested a notification.
1380 * KERN_INVALID_TASK The space is null.
1381 * KERN_INVALID_TASK The space is dead.
1382 * KERN_INVALID_VALUE Bad id value.
1383 * KERN_INVALID_NAME Name doesn't denote a right.
1384 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1385 * KERN_INVALID_CAPABILITY The notify port is dead.
1386 * MACH_NOTIFY_PORT_DESTROYED:
1387 * KERN_INVALID_VALUE Sync isn't zero.
1388 * MACH_NOTIFY_DEAD_NAME:
1389 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1390 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1391 * sync is zero or notify is IP_NULL.
1392 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1393 * generating immediate notif. would overflow urefs.
1397 mach_port_request_notification(
1399 mach_port_name_t name
,
1401 mach_port_mscount_t sync
,
1403 ipc_port_t
*previousp
)
1407 if (space
== IS_NULL
)
1408 return KERN_INVALID_TASK
;
1410 if (notify
== IP_DEAD
)
1411 return KERN_INVALID_CAPABILITY
;
1415 * Requesting notifications on RPC ports is an error.
1421 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1422 if (kr
!= KERN_SUCCESS
)
1425 port
= (ipc_port_t
) entry
->ie_object
;
1427 if (port
->ip_subsystem
!= NULL
) {
1428 is_write_unlock(space
);
1429 panic("mach_port_request_notification: on RPC port!!");
1430 return KERN_INVALID_CAPABILITY
;
1432 is_write_unlock(space
);
1438 case MACH_NOTIFY_PORT_DESTROYED
: {
1439 ipc_port_t port
, previous
;
1442 return KERN_INVALID_VALUE
;
1444 if (!MACH_PORT_VALID(name
))
1445 return KERN_INVALID_RIGHT
;
1447 kr
= ipc_port_translate_receive(space
, name
, &port
);
1448 if (kr
!= KERN_SUCCESS
)
1450 /* port is locked and active */
1452 ipc_port_pdrequest(port
, notify
, &previous
);
1453 /* port is unlocked */
1455 *previousp
= previous
;
1459 case MACH_NOTIFY_NO_SENDERS
: {
1462 if (!MACH_PORT_VALID(name
))
1463 return KERN_INVALID_RIGHT
;
1465 kr
= ipc_port_translate_receive(space
, name
, &port
);
1466 if (kr
!= KERN_SUCCESS
)
1468 /* port is locked and active */
1470 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1471 /* port is unlocked */
1475 case MACH_NOTIFY_DEAD_NAME
:
1477 if (!MACH_PORT_VALID(name
)) {
1480 * Should do immediate delivery check -
1481 * will do that in the near future.
1483 return KERN_INVALID_ARGUMENT
;
1486 kr
= ipc_right_dnrequest(space
, name
, sync
!= 0,
1488 if (kr
!= KERN_SUCCESS
)
1493 return KERN_INVALID_VALUE
;
1496 return KERN_SUCCESS
;
1500 * Routine: mach_port_insert_right [kernel call]
1502 * Inserts a right into a space, as if the space
1503 * voluntarily received the right in a message,
1504 * except that the right gets the specified name.
1508 * KERN_SUCCESS Inserted the right.
1509 * KERN_INVALID_TASK The space is null.
1510 * KERN_INVALID_TASK The space is dead.
1511 * KERN_INVALID_VALUE The name isn't a legal name.
1512 * KERN_NAME_EXISTS The name already denotes a right.
1513 * KERN_INVALID_VALUE Message doesn't carry a port right.
1514 * KERN_INVALID_CAPABILITY Port is null or dead.
1515 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1516 * KERN_RIGHT_EXISTS Space has rights under another name.
1517 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1521 mach_port_insert_right(
1523 mach_port_name_t name
,
1525 mach_msg_type_name_t polyPoly
)
1527 if (space
== IS_NULL
)
1528 return KERN_INVALID_TASK
;
1530 if (!MACH_PORT_VALID(name
) ||
1531 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1532 return KERN_INVALID_VALUE
;
1534 if (!IO_VALID((ipc_object_t
) poly
))
1535 return KERN_INVALID_CAPABILITY
;
1537 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1538 polyPoly
, FALSE
, name
);
1542 * Routine: mach_port_extract_right [kernel call]
1544 * Extracts a right from a space, as if the space
1545 * voluntarily sent the right to the caller.
1549 * KERN_SUCCESS Extracted the right.
1550 * KERN_INVALID_TASK The space is null.
1551 * KERN_INVALID_TASK The space is dead.
1552 * KERN_INVALID_VALUE Requested type isn't a port right.
1553 * KERN_INVALID_NAME Name doesn't denote a right.
1554 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1558 mach_port_extract_right(
1560 mach_port_name_t name
,
1561 mach_msg_type_name_t msgt_name
,
1563 mach_msg_type_name_t
*polyPoly
)
1567 if (space
== IS_NULL
)
1568 return KERN_INVALID_TASK
;
1570 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1571 return KERN_INVALID_VALUE
;
1573 if (!MACH_PORT_VALID(name
)) {
1575 * really should copy out a dead name, if it is a send or
1576 * send-once right being copied, but instead return an
1579 return KERN_INVALID_RIGHT
;
1582 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1584 if (kr
== KERN_SUCCESS
)
1585 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1591 mach_port_get_attributes(
1593 mach_port_name_t name
,
1595 mach_port_info_t info
,
1596 mach_msg_type_number_t
*count
)
1601 if (space
== IS_NULL
)
1602 return KERN_INVALID_TASK
;
1605 case MACH_PORT_LIMITS_INFO
: {
1606 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1608 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1609 return KERN_FAILURE
;
1611 if (!MACH_PORT_VALID(name
)) {
1616 kr
= ipc_port_translate_receive(space
, name
, &port
);
1617 if (kr
!= KERN_SUCCESS
)
1619 /* port is locked and active */
1621 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1622 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1627 case MACH_PORT_RECEIVE_STATUS
: {
1628 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1631 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1632 return KERN_FAILURE
;
1634 if (!MACH_PORT_VALID(name
))
1635 return KERN_INVALID_RIGHT
;
1637 kr
= ipc_port_translate_receive(space
, name
, &port
);
1638 if (kr
!= KERN_SUCCESS
)
1640 /* port is locked and active */
1642 statusp
->mps_pset
= port
->ip_pset_count
;
1645 imq_lock(&port
->ip_messages
);
1646 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1647 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1648 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1649 imq_unlock(&port
->ip_messages
);
1652 statusp
->mps_mscount
= port
->ip_mscount
;
1653 statusp
->mps_sorights
= port
->ip_sorights
;
1654 statusp
->mps_srights
= port
->ip_srights
> 0;
1655 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1656 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1657 statusp
->mps_flags
= 0;
1659 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1664 case MACH_PORT_DNREQUESTS_SIZE
: {
1665 ipc_port_request_t table
;
1667 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1668 return KERN_FAILURE
;
1670 if (!MACH_PORT_VALID(name
)) {
1675 kr
= ipc_port_translate_receive(space
, name
, &port
);
1676 if (kr
!= KERN_SUCCESS
)
1678 /* port is locked and active */
1680 table
= port
->ip_dnrequests
;
1681 if (table
== IPR_NULL
)
1684 *(int *)info
= table
->ipr_size
->its_size
;
1685 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1691 return KERN_INVALID_ARGUMENT
;
1695 return KERN_SUCCESS
;
1699 mach_port_set_attributes(
1701 mach_port_name_t name
,
1703 mach_port_info_t info
,
1704 mach_msg_type_number_t count
)
1709 if (space
== IS_NULL
)
1710 return KERN_INVALID_TASK
;
1714 case MACH_PORT_LIMITS_INFO
: {
1715 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1717 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1718 return KERN_FAILURE
;
1720 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1721 return KERN_INVALID_VALUE
;
1723 if (!MACH_PORT_VALID(name
))
1724 return KERN_INVALID_RIGHT
;
1726 kr
= ipc_port_translate_receive(space
, name
, &port
);
1727 if (kr
!= KERN_SUCCESS
)
1729 /* port is locked and active */
1731 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1735 case MACH_PORT_DNREQUESTS_SIZE
: {
1736 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1737 return KERN_FAILURE
;
1739 if (!MACH_PORT_VALID(name
))
1740 return KERN_INVALID_RIGHT
;
1742 kr
= ipc_port_translate_receive(space
, name
, &port
);
1743 if (kr
!= KERN_SUCCESS
)
1745 /* port is locked and active */
1747 kr
= ipc_port_dngrow(port
, *(int *)info
);
1748 if (kr
!= KERN_SUCCESS
)
1753 return KERN_INVALID_ARGUMENT
;
1756 return KERN_SUCCESS
;
1760 * Routine: mach_port_insert_member [kernel call]
1762 * Add the receive right, specified by name, to
1764 * The port cannot already be a member of the set.
1768 * KERN_SUCCESS Moved the port.
1769 * KERN_INVALID_TASK The space is null.
1770 * KERN_INVALID_TASK The space is dead.
1771 * KERN_INVALID_NAME name didn't denote a right.
1772 * KERN_INVALID_RIGHT name didn't denote a receive right.
1773 * KERN_INVALID_NAME pset_name didn't denote a right.
1774 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1775 * KERN_ALREADY_IN_SET name was already a member of pset.
1779 mach_port_insert_member(
1781 mach_port_name_t name
,
1782 mach_port_name_t psname
)
1788 if (space
== IS_NULL
)
1789 return KERN_INVALID_TASK
;
1791 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1792 return KERN_INVALID_RIGHT
;
1794 kr
= ipc_object_translate_two(space
,
1795 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1796 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1797 if (kr
!= KERN_SUCCESS
)
1800 /* obj and psobj are locked (and were locked in that order) */
1801 assert(psobj
!= IO_NULL
);
1802 assert(obj
!= IO_NULL
);
1804 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1811 * Routine: mach_port_extract_member [kernel call]
1813 * Remove a port from one portset that it is a member of.
1817 * KERN_SUCCESS Moved the port.
1818 * KERN_INVALID_TASK The space is null.
1819 * KERN_INVALID_TASK The space is dead.
1820 * KERN_INVALID_NAME Member didn't denote a right.
1821 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1822 * KERN_INVALID_NAME After didn't denote a right.
1823 * KERN_INVALID_RIGHT After didn't denote a port set right.
1825 * After is MACH_PORT_NULL and Member isn't in a port set.
1829 mach_port_extract_member(
1831 mach_port_name_t name
,
1832 mach_port_name_t psname
)
1838 if (space
== IS_NULL
)
1839 return KERN_INVALID_TASK
;
1841 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1842 return KERN_INVALID_RIGHT
;
1844 kr
= ipc_object_translate_two(space
,
1845 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1846 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1847 if (kr
!= KERN_SUCCESS
)
1850 /* obj and psobj are both locked (and were locked in that order) */
1851 assert(psobj
!= IO_NULL
);
1852 assert(obj
!= IO_NULL
);
1854 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1861 * task_set_port_space:
1863 * Set port name space of task to specified size.
1866 task_set_port_space(
1872 is_write_lock(space
);
1873 kr
= ipc_entry_grow_table(space
, table_entries
);
1874 if (kr
== KERN_SUCCESS
)
1875 is_write_unlock(space
);
1880 * Get a (new) label handle representing the given port's port label.
1882 #if CONFIG_MACF_MACH
1886 mach_port_name_t name
,
1887 mach_port_name_t
*outlabel
)
1895 if (!MACH_PORT_VALID(name
))
1896 return KERN_INVALID_NAME
;
1898 /* Lookup the port name in the task's space. */
1899 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1900 if (kr
!= KERN_SUCCESS
)
1903 port
= (ipc_port_t
) entry
->ie_object
;
1904 dead
= ipc_right_check(space
, port
, name
, entry
);
1906 is_write_unlock(space
);
1907 return KERN_INVALID_RIGHT
;
1909 /* port is now locked */
1911 is_write_unlock(space
);
1912 /* Make sure we are not dealing with a label handle. */
1913 if (ip_kotype(port
) == IKOT_LABELH
) {
1914 /* already is a label handle! */
1916 return KERN_INVALID_ARGUMENT
;
1919 /* Copy the port label and stash it in a new label handle. */
1920 mac_port_label_init(&outl
);
1921 mac_port_label_copy(&port
->ip_label
, &outl
);
1922 kr
= labelh_new_user(space
, &outl
, outlabel
);
1925 return KERN_SUCCESS
;
1930 __unused ipc_space_t space
,
1931 __unused mach_port_name_t name
,
1932 __unused mach_port_name_t
*outlabel
)
1934 return KERN_INVALID_ARGUMENT
;
1939 * also works on label handles
1941 #if CONFIG_MACF_MACH
1943 mach_get_label_text(
1945 mach_port_name_t name
,
1946 labelstr_t policies
,
1947 labelstr_t outlabel
)
1954 if (space
== IS_NULL
|| space
->is_task
== NULL
)
1955 return KERN_INVALID_TASK
;
1957 if (!MACH_PORT_VALID(name
))
1958 return KERN_INVALID_NAME
;
1960 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1961 if (kr
!= KERN_SUCCESS
)
1964 dead
= ipc_right_check(space
, (ipc_port_t
) entry
->ie_object
, name
,
1967 is_write_unlock(space
);
1968 return KERN_INVALID_RIGHT
;
1970 /* object (port) is now locked */
1972 is_write_unlock (space
);
1973 l
= io_getlabel(entry
->ie_object
);
1975 mac_port_label_externalize(l
, policies
, outlabel
, 512, 0);
1977 io_unlocklabel(entry
->ie_object
);
1978 io_unlock(entry
->ie_object
);
1979 return KERN_SUCCESS
;
1983 mach_get_label_text(
1984 __unused ipc_space_t space
,
1985 __unused mach_port_name_t name
,
1986 __unused labelstr_t policies
,
1987 __unused labelstr_t outlabel
)
1989 return KERN_INVALID_ARGUMENT
;
1994 #if CONFIG_MACF_MACH
1996 mach_set_port_label(
1998 mach_port_name_t name
,
1999 labelstr_t labelstr
)
2007 if (space
== IS_NULL
|| space
->is_task
== NULL
)
2008 return KERN_INVALID_TASK
;
2010 if (!MACH_PORT_VALID(name
))
2011 return KERN_INVALID_NAME
;
2013 mac_port_label_init(&inl
);
2014 rc
= mac_port_label_internalize(&inl
, labelstr
);
2016 return KERN_INVALID_ARGUMENT
;
2018 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2019 if (kr
!= KERN_SUCCESS
)
2022 if (io_otype(entMACry
->ie_object
) != IOT_PORT
) {
2023 is_write_unlock(space
);
2024 return KERN_INVALID_RIGHT
;
2027 port
= (ipc_port_t
) entry
->ie_object
;
2030 tasklabel_lock(space
->is_task
);
2031 rc
= mac_port_check_label_update(&space
->is_task
->maclabel
,
2032 &port
->ip_label
, &inl
);
2033 tasklabel_unlock(space
->is_task
);
2035 kr
= KERN_NO_ACCESS
;
2037 mac_port_label_copy(&inl
, &port
->ip_label
);
2040 is_write_unlock(space
);
2045 mach_set_port_label(
2046 ipc_space_t space __unused
,
2047 mach_port_name_t name __unused
,
2048 labelstr_t labelstr __unused
)
2050 return KERN_INVALID_ARGUMENT
;