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(
117 ipc_entry_num_t maxnames
,
118 mach_port_name_t
*names
,
119 ipc_entry_num_t
*actualp
);
123 mach_port_guard_exception(
124 mach_port_name_t name
,
129 /* Needs port locked */
130 void mach_port_get_status_helper(
132 mach_port_status_t
*status
);
134 /* Zeroed template of qos flags */
136 static mach_port_qos_t qos_template
;
139 * Routine: mach_port_names_helper
141 * A helper function for mach_port_names.
144 * Space containing entry is [at least] read-locked.
148 mach_port_names_helper(
149 ipc_port_timestamp_t timestamp
,
151 mach_port_name_t name
,
152 mach_port_name_t
*names
,
153 mach_port_type_t
*types
,
154 ipc_entry_num_t
*actualp
)
156 ipc_entry_bits_t bits
;
157 ipc_port_request_index_t request
;
158 mach_port_type_t type
= 0;
159 ipc_entry_num_t actual
;
162 bits
= entry
->ie_bits
;
163 request
= entry
->ie_request
;
164 port
= (ipc_port_t
) entry
->ie_object
;
166 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
167 assert(IP_VALID(port
));
169 if (request
!= IE_REQ_NONE
) {
171 assert(ip_active(port
));
172 type
|= ipc_port_request_type(port
, name
, request
);
176 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
177 mach_port_type_t reqtype
;
179 assert(IP_VALID(port
));
182 reqtype
= (request
!= IE_REQ_NONE
) ?
183 ipc_port_request_type(port
, name
, request
) : 0;
186 * If the port is alive, or was alive when the mach_port_names
187 * started, then return that fact. Otherwise, pretend we found
190 if (ip_active(port
) || IP_TIMESTAMP_ORDER(timestamp
, port
->ip_timestamp
)) {
193 bits
&= ~(IE_BITS_TYPE_MASK
);
194 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
195 /* account for additional reference for dead-name notification */
202 type
|= IE_BITS_TYPE(bits
);
205 names
[actual
] = name
;
206 types
[actual
] = type
;
211 * Routine: mach_port_names [kernel call]
213 * Retrieves a list of the rights present in the space,
214 * along with type information. (Same as returned
215 * by mach_port_type.) The names are returned in
216 * no particular order, but they (and the type info)
217 * are an accurate snapshot of the space.
221 * KERN_SUCCESS Arrays of names and types returned.
222 * KERN_INVALID_TASK The space is null.
223 * KERN_INVALID_TASK The space is dead.
224 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
230 mach_port_name_t
**namesp
,
231 mach_msg_type_number_t
*namesCnt
,
232 mach_port_type_t
**typesp
,
233 mach_msg_type_number_t
*typesCnt
)
236 ipc_entry_num_t tsize
;
237 mach_port_index_t index
;
238 ipc_entry_num_t actual
; /* this many names */
239 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
240 mach_port_name_t
*names
;
241 mach_port_type_t
*types
;
244 vm_size_t size
; /* size of allocated memory */
245 vm_offset_t addr1
; /* allocated memory, for names */
246 vm_offset_t addr2
; /* allocated memory, for types */
247 vm_map_copy_t memory1
; /* copied-in memory, for names */
248 vm_map_copy_t memory2
; /* copied-in memory, for types */
250 /* safe simplifying assumption */
251 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
253 if (space
== IS_NULL
)
254 return KERN_INVALID_TASK
;
259 ipc_entry_num_t bound
;
260 vm_size_t size_needed
;
263 if (!is_active(space
)) {
264 is_read_unlock(space
);
266 kmem_free(ipc_kernel_map
, addr1
, size
);
267 kmem_free(ipc_kernel_map
, addr2
, size
);
269 return KERN_INVALID_TASK
;
272 /* upper bound on number of names in the space */
273 bound
= space
->is_table_size
;
274 size_needed
= vm_map_round_page(
275 (bound
* sizeof(mach_port_name_t
)),
276 VM_MAP_PAGE_MASK(ipc_kernel_map
));
278 if (size_needed
<= size
)
281 is_read_unlock(space
);
284 kmem_free(ipc_kernel_map
, addr1
, size
);
285 kmem_free(ipc_kernel_map
, addr2
, size
);
289 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, VM_FLAGS_ANYWHERE
);
290 if (kr
!= KERN_SUCCESS
)
291 return KERN_RESOURCE_SHORTAGE
;
293 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, VM_FLAGS_ANYWHERE
);
294 if (kr
!= KERN_SUCCESS
) {
295 kmem_free(ipc_kernel_map
, addr1
, size
);
296 return KERN_RESOURCE_SHORTAGE
;
299 /* can't fault while we hold locks */
303 vm_map_trunc_page(addr1
,
304 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
305 vm_map_round_page(addr1
+ size
,
306 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
307 VM_PROT_READ
|VM_PROT_WRITE
,
309 if (kr
!= KERN_SUCCESS
) {
310 kmem_free(ipc_kernel_map
, addr1
, size
);
311 kmem_free(ipc_kernel_map
, addr2
, size
);
312 return KERN_RESOURCE_SHORTAGE
;
317 vm_map_trunc_page(addr2
,
318 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
319 vm_map_round_page(addr2
+ size
,
320 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
321 VM_PROT_READ
|VM_PROT_WRITE
,
323 if (kr
!= KERN_SUCCESS
) {
324 kmem_free(ipc_kernel_map
, addr1
, size
);
325 kmem_free(ipc_kernel_map
, addr2
, size
);
326 return KERN_RESOURCE_SHORTAGE
;
330 /* space is read-locked and active */
332 names
= (mach_port_name_t
*) addr1
;
333 types
= (mach_port_type_t
*) addr2
;
336 timestamp
= ipc_port_timestamp();
338 table
= space
->is_table
;
339 tsize
= space
->is_table_size
;
341 for (index
= 0; index
< tsize
; index
++) {
342 ipc_entry_t entry
= &table
[index
];
343 ipc_entry_bits_t bits
= entry
->ie_bits
;
345 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
346 mach_port_name_t name
;
348 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
349 mach_port_names_helper(timestamp
, entry
, name
, names
,
354 is_read_unlock(space
);
357 memory1
= VM_MAP_COPY_NULL
;
358 memory2
= VM_MAP_COPY_NULL
;
361 kmem_free(ipc_kernel_map
, addr1
, size
);
362 kmem_free(ipc_kernel_map
, addr2
, size
);
366 vm_size_t vm_size_used
;
368 size_used
= actual
* sizeof(mach_port_name_t
);
370 vm_map_round_page(size_used
,
371 VM_MAP_PAGE_MASK(ipc_kernel_map
));
374 * Make used memory pageable and get it into
375 * copied-in form. Free any unused memory.
380 vm_map_trunc_page(addr1
,
381 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
382 vm_map_round_page(addr1
+ vm_size_used
,
383 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
385 assert(kr
== KERN_SUCCESS
);
389 vm_map_trunc_page(addr2
,
390 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
391 vm_map_round_page(addr2
+ vm_size_used
,
392 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
394 assert(kr
== KERN_SUCCESS
);
396 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr1
,
397 (vm_map_size_t
)size_used
, TRUE
, &memory1
);
398 assert(kr
== KERN_SUCCESS
);
400 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr2
,
401 (vm_map_size_t
)size_used
, TRUE
, &memory2
);
402 assert(kr
== KERN_SUCCESS
);
404 if (vm_size_used
!= size
) {
405 kmem_free(ipc_kernel_map
,
406 addr1
+ vm_size_used
, size
- vm_size_used
);
407 kmem_free(ipc_kernel_map
,
408 addr2
+ vm_size_used
, size
- vm_size_used
);
412 *namesp
= (mach_port_name_t
*) memory1
;
414 *typesp
= (mach_port_type_t
*) memory2
;
420 * Routine: mach_port_type [kernel call]
422 * Retrieves the type of a right in the space.
423 * The type is a bitwise combination of one or more
424 * of the following type bits:
425 * MACH_PORT_TYPE_SEND
426 * MACH_PORT_TYPE_RECEIVE
427 * MACH_PORT_TYPE_SEND_ONCE
428 * MACH_PORT_TYPE_PORT_SET
429 * MACH_PORT_TYPE_DEAD_NAME
430 * In addition, the following pseudo-type bits may be present:
431 * MACH_PORT_TYPE_DNREQUEST
432 * A dead-name notification is requested.
436 * KERN_SUCCESS Type is returned.
437 * KERN_INVALID_TASK The space is null.
438 * KERN_INVALID_TASK The space is dead.
439 * KERN_INVALID_NAME The name doesn't denote a right.
445 mach_port_name_t name
,
446 mach_port_type_t
*typep
)
448 mach_port_urefs_t urefs
;
452 if (space
== IS_NULL
)
453 return KERN_INVALID_TASK
;
455 if (name
== MACH_PORT_NULL
)
456 return KERN_INVALID_NAME
;
458 if (name
== MACH_PORT_DEAD
) {
459 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
463 kr
= ipc_right_lookup_write(space
, name
, &entry
);
464 if (kr
!= KERN_SUCCESS
)
467 /* space is write-locked and active */
468 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
469 /* space is unlocked */
472 /* JMM - workaround rdar://problem/9121297 (CF being too picky on these bits). */
473 *typep
&= ~(MACH_PORT_TYPE_SPREQUEST
| MACH_PORT_TYPE_SPREQUEST_DELAYED
);
480 * Routine: mach_port_rename [kernel call]
482 * Changes the name denoting a right,
483 * from oname to nname.
487 * KERN_SUCCESS The right is renamed.
488 * KERN_INVALID_TASK The space is null.
489 * KERN_INVALID_TASK The space is dead.
490 * KERN_INVALID_NAME The oname doesn't denote a right.
491 * KERN_INVALID_VALUE The nname isn't a legal name.
492 * KERN_NAME_EXISTS The nname already denotes a right.
493 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
495 * This interface is obsolete and always returns
496 * KERN_NOT_SUPPORTED.
501 __unused ipc_space_t space
,
502 __unused mach_port_name_t oname
,
503 __unused mach_port_name_t nname
)
505 return KERN_NOT_SUPPORTED
;
510 * Routine: mach_port_allocate_name [kernel call]
512 * Allocates a right in a space, using a specific name
513 * for the new right. Possible rights:
514 * MACH_PORT_RIGHT_RECEIVE
515 * MACH_PORT_RIGHT_PORT_SET
516 * MACH_PORT_RIGHT_DEAD_NAME
518 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
519 * has no extant send or send-once rights and no queued
520 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
521 * and its make-send count is 0. It is not a member of
522 * a port set. It has no registered no-senders or
523 * port-destroyed notification requests.
525 * A new port set has no members.
527 * A new dead name has one user reference.
531 * KERN_SUCCESS The right is allocated.
532 * KERN_INVALID_TASK The space is null.
533 * KERN_INVALID_TASK The space is dead.
534 * KERN_INVALID_VALUE The name isn't a legal name.
535 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
536 * KERN_NAME_EXISTS The name already denotes a right.
537 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
539 * Restrictions on name allocation: NT bits are reserved by kernel,
540 * must be set on any chosen name. Can't do this at all in kernel
545 mach_port_allocate_name(
547 mach_port_right_t right
,
548 mach_port_name_t name
)
551 mach_port_qos_t qos
= qos_template
;
555 if (!MACH_PORT_VALID(name
))
556 return KERN_INVALID_VALUE
;
558 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
564 * Routine: mach_port_allocate [kernel call]
566 * Allocates a right in a space. Like mach_port_allocate_name,
567 * except that the implementation picks a name for the right.
568 * The name may be any legal name in the space that doesn't
569 * currently denote a right.
573 * KERN_SUCCESS The right is allocated.
574 * KERN_INVALID_TASK The space is null.
575 * KERN_INVALID_TASK The space is dead.
576 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
577 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
578 * KERN_NO_SPACE No room in space for another right.
584 mach_port_right_t right
,
585 mach_port_name_t
*namep
)
588 mach_port_qos_t qos
= qos_template
;
590 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
596 * Routine: mach_port_allocate_qos [kernel call]
598 * Allocates a right, with qos options, in a space. Like
599 * mach_port_allocate_name, except that the implementation
600 * picks a name for the right. The name may be any legal name
601 * in the space that doesn't currently denote a right.
605 * KERN_SUCCESS The right is allocated.
606 * KERN_INVALID_TASK The space is null.
607 * KERN_INVALID_TASK The space is dead.
608 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
609 * KERN_INVALID_ARGUMENT The qos request was invalid.
610 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
611 * KERN_NO_SPACE No room in space for another right.
615 mach_port_allocate_qos(
617 mach_port_right_t right
,
618 mach_port_qos_t
*qosp
,
619 mach_port_name_t
*namep
)
624 return KERN_INVALID_ARGUMENT
;
625 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
631 * Routine: mach_port_allocate_full [kernel call]
633 * Allocates a right in a space. Supports all of the
634 * special cases, such as specifying a subsystem,
635 * a specific name, a real-time port, etc.
636 * The name may be any legal name in the space that doesn't
637 * currently denote a right.
641 * KERN_SUCCESS The right is allocated.
642 * KERN_INVALID_TASK The space is null.
643 * KERN_INVALID_TASK The space is dead.
644 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
645 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
646 * KERN_NO_SPACE No room in space for another right.
650 mach_port_allocate_full(
652 mach_port_right_t right
,
654 mach_port_qos_t
*qosp
,
655 mach_port_name_t
*namep
)
657 ipc_kmsg_t kmsg
= IKM_NULL
;
660 if (space
== IS_NULL
)
661 return (KERN_INVALID_TASK
);
663 if (proto
!= MACH_PORT_NULL
)
664 return (KERN_INVALID_VALUE
);
667 if (!MACH_PORT_VALID (*namep
))
668 return (KERN_INVALID_VALUE
);
671 if (qosp
->prealloc
) {
672 if (qosp
->len
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
) {
673 return KERN_RESOURCE_SHORTAGE
;
675 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
677 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
678 return (KERN_INVALID_VALUE
);
680 kmsg
= (ipc_kmsg_t
)ipc_kmsg_prealloc(size
);
681 if (kmsg
== IKM_NULL
)
682 return (KERN_RESOURCE_SHORTAGE
);
687 case MACH_PORT_RIGHT_RECEIVE
:
692 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
694 kr
= ipc_port_alloc(space
, namep
, &port
);
695 if (kr
== KERN_SUCCESS
) {
696 if (kmsg
!= IKM_NULL
)
697 ipc_kmsg_set_prealloc(kmsg
, port
);
701 } else if (kmsg
!= IKM_NULL
)
706 case MACH_PORT_RIGHT_PORT_SET
:
711 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
713 kr
= ipc_pset_alloc(space
, namep
, &pset
);
714 if (kr
== KERN_SUCCESS
)
719 case MACH_PORT_RIGHT_DEAD_NAME
:
720 kr
= ipc_object_alloc_dead(space
, namep
);
724 kr
= KERN_INVALID_VALUE
;
732 * Routine: mach_port_destroy [kernel call]
734 * Cleans up and destroys all rights denoted by a name
735 * in a space. The destruction of a receive right
736 * destroys the port, unless a port-destroyed request
737 * has been made for it; the destruction of a port-set right
738 * destroys the port set.
742 * KERN_SUCCESS The name is destroyed.
743 * KERN_INVALID_TASK The space is null.
744 * KERN_INVALID_TASK The space is dead.
745 * KERN_INVALID_NAME The name doesn't denote a right.
751 mach_port_name_t name
)
756 if (space
== IS_NULL
)
757 return KERN_INVALID_TASK
;
759 if (!MACH_PORT_VALID(name
))
762 kr
= ipc_right_lookup_write(space
, name
, &entry
);
763 if (kr
!= KERN_SUCCESS
)
765 /* space is write-locked and active */
767 kr
= ipc_right_destroy(space
, name
, entry
, TRUE
, 0); /* unlocks space */
772 * Routine: mach_port_deallocate [kernel call]
774 * Deallocates a user reference from a send right,
775 * send-once right, or a dead-name right. May
776 * deallocate the right, if this is the last uref,
777 * and destroy the name, if it doesn't denote
782 * KERN_SUCCESS The uref is deallocated.
783 * KERN_INVALID_TASK The space is null.
784 * KERN_INVALID_TASK The space is dead.
785 * KERN_INVALID_NAME The name doesn't denote a right.
786 * KERN_INVALID_RIGHT The right isn't correct.
790 mach_port_deallocate(
792 mach_port_name_t name
)
797 if (space
== IS_NULL
)
798 return KERN_INVALID_TASK
;
800 if (!MACH_PORT_VALID(name
))
803 kr
= ipc_right_lookup_write(space
, name
, &entry
);
804 if (kr
!= KERN_SUCCESS
)
806 /* space is write-locked */
808 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
813 * Routine: mach_port_get_refs [kernel call]
815 * Retrieves the number of user references held by a right.
816 * Receive rights, port-set rights, and send-once rights
817 * always have one user reference. Returns zero if the
818 * name denotes a right, but not the queried right.
822 * KERN_SUCCESS Number of urefs returned.
823 * KERN_INVALID_TASK The space is null.
824 * KERN_INVALID_TASK The space is dead.
825 * KERN_INVALID_VALUE "right" isn't a legal value.
826 * KERN_INVALID_NAME The name doesn't denote a right.
832 mach_port_name_t name
,
833 mach_port_right_t right
,
834 mach_port_urefs_t
*urefsp
)
836 mach_port_type_t type
;
837 mach_port_urefs_t urefs
;
841 if (space
== IS_NULL
)
842 return KERN_INVALID_TASK
;
844 if (right
>= MACH_PORT_RIGHT_NUMBER
)
845 return KERN_INVALID_VALUE
;
847 if (!MACH_PORT_VALID(name
)) {
848 if (right
== MACH_PORT_RIGHT_SEND
||
849 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
853 return KERN_INVALID_NAME
;
856 kr
= ipc_right_lookup_write(space
, name
, &entry
);
857 if (kr
!= KERN_SUCCESS
)
860 /* space is write-locked and active */
861 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
);
862 /* space is unlocked */
864 if (kr
!= KERN_SUCCESS
)
867 if (type
& MACH_PORT_TYPE(right
))
869 case MACH_PORT_RIGHT_SEND_ONCE
:
873 case MACH_PORT_RIGHT_PORT_SET
:
874 case MACH_PORT_RIGHT_RECEIVE
:
878 case MACH_PORT_RIGHT_DEAD_NAME
:
879 case MACH_PORT_RIGHT_SEND
:
885 panic("mach_port_get_refs: strange rights");
894 * Routine: mach_port_mod_refs
896 * Modifies the number of user references held by a right.
897 * The resulting number of user references must be non-negative.
898 * If it is zero, the right is deallocated. If the name
899 * doesn't denote other rights, it is destroyed.
903 * KERN_SUCCESS Modified number of urefs.
904 * KERN_INVALID_TASK The space is null.
905 * KERN_INVALID_TASK The space is dead.
906 * KERN_INVALID_VALUE "right" isn't a legal value.
907 * KERN_INVALID_NAME The name doesn't denote a right.
908 * KERN_INVALID_RIGHT Name doesn't denote specified right.
909 * KERN_INVALID_VALUE Impossible modification to urefs.
910 * KERN_UREFS_OVERFLOW Urefs would overflow.
916 mach_port_name_t name
,
917 mach_port_right_t right
,
918 mach_port_delta_t delta
)
923 if (space
== IS_NULL
)
924 return KERN_INVALID_TASK
;
926 if (right
>= MACH_PORT_RIGHT_NUMBER
)
927 return KERN_INVALID_VALUE
;
929 if (!MACH_PORT_VALID(name
)) {
930 if (right
== MACH_PORT_RIGHT_SEND
||
931 right
== MACH_PORT_RIGHT_SEND_ONCE
)
933 return KERN_INVALID_NAME
;
936 kr
= ipc_right_lookup_write(space
, name
, &entry
);
937 if (kr
!= KERN_SUCCESS
)
939 /* space is write-locked and active */
941 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
947 * Routine: mach_port_peek [kernel call]
949 * Peek at the message queue for the specified receive
950 * right and return info about a message in the queue.
952 * On input, seqnop points to a sequence number value
953 * to match the message being peeked. If zero is specified
954 * as the seqno, the first message in the queue will be
957 * Only the following trailer types are currently supported:
958 * MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)
960 * or'ed with one of these element types:
961 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_NULL)
962 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SEQNO)
963 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER)
964 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT)
966 * On input, the value pointed to by trailer_sizep must be
967 * large enough to hold the requested trailer size.
969 * The message sequence number, id, size, requested trailer info
970 * and requested trailer size are returned in their respective
971 * output parameters upon success.
976 * KERN_SUCCESS Matching message found, out parameters set.
977 * KERN_INVALID_TASK The space is null or dead.
978 * KERN_INVALID_NAME The name doesn't denote a right.
979 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
980 * KERN_INVALID_VALUE The input parameter values are out of bounds.
981 * KERN_FAILURE The requested message was not found.
987 mach_port_name_t name
,
988 mach_msg_trailer_type_t trailer_type
,
989 mach_port_seqno_t
*seqnop
,
990 mach_msg_size_t
*msg_sizep
,
991 mach_msg_id_t
*msg_idp
,
992 mach_msg_trailer_info_t trailer_infop
,
993 mach_msg_type_number_t
*trailer_sizep
)
998 mach_msg_max_trailer_t max_trailer
;
1000 if (space
== IS_NULL
)
1001 return KERN_INVALID_TASK
;
1003 if (!MACH_PORT_VALID(name
))
1004 return KERN_INVALID_RIGHT
;
1007 * We don't allow anything greater than the audit trailer - to avoid
1008 * leaking the context pointer and to avoid variable-sized context issues.
1010 if (GET_RCV_ELEMENTS(trailer_type
) > MACH_RCV_TRAILER_AUDIT
||
1011 REQUESTED_TRAILER_SIZE(TRUE
, trailer_type
) > *trailer_sizep
)
1012 return KERN_INVALID_VALUE
;
1014 *trailer_sizep
= REQUESTED_TRAILER_SIZE(TRUE
, trailer_type
);
1016 kr
= ipc_port_translate_receive(space
, name
, &port
);
1017 if (kr
!= KERN_SUCCESS
)
1020 /* Port locked and active */
1022 found
= ipc_mqueue_peek(&port
->ip_messages
, seqnop
,
1023 msg_sizep
, msg_idp
, &max_trailer
);
1027 return KERN_FAILURE
;
1029 max_trailer
.msgh_seqno
= *seqnop
;
1030 memcpy(trailer_infop
, &max_trailer
, *trailer_sizep
);
1032 return KERN_SUCCESS
;
1036 * Routine: mach_port_set_mscount [kernel call]
1038 * Changes a receive right's make-send count.
1042 * KERN_SUCCESS Set make-send count.
1043 * KERN_INVALID_TASK The space is null.
1044 * KERN_INVALID_TASK The space is dead.
1045 * KERN_INVALID_NAME The name doesn't denote a right.
1046 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1050 mach_port_set_mscount(
1052 mach_port_name_t name
,
1053 mach_port_mscount_t mscount
)
1058 if (space
== IS_NULL
)
1059 return KERN_INVALID_TASK
;
1061 if (!MACH_PORT_VALID(name
))
1062 return KERN_INVALID_RIGHT
;
1064 kr
= ipc_port_translate_receive(space
, name
, &port
);
1065 if (kr
!= KERN_SUCCESS
)
1067 /* port is locked and active */
1069 ipc_port_set_mscount(port
, mscount
);
1072 return KERN_SUCCESS
;
1076 * Routine: mach_port_set_seqno [kernel call]
1078 * Changes a receive right's sequence number.
1082 * KERN_SUCCESS Set sequence number.
1083 * KERN_INVALID_TASK The space is null.
1084 * KERN_INVALID_TASK The space is dead.
1085 * KERN_INVALID_NAME The name doesn't denote a right.
1086 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1090 mach_port_set_seqno(
1092 mach_port_name_t name
,
1093 mach_port_seqno_t seqno
)
1098 if (space
== IS_NULL
)
1099 return KERN_INVALID_TASK
;
1101 if (!MACH_PORT_VALID(name
))
1102 return KERN_INVALID_RIGHT
;
1104 kr
= ipc_port_translate_receive(space
, name
, &port
);
1105 if (kr
!= KERN_SUCCESS
)
1107 /* port is locked and active */
1109 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
1112 return KERN_SUCCESS
;
1116 * Routine: mach_port_get_context [kernel call]
1118 * Returns a receive right's context pointer.
1122 * KERN_SUCCESS Set context pointer.
1123 * KERN_INVALID_TASK The space is null.
1124 * KERN_INVALID_TASK The space is dead.
1125 * KERN_INVALID_NAME The name doesn't denote a right.
1126 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1130 mach_port_get_context(
1132 mach_port_name_t name
,
1133 mach_vm_address_t
*context
)
1138 if (space
== IS_NULL
)
1139 return KERN_INVALID_TASK
;
1141 if (!MACH_PORT_VALID(name
))
1142 return KERN_INVALID_RIGHT
;
1144 kr
= ipc_port_translate_receive(space
, name
, &port
);
1145 if (kr
!= KERN_SUCCESS
)
1148 /* Port locked and active */
1150 /* For strictly guarded ports, return empty context (which acts as guard) */
1151 if (port
->ip_strict_guard
)
1154 *context
= port
->ip_context
;
1157 return KERN_SUCCESS
;
1162 * Routine: mach_port_set_context [kernel call]
1164 * Changes a receive right's context pointer.
1168 * KERN_SUCCESS Set context pointer.
1169 * KERN_INVALID_TASK The space is null.
1170 * KERN_INVALID_TASK The space is dead.
1171 * KERN_INVALID_NAME The name doesn't denote a right.
1172 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1176 mach_port_set_context(
1178 mach_port_name_t name
,
1179 mach_vm_address_t context
)
1184 if (space
== IS_NULL
)
1185 return KERN_INVALID_TASK
;
1187 if (!MACH_PORT_VALID(name
))
1188 return KERN_INVALID_RIGHT
;
1190 kr
= ipc_port_translate_receive(space
, name
, &port
);
1191 if (kr
!= KERN_SUCCESS
)
1194 /* port is locked and active */
1195 if(port
->ip_strict_guard
) {
1196 uint64_t portguard
= port
->ip_context
;
1198 /* For strictly guarded ports, disallow overwriting context; Raise Exception */
1199 mach_port_guard_exception(name
, context
, portguard
, kGUARD_EXC_SET_CONTEXT
);
1200 return KERN_INVALID_ARGUMENT
;
1203 port
->ip_context
= context
;
1206 return KERN_SUCCESS
;
1211 * Routine: mach_port_get_set_status [kernel call]
1213 * Retrieves a list of members in a port set.
1214 * Returns the space's name for each receive right member.
1218 * KERN_SUCCESS Retrieved list of members.
1219 * KERN_INVALID_TASK The space is null.
1220 * KERN_INVALID_TASK The space is dead.
1221 * KERN_INVALID_NAME The name doesn't denote a right.
1222 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1223 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1227 mach_port_get_set_status(
1229 mach_port_name_t name
,
1230 mach_port_name_t
**members
,
1231 mach_msg_type_number_t
*membersCnt
)
1233 ipc_entry_num_t actual
; /* this many members */
1234 ipc_entry_num_t maxnames
; /* space for this many members */
1237 vm_size_t size
; /* size of allocated memory */
1238 vm_offset_t addr
; /* allocated memory */
1239 vm_map_copy_t memory
; /* copied-in memory */
1241 if (space
== IS_NULL
)
1242 return KERN_INVALID_TASK
;
1244 if (!MACH_PORT_VALID(name
))
1245 return KERN_INVALID_RIGHT
;
1247 size
= VM_MAP_PAGE_SIZE(ipc_kernel_map
); /* initial guess */
1250 mach_port_name_t
*names
;
1254 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, VM_FLAGS_ANYWHERE
);
1255 if (kr
!= KERN_SUCCESS
)
1256 return KERN_RESOURCE_SHORTAGE
;
1258 /* can't fault while we hold locks */
1260 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1261 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1262 assert(kr
== KERN_SUCCESS
);
1264 kr
= ipc_object_translate(space
, name
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1265 if (kr
!= KERN_SUCCESS
) {
1266 kmem_free(ipc_kernel_map
, addr
, size
);
1270 /* just use a portset reference from here on out */
1271 pset
= (ipc_pset_t
) psobj
;
1272 ips_reference(pset
);
1275 names
= (mach_port_name_t
*) addr
;
1276 maxnames
= (ipc_entry_num_t
)(size
/ sizeof(mach_port_name_t
));
1278 ipc_mqueue_set_gather_member_names(&pset
->ips_messages
, maxnames
, names
, &actual
);
1280 /* release the portset reference */
1283 if (actual
<= maxnames
)
1286 /* didn't have enough memory; allocate more */
1287 kmem_free(ipc_kernel_map
, addr
, size
);
1288 size
= vm_map_round_page(
1289 (actual
* sizeof(mach_port_name_t
)),
1290 VM_MAP_PAGE_MASK(ipc_kernel_map
)) +
1291 VM_MAP_PAGE_SIZE(ipc_kernel_map
);
1295 memory
= VM_MAP_COPY_NULL
;
1297 kmem_free(ipc_kernel_map
, addr
, size
);
1299 vm_size_t size_used
;
1300 vm_size_t vm_size_used
;
1302 size_used
= actual
* sizeof(mach_port_name_t
);
1303 vm_size_used
= vm_map_round_page(
1305 VM_MAP_PAGE_MASK(ipc_kernel_map
));
1308 * Make used memory pageable and get it into
1309 * copied-in form. Free any unused memory.
1314 vm_map_trunc_page(addr
,
1315 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
1316 vm_map_round_page(addr
+ vm_size_used
,
1317 VM_MAP_PAGE_MASK(ipc_kernel_map
)),
1319 assert(kr
== KERN_SUCCESS
);
1321 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr
,
1322 (vm_map_size_t
)size_used
, TRUE
, &memory
);
1323 assert(kr
== KERN_SUCCESS
);
1325 if (vm_size_used
!= size
)
1326 kmem_free(ipc_kernel_map
,
1327 addr
+ vm_size_used
, size
- vm_size_used
);
1330 *members
= (mach_port_name_t
*) memory
;
1331 *membersCnt
= actual
;
1332 return KERN_SUCCESS
;
1336 * Routine: mach_port_move_member [kernel call]
1338 * If after is MACH_PORT_NULL, removes member
1339 * from the port set it is in. Otherwise, adds
1340 * member to after, removing it from any set
1341 * it might already be in.
1345 * KERN_SUCCESS Moved the port.
1346 * KERN_INVALID_TASK The space is null.
1347 * KERN_INVALID_TASK The space is dead.
1348 * KERN_INVALID_NAME Member didn't denote a right.
1349 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1350 * KERN_INVALID_NAME After didn't denote a right.
1351 * KERN_INVALID_RIGHT After didn't denote a port set right.
1353 * After is MACH_PORT_NULL and Member isn't in a port set.
1357 mach_port_move_member(
1359 mach_port_name_t member
,
1360 mach_port_name_t after
)
1366 wait_queue_link_t wql
;
1367 queue_head_t links_data
;
1368 queue_t links
= &links_data
;
1370 if (space
== IS_NULL
)
1371 return KERN_INVALID_TASK
;
1373 if (!MACH_PORT_VALID(member
))
1374 return KERN_INVALID_RIGHT
;
1376 if (after
== MACH_PORT_DEAD
)
1377 return KERN_INVALID_RIGHT
;
1378 else if (after
== MACH_PORT_NULL
)
1379 wql
= WAIT_QUEUE_LINK_NULL
;
1381 wql
= wait_queue_link_allocate();
1385 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1386 if (kr
!= KERN_SUCCESS
)
1388 /* space is read-locked and active */
1390 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1391 is_read_unlock(space
);
1392 kr
= KERN_INVALID_RIGHT
;
1396 port
= (ipc_port_t
) entry
->ie_object
;
1397 assert(port
!= IP_NULL
);
1399 if (after
== MACH_PORT_NULL
)
1402 entry
= ipc_entry_lookup(space
, after
);
1403 if (entry
== IE_NULL
) {
1404 is_read_unlock(space
);
1405 kr
= KERN_INVALID_NAME
;
1409 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1410 is_read_unlock(space
);
1411 kr
= KERN_INVALID_RIGHT
;
1415 nset
= (ipc_pset_t
) entry
->ie_object
;
1416 assert(nset
!= IPS_NULL
);
1419 ipc_pset_remove_from_all(port
, links
);
1421 if (nset
!= IPS_NULL
) {
1423 kr
= ipc_pset_add(nset
, port
, wql
);
1427 is_read_unlock(space
);
1430 if (kr
!= KERN_SUCCESS
&& wql
!= WAIT_QUEUE_LINK_NULL
)
1431 wait_queue_link_free(wql
);
1432 while(!queue_empty(links
)) {
1433 wql
= (wait_queue_link_t
) dequeue(links
);
1434 wait_queue_link_free(wql
);
1441 * Routine: mach_port_request_notification [kernel call]
1443 * Requests a notification. The caller supplies
1444 * a send-once right for the notification to use,
1445 * and the call returns the previously registered
1446 * send-once right, if any. Possible types:
1448 * MACH_NOTIFY_PORT_DESTROYED
1449 * Requests a port-destroyed notification
1450 * for a receive right. Sync should be zero.
1451 * MACH_NOTIFY_NO_SENDERS
1452 * Requests a no-senders notification for a
1453 * receive right. If there are currently no
1454 * senders, sync is less than or equal to the
1455 * current make-send count, and a send-once right
1456 * is supplied, then an immediate no-senders
1457 * notification is generated.
1458 * MACH_NOTIFY_DEAD_NAME
1459 * Requests a dead-name notification for a send
1460 * or receive right. If the name is already a
1461 * dead name, sync is non-zero, and a send-once
1462 * right is supplied, then an immediate dead-name
1463 * notification is generated.
1467 * KERN_SUCCESS Requested a notification.
1468 * KERN_INVALID_TASK The space is null.
1469 * KERN_INVALID_TASK The space is dead.
1470 * KERN_INVALID_VALUE Bad id value.
1471 * KERN_INVALID_NAME Name doesn't denote a right.
1472 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1473 * KERN_INVALID_CAPABILITY The notify port is dead.
1474 * MACH_NOTIFY_PORT_DESTROYED:
1475 * KERN_INVALID_VALUE Sync isn't zero.
1476 * MACH_NOTIFY_DEAD_NAME:
1477 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1478 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1479 * sync is zero or notify is IP_NULL.
1480 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1481 * generating immediate notif. would overflow urefs.
1485 mach_port_request_notification(
1487 mach_port_name_t name
,
1489 mach_port_mscount_t sync
,
1491 ipc_port_t
*previousp
)
1495 if (space
== IS_NULL
)
1496 return KERN_INVALID_TASK
;
1498 if (notify
== IP_DEAD
)
1499 return KERN_INVALID_CAPABILITY
;
1503 * Requesting notifications on RPC ports is an error.
1509 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1510 if (kr
!= KERN_SUCCESS
)
1513 port
= (ipc_port_t
) entry
->ie_object
;
1515 if (port
->ip_subsystem
!= NULL
) {
1516 is_write_unlock(space
);
1517 panic("mach_port_request_notification: on RPC port!!");
1518 return KERN_INVALID_CAPABILITY
;
1520 is_write_unlock(space
);
1526 case MACH_NOTIFY_PORT_DESTROYED
: {
1527 ipc_port_t port
, previous
;
1530 return KERN_INVALID_VALUE
;
1532 if (!MACH_PORT_VALID(name
))
1533 return KERN_INVALID_RIGHT
;
1535 kr
= ipc_port_translate_receive(space
, name
, &port
);
1536 if (kr
!= KERN_SUCCESS
)
1538 /* port is locked and active */
1540 ipc_port_pdrequest(port
, notify
, &previous
);
1541 /* port is unlocked */
1543 *previousp
= previous
;
1547 case MACH_NOTIFY_NO_SENDERS
: {
1550 if (!MACH_PORT_VALID(name
))
1551 return KERN_INVALID_RIGHT
;
1553 kr
= ipc_port_translate_receive(space
, name
, &port
);
1554 if (kr
!= KERN_SUCCESS
)
1556 /* port is locked and active */
1558 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1559 /* port is unlocked */
1563 case MACH_NOTIFY_SEND_POSSIBLE
:
1565 if (!MACH_PORT_VALID(name
)) {
1566 return KERN_INVALID_ARGUMENT
;
1569 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1570 TRUE
, notify
, previousp
);
1571 if (kr
!= KERN_SUCCESS
)
1575 case MACH_NOTIFY_DEAD_NAME
:
1577 if (!MACH_PORT_VALID(name
)) {
1580 * Should do immediate delivery check -
1581 * will do that in the near future.
1583 return KERN_INVALID_ARGUMENT
;
1586 kr
= ipc_right_request_alloc(space
, name
, sync
!= 0,
1587 FALSE
, notify
, previousp
);
1588 if (kr
!= KERN_SUCCESS
)
1593 return KERN_INVALID_VALUE
;
1596 return KERN_SUCCESS
;
1600 * Routine: mach_port_insert_right [kernel call]
1602 * Inserts a right into a space, as if the space
1603 * voluntarily received the right in a message,
1604 * except that the right gets the specified name.
1608 * KERN_SUCCESS Inserted the right.
1609 * KERN_INVALID_TASK The space is null.
1610 * KERN_INVALID_TASK The space is dead.
1611 * KERN_INVALID_VALUE The name isn't a legal name.
1612 * KERN_NAME_EXISTS The name already denotes a right.
1613 * KERN_INVALID_VALUE Message doesn't carry a port right.
1614 * KERN_INVALID_CAPABILITY Port is null or dead.
1615 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1616 * KERN_RIGHT_EXISTS Space has rights under another name.
1617 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1621 mach_port_insert_right(
1623 mach_port_name_t name
,
1625 mach_msg_type_name_t polyPoly
)
1627 if (space
== IS_NULL
)
1628 return KERN_INVALID_TASK
;
1630 if (!MACH_PORT_VALID(name
) ||
1631 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1632 return KERN_INVALID_VALUE
;
1634 if (!IO_VALID((ipc_object_t
) poly
))
1635 return KERN_INVALID_CAPABILITY
;
1637 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1638 polyPoly
, FALSE
, name
);
1642 * Routine: mach_port_extract_right [kernel call]
1644 * Extracts a right from a space, as if the space
1645 * voluntarily sent the right to the caller.
1649 * KERN_SUCCESS Extracted the right.
1650 * KERN_INVALID_TASK The space is null.
1651 * KERN_INVALID_TASK The space is dead.
1652 * KERN_INVALID_VALUE Requested type isn't a port right.
1653 * KERN_INVALID_NAME Name doesn't denote a right.
1654 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1658 mach_port_extract_right(
1660 mach_port_name_t name
,
1661 mach_msg_type_name_t msgt_name
,
1663 mach_msg_type_name_t
*polyPoly
)
1667 if (space
== IS_NULL
)
1668 return KERN_INVALID_TASK
;
1670 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1671 return KERN_INVALID_VALUE
;
1673 if (!MACH_PORT_VALID(name
)) {
1675 * really should copy out a dead name, if it is a send or
1676 * send-once right being copied, but instead return an
1679 return KERN_INVALID_RIGHT
;
1682 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1684 if (kr
== KERN_SUCCESS
)
1685 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1690 * Routine: mach_port_get_status_helper [helper]
1692 * Populates a mach_port_status_t structure with
1695 * Port needs to be locked
1699 void mach_port_get_status_helper(
1701 mach_port_status_t
*statusp
)
1704 statusp
->mps_pset
= port
->ip_pset_count
;
1707 imq_lock(&port
->ip_messages
);
1708 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1709 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1710 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1711 imq_unlock(&port
->ip_messages
);
1714 statusp
->mps_mscount
= port
->ip_mscount
;
1715 statusp
->mps_sorights
= port
->ip_sorights
;
1716 statusp
->mps_srights
= port
->ip_srights
> 0;
1717 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1718 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1719 statusp
->mps_flags
= 0;
1720 statusp
->mps_flags
|= ((port
->ip_impdonation
) ? MACH_PORT_STATUS_FLAG_IMP_DONATION
:0);
1721 statusp
->mps_flags
|= ((port
->ip_tempowner
) ? MACH_PORT_STATUS_FLAG_TEMPOWNER
:0);
1722 statusp
->mps_flags
|= ((port
->ip_taskptr
) ? MACH_PORT_STATUS_FLAG_TASKPTR
:0);
1723 statusp
->mps_flags
|= ((port
->ip_guarded
) ? MACH_PORT_STATUS_FLAG_GUARDED
:0);
1724 statusp
->mps_flags
|= ((port
->ip_strict_guard
) ? MACH_PORT_STATUS_FLAG_STRICT_GUARD
:0);
1731 mach_port_get_attributes(
1733 mach_port_name_t name
,
1735 mach_port_info_t info
,
1736 mach_msg_type_number_t
*count
)
1741 if (space
== IS_NULL
)
1742 return KERN_INVALID_TASK
;
1745 case MACH_PORT_LIMITS_INFO
: {
1746 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1748 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1749 return KERN_FAILURE
;
1751 if (!MACH_PORT_VALID(name
)) {
1756 kr
= ipc_port_translate_receive(space
, name
, &port
);
1757 if (kr
!= KERN_SUCCESS
)
1759 /* port is locked and active */
1761 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1762 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1767 case MACH_PORT_RECEIVE_STATUS
: {
1768 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1770 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1771 return KERN_FAILURE
;
1773 if (!MACH_PORT_VALID(name
))
1774 return KERN_INVALID_RIGHT
;
1776 kr
= ipc_port_translate_receive(space
, name
, &port
);
1777 if (kr
!= KERN_SUCCESS
)
1779 /* port is locked and active */
1780 mach_port_get_status_helper(port
, statusp
);
1781 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1786 case MACH_PORT_DNREQUESTS_SIZE
: {
1787 ipc_port_request_t table
;
1789 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1790 return KERN_FAILURE
;
1792 if (!MACH_PORT_VALID(name
)) {
1797 kr
= ipc_port_translate_receive(space
, name
, &port
);
1798 if (kr
!= KERN_SUCCESS
)
1800 /* port is locked and active */
1802 table
= port
->ip_requests
;
1803 if (table
== IPR_NULL
)
1806 *(int *)info
= table
->ipr_size
->its_size
;
1807 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1812 case MACH_PORT_INFO_EXT
: {
1813 mach_port_info_ext_t
*mp_info
= (mach_port_info_ext_t
*)info
;
1814 if (*count
< MACH_PORT_INFO_EXT_COUNT
)
1815 return KERN_FAILURE
;
1817 if (!MACH_PORT_VALID(name
))
1818 return KERN_INVALID_RIGHT
;
1820 kr
= ipc_port_translate_receive(space
, name
, &port
);
1821 if (kr
!= KERN_SUCCESS
)
1823 /* port is locked and active */
1824 mach_port_get_status_helper(port
, &mp_info
->mpie_status
);
1825 mp_info
->mpie_boost_cnt
= port
->ip_impcount
;
1826 *count
= MACH_PORT_INFO_EXT_COUNT
;
1832 return KERN_INVALID_ARGUMENT
;
1836 return KERN_SUCCESS
;
1840 mach_port_set_attributes(
1842 mach_port_name_t name
,
1844 mach_port_info_t info
,
1845 mach_msg_type_number_t count
)
1850 if (space
== IS_NULL
)
1851 return KERN_INVALID_TASK
;
1855 case MACH_PORT_LIMITS_INFO
: {
1856 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1858 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1859 return KERN_FAILURE
;
1861 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1862 return KERN_INVALID_VALUE
;
1864 if (!MACH_PORT_VALID(name
))
1865 return KERN_INVALID_RIGHT
;
1867 kr
= ipc_port_translate_receive(space
, name
, &port
);
1868 if (kr
!= KERN_SUCCESS
)
1870 /* port is locked and active */
1872 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1876 case MACH_PORT_DNREQUESTS_SIZE
: {
1877 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1878 return KERN_FAILURE
;
1880 if (!MACH_PORT_VALID(name
))
1881 return KERN_INVALID_RIGHT
;
1883 kr
= ipc_port_translate_receive(space
, name
, &port
);
1884 if (kr
!= KERN_SUCCESS
)
1886 /* port is locked and active */
1888 kr
= ipc_port_request_grow(port
, *(int *)info
);
1889 if (kr
!= KERN_SUCCESS
)
1893 case MACH_PORT_TEMPOWNER
:
1894 if (!MACH_PORT_VALID(name
))
1895 return KERN_INVALID_RIGHT
;
1897 task_t release_imp_task
= TASK_NULL
;
1898 natural_t assertcnt
= 0;
1900 kr
= ipc_port_translate_receive(space
, name
, &port
);
1901 if (kr
!= KERN_SUCCESS
)
1904 /* port is locked and active */
1906 if (port
->ip_tempowner
!= 0) {
1907 if (port
->ip_taskptr
!= 0) {
1908 release_imp_task
= port
->ip_imp_task
;
1909 port
->ip_taskptr
= 0;
1910 port
->ip_imp_task
= TASK_NULL
;
1911 assertcnt
= port
->ip_impcount
;
1914 assertcnt
= port
->ip_impcount
;
1917 port
->ip_impdonation
= 1;
1918 port
->ip_tempowner
= 1;
1921 #if IMPORTANCE_INHERITANCE
1922 /* drop assertions from previous destination task */
1923 if (release_imp_task
!= TASK_NULL
) {
1924 assert(release_imp_task
->imp_receiver
!= 0);
1926 task_importance_drop_internal_assertion(release_imp_task
, assertcnt
);
1927 task_deallocate(release_imp_task
);
1928 } else if (assertcnt
> 0) {
1929 release_imp_task
= current_task();
1930 if (release_imp_task
->imp_receiver
!= 0)
1931 task_importance_drop_internal_assertion(release_imp_task
, assertcnt
);
1934 if (release_imp_task
!= TASK_NULL
)
1935 task_deallocate(release_imp_task
);
1936 #endif /* IMPORTANCE_INHERITANCE */
1939 #if IMPORTANCE_INHERITANCE
1940 case MACH_PORT_IMPORTANCE_RECEIVER
:
1941 if (!MACH_PORT_VALID(name
))
1942 return KERN_INVALID_RIGHT
;
1944 kr
= ipc_port_translate_receive(space
, name
, &port
);
1945 if (kr
!= KERN_SUCCESS
)
1947 /* port is locked and active */
1949 port
->ip_impdonation
= 1;
1953 #endif /* IMPORTANCE_INHERITANCE */
1956 return KERN_INVALID_ARGUMENT
;
1959 return KERN_SUCCESS
;
1963 * Routine: mach_port_insert_member [kernel call]
1965 * Add the receive right, specified by name, to
1967 * The port cannot already be a member of the set.
1971 * KERN_SUCCESS Moved the port.
1972 * KERN_INVALID_TASK The space is null.
1973 * KERN_INVALID_TASK The space is dead.
1974 * KERN_INVALID_NAME name didn't denote a right.
1975 * KERN_INVALID_RIGHT name didn't denote a receive right.
1976 * KERN_INVALID_NAME pset_name didn't denote a right.
1977 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1978 * KERN_ALREADY_IN_SET name was already a member of pset.
1982 mach_port_insert_member(
1984 mach_port_name_t name
,
1985 mach_port_name_t psname
)
1990 wait_queue_link_t wql
;
1992 if (space
== IS_NULL
)
1993 return KERN_INVALID_TASK
;
1995 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1996 return KERN_INVALID_RIGHT
;
1998 wql
= wait_queue_link_allocate();
2000 kr
= ipc_object_translate_two(space
,
2001 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
2002 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
2003 if (kr
!= KERN_SUCCESS
)
2006 /* obj and psobj are locked (and were locked in that order) */
2007 assert(psobj
!= IO_NULL
);
2008 assert(obj
!= IO_NULL
);
2010 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
, wql
);
2015 if (kr
!= KERN_SUCCESS
)
2016 wait_queue_link_free(wql
);
2022 * Routine: mach_port_extract_member [kernel call]
2024 * Remove a port from one portset that it is a member of.
2028 * KERN_SUCCESS Moved the port.
2029 * KERN_INVALID_TASK The space is null.
2030 * KERN_INVALID_TASK The space is dead.
2031 * KERN_INVALID_NAME Member didn't denote a right.
2032 * KERN_INVALID_RIGHT Member didn't denote a receive right.
2033 * KERN_INVALID_NAME After didn't denote a right.
2034 * KERN_INVALID_RIGHT After didn't denote a port set right.
2036 * After is MACH_PORT_NULL and Member isn't in a port set.
2040 mach_port_extract_member(
2042 mach_port_name_t name
,
2043 mach_port_name_t psname
)
2048 wait_queue_link_t wql
= WAIT_QUEUE_LINK_NULL
;
2050 if (space
== IS_NULL
)
2051 return KERN_INVALID_TASK
;
2053 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
2054 return KERN_INVALID_RIGHT
;
2056 kr
= ipc_object_translate_two(space
,
2057 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
2058 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
2059 if (kr
!= KERN_SUCCESS
)
2062 /* obj and psobj are both locked (and were locked in that order) */
2063 assert(psobj
!= IO_NULL
);
2064 assert(obj
!= IO_NULL
);
2066 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
, &wql
);
2070 if (wql
!= WAIT_QUEUE_LINK_NULL
)
2071 wait_queue_link_free(wql
);
2077 * task_set_port_space:
2079 * Set port name space of task to specified size.
2082 task_set_port_space(
2088 is_write_lock(space
);
2090 if (!is_active(space
)) {
2091 is_write_unlock(space
);
2092 return KERN_INVALID_TASK
;
2095 kr
= ipc_entry_grow_table(space
, table_entries
);
2096 if (kr
== KERN_SUCCESS
)
2097 is_write_unlock(space
);
2102 * Routine: mach_port_guard_locked [helper routine]
2104 * Sets a new guard for a locked port.
2108 * KERN_SUCCESS Port Guarded.
2109 * KERN_INVALID_ARGUMENT Port already contains a context/guard.
2111 static kern_return_t
2112 mach_port_guard_locked(
2117 if (port
->ip_context
)
2118 return KERN_INVALID_ARGUMENT
;
2120 port
->ip_context
= guard
;
2121 port
->ip_guarded
= 1;
2122 port
->ip_strict_guard
= (strict
)?1:0;
2123 return KERN_SUCCESS
;
2127 * Routine: mach_port_unguard_locked [helper routine]
2129 * Removes guard for a locked port.
2133 * KERN_SUCCESS Port Unguarded.
2134 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
2135 * This also raises a EXC_GUARD exception.
2137 static kern_return_t
2138 mach_port_unguard_locked(
2140 mach_port_name_t name
,
2143 /* Port locked and active */
2144 if (!port
->ip_guarded
) {
2145 /* Port already unguarded; Raise exception */
2146 mach_port_guard_exception(name
, guard
, 0, kGUARD_EXC_UNGUARDED
);
2147 return KERN_INVALID_ARGUMENT
;
2150 if (port
->ip_context
!= guard
) {
2151 /* Incorrect guard; Raise exception */
2152 mach_port_guard_exception(name
, guard
, port
->ip_context
, kGUARD_EXC_INCORRECT_GUARD
);
2153 return KERN_INVALID_ARGUMENT
;
2156 port
->ip_context
= 0;
2157 port
->ip_guarded
= port
->ip_strict_guard
= 0;
2158 return KERN_SUCCESS
;
2163 * Routine: mach_port_guard_exception [helper routine]
2165 * Marks the thread with AST_GUARD for mach port guard violation.
2166 * Also saves exception info in thread structure.
2170 * KERN_FAILURE Thread marked with AST_GUARD.
2173 mach_port_guard_exception(
2174 mach_port_name_t name
,
2179 thread_t t
= current_thread();
2180 uint64_t code
, subcode
;
2182 /* Log exception info to syslog */
2183 printf( "Mach Port Guard Exception - "
2186 "Expected Guard: 0x%x, "
2187 "Received Guard: 0x%x\n",
2190 (unsigned)portguard
,
2194 * EXC_GUARD namespace for mach ports
2197 * Mach Port guards use the exception codes like
2200 * +----------------------------------------------------------------+
2201 * |[63:61] GUARD_TYPE_MACH_PORT | [60:32] flavor | [31:0] port name|
2202 * +----------------------------------------------------------------+
2205 * +----------------------------------------------------------------+
2206 * | [63:0] guard value |
2207 * +----------------------------------------------------------------+
2210 code
= (((uint64_t)GUARD_TYPE_MACH_PORT
) << 61) |
2211 (((uint64_t)reason
) << 32) |
2213 subcode
= (uint64_t)(portguard
);
2215 t
->guard_exc_info
.code
= code
;
2216 t
->guard_exc_info
.subcode
= subcode
;
2218 /* Mark thread with AST_GUARD */
2219 thread_guard_violation(t
, GUARD_TYPE_MACH_PORT
);
2220 return KERN_FAILURE
;
2225 * Routine: mach_port_guard_ast
2227 * Raises an exception for mach port guard violation.
2235 mach_port_guard_ast(thread_t t
)
2237 mach_exception_data_type_t code
[EXCEPTION_CODE_MAX
];
2239 code
[0] = t
->guard_exc_info
.code
;
2240 code
[1] = t
->guard_exc_info
.subcode
;
2242 /* Raise an EXC_GUARD exception */
2243 exception_triage(EXC_GUARD
, code
, EXCEPTION_CODE_MAX
);
2245 /* Terminate task which caused the exception */
2246 (void) task_terminate_internal(current_task());
2251 * Routine: mach_port_construct [kernel call]
2253 * Constructs a mach port with the provided set of options.
2257 * KERN_SUCCESS The right is allocated.
2258 * KERN_INVALID_TASK The space is null.
2259 * KERN_INVALID_TASK The space is dead.
2260 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
2261 * KERN_NO_SPACE No room in space for another right.
2262 * KERN_FAILURE Illegal option values requested.
2266 mach_port_construct(
2268 mach_port_options_t
*options
,
2270 mach_port_name_t
*name
)
2275 if (space
== IS_NULL
)
2276 return (KERN_INVALID_TASK
);
2278 /* Allocate a new port in the IPC space */
2279 kr
= ipc_port_alloc(space
, name
, &port
);
2280 if (kr
!= KERN_SUCCESS
)
2283 /* Port locked and active */
2284 if (options
->flags
& MPO_CONTEXT_AS_GUARD
) {
2285 kr
= mach_port_guard_locked(port
, (uint64_t) context
, (options
->flags
& MPO_STRICT
));
2286 /* A newly allocated and locked port should always be guarded successfully */
2287 assert(kr
== KERN_SUCCESS
);
2289 port
->ip_context
= context
;
2295 /* Set port attributes as requested */
2297 if (options
->flags
& MPO_QLIMIT
) {
2298 kr
= mach_port_set_attributes(space
, *name
, MACH_PORT_LIMITS_INFO
,
2299 (mach_port_info_t
)&options
->mpl
, sizeof(options
->mpl
)/sizeof(int));
2300 if (kr
!= KERN_SUCCESS
)
2304 if (options
->flags
& MPO_TEMPOWNER
) {
2305 kr
= mach_port_set_attributes(space
, *name
, MACH_PORT_TEMPOWNER
, NULL
, 0);
2306 if (kr
!= KERN_SUCCESS
)
2310 if (options
->flags
& MPO_IMPORTANCE_RECEIVER
) {
2311 kr
= mach_port_set_attributes(space
, *name
, MACH_PORT_IMPORTANCE_RECEIVER
, NULL
, 0);
2312 if (kr
!= KERN_SUCCESS
)
2316 if (options
->flags
& MPO_INSERT_SEND_RIGHT
) {
2317 kr
= ipc_object_copyin(space
, *name
, MACH_MSG_TYPE_MAKE_SEND
, (ipc_object_t
*)&port
);
2318 if (kr
!= KERN_SUCCESS
)
2321 kr
= mach_port_insert_right(space
, *name
, port
, MACH_MSG_TYPE_PORT_SEND
);
2322 if (kr
!= KERN_SUCCESS
)
2326 return KERN_SUCCESS
;
2329 /* Attempt to destroy port. If its already destroyed by some other thread, we're done */
2330 (void) mach_port_destruct(space
, *name
, 0, context
);
2335 * Routine: mach_port_destruct [kernel call]
2337 * Destroys a mach port with appropriate guard
2341 * KERN_SUCCESS The name is destroyed.
2342 * KERN_INVALID_TASK The space is null.
2343 * KERN_INVALID_TASK The space is dead.
2344 * KERN_INVALID_NAME The name doesn't denote a right.
2345 * KERN_INVALID_RIGHT The right isn't correct.
2346 * KERN_INVALID_VALUE The delta for send right is incorrect.
2347 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
2348 * This also raises a EXC_GUARD exception.
2354 mach_port_name_t name
,
2355 mach_port_delta_t srdelta
,
2361 if (space
== IS_NULL
)
2362 return KERN_INVALID_TASK
;
2364 if (!MACH_PORT_VALID(name
))
2365 return KERN_INVALID_NAME
;
2367 /* Remove reference for receive right */
2368 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2369 if (kr
!= KERN_SUCCESS
)
2371 /* space is write-locked and active */
2372 kr
= ipc_right_destruct(space
, name
, entry
, srdelta
, guard
); /* unlocks */
2378 * Routine: mach_port_guard [kernel call]
2380 * Guard a mach port with specified guard value.
2381 * The context field of the port is used as the guard.
2385 * KERN_SUCCESS The name is destroyed.
2386 * KERN_INVALID_TASK The space is null.
2387 * KERN_INVALID_TASK The space is dead.
2388 * KERN_INVALID_NAME The name doesn't denote a right.
2389 * KERN_INVALID_RIGHT The right isn't correct.
2390 * KERN_INVALID_ARGUMENT Port already contains a context/guard.
2395 mach_port_name_t name
,
2402 if (space
== IS_NULL
)
2403 return KERN_INVALID_TASK
;
2405 if (!MACH_PORT_VALID(name
))
2406 return KERN_INVALID_NAME
;
2408 /* Guard can be applied only to receive rights */
2409 kr
= ipc_port_translate_receive(space
, name
, &port
);
2410 if (kr
!= KERN_SUCCESS
)
2413 /* Port locked and active */
2414 kr
= mach_port_guard_locked(port
, guard
, strict
);
2422 * Routine: mach_port_unguard [kernel call]
2424 * Unguard a mach port with specified guard value.
2428 * KERN_SUCCESS The name is destroyed.
2429 * KERN_INVALID_TASK The space is null.
2430 * KERN_INVALID_TASK The space is dead.
2431 * KERN_INVALID_NAME The name doesn't denote a right.
2432 * KERN_INVALID_RIGHT The right isn't correct.
2433 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
2434 * This also raises a EXC_GUARD exception.
2439 mach_port_name_t name
,
2446 if (space
== IS_NULL
)
2447 return KERN_INVALID_TASK
;
2449 if (!MACH_PORT_VALID(name
))
2450 return KERN_INVALID_NAME
;
2452 kr
= ipc_port_translate_receive(space
, name
, &port
);
2453 if (kr
!= KERN_SUCCESS
)
2456 /* Port locked and active */
2457 kr
= mach_port_unguard_locked(port
, name
, guard
);
2463 * Get a (new) label handle representing the given port's port label.
2465 #if CONFIG_MACF_MACH
2469 mach_port_name_t name
,
2470 mach_port_name_t
*outlabel
)
2478 if (!MACH_PORT_VALID(name
))
2479 return KERN_INVALID_NAME
;
2481 /* Lookup the port name in the task's space. */
2482 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2483 if (kr
!= KERN_SUCCESS
)
2486 port
= (ipc_port_t
) entry
->ie_object
;
2487 dead
= ipc_right_check(space
, port
, name
, entry
);
2489 is_write_unlock(space
);
2491 return KERN_INVALID_RIGHT
;
2493 /* port is now locked */
2495 is_write_unlock(space
);
2496 /* Make sure we are not dealing with a label handle. */
2497 if (ip_kotype(port
) == IKOT_LABELH
) {
2498 /* already is a label handle! */
2500 return KERN_INVALID_ARGUMENT
;
2503 /* Copy the port label and stash it in a new label handle. */
2504 mac_port_label_init(&outl
);
2505 mac_port_label_copy(&port
->ip_label
, &outl
);
2506 kr
= labelh_new_user(space
, &outl
, outlabel
);
2509 return KERN_SUCCESS
;
2514 __unused ipc_space_t space
,
2515 __unused mach_port_name_t name
,
2516 __unused mach_port_name_t
*outlabel
)
2518 return KERN_INVALID_ARGUMENT
;
2523 * also works on label handles
2525 #if CONFIG_MACF_MACH
2527 mach_get_label_text(
2529 mach_port_name_t name
,
2530 labelstr_t policies
,
2531 labelstr_t outlabel
)
2539 if (space
== IS_NULL
|| space
->is_task
== NULL
)
2540 return KERN_INVALID_TASK
;
2542 if (!MACH_PORT_VALID(name
))
2543 return KERN_INVALID_NAME
;
2545 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2546 if (kr
!= KERN_SUCCESS
)
2549 port
= (ipc_port_t
)entry
->ie_object
;
2550 dead
= ipc_right_check(space
, port
, name
, entry
);
2552 is_write_unlock(space
);
2554 return KERN_INVALID_RIGHT
;
2556 /* object (port) is now locked */
2558 is_write_unlock (space
);
2559 l
= io_getlabel(entry
->ie_object
);
2561 mac_port_label_externalize(l
, policies
, outlabel
, 512, 0);
2563 io_unlocklabel(entry
->ie_object
);
2564 io_unlock(entry
->ie_object
);
2565 return KERN_SUCCESS
;
2569 mach_get_label_text(
2570 __unused ipc_space_t space
,
2571 __unused mach_port_name_t name
,
2572 __unused labelstr_t policies
,
2573 __unused labelstr_t outlabel
)
2575 return KERN_INVALID_ARGUMENT
;
2580 #if CONFIG_MACF_MACH
2582 mach_set_port_label(
2584 mach_port_name_t name
,
2585 labelstr_t labelstr
)
2593 if (space
== IS_NULL
|| space
->is_task
== NULL
)
2594 return KERN_INVALID_TASK
;
2596 if (!MACH_PORT_VALID(name
))
2597 return KERN_INVALID_NAME
;
2599 mac_port_label_init(&inl
);
2600 rc
= mac_port_label_internalize(&inl
, labelstr
);
2602 return KERN_INVALID_ARGUMENT
;
2604 kr
= ipc_right_lookup_write(space
, name
, &entry
);
2605 if (kr
!= KERN_SUCCESS
)
2608 if (io_otype(entMACry
->ie_object
) != IOT_PORT
) {
2609 is_write_unlock(space
);
2610 return KERN_INVALID_RIGHT
;
2613 port
= (ipc_port_t
) entry
->ie_object
;
2616 tasklabel_lock(space
->is_task
);
2617 rc
= mac_port_check_label_update(&space
->is_task
->maclabel
,
2618 &port
->ip_label
, &inl
);
2619 tasklabel_unlock(space
->is_task
);
2621 kr
= KERN_NO_ACCESS
;
2623 mac_port_label_copy(&inl
, &port
->ip_label
);
2626 is_write_unlock(space
);
2631 mach_set_port_label(
2632 ipc_space_t space __unused
,
2633 mach_port_name_t name __unused
,
2634 labelstr_t labelstr __unused
)
2636 return KERN_INVALID_ARGUMENT
;