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(
112 assert(object
->io_references
> 0);
113 io_reference(object
);
118 * Routine: ipc_object_release
120 * Release a reference to an object.
128 assert(object
->io_references
> 0);
130 io_check_unlock(object
);
134 * Routine: ipc_object_translate
136 * Look up an object in a space.
138 * Nothing locked before. If successful, the object
139 * is returned locked. The caller doesn't get a ref.
141 * KERN_SUCCESS Object returned locked.
142 * KERN_INVALID_TASK The space is dead.
143 * KERN_INVALID_NAME The name doesn't denote a right.
144 * KERN_INVALID_RIGHT Name doesn't denote the correct right.
148 ipc_object_translate(
150 mach_port_name_t name
,
151 mach_port_right_t right
,
152 ipc_object_t
*objectp
)
158 kr
= ipc_right_lookup_read(space
, name
, &entry
);
159 if (kr
!= KERN_SUCCESS
)
161 /* space is read-locked and active */
163 if ((entry
->ie_bits
& MACH_PORT_TYPE(right
)) == MACH_PORT_TYPE_NONE
) {
164 is_read_unlock(space
);
165 return KERN_INVALID_RIGHT
;
168 object
= entry
->ie_object
;
169 assert(object
!= IO_NULL
);
172 is_read_unlock(space
);
179 * Routine: ipc_object_translate_two
181 * Look up two objects in a space.
183 * Nothing locked before. If successful, the objects
184 * are returned locked. The caller doesn't get a ref.
186 * KERN_SUCCESS Objects returned locked.
187 * KERN_INVALID_TASK The space is dead.
188 * KERN_INVALID_NAME A name doesn't denote a right.
189 * KERN_INVALID_RIGHT A name doesn't denote the correct right.
193 ipc_object_translate_two(
195 mach_port_name_t name1
,
196 mach_port_right_t right1
,
197 ipc_object_t
*objectp1
,
198 mach_port_name_t name2
,
199 mach_port_right_t right2
,
200 ipc_object_t
*objectp2
)
207 kr
= ipc_right_lookup_two_read(space
, name1
, &entry1
, name2
, &entry2
);
208 if (kr
!= KERN_SUCCESS
)
210 /* space is read-locked and active */
212 if ((entry1
->ie_bits
& MACH_PORT_TYPE(right1
)) == MACH_PORT_TYPE_NONE
) {
213 is_read_unlock(space
);
214 return KERN_INVALID_RIGHT
;
217 if ((entry2
->ie_bits
& MACH_PORT_TYPE(right2
)) == MACH_PORT_TYPE_NONE
) {
218 is_read_unlock(space
);
219 return KERN_INVALID_RIGHT
;
222 object
= entry1
->ie_object
;
223 assert(object
!= IO_NULL
);
227 object
= entry2
->ie_object
;
228 assert(object
!= IO_NULL
);
232 is_read_unlock(space
);
237 * Routine: ipc_object_alloc_dead
239 * Allocate a dead-name entry.
243 * KERN_SUCCESS The dead name is allocated.
244 * KERN_INVALID_TASK The space is dead.
245 * KERN_NO_SPACE No room for an entry in the space.
246 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
250 ipc_object_alloc_dead(
252 mach_port_name_t
*namep
)
257 kr
= ipc_entry_alloc(space
, namep
, &entry
);
258 if (kr
!= KERN_SUCCESS
)
260 /* space is write-locked */
262 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
264 assert(entry
->ie_object
== IO_NULL
);
265 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
267 is_write_unlock(space
);
272 * Routine: ipc_object_alloc_dead_name
274 * Allocate a dead-name entry, with a specific name.
278 * KERN_SUCCESS The dead name is allocated.
279 * KERN_INVALID_TASK The space is dead.
280 * KERN_NAME_EXISTS The name already denotes a right.
281 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
285 ipc_object_alloc_dead_name(
287 mach_port_name_t name
)
292 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
293 if (kr
!= KERN_SUCCESS
)
295 /* space is write-locked */
297 if (ipc_right_inuse(space
, name
, entry
))
298 return KERN_NAME_EXISTS
;
300 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
302 assert(entry
->ie_object
== IO_NULL
);
303 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
305 is_write_unlock(space
);
310 * Routine: ipc_object_alloc
312 * Allocate an object.
314 * Nothing locked. If successful, the object is returned locked.
315 * The caller doesn't get a reference for the object.
317 * KERN_SUCCESS The object is allocated.
318 * KERN_INVALID_TASK The space is dead.
319 * KERN_NO_SPACE No room for an entry in the space.
320 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
326 ipc_object_type_t otype
,
327 mach_port_type_t type
,
328 mach_port_urefs_t urefs
,
329 mach_port_name_t
*namep
,
330 ipc_object_t
*objectp
)
336 assert(otype
< IOT_NUMBER
);
337 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
338 assert(type
!= MACH_PORT_TYPE_NONE
);
339 assert(urefs
<= MACH_PORT_UREFS_MAX
);
341 object
= io_alloc(otype
);
342 if (object
== IO_NULL
)
343 return KERN_RESOURCE_SHORTAGE
;
345 if (otype
== IOT_PORT
) {
346 ipc_port_t port
= (ipc_port_t
)object
;
348 bzero((char *)port
, sizeof(*port
));
350 mac_port_label_init(&port
->ip_label
);
352 } else if (otype
== IOT_PORT_SET
) {
353 ipc_pset_t pset
= (ipc_pset_t
)object
;
355 bzero((char *)pset
, sizeof(*pset
));
358 io_lock_init(object
);
359 *namep
= CAST_MACH_PORT_TO_NAME(object
);
360 kr
= ipc_entry_alloc(space
, namep
, &entry
);
361 if (kr
!= KERN_SUCCESS
) {
362 io_free(otype
, object
);
365 /* space is write-locked */
367 entry
->ie_bits
|= type
| urefs
;
368 entry
->ie_object
= object
;
371 is_write_unlock(space
);
373 object
->io_references
= 1; /* for entry, not caller */
374 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
381 * Routine: ipc_object_alloc_name
383 * Allocate an object, with a specific name.
385 * Nothing locked. If successful, the object is returned locked.
386 * The caller doesn't get a reference for the object.
388 * KERN_SUCCESS The object is allocated.
389 * KERN_INVALID_TASK The space is dead.
390 * KERN_NAME_EXISTS The name already denotes a right.
391 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
395 ipc_object_alloc_name(
397 ipc_object_type_t otype
,
398 mach_port_type_t type
,
399 mach_port_urefs_t urefs
,
400 mach_port_name_t name
,
401 ipc_object_t
*objectp
)
407 assert(otype
< IOT_NUMBER
);
408 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
409 assert(type
!= MACH_PORT_TYPE_NONE
);
410 assert(urefs
<= MACH_PORT_UREFS_MAX
);
412 object
= io_alloc(otype
);
413 if (object
== IO_NULL
)
414 return KERN_RESOURCE_SHORTAGE
;
416 if (otype
== IOT_PORT
) {
417 ipc_port_t port
= (ipc_port_t
)object
;
419 bzero((char *)port
, sizeof(*port
));
421 mac_port_label_init(&port
->ip_label
);
423 } else if (otype
== IOT_PORT_SET
) {
424 ipc_pset_t pset
= (ipc_pset_t
)object
;
426 bzero((char *)pset
, sizeof(*pset
));
429 io_lock_init(object
);
430 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
431 if (kr
!= KERN_SUCCESS
) {
432 io_free(otype
, object
);
435 /* space is write-locked */
437 if (ipc_right_inuse(space
, name
, entry
)) {
438 io_free(otype
, object
);
439 return KERN_NAME_EXISTS
;
442 entry
->ie_bits
|= type
| urefs
;
443 entry
->ie_object
= object
;
446 is_write_unlock(space
);
448 object
->io_references
= 1; /* for entry, not caller */
449 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
456 * Routine: ipc_object_copyin_type
458 * Convert a send type name to a received type name.
462 ipc_object_copyin_type(
463 mach_msg_type_name_t msgt_name
)
467 case MACH_MSG_TYPE_MOVE_RECEIVE
:
468 case MACH_MSG_TYPE_COPY_RECEIVE
:
469 return MACH_MSG_TYPE_PORT_RECEIVE
;
471 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
472 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
473 return MACH_MSG_TYPE_PORT_SEND_ONCE
;
475 case MACH_MSG_TYPE_MOVE_SEND
:
476 case MACH_MSG_TYPE_MAKE_SEND
:
477 case MACH_MSG_TYPE_COPY_SEND
:
478 return MACH_MSG_TYPE_PORT_SEND
;
481 return MACH_MSG_TYPE_PORT_NONE
;
486 * Routine: ipc_object_copyin
488 * Copyin a capability from a space.
489 * If successful, the caller gets a ref
490 * for the resulting object, unless it is IO_DEAD.
494 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
495 * KERN_INVALID_TASK The space is dead.
496 * KERN_INVALID_NAME Name doesn't exist in space.
497 * KERN_INVALID_RIGHT Name doesn't denote correct right.
503 mach_port_name_t name
,
504 mach_msg_type_name_t msgt_name
,
505 ipc_object_t
*objectp
)
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
)
520 /* space is write-locked and active */
522 kr
= ipc_right_copyin(space
, name
, entry
,
525 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
526 ipc_entry_dealloc(space
, name
, entry
);
527 is_write_unlock(space
);
529 if ((kr
== KERN_SUCCESS
) && (soright
!= IP_NULL
))
530 ipc_notify_port_deleted(soright
, name
);
536 * Routine: ipc_object_copyin_from_kernel
538 * Copyin a naked capability from the kernel.
540 * MACH_MSG_TYPE_MOVE_RECEIVE
541 * The receiver must be ipc_space_kernel
542 * or the receive right must already be in limbo.
543 * Consumes the naked receive right.
544 * MACH_MSG_TYPE_COPY_SEND
545 * A naked send right must be supplied.
546 * The port gains a reference, and a send right
547 * if the port is still active.
548 * MACH_MSG_TYPE_MAKE_SEND
549 * The receiver must be ipc_space_kernel.
550 * The port gains a reference and a send right.
551 * MACH_MSG_TYPE_MOVE_SEND
552 * Consumes a naked send right.
553 * MACH_MSG_TYPE_MAKE_SEND_ONCE
554 * The port gains a reference and a send-once right.
555 * Receiver also be the caller of device subsystem,
557 * MACH_MSG_TYPE_MOVE_SEND_ONCE
558 * Consumes a naked send-once right.
564 ipc_object_copyin_from_kernel(
566 mach_msg_type_name_t msgt_name
)
568 assert(IO_VALID(object
));
571 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
572 ipc_port_t port
= (ipc_port_t
) object
;
575 assert(ip_active(port
));
576 if (port
->ip_destination
!= IP_NULL
) {
577 assert(port
->ip_receiver
== ipc_space_kernel
);
579 /* relevant part of ipc_port_clear_receiver */
580 ipc_port_set_mscount(port
, 0);
582 port
->ip_receiver_name
= MACH_PORT_NULL
;
583 port
->ip_destination
= IP_NULL
;
589 case MACH_MSG_TYPE_COPY_SEND
: {
590 ipc_port_t port
= (ipc_port_t
) object
;
593 if (ip_active(port
)) {
594 assert(port
->ip_srights
> 0);
602 case MACH_MSG_TYPE_MAKE_SEND
: {
603 ipc_port_t port
= (ipc_port_t
) object
;
606 assert(ip_active(port
));
607 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
608 assert(port
->ip_receiver
== ipc_space_kernel
);
617 case MACH_MSG_TYPE_MOVE_SEND
: {
618 /* move naked send right into the message */
619 assert(((ipc_port_t
)object
)->ip_srights
);
623 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
624 ipc_port_t port
= (ipc_port_t
) object
;
627 assert(ip_active(port
));
628 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
636 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
637 /* move naked send-once right into the message */
638 assert(((ipc_port_t
)object
)->ip_sorights
);
643 panic("ipc_object_copyin_from_kernel: strange rights");
648 * Routine: ipc_object_destroy
650 * Destroys a naked capability.
651 * Consumes a ref for the object.
653 * A receive right should be in limbo or in transit.
661 mach_msg_type_name_t msgt_name
)
663 assert(IO_VALID(object
));
664 assert(io_otype(object
) == IOT_PORT
);
667 case MACH_MSG_TYPE_PORT_SEND
:
668 ipc_port_release_send((ipc_port_t
) object
);
671 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
672 ipc_notify_send_once((ipc_port_t
) object
);
675 case MACH_MSG_TYPE_PORT_RECEIVE
:
676 ipc_port_release_receive((ipc_port_t
) object
);
680 panic("ipc_object_destroy: strange rights");
685 * Routine: ipc_object_destroy_dest
687 * Destroys a naked capability for the destination of
688 * of a message. Consumes a ref for the object.
695 ipc_object_destroy_dest(
697 mach_msg_type_name_t msgt_name
)
699 assert(IO_VALID(object
));
700 assert(io_otype(object
) == IOT_PORT
);
703 case MACH_MSG_TYPE_PORT_SEND
:
704 ipc_port_release_send((ipc_port_t
) object
);
707 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
708 if (io_active(object
) &&
709 !ip_full_kernel((ipc_port_t
) object
))
710 ipc_notify_send_once((ipc_port_t
) object
);
712 ipc_port_release_sonce((ipc_port_t
) object
);
716 panic("ipc_object_destroy_dest: strange rights");
721 * Routine: ipc_object_copyout
723 * Copyout a capability, placing it into a space.
724 * If successful, consumes a ref for the object.
728 * KERN_SUCCESS Copied out object, consumed ref.
729 * KERN_INVALID_TASK The space is dead.
730 * KERN_INVALID_CAPABILITY The object is dead.
731 * KERN_NO_SPACE No room in space for another right.
732 * KERN_RESOURCE_SHORTAGE No memory available.
733 * KERN_UREFS_OVERFLOW Urefs limit exceeded
734 * and overflow wasn't specified.
741 mach_msg_type_name_t msgt_name
,
743 mach_port_name_t
*namep
)
745 mach_port_name_t name
;
749 assert(IO_VALID(object
));
750 assert(io_otype(object
) == IOT_PORT
);
752 is_write_lock(space
);
755 if (!space
->is_active
) {
756 is_write_unlock(space
);
757 return KERN_INVALID_TASK
;
760 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
761 ipc_right_reverse(space
, object
, &name
, &entry
)) {
762 /* object is locked and active */
764 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
768 name
= CAST_MACH_PORT_TO_NAME(object
);
769 kr
= ipc_entry_get(space
, &name
, &entry
);
770 if (kr
!= KERN_SUCCESS
) {
771 /* unlocks/locks space, so must start again */
773 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
774 if (kr
!= KERN_SUCCESS
)
775 return kr
; /* space is unlocked */
780 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
781 assert(entry
->ie_object
== IO_NULL
);
784 if (!io_active(object
)) {
786 ipc_entry_dealloc(space
, name
, entry
);
787 is_write_unlock(space
);
788 return KERN_INVALID_CAPABILITY
;
791 entry
->ie_object
= object
;
795 /* space is write-locked and active, object is locked and active */
797 kr
= ipc_right_copyout(space
, name
, entry
,
798 msgt_name
, overflow
, object
);
799 /* object is unlocked */
800 is_write_unlock(space
);
802 if (kr
== KERN_SUCCESS
)
808 * Routine: ipc_object_copyout_name
810 * Copyout a capability, placing it into a space.
811 * The specified name is used for the capability.
812 * If successful, consumes a ref for the object.
816 * KERN_SUCCESS Copied out object, consumed ref.
817 * KERN_INVALID_TASK The space is dead.
818 * KERN_INVALID_CAPABILITY The object is dead.
819 * KERN_RESOURCE_SHORTAGE No memory available.
820 * KERN_UREFS_OVERFLOW Urefs limit exceeded
821 * and overflow wasn't specified.
822 * KERN_RIGHT_EXISTS Space has rights under another name.
823 * KERN_NAME_EXISTS Name is already used.
827 ipc_object_copyout_name(
830 mach_msg_type_name_t msgt_name
,
832 mach_port_name_t name
)
834 mach_port_name_t oname
;
839 assert(IO_VALID(object
));
840 assert(io_otype(object
) == IOT_PORT
);
842 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
843 if (kr
!= KERN_SUCCESS
)
845 /* space is write-locked and active */
847 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
848 ipc_right_reverse(space
, object
, &oname
, &oentry
)) {
849 /* object is locked and active */
854 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
855 ipc_entry_dealloc(space
, name
, entry
);
857 is_write_unlock(space
);
858 return KERN_RIGHT_EXISTS
;
861 assert(entry
== oentry
);
862 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
864 if (ipc_right_inuse(space
, name
, entry
))
865 return KERN_NAME_EXISTS
;
867 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
868 assert(entry
->ie_object
== IO_NULL
);
871 if (!io_active(object
)) {
873 ipc_entry_dealloc(space
, name
, entry
);
874 is_write_unlock(space
);
875 return KERN_INVALID_CAPABILITY
;
878 entry
->ie_object
= object
;
881 /* space is write-locked and active, object is locked and active */
883 kr
= ipc_right_copyout(space
, name
, entry
,
884 msgt_name
, overflow
, object
);
885 /* object is unlocked */
886 is_write_unlock(space
);
891 * Routine: ipc_object_copyout_dest
893 * Translates/consumes the destination right of a message.
894 * This is unlike normal copyout because the right is consumed
895 * in a funny way instead of being given to the receiving space.
896 * The receiver gets his name for the port, if he has receive
897 * rights, otherwise MACH_PORT_NULL.
899 * The object is locked and active. Nothing else locked.
900 * The object is unlocked and loses a reference.
904 ipc_object_copyout_dest(
907 mach_msg_type_name_t msgt_name
,
908 mach_port_name_t
*namep
)
910 mach_port_name_t name
;
912 assert(IO_VALID(object
));
913 assert(io_active(object
));
918 * If the space is the receiver/owner of the object,
919 * then we quietly consume the right and return
920 * the space's name for the object. Otherwise
921 * we destroy the right and return MACH_PORT_NULL.
925 case MACH_MSG_TYPE_PORT_SEND
: {
926 ipc_port_t port
= (ipc_port_t
) object
;
927 ipc_port_t nsrequest
= IP_NULL
;
928 mach_port_mscount_t mscount
;
930 if (port
->ip_receiver
== space
)
931 name
= port
->ip_receiver_name
;
933 name
= MACH_PORT_NULL
;
935 assert(port
->ip_srights
> 0);
936 if (--port
->ip_srights
== 0 &&
937 port
->ip_nsrequest
!= IP_NULL
) {
938 nsrequest
= port
->ip_nsrequest
;
939 port
->ip_nsrequest
= IP_NULL
;
940 mscount
= port
->ip_mscount
;
942 ipc_notify_no_senders(nsrequest
, mscount
);
948 case MACH_MSG_TYPE_PORT_SEND_ONCE
: {
949 ipc_port_t port
= (ipc_port_t
) object
;
951 assert(port
->ip_sorights
> 0);
953 if (port
->ip_receiver
== space
) {
954 /* quietly consume the send-once right */
957 name
= port
->ip_receiver_name
;
961 * A very bizarre case. The message
962 * was received, but before this copyout
963 * happened the space lost receive rights.
964 * We can't quietly consume the soright
965 * out from underneath some other task,
966 * so generate a send-once notification.
969 ip_reference(port
); /* restore ref */
972 ipc_notify_send_once(port
);
973 name
= MACH_PORT_NULL
;
980 panic("ipc_object_copyout_dest: strange rights");
981 name
= MACH_PORT_DEAD
;
988 * Routine: ipc_object_rename
990 * Rename an entry in a space.
994 * KERN_SUCCESS Renamed the entry.
995 * KERN_INVALID_TASK The space was dead.
996 * KERN_INVALID_NAME oname didn't denote an entry.
997 * KERN_NAME_EXISTS nname already denoted an entry.
998 * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
1004 mach_port_name_t oname
,
1005 mach_port_name_t nname
)
1007 ipc_entry_t oentry
, nentry
;
1010 kr
= ipc_entry_alloc_name(space
, nname
, &nentry
);
1011 if (kr
!= KERN_SUCCESS
)
1014 /* space is write-locked and active */
1016 if (ipc_right_inuse(space
, nname
, nentry
)) {
1017 /* space is unlocked */
1018 return KERN_NAME_EXISTS
;
1021 /* don't let ipc_entry_lookup see the uninitialized new entry */
1023 if ((oname
== nname
) ||
1024 ((oentry
= ipc_entry_lookup(space
, oname
)) == IE_NULL
)) {
1025 ipc_entry_dealloc(space
, nname
, nentry
);
1026 is_write_unlock(space
);
1027 return KERN_INVALID_NAME
;
1030 kr
= ipc_right_rename(space
, oname
, oentry
, nname
, nentry
);
1031 /* space is unlocked */
1036 * Get a label out of a port, to be used by a kernel call
1037 * that takes a security label as a parameter. In this case, we want
1038 * to use the label stored in the label handle and not the label on its
1041 * The port should be locked for this call. The lock protecting
1042 * label handle contents should not be necessary, as they can only
1043 * be modified when a label handle with one reference is a task label.
1044 * User allocated label handles can never be modified.
1046 #if CONFIG_MACF_MACH
1047 struct label
*io_getlabel (ipc_object_t objp
)
1049 ipc_port_t port
= (ipc_port_t
)objp
;
1051 assert(io_otype(objp
) == IOT_PORT
);
1053 if (ip_kotype(port
) == IKOT_LABELH
)
1054 return &((ipc_labelh_t
) port
->ip_kobject
)->lh_label
;
1056 return &port
->ip_label
;
1061 * Check whether the object is a port if so, free it. But
1062 * keep track of that fact.
1067 ipc_object_t object
)
1071 if (otype
== IOT_PORT
) {
1072 port
= (ipc_port_t
) object
;
1073 ipc_port_finalize(port
);
1075 io_lock_destroy(object
);
1076 zfree(ipc_object_zones
[otype
], object
);
1079 #include <mach_kdb.h>
1082 #include <ddb/db_output.h>
1084 #define printf kdbprintf
1087 * Routine: ipc_object_print
1089 * Pretty-print an object for kdb.
1092 const char *ikot_print_array
[IKOT_MAX_TYPE
] = {
1103 "(DEVICE) ", /* 10 */
1113 "(ACTIVATION) ", /* 20 */
1119 "(CLOCK_CTRL) ", /* 26 */
1120 "(IOKIT_SPARE) ", /* 27 */
1121 "(NAMED_MEM_ENTRY) ", /* 28 */
1123 "(IOKIT_OBJECT) ", /* 30 */
1125 "(MEM_OBJ_CONTROL) ",
1126 "(AU_SESSIONPORT) ", /* 33 */
1127 "(FILEPORT)", /* 34 */
1128 #if CONFIG_MACF_MACH
1132 * Add new entries here.
1133 * Please keep in sync with kern/ipc_kobject.h
1135 "(UNKNOWN) " /* magic catchall */
1140 ipc_object_t object
)
1144 iprintf("%s", io_active(object
) ? "active" : "dead");
1145 printf(", refs=%d", object
->io_references
);
1146 printf(", otype=%d", io_otype(object
));
1147 kotype
= io_kotype(object
);
1148 if (kotype
>= 0 && kotype
< IKOT_MAX_TYPE
)
1149 printf(", kotype=%d %s\n", io_kotype(object
),
1150 ikot_print_array
[kotype
]);
1152 printf(", kotype=0x%x %s\n", io_kotype(object
),
1153 ikot_print_array
[IKOT_UNKNOWN
]);
1156 #endif /* MACH_KDB */