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/ipc_object.c
70 * Functions to manipulate IPC objects.
73 #include <mach/mach_types.h>
74 #include <mach/boolean.h>
75 #include <mach/kern_return.h>
76 #include <mach/port.h>
77 #include <mach/message.h>
79 #include <kern/kern_types.h>
80 #include <kern/misc_protos.h>
81 #include <kern/ipc_kobject.h>
83 #include <ipc/ipc_types.h>
84 #include <ipc/ipc_importance.h>
86 #include <ipc/ipc_space.h>
87 #include <ipc/ipc_entry.h>
88 #include <ipc/ipc_object.h>
89 #include <ipc/ipc_hash.h>
90 #include <ipc/ipc_right.h>
91 #include <ipc/ipc_notify.h>
92 #include <ipc/ipc_port.h>
93 #include <ipc/ipc_pset.h>
95 #include <security/mac_mach_internal.h>
97 zone_t ipc_object_zones
[IOT_NUMBER
];
100 * Routine: ipc_object_reference
102 * Take a reference to an object.
106 ipc_object_reference(
109 io_reference(object
);
113 * Routine: ipc_object_release
115 * Release a reference to an object.
126 * Routine: ipc_object_translate
128 * Look up an object in a space.
130 * Nothing locked before. If successful, the object
131 * is returned active and locked. The caller doesn't get a ref.
133 * KERN_SUCCESS Object returned locked.
134 * KERN_INVALID_TASK The space is dead.
135 * KERN_INVALID_NAME The name doesn't denote a right
136 * KERN_INVALID_RIGHT Name doesn't denote the correct right
139 ipc_object_translate(
141 mach_port_name_t name
,
142 mach_port_right_t right
,
143 ipc_object_t
*objectp
)
149 if (!MACH_PORT_RIGHT_VALID_TRANSLATE(right
)) {
150 return KERN_INVALID_RIGHT
;
153 kr
= ipc_right_lookup_read(space
, name
, &entry
);
154 if (kr
!= KERN_SUCCESS
) {
157 /* space is read-locked and active */
159 if ((entry
->ie_bits
& MACH_PORT_TYPE(right
)) == MACH_PORT_TYPE_NONE
) {
160 is_read_unlock(space
);
161 return KERN_INVALID_RIGHT
;
164 object
= entry
->ie_object
;
165 assert(object
!= IO_NULL
);
168 is_read_unlock(space
);
170 if (!io_active(object
)) {
172 return KERN_INVALID_NAME
;
180 * Routine: ipc_object_translate_two
182 * Look up two objects in a space.
184 * Nothing locked before. If successful, the objects
185 * are returned locked. The caller doesn't get a ref.
187 * KERN_SUCCESS Objects returned locked.
188 * KERN_INVALID_TASK The space is dead.
189 * KERN_INVALID_NAME A name doesn't denote a right.
190 * KERN_INVALID_RIGHT A name doesn't denote the correct right.
194 ipc_object_translate_two(
196 mach_port_name_t name1
,
197 mach_port_right_t right1
,
198 ipc_object_t
*objectp1
,
199 mach_port_name_t name2
,
200 mach_port_right_t right2
,
201 ipc_object_t
*objectp2
)
205 ipc_object_t object1
, object2
;
207 boolean_t doguard
= TRUE
;
209 kr
= ipc_right_lookup_two_read(space
, name1
, &entry1
, name2
, &entry2
);
210 if (kr
!= KERN_SUCCESS
) {
213 /* space is read-locked and active */
215 if ((entry1
->ie_bits
& MACH_PORT_TYPE(right1
)) == MACH_PORT_TYPE_NONE
) {
216 /* If looking for receive, and the entry used to hold one, give a pass on EXC_GUARD */
217 if ((right1
& MACH_PORT_RIGHT_RECEIVE
) == MACH_PORT_RIGHT_RECEIVE
&&
218 (entry1
->ie_bits
& MACH_PORT_TYPE_EX_RECEIVE
) == MACH_PORT_TYPE_EX_RECEIVE
) {
221 is_read_unlock(space
);
223 mach_port_guard_exception(name1
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
225 return KERN_INVALID_RIGHT
;
228 if ((entry2
->ie_bits
& MACH_PORT_TYPE(right2
)) == MACH_PORT_TYPE_NONE
) {
229 /* If looking for receive, and the entry used to hold one, give a pass on EXC_GUARD */
230 if ((right2
& MACH_PORT_RIGHT_RECEIVE
) == MACH_PORT_RIGHT_RECEIVE
&&
231 (entry2
->ie_bits
& MACH_PORT_TYPE_EX_RECEIVE
) == MACH_PORT_TYPE_EX_RECEIVE
) {
234 is_read_unlock(space
);
236 mach_port_guard_exception(name2
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
238 return KERN_INVALID_RIGHT
;
241 object1
= entry1
->ie_object
;
242 assert(object1
!= IO_NULL
);
244 if (!io_active(object1
)) {
246 is_read_unlock(space
);
247 return KERN_INVALID_NAME
;
250 object2
= entry2
->ie_object
;
251 assert(object2
!= IO_NULL
);
253 if (!io_active(object2
)) {
256 is_read_unlock(space
);
257 return KERN_INVALID_NAME
;
263 is_read_unlock(space
);
268 * Routine: ipc_object_alloc_dead
270 * Allocate a dead-name entry.
274 * KERN_SUCCESS The dead name is allocated.
275 * KERN_INVALID_TASK The space is dead.
276 * KERN_NO_SPACE No room for an entry in the space.
277 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
281 ipc_object_alloc_dead(
283 mach_port_name_t
*namep
)
288 kr
= ipc_entry_alloc(space
, namep
, &entry
);
289 if (kr
!= KERN_SUCCESS
) {
292 /* space is write-locked */
294 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
296 assert(entry
->ie_object
== IO_NULL
);
297 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
298 ipc_entry_modified(space
, *namep
, entry
);
299 is_write_unlock(space
);
304 * Routine: ipc_object_alloc_dead_name
306 * Allocate a dead-name entry, with a specific name.
310 * KERN_SUCCESS The dead name is allocated.
311 * KERN_INVALID_TASK The space is dead.
312 * KERN_NAME_EXISTS The name already denotes a right.
313 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
317 ipc_object_alloc_dead_name(
319 mach_port_name_t name
)
324 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
325 if (kr
!= KERN_SUCCESS
) {
328 /* space is write-locked */
330 if (ipc_right_inuse(space
, name
, entry
)) {
331 return KERN_NAME_EXISTS
;
334 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
336 assert(entry
->ie_object
== IO_NULL
);
337 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
338 ipc_entry_modified(space
, name
, entry
);
339 is_write_unlock(space
);
344 * Routine: ipc_object_alloc
346 * Allocate an object.
348 * Nothing locked. If successful, the object is returned locked.
349 * The space is write locked on successful return.
350 * The caller doesn't get a reference for the object.
352 * KERN_SUCCESS The object is allocated.
353 * KERN_INVALID_TASK The space is dead.
354 * KERN_NO_SPACE No room for an entry in the space.
355 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
361 ipc_object_type_t otype
,
362 mach_port_type_t type
,
363 mach_port_urefs_t urefs
,
364 mach_port_name_t
*namep
,
365 ipc_object_t
*objectp
)
371 assert(otype
< IOT_NUMBER
);
372 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
373 assert(type
!= MACH_PORT_TYPE_NONE
);
374 assert(urefs
<= MACH_PORT_UREFS_MAX
);
376 object
= io_alloc(otype
);
377 if (object
== IO_NULL
) {
378 return KERN_RESOURCE_SHORTAGE
;
381 if (otype
== IOT_PORT
) {
382 ipc_port_t port
= ip_object_to_port(object
);
384 bzero((char *)port
, sizeof(*port
));
385 } else if (otype
== IOT_PORT_SET
) {
386 ipc_pset_t pset
= ips_object_to_pset(object
);
388 bzero((char *)pset
, sizeof(*pset
));
391 io_lock_init(object
);
392 *namep
= CAST_MACH_PORT_TO_NAME(object
);
393 kr
= ipc_entry_alloc(space
, namep
, &entry
);
394 if (kr
!= KERN_SUCCESS
) {
395 io_free(otype
, object
);
398 /* space is write-locked */
400 entry
->ie_bits
|= type
| urefs
;
401 entry
->ie_object
= object
;
402 ipc_entry_modified(space
, *namep
, entry
);
404 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
407 object
->io_references
= 1; /* for entry, not caller */
414 * Routine: ipc_object_alloc_name
416 * Allocate an object, with a specific name.
418 * Nothing locked. If successful, the object is returned locked.
419 * The caller doesn't get a reference for the object.
421 * KERN_SUCCESS The object is allocated.
422 * KERN_INVALID_TASK The space is dead.
423 * KERN_NAME_EXISTS The name already denotes a right.
424 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
428 ipc_object_alloc_name(
430 ipc_object_type_t otype
,
431 mach_port_type_t type
,
432 mach_port_urefs_t urefs
,
433 mach_port_name_t name
,
434 ipc_object_t
*objectp
)
440 assert(otype
< IOT_NUMBER
);
441 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
442 assert(type
!= MACH_PORT_TYPE_NONE
);
443 assert(urefs
<= MACH_PORT_UREFS_MAX
);
445 object
= io_alloc(otype
);
446 if (object
== IO_NULL
) {
447 return KERN_RESOURCE_SHORTAGE
;
450 if (otype
== IOT_PORT
) {
451 ipc_port_t port
= ip_object_to_port(object
);
453 bzero((char *)port
, sizeof(*port
));
454 } else if (otype
== IOT_PORT_SET
) {
455 ipc_pset_t pset
= ips_object_to_pset(object
);
457 bzero((char *)pset
, sizeof(*pset
));
460 io_lock_init(object
);
461 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
462 if (kr
!= KERN_SUCCESS
) {
463 io_free(otype
, object
);
466 /* space is write-locked */
468 if (ipc_right_inuse(space
, name
, entry
)) {
469 io_free(otype
, object
);
470 return KERN_NAME_EXISTS
;
473 entry
->ie_bits
|= type
| urefs
;
474 entry
->ie_object
= object
;
475 ipc_entry_modified(space
, name
, entry
);
477 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
480 is_write_unlock(space
);
482 object
->io_references
= 1; /* for entry, not caller */
488 /* Routine: ipc_object_validate
490 * Validates an ipc port or port set as belonging to the correct
498 int otype
= (io_otype(object
) == IOT_PORT_SET
) ? IOT_PORT_SET
: IOT_PORT
;
499 zone_require(object
, ipc_object_zones
[otype
]);
503 * Routine: ipc_object_copyin_type
505 * Convert a send type name to a received type name.
509 ipc_object_copyin_type(
510 mach_msg_type_name_t msgt_name
)
513 case MACH_MSG_TYPE_MOVE_RECEIVE
:
514 return MACH_MSG_TYPE_PORT_RECEIVE
;
516 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
517 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
518 return MACH_MSG_TYPE_PORT_SEND_ONCE
;
520 case MACH_MSG_TYPE_MOVE_SEND
:
521 case MACH_MSG_TYPE_MAKE_SEND
:
522 case MACH_MSG_TYPE_COPY_SEND
:
523 return MACH_MSG_TYPE_PORT_SEND
;
525 case MACH_MSG_TYPE_DISPOSE_RECEIVE
:
526 case MACH_MSG_TYPE_DISPOSE_SEND
:
527 case MACH_MSG_TYPE_DISPOSE_SEND_ONCE
:
530 return MACH_MSG_TYPE_PORT_NONE
;
535 * Routine: ipc_object_copyin
537 * Copyin a capability from a space.
538 * If successful, the caller gets a ref
539 * for the resulting object, unless it is IO_DEAD.
543 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
544 * KERN_INVALID_TASK The space is dead.
545 * KERN_INVALID_NAME Name doesn't exist in space.
546 * KERN_INVALID_RIGHT Name doesn't denote correct right.
552 mach_port_name_t name
,
553 mach_msg_type_name_t msgt_name
,
554 ipc_object_t
*objectp
,
555 mach_port_context_t context
,
556 mach_msg_guard_flags_t
*guard_flags
,
557 ipc_kmsg_flags_t kmsg_flags
)
561 ipc_port_t release_port
;
565 ipc_right_copyin_flags_t irc_flags
= IPC_RIGHT_COPYIN_FLAGS_DEADOK
;
566 if (kmsg_flags
& IPC_KMSG_FLAGS_ALLOW_IMMOVABLE_SEND
) {
567 irc_flags
|= IPC_RIGHT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
;
571 * Could first try a read lock when doing
572 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
573 * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
576 kr
= ipc_right_lookup_write(space
, name
, &entry
);
577 if (kr
!= KERN_SUCCESS
) {
580 /* space is write-locked and active */
582 release_port
= IP_NULL
;
583 kr
= ipc_right_copyin(space
, name
, entry
,
584 msgt_name
, irc_flags
,
590 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
591 ipc_entry_dealloc(space
, name
, entry
);
593 is_write_unlock(space
);
595 #if IMPORTANCE_INHERITANCE
596 if (0 < assertcnt
&& ipc_importance_task_is_any_receiver_type(current_task()->task_imp_base
)) {
597 ipc_importance_task_drop_internal_assertion(current_task()->task_imp_base
, assertcnt
);
599 #endif /* IMPORTANCE_INHERITANCE */
601 if (release_port
!= IP_NULL
) {
602 ip_release(release_port
);
605 if ((kr
== KERN_SUCCESS
) && (soright
!= IP_NULL
)) {
606 ipc_notify_port_deleted(soright
, name
);
613 * Routine: ipc_object_copyin_from_kernel
615 * Copyin a naked capability from the kernel.
617 * MACH_MSG_TYPE_MOVE_RECEIVE
618 * The receiver must be ipc_space_kernel
619 * or the receive right must already be in limbo.
620 * Consumes the naked receive right.
621 * MACH_MSG_TYPE_COPY_SEND
622 * A naked send right must be supplied.
623 * The port gains a reference, and a send right
624 * if the port is still active.
625 * MACH_MSG_TYPE_MAKE_SEND
626 * The receiver must be ipc_space_kernel.
627 * The port gains a reference and a send right.
628 * MACH_MSG_TYPE_MOVE_SEND
629 * Consumes a naked send right.
630 * MACH_MSG_TYPE_MAKE_SEND_ONCE
631 * The port gains a reference and a send-once right.
632 * Receiver also be the caller of device subsystem,
634 * MACH_MSG_TYPE_MOVE_SEND_ONCE
635 * Consumes a naked send-once right.
641 ipc_object_copyin_from_kernel(
643 mach_msg_type_name_t msgt_name
)
645 assert(IO_VALID(object
));
648 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
649 ipc_port_t port
= ip_object_to_port(object
);
652 imq_lock(&port
->ip_messages
);
653 require_ip_active(port
);
654 if (port
->ip_destination
!= IP_NULL
) {
655 assert(port
->ip_receiver
== ipc_space_kernel
);
656 assert(port
->ip_immovable_receive
== 0);
658 /* relevant part of ipc_port_clear_receiver */
659 port
->ip_mscount
= 0;
660 port
->ip_receiver_name
= MACH_PORT_NULL
;
661 port
->ip_destination
= IP_NULL
;
663 imq_unlock(&port
->ip_messages
);
668 case MACH_MSG_TYPE_COPY_SEND
: {
669 ipc_port_t port
= ip_object_to_port(object
);
672 if (ip_active(port
)) {
673 assert(port
->ip_srights
> 0);
681 case MACH_MSG_TYPE_MAKE_SEND
: {
682 ipc_port_t port
= ip_object_to_port(object
);
685 if (ip_active(port
)) {
686 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
687 assert((port
->ip_receiver
== ipc_space_kernel
) ||
688 (port
->ip_receiver
->is_node_id
!= HOST_LOCAL_NODE
));
698 case MACH_MSG_TYPE_MOVE_SEND
: {
699 /* move naked send right into the message */
700 assert(ip_object_to_port(object
)->ip_srights
);
704 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
705 ipc_port_t port
= ip_object_to_port(object
);
708 if (ip_active(port
)) {
709 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
711 ipc_port_make_sonce_locked(port
);
716 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
717 /* move naked send-once right into the message */
718 assert(ip_object_to_port(object
)->ip_sorights
);
723 panic("ipc_object_copyin_from_kernel: strange rights");
728 * Routine: ipc_object_destroy
730 * Destroys a naked capability.
731 * Consumes a ref for the object.
733 * A receive right should be in limbo or in transit.
741 mach_msg_type_name_t msgt_name
)
743 assert(IO_VALID(object
));
744 assert(io_otype(object
) == IOT_PORT
);
747 case MACH_MSG_TYPE_PORT_SEND
:
748 ipc_port_release_send(ip_object_to_port(object
));
751 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
752 ipc_notify_send_once(ip_object_to_port(object
));
755 case MACH_MSG_TYPE_PORT_RECEIVE
:
756 ipc_port_release_receive(ip_object_to_port(object
));
760 panic("ipc_object_destroy: strange rights");
765 * Routine: ipc_object_destroy_dest
767 * Destroys a naked capability for the destination of
768 * of a message. Consumes a ref for the object.
775 ipc_object_destroy_dest(
777 mach_msg_type_name_t msgt_name
)
779 assert(IO_VALID(object
));
780 assert(io_otype(object
) == IOT_PORT
);
783 case MACH_MSG_TYPE_PORT_SEND
:
784 ipc_port_release_send(ip_object_to_port(object
));
787 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
788 if (io_active(object
) &&
789 !ip_full_kernel(ip_object_to_port(object
))) {
790 ipc_notify_send_once(ip_object_to_port(object
));
792 ipc_port_release_sonce(ip_object_to_port(object
));
797 panic("ipc_object_destroy_dest: strange rights");
802 * Routine: ipc_object_insert_send_right
804 * Insert a send right into an object already in the space.
805 * The specified name must already point to a valid object.
807 * Note: This really is a combined copyin()/copyout(),
808 * that avoids most of the overhead of being implemented that way.
810 * This is the fastpath for mach_port_insert_right.
815 * msgt_name must be MACH_MSG_TYPE_MAKE_SEND_ONCE or
816 * MACH_MSG_TYPE_MOVE_SEND_ONCE.
819 * KERN_SUCCESS Copied out object, consumed ref.
820 * KERN_INVALID_TASK The space is dead.
821 * KERN_INVALID_NAME Name doesn't exist in space.
822 * KERN_INVALID_CAPABILITY The object is dead.
823 * KERN_RIGHT_EXISTS Space has rights under another name.
826 ipc_object_insert_send_right(
828 mach_port_name_t name
,
829 mach_msg_type_name_t msgt_name
)
831 ipc_entry_bits_t bits
;
836 assert(msgt_name
== MACH_MSG_TYPE_MAKE_SEND
||
837 msgt_name
== MACH_MSG_TYPE_COPY_SEND
);
839 kr
= ipc_right_lookup_write(space
, name
, &entry
);
840 if (kr
!= KERN_SUCCESS
) {
843 /* space is write-locked and active */
845 if (!IO_VALID(entry
->ie_object
)) {
846 is_write_unlock(space
);
847 return KERN_INVALID_CAPABILITY
;
850 bits
= entry
->ie_bits
;
851 object
= entry
->ie_object
;
854 if (!io_active(object
)) {
855 kr
= KERN_INVALID_CAPABILITY
;
856 } else if (msgt_name
== MACH_MSG_TYPE_MAKE_SEND
) {
857 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
858 ipc_port_t port
= ip_object_to_port(object
);
860 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
862 bits
|= MACH_PORT_TYPE_SEND
;
864 /* leave urefs pegged to maximum if it overflowed */
865 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
866 bits
+= 1; /* increment urefs */
868 entry
->ie_bits
= bits
;
869 ipc_entry_modified(space
, name
, entry
);
872 kr
= KERN_INVALID_RIGHT
;
874 } else { // MACH_MSG_TYPE_COPY_SEND
875 if (bits
& MACH_PORT_TYPE_SEND
) {
876 /* leave urefs pegged to maximum if it overflowed */
877 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
878 entry
->ie_bits
= bits
+ 1; /* increment urefs */
880 ipc_entry_modified(space
, name
, entry
);
883 kr
= KERN_INVALID_RIGHT
;
888 is_write_unlock(space
);
894 * Routine: ipc_object_copyout
896 * Copyout a capability, placing it into a space.
897 * If successful, consumes a ref for the object.
901 * KERN_SUCCESS Copied out object, consumed ref.
902 * KERN_INVALID_TASK The space is dead.
903 * KERN_INVALID_CAPABILITY The object is dead.
904 * KERN_NO_SPACE No room in space for another right.
905 * KERN_RESOURCE_SHORTAGE No memory available.
906 * KERN_UREFS_OVERFLOW Urefs limit exceeded
907 * and overflow wasn't specified.
914 mach_msg_type_name_t msgt_name
,
915 mach_port_context_t
*context
,
916 mach_msg_guard_flags_t
*guard_flags
,
917 mach_port_name_t
*namep
)
919 struct knote
*kn
= current_thread()->ith_knote
;
920 mach_port_name_t name
;
924 assert(IO_VALID(object
));
925 assert(io_otype(object
) == IOT_PORT
);
927 if (ITH_KNOTE_VALID(kn
, msgt_name
)) {
928 filt_machport_turnstile_prepare_lazily(kn
,
929 msgt_name
, ip_object_to_port(object
));
932 is_write_lock(space
);
935 if (!is_active(space
)) {
936 is_write_unlock(space
);
937 return KERN_INVALID_TASK
;
940 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
941 ipc_right_reverse(space
, object
, &name
, &entry
)) {
942 /* object is locked and active */
944 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
949 name
= CAST_MACH_PORT_TO_NAME(object
);
950 kr
= ipc_entry_get(space
, &name
, &entry
);
951 if (kr
!= KERN_SUCCESS
) {
952 /* unlocks/locks space, so must start again */
954 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
955 if (kr
!= KERN_SUCCESS
) {
956 return kr
; /* space is unlocked */
961 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
962 assert(entry
->ie_object
== IO_NULL
);
965 if (!io_active(object
)) {
967 ipc_entry_dealloc(space
, name
, entry
);
968 is_write_unlock(space
);
969 return KERN_INVALID_CAPABILITY
;
972 /* Don't actually copyout rights we aren't allowed to */
973 if (!ip_label_check(space
, ip_object_to_port(object
), msgt_name
)) {
975 ipc_entry_dealloc(space
, name
, entry
);
976 is_write_unlock(space
);
979 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
980 ipc_port_release_sonce(ip_object_to_port(object
));
982 case MACH_MSG_TYPE_PORT_SEND
:
983 ipc_port_release_send(ip_object_to_port(object
));
987 * We don't allow labeling of "kobjects" with receive
988 * rights at user-space or port-sets. So, if we get this far,
989 * something went VERY wrong.
991 panic("ipc_object_copyout: bad port label check failure");
993 return KERN_INVALID_CAPABILITY
;
996 entry
->ie_object
= object
;
1000 /* space is write-locked and active, object is locked and active */
1002 kr
= ipc_right_copyout(space
, name
, entry
,
1003 msgt_name
, context
, guard_flags
, object
);
1005 /* object is unlocked */
1006 is_write_unlock(space
);
1008 if (kr
== KERN_SUCCESS
) {
1015 * Routine: ipc_object_copyout_name
1017 * Copyout a capability, placing it into a space.
1018 * The specified name is used for the capability.
1019 * If successful, consumes a ref for the object.
1023 * KERN_SUCCESS Copied out object, consumed ref.
1024 * KERN_INVALID_TASK The space is dead.
1025 * KERN_INVALID_CAPABILITY The object is dead.
1026 * KERN_RESOURCE_SHORTAGE No memory available.
1027 * KERN_UREFS_OVERFLOW Urefs limit exceeded
1028 * and overflow wasn't specified.
1029 * KERN_RIGHT_EXISTS Space has rights under another name.
1030 * KERN_NAME_EXISTS Name is already used.
1034 ipc_object_copyout_name(
1036 ipc_object_t object
,
1037 mach_msg_type_name_t msgt_name
,
1038 mach_port_name_t name
)
1040 mach_port_name_t oname
;
1045 #if IMPORTANCE_INHERITANCE
1047 ipc_importance_task_t task_imp
= IIT_NULL
;
1048 #endif /* IMPORTANCE_INHERITANCE */
1050 assert(IO_VALID(object
));
1051 assert(io_otype(object
) == IOT_PORT
);
1053 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
1054 if (kr
!= KERN_SUCCESS
) {
1057 /* space is write-locked and active */
1059 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
1060 ipc_right_reverse(space
, object
, &oname
, &oentry
)) {
1061 /* object is locked and active */
1063 if (name
!= oname
) {
1066 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
1067 ipc_entry_dealloc(space
, name
, entry
);
1070 is_write_unlock(space
);
1071 return KERN_RIGHT_EXISTS
;
1074 assert(entry
== oentry
);
1075 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
1077 if (ipc_right_inuse(space
, name
, entry
)) {
1078 return KERN_NAME_EXISTS
;
1081 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
1082 assert(entry
->ie_object
== IO_NULL
);
1085 if (!io_active(object
)) {
1087 ipc_entry_dealloc(space
, name
, entry
);
1088 is_write_unlock(space
);
1089 return KERN_INVALID_CAPABILITY
;
1092 /* Don't actually copyout rights we aren't allowed to */
1093 if (!ip_label_check(space
, ip_object_to_port(object
), msgt_name
)) {
1095 ipc_entry_dealloc(space
, name
, entry
);
1096 is_write_unlock(space
);
1098 switch (msgt_name
) {
1099 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
1100 ipc_port_release_sonce(ip_object_to_port(object
));
1102 case MACH_MSG_TYPE_PORT_SEND
:
1103 ipc_port_release_send(ip_object_to_port(object
));
1106 panic("ipc_object_copyout_name: bad port label check failure");
1108 return KERN_INVALID_CAPABILITY
;
1111 entry
->ie_object
= object
;
1114 /* space is write-locked and active, object is locked and active */
1116 #if IMPORTANCE_INHERITANCE
1118 * We are slamming a receive right into the space, without
1119 * first having been enqueued on a port destined there. So,
1120 * we have to arrange to boost the task appropriately if this
1121 * port has assertions (and the task wants them).
1123 if (msgt_name
== MACH_MSG_TYPE_PORT_RECEIVE
) {
1124 ipc_port_t port
= ip_object_to_port(object
);
1126 if (space
->is_task
!= TASK_NULL
) {
1127 task_imp
= space
->is_task
->task_imp_base
;
1128 if (ipc_importance_task_is_any_receiver_type(task_imp
)) {
1129 assertcnt
= port
->ip_impcount
;
1130 ipc_importance_task_reference(task_imp
);
1132 task_imp
= IIT_NULL
;
1136 /* take port out of limbo */
1137 assert(port
->ip_tempowner
!= 0);
1138 port
->ip_tempowner
= 0;
1141 #endif /* IMPORTANCE_INHERITANCE */
1143 kr
= ipc_right_copyout(space
, name
, entry
,
1144 msgt_name
, NULL
, NULL
, object
);
1146 /* object is unlocked */
1147 is_write_unlock(space
);
1149 #if IMPORTANCE_INHERITANCE
1151 * Add the assertions to the task that we captured before
1153 if (task_imp
!= IIT_NULL
) {
1154 ipc_importance_task_hold_internal_assertion(task_imp
, assertcnt
);
1155 ipc_importance_task_release(task_imp
);
1157 #endif /* IMPORTANCE_INHERITANCE */
1163 * Routine: ipc_object_copyout_dest
1165 * Translates/consumes the destination right of a message.
1166 * This is unlike normal copyout because the right is consumed
1167 * in a funny way instead of being given to the receiving space.
1168 * The receiver gets his name for the port, if he has receive
1169 * rights, otherwise MACH_PORT_NULL.
1171 * The object is locked and active. Nothing else locked.
1172 * The object is unlocked and loses a reference.
1176 ipc_object_copyout_dest(
1178 ipc_object_t object
,
1179 mach_msg_type_name_t msgt_name
,
1180 mach_port_name_t
*namep
)
1182 mach_port_name_t name
;
1184 assert(IO_VALID(object
));
1185 assert(io_active(object
));
1188 * If the space is the receiver/owner of the object,
1189 * then we quietly consume the right and return
1190 * the space's name for the object. Otherwise
1191 * we destroy the right and return MACH_PORT_NULL.
1194 switch (msgt_name
) {
1195 case MACH_MSG_TYPE_PORT_SEND
: {
1196 ipc_port_t port
= ip_object_to_port(object
);
1197 ipc_port_t nsrequest
= IP_NULL
;
1198 mach_port_mscount_t mscount
;
1200 if (port
->ip_receiver
== space
) {
1201 name
= port
->ip_receiver_name
;
1203 name
= MACH_PORT_NULL
;
1206 assert(port
->ip_srights
> 0);
1207 if (--port
->ip_srights
== 0 &&
1208 port
->ip_nsrequest
!= IP_NULL
) {
1209 nsrequest
= port
->ip_nsrequest
;
1210 port
->ip_nsrequest
= IP_NULL
;
1211 mscount
= port
->ip_mscount
;
1212 ipc_port_clear_sync_rcv_thread_boost_locked(port
);
1214 ipc_notify_no_senders(nsrequest
, mscount
);
1216 ipc_port_clear_sync_rcv_thread_boost_locked(port
);
1224 case MACH_MSG_TYPE_PORT_SEND_ONCE
: {
1225 ipc_port_t port
= ip_object_to_port(object
);
1227 assert(port
->ip_sorights
> 0);
1229 if (port
->ip_receiver
== space
) {
1230 /* quietly consume the send-once right */
1232 port
->ip_sorights
--;
1233 name
= port
->ip_receiver_name
;
1234 ipc_port_clear_sync_rcv_thread_boost_locked(port
);
1239 * A very bizarre case. The message
1240 * was received, but before this copyout
1241 * happened the space lost receive rights.
1242 * We can't quietly consume the soright
1243 * out from underneath some other task,
1244 * so generate a send-once notification.
1249 ipc_notify_send_once(port
);
1250 name
= MACH_PORT_NULL
;
1257 panic("ipc_object_copyout_dest: strange rights");
1258 name
= MACH_PORT_DEAD
;
1267 * Validate, then acquire a lock on an ipc object
1271 io_lock(ipc_object_t io
)
1273 ipc_object_validate(io
);
1274 lck_spin_lock_grp(&(io
)->io_lock_data
, &ipc_lck_grp
);
1278 * Routine: io_lock_try
1280 * Validate, then try to acquire a lock on an object,
1281 * fail if there is an existing busy lock
1285 io_lock_try(ipc_object_t io
)
1287 ipc_object_validate(io
);
1288 return lck_spin_try_lock_grp(&(io
)->io_lock_data
, &ipc_lck_grp
);
1292 * Check whether the object is a port if so, free it. But
1293 * keep track of that fact.
1298 ipc_object_t object
)
1300 if (otype
== IOT_PORT
) {
1301 ipc_port_finalize(ip_object_to_port(object
));
1303 io_lock_destroy(object
);
1304 zfree(ipc_object_zones
[otype
], object
);