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 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 kr
= ipc_right_lookup_read(space
, name
, &entry
);
150 if (kr
!= KERN_SUCCESS
) {
153 /* space is read-locked and active */
155 if ((entry
->ie_bits
& MACH_PORT_TYPE(right
)) == MACH_PORT_TYPE_NONE
) {
156 is_read_unlock(space
);
157 return KERN_INVALID_RIGHT
;
160 object
= entry
->ie_object
;
161 assert(object
!= IO_NULL
);
164 is_read_unlock(space
);
171 * Routine: ipc_object_translate_two
173 * Look up two objects in a space.
175 * Nothing locked before. If successful, the objects
176 * are returned locked. The caller doesn't get a ref.
178 * KERN_SUCCESS Objects returned locked.
179 * KERN_INVALID_TASK The space is dead.
180 * KERN_INVALID_NAME A name doesn't denote a right.
181 * KERN_INVALID_RIGHT A name doesn't denote the correct right.
185 ipc_object_translate_two(
187 mach_port_name_t name1
,
188 mach_port_right_t right1
,
189 ipc_object_t
*objectp1
,
190 mach_port_name_t name2
,
191 mach_port_right_t right2
,
192 ipc_object_t
*objectp2
)
199 kr
= ipc_right_lookup_two_read(space
, name1
, &entry1
, name2
, &entry2
);
200 if (kr
!= KERN_SUCCESS
) {
203 /* space is read-locked and active */
205 if ((entry1
->ie_bits
& MACH_PORT_TYPE(right1
)) == MACH_PORT_TYPE_NONE
) {
206 is_read_unlock(space
);
207 mach_port_guard_exception(name1
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
208 return KERN_INVALID_RIGHT
;
211 if ((entry2
->ie_bits
& MACH_PORT_TYPE(right2
)) == MACH_PORT_TYPE_NONE
) {
212 is_read_unlock(space
);
213 mach_port_guard_exception(name2
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
214 return KERN_INVALID_RIGHT
;
217 object
= entry1
->ie_object
;
218 assert(object
!= IO_NULL
);
222 object
= entry2
->ie_object
;
223 assert(object
!= IO_NULL
);
227 is_read_unlock(space
);
232 * Routine: ipc_object_alloc_dead
234 * Allocate a dead-name entry.
238 * KERN_SUCCESS The dead name is allocated.
239 * KERN_INVALID_TASK The space is dead.
240 * KERN_NO_SPACE No room for an entry in the space.
241 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
245 ipc_object_alloc_dead(
247 mach_port_name_t
*namep
)
252 kr
= ipc_entry_alloc(space
, namep
, &entry
);
253 if (kr
!= KERN_SUCCESS
) {
256 /* space is write-locked */
258 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
260 assert(entry
->ie_object
== IO_NULL
);
261 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
262 ipc_entry_modified(space
, *namep
, entry
);
263 is_write_unlock(space
);
268 * Routine: ipc_object_alloc_dead_name
270 * Allocate a dead-name entry, with a specific name.
274 * KERN_SUCCESS The dead name is allocated.
275 * KERN_INVALID_TASK The space is dead.
276 * KERN_NAME_EXISTS The name already denotes a right.
277 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
281 ipc_object_alloc_dead_name(
283 mach_port_name_t name
)
288 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
289 if (kr
!= KERN_SUCCESS
) {
292 /* space is write-locked */
294 if (ipc_right_inuse(space
, name
, entry
)) {
295 return KERN_NAME_EXISTS
;
298 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
300 assert(entry
->ie_object
== IO_NULL
);
301 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
302 ipc_entry_modified(space
, name
, entry
);
303 is_write_unlock(space
);
308 * Routine: ipc_object_alloc
310 * Allocate an object.
312 * Nothing locked. If successful, the object is returned locked.
313 * The space is write locked on successful return.
314 * The caller doesn't get a reference for the object.
316 * KERN_SUCCESS The object is allocated.
317 * KERN_INVALID_TASK The space is dead.
318 * KERN_NO_SPACE No room for an entry in the space.
319 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
325 ipc_object_type_t otype
,
326 mach_port_type_t type
,
327 mach_port_urefs_t urefs
,
328 mach_port_name_t
*namep
,
329 ipc_object_t
*objectp
)
335 assert(otype
< IOT_NUMBER
);
336 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
337 assert(type
!= MACH_PORT_TYPE_NONE
);
338 assert(urefs
<= MACH_PORT_UREFS_MAX
);
340 object
= io_alloc(otype
);
341 if (object
== IO_NULL
) {
342 return KERN_RESOURCE_SHORTAGE
;
345 if (otype
== IOT_PORT
) {
346 ipc_port_t port
= (ipc_port_t
)object
;
348 bzero((char *)port
, sizeof(*port
));
349 } else if (otype
== IOT_PORT_SET
) {
350 ipc_pset_t pset
= (ipc_pset_t
)object
;
352 bzero((char *)pset
, sizeof(*pset
));
355 io_lock_init(object
);
356 *namep
= CAST_MACH_PORT_TO_NAME(object
);
357 kr
= ipc_entry_alloc(space
, namep
, &entry
);
358 if (kr
!= KERN_SUCCESS
) {
359 io_free(otype
, object
);
362 /* space is write-locked */
364 entry
->ie_bits
|= type
| urefs
;
365 entry
->ie_object
= object
;
366 ipc_entry_modified(space
, *namep
, entry
);
370 object
->io_references
= 1; /* for entry, not caller */
371 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
378 * Routine: ipc_object_alloc_name
380 * Allocate an object, with a specific name.
382 * Nothing locked. If successful, the object is returned locked.
383 * The caller doesn't get a reference for the object.
385 * KERN_SUCCESS The object is allocated.
386 * KERN_INVALID_TASK The space is dead.
387 * KERN_NAME_EXISTS The name already denotes a right.
388 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
392 ipc_object_alloc_name(
394 ipc_object_type_t otype
,
395 mach_port_type_t type
,
396 mach_port_urefs_t urefs
,
397 mach_port_name_t name
,
398 ipc_object_t
*objectp
)
404 assert(otype
< IOT_NUMBER
);
405 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
406 assert(type
!= MACH_PORT_TYPE_NONE
);
407 assert(urefs
<= MACH_PORT_UREFS_MAX
);
409 object
= io_alloc(otype
);
410 if (object
== IO_NULL
) {
411 return KERN_RESOURCE_SHORTAGE
;
414 if (otype
== IOT_PORT
) {
415 ipc_port_t port
= (ipc_port_t
)object
;
417 bzero((char *)port
, sizeof(*port
));
418 } else if (otype
== IOT_PORT_SET
) {
419 ipc_pset_t pset
= (ipc_pset_t
)object
;
421 bzero((char *)pset
, sizeof(*pset
));
424 io_lock_init(object
);
425 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
426 if (kr
!= KERN_SUCCESS
) {
427 io_free(otype
, object
);
430 /* space is write-locked */
432 if (ipc_right_inuse(space
, name
, entry
)) {
433 io_free(otype
, object
);
434 return KERN_NAME_EXISTS
;
437 entry
->ie_bits
|= type
| urefs
;
438 entry
->ie_object
= object
;
439 ipc_entry_modified(space
, name
, entry
);
442 is_write_unlock(space
);
444 object
->io_references
= 1; /* for entry, not caller */
445 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
452 * Routine: ipc_object_copyin_type
454 * Convert a send type name to a received type name.
458 ipc_object_copyin_type(
459 mach_msg_type_name_t msgt_name
)
462 case MACH_MSG_TYPE_MOVE_RECEIVE
:
463 return MACH_MSG_TYPE_PORT_RECEIVE
;
465 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
466 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
467 return MACH_MSG_TYPE_PORT_SEND_ONCE
;
469 case MACH_MSG_TYPE_MOVE_SEND
:
470 case MACH_MSG_TYPE_MAKE_SEND
:
471 case MACH_MSG_TYPE_COPY_SEND
:
472 return MACH_MSG_TYPE_PORT_SEND
;
474 case MACH_MSG_TYPE_DISPOSE_RECEIVE
:
475 case MACH_MSG_TYPE_DISPOSE_SEND
:
476 case MACH_MSG_TYPE_DISPOSE_SEND_ONCE
:
479 return MACH_MSG_TYPE_PORT_NONE
;
484 * Routine: ipc_object_copyin
486 * Copyin a capability from a space.
487 * If successful, the caller gets a ref
488 * for the resulting object, unless it is IO_DEAD.
492 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
493 * KERN_INVALID_TASK The space is dead.
494 * KERN_INVALID_NAME Name doesn't exist in space.
495 * KERN_INVALID_RIGHT Name doesn't denote correct right.
501 mach_port_name_t name
,
502 mach_msg_type_name_t msgt_name
,
503 ipc_object_t
*objectp
)
507 ipc_port_t release_port
;
512 * Could first try a read lock when doing
513 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
514 * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
517 kr
= ipc_right_lookup_write(space
, name
, &entry
);
518 if (kr
!= KERN_SUCCESS
) {
521 /* space is write-locked and active */
523 release_port
= IP_NULL
;
524 kr
= ipc_right_copyin(space
, name
, entry
,
525 msgt_name
, IPC_RIGHT_COPYIN_FLAGS_DEADOK
,
529 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
530 ipc_entry_dealloc(space
, name
, entry
);
532 is_write_unlock(space
);
534 #if IMPORTANCE_INHERITANCE
535 if (0 < assertcnt
&& ipc_importance_task_is_any_receiver_type(current_task()->task_imp_base
)) {
536 ipc_importance_task_drop_internal_assertion(current_task()->task_imp_base
, assertcnt
);
538 #endif /* IMPORTANCE_INHERITANCE */
540 if (release_port
!= IP_NULL
) {
541 ip_release(release_port
);
544 if ((kr
== KERN_SUCCESS
) && (soright
!= IP_NULL
)) {
545 ipc_notify_port_deleted(soright
, name
);
552 * Routine: ipc_object_copyin_from_kernel
554 * Copyin a naked capability from the kernel.
556 * MACH_MSG_TYPE_MOVE_RECEIVE
557 * The receiver must be ipc_space_kernel
558 * or the receive right must already be in limbo.
559 * Consumes the naked receive right.
560 * MACH_MSG_TYPE_COPY_SEND
561 * A naked send right must be supplied.
562 * The port gains a reference, and a send right
563 * if the port is still active.
564 * MACH_MSG_TYPE_MAKE_SEND
565 * The receiver must be ipc_space_kernel.
566 * The port gains a reference and a send right.
567 * MACH_MSG_TYPE_MOVE_SEND
568 * Consumes a naked send right.
569 * MACH_MSG_TYPE_MAKE_SEND_ONCE
570 * The port gains a reference and a send-once right.
571 * Receiver also be the caller of device subsystem,
573 * MACH_MSG_TYPE_MOVE_SEND_ONCE
574 * Consumes a naked send-once right.
580 ipc_object_copyin_from_kernel(
582 mach_msg_type_name_t msgt_name
)
584 assert(IO_VALID(object
));
587 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
588 ipc_port_t port
= (ipc_port_t
) object
;
591 imq_lock(&port
->ip_messages
);
592 assert(ip_active(port
));
593 if (port
->ip_destination
!= IP_NULL
) {
594 assert(port
->ip_receiver
== ipc_space_kernel
);
596 /* relevant part of ipc_port_clear_receiver */
597 ipc_port_set_mscount(port
, 0);
599 port
->ip_receiver_name
= MACH_PORT_NULL
;
600 port
->ip_destination
= IP_NULL
;
602 imq_unlock(&port
->ip_messages
);
607 case MACH_MSG_TYPE_COPY_SEND
: {
608 ipc_port_t port
= (ipc_port_t
) object
;
611 if (ip_active(port
)) {
612 assert(port
->ip_srights
> 0);
620 case MACH_MSG_TYPE_MAKE_SEND
: {
621 ipc_port_t port
= (ipc_port_t
) object
;
624 if (ip_active(port
)) {
625 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
626 assert((port
->ip_receiver
== ipc_space_kernel
) ||
627 (port
->ip_receiver
->is_node_id
!= HOST_LOCAL_NODE
));
637 case MACH_MSG_TYPE_MOVE_SEND
: {
638 /* move naked send right into the message */
639 assert(((ipc_port_t
)object
)->ip_srights
);
643 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
644 ipc_port_t port
= (ipc_port_t
) object
;
647 if (ip_active(port
)) {
648 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
656 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
657 /* move naked send-once right into the message */
658 assert(((ipc_port_t
)object
)->ip_sorights
);
663 panic("ipc_object_copyin_from_kernel: strange rights");
668 * Routine: ipc_object_destroy
670 * Destroys a naked capability.
671 * Consumes a ref for the object.
673 * A receive right should be in limbo or in transit.
681 mach_msg_type_name_t msgt_name
)
683 assert(IO_VALID(object
));
684 assert(io_otype(object
) == IOT_PORT
);
687 case MACH_MSG_TYPE_PORT_SEND
:
688 ipc_port_release_send((ipc_port_t
) object
);
691 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
692 ipc_notify_send_once((ipc_port_t
) object
);
695 case MACH_MSG_TYPE_PORT_RECEIVE
:
696 ipc_port_release_receive((ipc_port_t
) object
);
700 panic("ipc_object_destroy: strange rights");
705 * Routine: ipc_object_destroy_dest
707 * Destroys a naked capability for the destination of
708 * of a message. Consumes a ref for the object.
715 ipc_object_destroy_dest(
717 mach_msg_type_name_t msgt_name
)
719 assert(IO_VALID(object
));
720 assert(io_otype(object
) == IOT_PORT
);
723 case MACH_MSG_TYPE_PORT_SEND
:
724 ipc_port_release_send((ipc_port_t
) object
);
727 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
728 if (io_active(object
) &&
729 !ip_full_kernel((ipc_port_t
) object
)) {
730 ipc_notify_send_once((ipc_port_t
) object
);
732 ipc_port_release_sonce((ipc_port_t
) object
);
737 panic("ipc_object_destroy_dest: strange rights");
742 * Routine: ipc_object_copyout
744 * Copyout a capability, placing it into a space.
745 * If successful, consumes a ref for the object.
749 * KERN_SUCCESS Copied out object, consumed ref.
750 * KERN_INVALID_TASK The space is dead.
751 * KERN_INVALID_CAPABILITY The object is dead.
752 * KERN_NO_SPACE No room in space for another right.
753 * KERN_RESOURCE_SHORTAGE No memory available.
754 * KERN_UREFS_OVERFLOW Urefs limit exceeded
755 * and overflow wasn't specified.
762 mach_msg_type_name_t msgt_name
,
764 mach_port_name_t
*namep
)
766 struct knote
*kn
= current_thread()->ith_knote
;
767 mach_port_name_t name
;
771 assert(IO_VALID(object
));
772 assert(io_otype(object
) == IOT_PORT
);
774 if (ITH_KNOTE_VALID(kn
, msgt_name
)) {
775 filt_machport_turnstile_prepare_lazily(kn
,
776 msgt_name
, (ipc_port_t
)object
);
779 is_write_lock(space
);
782 if (!is_active(space
)) {
783 is_write_unlock(space
);
784 return KERN_INVALID_TASK
;
787 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
788 ipc_right_reverse(space
, object
, &name
, &entry
)) {
789 /* object is locked and active */
791 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
795 name
= CAST_MACH_PORT_TO_NAME(object
);
796 kr
= ipc_entry_get(space
, &name
, &entry
);
797 if (kr
!= KERN_SUCCESS
) {
798 /* unlocks/locks space, so must start again */
800 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
801 if (kr
!= KERN_SUCCESS
) {
802 return kr
; /* space is unlocked */
807 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
808 assert(entry
->ie_object
== IO_NULL
);
811 if (!io_active(object
)) {
813 ipc_entry_dealloc(space
, name
, entry
);
814 is_write_unlock(space
);
815 return KERN_INVALID_CAPABILITY
;
818 entry
->ie_object
= object
;
822 /* space is write-locked and active, object is locked and active */
824 kr
= ipc_right_copyout(space
, name
, entry
,
825 msgt_name
, overflow
, object
);
827 /* object is unlocked */
828 is_write_unlock(space
);
830 if (kr
== KERN_SUCCESS
) {
837 * Routine: ipc_object_copyout_name
839 * Copyout a capability, placing it into a space.
840 * The specified name is used for the capability.
841 * If successful, consumes a ref for the object.
845 * KERN_SUCCESS Copied out object, consumed ref.
846 * KERN_INVALID_TASK The space is dead.
847 * KERN_INVALID_CAPABILITY The object is dead.
848 * KERN_RESOURCE_SHORTAGE No memory available.
849 * KERN_UREFS_OVERFLOW Urefs limit exceeded
850 * and overflow wasn't specified.
851 * KERN_RIGHT_EXISTS Space has rights under another name.
852 * KERN_NAME_EXISTS Name is already used.
856 ipc_object_copyout_name(
859 mach_msg_type_name_t msgt_name
,
861 mach_port_name_t name
)
863 mach_port_name_t oname
;
867 struct knote
*kn
= current_thread()->ith_knote
;
869 #if IMPORTANCE_INHERITANCE
871 ipc_importance_task_t task_imp
= IIT_NULL
;
872 #endif /* IMPORTANCE_INHERITANCE */
874 assert(IO_VALID(object
));
875 assert(io_otype(object
) == IOT_PORT
);
877 if (ITH_KNOTE_VALID(kn
, msgt_name
)) {
878 filt_machport_turnstile_prepare_lazily(kn
,
879 msgt_name
, (ipc_port_t
)object
);
882 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
883 if (kr
!= KERN_SUCCESS
) {
886 /* space is write-locked and active */
888 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
889 ipc_right_reverse(space
, object
, &oname
, &oentry
)) {
890 /* object is locked and active */
895 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
896 ipc_entry_dealloc(space
, name
, entry
);
899 is_write_unlock(space
);
900 return KERN_RIGHT_EXISTS
;
903 assert(entry
== oentry
);
904 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
906 if (ipc_right_inuse(space
, name
, entry
)) {
907 return KERN_NAME_EXISTS
;
910 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
911 assert(entry
->ie_object
== IO_NULL
);
914 if (!io_active(object
)) {
916 ipc_entry_dealloc(space
, name
, entry
);
917 is_write_unlock(space
);
918 return KERN_INVALID_CAPABILITY
;
921 entry
->ie_object
= object
;
924 /* space is write-locked and active, object is locked and active */
926 #if IMPORTANCE_INHERITANCE
928 * We are slamming a receive right into the space, without
929 * first having been enqueued on a port destined there. So,
930 * we have to arrange to boost the task appropriately if this
931 * port has assertions (and the task wants them).
933 if (msgt_name
== MACH_MSG_TYPE_PORT_RECEIVE
) {
934 ipc_port_t port
= (ipc_port_t
)object
;
936 if (space
->is_task
!= TASK_NULL
) {
937 task_imp
= space
->is_task
->task_imp_base
;
938 if (ipc_importance_task_is_any_receiver_type(task_imp
)) {
939 assertcnt
= port
->ip_impcount
;
940 ipc_importance_task_reference(task_imp
);
946 /* take port out of limbo */
947 assert(port
->ip_tempowner
!= 0);
948 port
->ip_tempowner
= 0;
951 #endif /* IMPORTANCE_INHERITANCE */
953 kr
= ipc_right_copyout(space
, name
, entry
,
954 msgt_name
, overflow
, object
);
956 /* object is unlocked */
957 is_write_unlock(space
);
959 #if IMPORTANCE_INHERITANCE
961 * Add the assertions to the task that we captured before
963 if (task_imp
!= IIT_NULL
) {
964 ipc_importance_task_hold_internal_assertion(task_imp
, assertcnt
);
965 ipc_importance_task_release(task_imp
);
967 #endif /* IMPORTANCE_INHERITANCE */
973 * Routine: ipc_object_copyout_dest
975 * Translates/consumes the destination right of a message.
976 * This is unlike normal copyout because the right is consumed
977 * in a funny way instead of being given to the receiving space.
978 * The receiver gets his name for the port, if he has receive
979 * rights, otherwise MACH_PORT_NULL.
981 * The object is locked and active. Nothing else locked.
982 * The object is unlocked and loses a reference.
986 ipc_object_copyout_dest(
989 mach_msg_type_name_t msgt_name
,
990 mach_port_name_t
*namep
)
992 mach_port_name_t name
;
994 assert(IO_VALID(object
));
995 assert(io_active(object
));
1000 * If the space is the receiver/owner of the object,
1001 * then we quietly consume the right and return
1002 * the space's name for the object. Otherwise
1003 * we destroy the right and return MACH_PORT_NULL.
1006 switch (msgt_name
) {
1007 case MACH_MSG_TYPE_PORT_SEND
: {
1008 ipc_port_t port
= (ipc_port_t
) object
;
1009 ipc_port_t nsrequest
= IP_NULL
;
1010 mach_port_mscount_t mscount
;
1012 if (port
->ip_receiver
== space
) {
1013 name
= port
->ip_receiver_name
;
1015 name
= MACH_PORT_NULL
;
1018 assert(port
->ip_srights
> 0);
1019 if (--port
->ip_srights
== 0 &&
1020 port
->ip_nsrequest
!= IP_NULL
) {
1021 nsrequest
= port
->ip_nsrequest
;
1022 port
->ip_nsrequest
= IP_NULL
;
1023 mscount
= port
->ip_mscount
;
1025 ipc_notify_no_senders(nsrequest
, mscount
);
1032 case MACH_MSG_TYPE_PORT_SEND_ONCE
: {
1033 ipc_port_t port
= (ipc_port_t
) object
;
1035 assert(port
->ip_sorights
> 0);
1037 if (port
->ip_receiver
== space
) {
1038 /* quietly consume the send-once right */
1040 port
->ip_sorights
--;
1041 name
= port
->ip_receiver_name
;
1045 * A very bizarre case. The message
1046 * was received, but before this copyout
1047 * happened the space lost receive rights.
1048 * We can't quietly consume the soright
1049 * out from underneath some other task,
1050 * so generate a send-once notification.
1053 ip_reference(port
); /* restore ref */
1056 ipc_notify_send_once(port
);
1057 name
= MACH_PORT_NULL
;
1064 panic("ipc_object_copyout_dest: strange rights");
1065 name
= MACH_PORT_DEAD
;
1072 * Routine: ipc_object_rename
1074 * Rename an entry in a space.
1078 * KERN_SUCCESS Renamed the entry.
1079 * KERN_INVALID_TASK The space was dead.
1080 * KERN_INVALID_NAME oname didn't denote an entry.
1081 * KERN_NAME_EXISTS nname already denoted an entry.
1082 * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
1088 mach_port_name_t oname
,
1089 mach_port_name_t nname
)
1091 ipc_entry_t oentry
, nentry
;
1094 kr
= ipc_entry_alloc_name(space
, nname
, &nentry
);
1095 if (kr
!= KERN_SUCCESS
) {
1099 /* space is write-locked and active */
1101 if (ipc_right_inuse(space
, nname
, nentry
)) {
1102 /* space is unlocked */
1103 return KERN_NAME_EXISTS
;
1106 /* don't let ipc_entry_lookup see the uninitialized new entry */
1108 if ((oname
== nname
) ||
1109 ((oentry
= ipc_entry_lookup(space
, oname
)) == IE_NULL
)) {
1110 ipc_entry_dealloc(space
, nname
, nentry
);
1111 is_write_unlock(space
);
1112 return KERN_INVALID_NAME
;
1115 kr
= ipc_right_rename(space
, oname
, oentry
, nname
, nentry
);
1116 /* space is unlocked */
1121 * Check whether the object is a port if so, free it. But
1122 * keep track of that fact.
1127 ipc_object_t object
)
1131 if (otype
== IOT_PORT
) {
1132 port
= (ipc_port_t
) object
;
1133 ipc_port_finalize(port
);
1135 io_lock_destroy(object
);
1136 zfree(ipc_object_zones
[otype
], object
);