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.
75 #include <mach/mach_types.h>
76 #include <mach/boolean.h>
77 #include <mach/kern_return.h>
78 #include <mach/port.h>
79 #include <mach/message.h>
81 #include <kern/kern_types.h>
82 #include <kern/misc_protos.h>
83 #include <kern/ipc_kobject.h>
85 #include <ipc/ipc_types.h>
87 #include <ipc/ipc_space.h>
88 #include <ipc/ipc_entry.h>
89 #include <ipc/ipc_object.h>
90 #include <ipc/ipc_hash.h>
91 #include <ipc/ipc_right.h>
92 #include <ipc/ipc_notify.h>
93 #include <ipc/ipc_port.h>
94 #include <ipc/ipc_pset.h>
95 #include <ipc/ipc_labelh.h>
97 #include <security/mac_mach_internal.h>
99 zone_t ipc_object_zones
[IOT_NUMBER
];
102 * Routine: ipc_object_reference
104 * Take a reference to an object.
108 ipc_object_reference(
111 io_reference(object
);
115 * Routine: ipc_object_release
117 * Release a reference to an object.
128 * Routine: ipc_object_translate
130 * Look up an object in a space.
132 * Nothing locked before. If successful, the object
133 * is returned locked. The caller doesn't get a ref.
135 * KERN_SUCCESS Object returned locked.
136 * KERN_INVALID_TASK The space is dead.
137 * KERN_INVALID_NAME The name doesn't denote a right.
138 * KERN_INVALID_RIGHT Name doesn't denote the correct right.
142 ipc_object_translate(
144 mach_port_name_t name
,
145 mach_port_right_t right
,
146 ipc_object_t
*objectp
)
152 kr
= ipc_right_lookup_read(space
, name
, &entry
);
153 if (kr
!= KERN_SUCCESS
)
155 /* space is read-locked and active */
157 if ((entry
->ie_bits
& MACH_PORT_TYPE(right
)) == MACH_PORT_TYPE_NONE
) {
158 is_read_unlock(space
);
159 return KERN_INVALID_RIGHT
;
162 object
= entry
->ie_object
;
163 assert(object
!= IO_NULL
);
166 is_read_unlock(space
);
173 * Routine: ipc_object_translate_two
175 * Look up two objects in a space.
177 * Nothing locked before. If successful, the objects
178 * are returned locked. The caller doesn't get a ref.
180 * KERN_SUCCESS Objects returned locked.
181 * KERN_INVALID_TASK The space is dead.
182 * KERN_INVALID_NAME A name doesn't denote a right.
183 * KERN_INVALID_RIGHT A name doesn't denote the correct right.
187 ipc_object_translate_two(
189 mach_port_name_t name1
,
190 mach_port_right_t right1
,
191 ipc_object_t
*objectp1
,
192 mach_port_name_t name2
,
193 mach_port_right_t right2
,
194 ipc_object_t
*objectp2
)
201 kr
= ipc_right_lookup_two_read(space
, name1
, &entry1
, name2
, &entry2
);
202 if (kr
!= KERN_SUCCESS
)
204 /* space is read-locked and active */
206 if ((entry1
->ie_bits
& MACH_PORT_TYPE(right1
)) == MACH_PORT_TYPE_NONE
) {
207 is_read_unlock(space
);
208 return KERN_INVALID_RIGHT
;
211 if ((entry2
->ie_bits
& MACH_PORT_TYPE(right2
)) == MACH_PORT_TYPE_NONE
) {
212 is_read_unlock(space
);
213 return KERN_INVALID_RIGHT
;
216 object
= entry1
->ie_object
;
217 assert(object
!= IO_NULL
);
221 object
= entry2
->ie_object
;
222 assert(object
!= IO_NULL
);
226 is_read_unlock(space
);
231 * Routine: ipc_object_alloc_dead
233 * Allocate a dead-name entry.
237 * KERN_SUCCESS The dead name is allocated.
238 * KERN_INVALID_TASK The space is dead.
239 * KERN_NO_SPACE No room for an entry in the space.
240 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
244 ipc_object_alloc_dead(
246 mach_port_name_t
*namep
)
251 kr
= ipc_entry_alloc(space
, namep
, &entry
);
252 if (kr
!= KERN_SUCCESS
)
254 /* space is write-locked */
256 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
258 assert(entry
->ie_object
== IO_NULL
);
259 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
260 ipc_entry_modified(space
, *namep
, entry
);
261 is_write_unlock(space
);
266 * Routine: ipc_object_alloc_dead_name
268 * Allocate a dead-name entry, with a specific name.
272 * KERN_SUCCESS The dead name is allocated.
273 * KERN_INVALID_TASK The space is dead.
274 * KERN_NAME_EXISTS The name already denotes a right.
275 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
279 ipc_object_alloc_dead_name(
281 mach_port_name_t name
)
286 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
287 if (kr
!= KERN_SUCCESS
)
289 /* space is write-locked */
291 if (ipc_right_inuse(space
, name
, entry
))
292 return KERN_NAME_EXISTS
;
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
, name
, entry
);
299 is_write_unlock(space
);
304 * Routine: ipc_object_alloc
306 * Allocate an object.
308 * Nothing locked. If successful, the object is returned locked.
309 * The space is write locked on successful return.
310 * The caller doesn't get a reference for the object.
312 * KERN_SUCCESS The object is allocated.
313 * KERN_INVALID_TASK The space is dead.
314 * KERN_NO_SPACE No room for an entry in the space.
315 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
321 ipc_object_type_t otype
,
322 mach_port_type_t type
,
323 mach_port_urefs_t urefs
,
324 mach_port_name_t
*namep
,
325 ipc_object_t
*objectp
)
331 assert(otype
< IOT_NUMBER
);
332 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
333 assert(type
!= MACH_PORT_TYPE_NONE
);
334 assert(urefs
<= MACH_PORT_UREFS_MAX
);
336 object
= io_alloc(otype
);
337 if (object
== IO_NULL
)
338 return KERN_RESOURCE_SHORTAGE
;
340 if (otype
== IOT_PORT
) {
341 ipc_port_t port
= (ipc_port_t
)object
;
343 bzero((char *)port
, sizeof(*port
));
345 mac_port_label_init(&port
->ip_label
);
347 } else if (otype
== IOT_PORT_SET
) {
348 ipc_pset_t pset
= (ipc_pset_t
)object
;
350 bzero((char *)pset
, sizeof(*pset
));
353 io_lock_init(object
);
354 *namep
= CAST_MACH_PORT_TO_NAME(object
);
355 kr
= ipc_entry_alloc(space
, namep
, &entry
);
356 if (kr
!= KERN_SUCCESS
) {
357 io_free(otype
, object
);
360 /* space is write-locked */
362 entry
->ie_bits
|= type
| urefs
;
363 entry
->ie_object
= object
;
364 ipc_entry_modified(space
, *namep
, entry
);
368 object
->io_references
= 1; /* for entry, not caller */
369 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
376 * Routine: ipc_object_alloc_name
378 * Allocate an object, with a specific name.
380 * Nothing locked. If successful, the object is returned locked.
381 * The caller doesn't get a reference for the object.
383 * KERN_SUCCESS The object is allocated.
384 * KERN_INVALID_TASK The space is dead.
385 * KERN_NAME_EXISTS The name already denotes a right.
386 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
390 ipc_object_alloc_name(
392 ipc_object_type_t otype
,
393 mach_port_type_t type
,
394 mach_port_urefs_t urefs
,
395 mach_port_name_t name
,
396 ipc_object_t
*objectp
)
402 assert(otype
< IOT_NUMBER
);
403 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
404 assert(type
!= MACH_PORT_TYPE_NONE
);
405 assert(urefs
<= MACH_PORT_UREFS_MAX
);
407 object
= io_alloc(otype
);
408 if (object
== IO_NULL
)
409 return KERN_RESOURCE_SHORTAGE
;
411 if (otype
== IOT_PORT
) {
412 ipc_port_t port
= (ipc_port_t
)object
;
414 bzero((char *)port
, sizeof(*port
));
416 mac_port_label_init(&port
->ip_label
);
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
)
463 case MACH_MSG_TYPE_MOVE_RECEIVE
:
464 case MACH_MSG_TYPE_COPY_RECEIVE
:
465 return MACH_MSG_TYPE_PORT_RECEIVE
;
467 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
468 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
469 return MACH_MSG_TYPE_PORT_SEND_ONCE
;
471 case MACH_MSG_TYPE_MOVE_SEND
:
472 case MACH_MSG_TYPE_MAKE_SEND
:
473 case MACH_MSG_TYPE_COPY_SEND
:
474 return MACH_MSG_TYPE_PORT_SEND
;
477 return MACH_MSG_TYPE_PORT_NONE
;
482 * Routine: ipc_object_copyin
484 * Copyin a capability from a space.
485 * If successful, the caller gets a ref
486 * for the resulting object, unless it is IO_DEAD.
490 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
491 * KERN_INVALID_TASK The space is dead.
492 * KERN_INVALID_NAME Name doesn't exist in space.
493 * KERN_INVALID_RIGHT Name doesn't denote correct right.
499 mach_port_name_t name
,
500 mach_msg_type_name_t msgt_name
,
501 ipc_object_t
*objectp
)
505 ipc_port_t release_port
;
507 queue_head_t links_data
;
508 queue_t links
= &links_data
;
509 wait_queue_link_t wql
;
511 #if IMPORTANCE_INHERITANCE
518 * Could first try a read lock when doing
519 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
520 * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
523 kr
= ipc_right_lookup_write(space
, name
, &entry
);
524 if (kr
!= KERN_SUCCESS
)
526 /* space is write-locked and active */
528 release_port
= IP_NULL
;
529 kr
= ipc_right_copyin(space
, name
, entry
,
533 #if IMPORTANCE_INHERITANCE
535 #endif /* IMPORTANCE_INHERITANCE */
537 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
538 ipc_entry_dealloc(space
, name
, entry
);
539 is_write_unlock(space
);
541 while(!queue_empty(links
)) {
542 wql
= (wait_queue_link_t
) dequeue(links
);
543 wait_queue_link_free(wql
);
546 #if IMPORTANCE_INHERITANCE
547 if (assertcnt
> 0 && current_task()->imp_receiver
!= 0) {
548 task_importance_drop_internal_assertion(current_task(), assertcnt
);
550 #endif /* IMPORTANCE_INHERITANCE */
552 if (release_port
!= IP_NULL
)
553 ip_release(release_port
);
555 if ((kr
== KERN_SUCCESS
) && (soright
!= IP_NULL
))
556 ipc_notify_port_deleted(soright
, name
);
562 * Routine: ipc_object_copyin_from_kernel
564 * Copyin a naked capability from the kernel.
566 * MACH_MSG_TYPE_MOVE_RECEIVE
567 * The receiver must be ipc_space_kernel
568 * or the receive right must already be in limbo.
569 * Consumes the naked receive right.
570 * MACH_MSG_TYPE_COPY_SEND
571 * A naked send right must be supplied.
572 * The port gains a reference, and a send right
573 * if the port is still active.
574 * MACH_MSG_TYPE_MAKE_SEND
575 * The receiver must be ipc_space_kernel.
576 * The port gains a reference and a send right.
577 * MACH_MSG_TYPE_MOVE_SEND
578 * Consumes a naked send right.
579 * MACH_MSG_TYPE_MAKE_SEND_ONCE
580 * The port gains a reference and a send-once right.
581 * Receiver also be the caller of device subsystem,
583 * MACH_MSG_TYPE_MOVE_SEND_ONCE
584 * Consumes a naked send-once right.
590 ipc_object_copyin_from_kernel(
592 mach_msg_type_name_t msgt_name
)
594 assert(IO_VALID(object
));
597 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
598 ipc_port_t port
= (ipc_port_t
) object
;
601 assert(ip_active(port
));
602 if (port
->ip_destination
!= IP_NULL
) {
603 assert(port
->ip_receiver
== ipc_space_kernel
);
605 /* relevant part of ipc_port_clear_receiver */
606 ipc_port_set_mscount(port
, 0);
608 port
->ip_receiver_name
= MACH_PORT_NULL
;
609 port
->ip_destination
= IP_NULL
;
615 case MACH_MSG_TYPE_COPY_SEND
: {
616 ipc_port_t port
= (ipc_port_t
) object
;
619 if (ip_active(port
)) {
620 assert(port
->ip_srights
> 0);
628 case MACH_MSG_TYPE_MAKE_SEND
: {
629 ipc_port_t port
= (ipc_port_t
) object
;
632 if (ip_active(port
)) {
633 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
634 assert(port
->ip_receiver
== ipc_space_kernel
);
644 case MACH_MSG_TYPE_MOVE_SEND
: {
645 /* move naked send right into the message */
646 assert(((ipc_port_t
)object
)->ip_srights
);
650 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
651 ipc_port_t port
= (ipc_port_t
) object
;
654 if (ip_active(port
)) {
655 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
663 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
664 /* move naked send-once right into the message */
665 assert(((ipc_port_t
)object
)->ip_sorights
);
670 panic("ipc_object_copyin_from_kernel: strange rights");
675 * Routine: ipc_object_destroy
677 * Destroys a naked capability.
678 * Consumes a ref for the object.
680 * A receive right should be in limbo or in transit.
688 mach_msg_type_name_t msgt_name
)
690 assert(IO_VALID(object
));
691 assert(io_otype(object
) == IOT_PORT
);
694 case MACH_MSG_TYPE_PORT_SEND
:
695 ipc_port_release_send((ipc_port_t
) object
);
698 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
699 ipc_notify_send_once((ipc_port_t
) object
);
702 case MACH_MSG_TYPE_PORT_RECEIVE
:
703 ipc_port_release_receive((ipc_port_t
) object
);
707 panic("ipc_object_destroy: strange rights");
712 * Routine: ipc_object_destroy_dest
714 * Destroys a naked capability for the destination of
715 * of a message. Consumes a ref for the object.
722 ipc_object_destroy_dest(
724 mach_msg_type_name_t msgt_name
)
726 assert(IO_VALID(object
));
727 assert(io_otype(object
) == IOT_PORT
);
730 case MACH_MSG_TYPE_PORT_SEND
:
731 ipc_port_release_send((ipc_port_t
) object
);
734 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
735 if (io_active(object
) &&
736 !ip_full_kernel((ipc_port_t
) object
))
737 ipc_notify_send_once((ipc_port_t
) object
);
739 ipc_port_release_sonce((ipc_port_t
) object
);
743 panic("ipc_object_destroy_dest: strange rights");
748 * Routine: ipc_object_copyout
750 * Copyout a capability, placing it into a space.
751 * If successful, consumes a ref for the object.
755 * KERN_SUCCESS Copied out object, consumed ref.
756 * KERN_INVALID_TASK The space is dead.
757 * KERN_INVALID_CAPABILITY The object is dead.
758 * KERN_NO_SPACE No room in space for another right.
759 * KERN_RESOURCE_SHORTAGE No memory available.
760 * KERN_UREFS_OVERFLOW Urefs limit exceeded
761 * and overflow wasn't specified.
768 mach_msg_type_name_t msgt_name
,
770 mach_port_name_t
*namep
)
772 mach_port_name_t name
;
776 assert(IO_VALID(object
));
777 assert(io_otype(object
) == IOT_PORT
);
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
)
836 * Routine: ipc_object_copyout_name
838 * Copyout a capability, placing it into a space.
839 * The specified name is used for the capability.
840 * If successful, consumes a ref for the object.
844 * KERN_SUCCESS Copied out object, consumed ref.
845 * KERN_INVALID_TASK The space is dead.
846 * KERN_INVALID_CAPABILITY The object is dead.
847 * KERN_RESOURCE_SHORTAGE No memory available.
848 * KERN_UREFS_OVERFLOW Urefs limit exceeded
849 * and overflow wasn't specified.
850 * KERN_RIGHT_EXISTS Space has rights under another name.
851 * KERN_NAME_EXISTS Name is already used.
855 ipc_object_copyout_name(
858 mach_msg_type_name_t msgt_name
,
860 mach_port_name_t name
)
862 mach_port_name_t oname
;
867 #if IMPORTANCE_INHERITANCE
869 task_t task
= TASK_NULL
;
870 #endif /* IMPORTANCE_INHERITANCE */
872 assert(IO_VALID(object
));
873 assert(io_otype(object
) == IOT_PORT
);
875 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
876 if (kr
!= KERN_SUCCESS
)
878 /* space is write-locked and active */
880 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
881 ipc_right_reverse(space
, object
, &oname
, &oentry
)) {
882 /* object is locked and active */
887 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
888 ipc_entry_dealloc(space
, name
, entry
);
890 is_write_unlock(space
);
891 return KERN_RIGHT_EXISTS
;
894 assert(entry
== oentry
);
895 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
897 if (ipc_right_inuse(space
, name
, entry
))
898 return KERN_NAME_EXISTS
;
900 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
901 assert(entry
->ie_object
== IO_NULL
);
904 if (!io_active(object
)) {
906 ipc_entry_dealloc(space
, name
, entry
);
907 is_write_unlock(space
);
908 return KERN_INVALID_CAPABILITY
;
911 entry
->ie_object
= object
;
914 /* space is write-locked and active, object is locked and active */
916 #if IMPORTANCE_INHERITANCE
918 * We are slamming a receive right into the space, without
919 * first having been enqueued on a port destined there. So,
920 * we have to arrange to boost the task appropriately if this
921 * port has assertions (and the task wants them).
923 if (msgt_name
== MACH_MSG_TYPE_PORT_RECEIVE
) {
924 ipc_port_t port
= (ipc_port_t
)object
;
926 if ((space
->is_task
!= TASK_NULL
) &&
927 (space
->is_task
->imp_receiver
!= 0)) {
928 assertcnt
= port
->ip_impcount
;
929 task
= space
->is_task
;
930 task_reference(task
);
933 /* take port out of limbo */
934 assert(port
->ip_tempowner
!= 0);
935 port
->ip_tempowner
= 0;
938 #endif /* IMPORTANCE_INHERITANCE */
940 kr
= ipc_right_copyout(space
, name
, entry
,
941 msgt_name
, overflow
, object
);
943 /* object is unlocked */
944 is_write_unlock(space
);
946 #if IMPORTANCE_INHERITANCE
948 * Add the assertions to the task that we captured before
950 if (task
!= TASK_NULL
) {
952 task_importance_hold_internal_assertion(task
, assertcnt
);
953 task_deallocate(task
);
955 #endif /* IMPORTANCE_INHERITANCE */
961 * Routine: ipc_object_copyout_dest
963 * Translates/consumes the destination right of a message.
964 * This is unlike normal copyout because the right is consumed
965 * in a funny way instead of being given to the receiving space.
966 * The receiver gets his name for the port, if he has receive
967 * rights, otherwise MACH_PORT_NULL.
969 * The object is locked and active. Nothing else locked.
970 * The object is unlocked and loses a reference.
974 ipc_object_copyout_dest(
977 mach_msg_type_name_t msgt_name
,
978 mach_port_name_t
*namep
)
980 mach_port_name_t name
;
982 assert(IO_VALID(object
));
983 assert(io_active(object
));
988 * If the space is the receiver/owner of the object,
989 * then we quietly consume the right and return
990 * the space's name for the object. Otherwise
991 * we destroy the right and return MACH_PORT_NULL.
995 case MACH_MSG_TYPE_PORT_SEND
: {
996 ipc_port_t port
= (ipc_port_t
) object
;
997 ipc_port_t nsrequest
= IP_NULL
;
998 mach_port_mscount_t mscount
;
1000 if (port
->ip_receiver
== space
)
1001 name
= port
->ip_receiver_name
;
1003 name
= MACH_PORT_NULL
;
1005 assert(port
->ip_srights
> 0);
1006 if (--port
->ip_srights
== 0 &&
1007 port
->ip_nsrequest
!= IP_NULL
) {
1008 nsrequest
= port
->ip_nsrequest
;
1009 port
->ip_nsrequest
= IP_NULL
;
1010 mscount
= port
->ip_mscount
;
1012 ipc_notify_no_senders(nsrequest
, mscount
);
1018 case MACH_MSG_TYPE_PORT_SEND_ONCE
: {
1019 ipc_port_t port
= (ipc_port_t
) object
;
1021 assert(port
->ip_sorights
> 0);
1023 if (port
->ip_receiver
== space
) {
1024 /* quietly consume the send-once right */
1026 port
->ip_sorights
--;
1027 name
= port
->ip_receiver_name
;
1031 * A very bizarre case. The message
1032 * was received, but before this copyout
1033 * happened the space lost receive rights.
1034 * We can't quietly consume the soright
1035 * out from underneath some other task,
1036 * so generate a send-once notification.
1039 ip_reference(port
); /* restore ref */
1042 ipc_notify_send_once(port
);
1043 name
= MACH_PORT_NULL
;
1050 panic("ipc_object_copyout_dest: strange rights");
1051 name
= MACH_PORT_DEAD
;
1058 * Routine: ipc_object_rename
1060 * Rename an entry in a space.
1064 * KERN_SUCCESS Renamed the entry.
1065 * KERN_INVALID_TASK The space was dead.
1066 * KERN_INVALID_NAME oname didn't denote an entry.
1067 * KERN_NAME_EXISTS nname already denoted an entry.
1068 * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
1074 mach_port_name_t oname
,
1075 mach_port_name_t nname
)
1077 ipc_entry_t oentry
, nentry
;
1080 kr
= ipc_entry_alloc_name(space
, nname
, &nentry
);
1081 if (kr
!= KERN_SUCCESS
)
1084 /* space is write-locked and active */
1086 if (ipc_right_inuse(space
, nname
, nentry
)) {
1087 /* space is unlocked */
1088 return KERN_NAME_EXISTS
;
1091 /* don't let ipc_entry_lookup see the uninitialized new entry */
1093 if ((oname
== nname
) ||
1094 ((oentry
= ipc_entry_lookup(space
, oname
)) == IE_NULL
)) {
1095 ipc_entry_dealloc(space
, nname
, nentry
);
1096 is_write_unlock(space
);
1097 return KERN_INVALID_NAME
;
1100 kr
= ipc_right_rename(space
, oname
, oentry
, nname
, nentry
);
1101 /* space is unlocked */
1106 * Get a label out of a port, to be used by a kernel call
1107 * that takes a security label as a parameter. In this case, we want
1108 * to use the label stored in the label handle and not the label on its
1111 * The port should be locked for this call. The lock protecting
1112 * label handle contents should not be necessary, as they can only
1113 * be modified when a label handle with one reference is a task label.
1114 * User allocated label handles can never be modified.
1116 #if CONFIG_MACF_MACH
1117 struct label
*io_getlabel (ipc_object_t objp
)
1119 ipc_port_t port
= (ipc_port_t
)objp
;
1121 assert(io_otype(objp
) == IOT_PORT
);
1123 if (ip_kotype(port
) == IKOT_LABELH
)
1124 return &((ipc_labelh_t
) port
->ip_kobject
)->lh_label
;
1126 return &port
->ip_label
;
1131 * Check whether the object is a port if so, free it. But
1132 * keep track of that fact.
1137 ipc_object_t object
)
1141 if (otype
== IOT_PORT
) {
1142 port
= (ipc_port_t
) object
;
1143 ipc_port_finalize(port
);
1145 io_lock_destroy(object
);
1146 zfree(ipc_object_zones
[otype
], object
);