2 * Copyright (c) 2000-2020 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 SECURITY_READ_ONLY_LATE(zone_t
) ipc_object_zones
[IOT_NUMBER
];
99 ZONE_INIT(&ipc_object_zones
[IOT_PORT
], "ipc ports", sizeof(struct ipc_port
),
100 ZC_NOENCRYPT
| ZC_CACHING
| ZC_ZFREE_CLEARMEM
| ZC_NOSEQUESTER
,
101 ZONE_ID_IPC_PORT
, NULL
);
103 ZONE_INIT(&ipc_object_zones
[IOT_PORT_SET
], "ipc port sets",
104 sizeof(struct ipc_pset
),
105 ZC_NOENCRYPT
| ZC_ZFREE_CLEARMEM
| ZC_NOSEQUESTER
,
106 ZONE_ID_IPC_PORT_SET
, NULL
);
109 * Routine: ipc_object_reference
111 * Take a reference to an object.
115 ipc_object_reference(
118 io_reference(object
);
122 * Routine: ipc_object_release
124 * Release a reference to an object.
135 * Routine: ipc_object_translate
137 * Look up an object in a space.
139 * Nothing locked before. If successful, the object
140 * is returned active and locked. The caller doesn't get a ref.
142 * KERN_SUCCESS Object returned locked.
143 * KERN_INVALID_TASK The space is dead.
144 * KERN_INVALID_NAME The name doesn't denote a right
145 * 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 if (!MACH_PORT_RIGHT_VALID_TRANSLATE(right
)) {
159 return KERN_INVALID_RIGHT
;
162 kr
= ipc_right_lookup_read(space
, name
, &entry
);
163 if (kr
!= KERN_SUCCESS
) {
166 /* space is read-locked and active */
168 if ((entry
->ie_bits
& MACH_PORT_TYPE(right
)) == MACH_PORT_TYPE_NONE
) {
169 is_read_unlock(space
);
170 return KERN_INVALID_RIGHT
;
173 object
= entry
->ie_object
;
174 assert(object
!= IO_NULL
);
177 is_read_unlock(space
);
179 if (!io_active(object
)) {
181 return KERN_INVALID_NAME
;
189 * Routine: ipc_object_translate_two
191 * Look up two objects in a space.
193 * Nothing locked before. If successful, the objects
194 * are returned locked. The caller doesn't get a ref.
196 * KERN_SUCCESS Objects returned locked.
197 * KERN_INVALID_TASK The space is dead.
198 * KERN_INVALID_NAME A name doesn't denote a right.
199 * KERN_INVALID_RIGHT A name doesn't denote the correct right.
203 ipc_object_translate_two(
205 mach_port_name_t name1
,
206 mach_port_right_t right1
,
207 ipc_object_t
*objectp1
,
208 mach_port_name_t name2
,
209 mach_port_right_t right2
,
210 ipc_object_t
*objectp2
)
214 ipc_object_t object1
, object2
;
216 boolean_t doguard
= TRUE
;
218 kr
= ipc_right_lookup_two_read(space
, name1
, &entry1
, name2
, &entry2
);
219 if (kr
!= KERN_SUCCESS
) {
222 /* space is read-locked and active */
224 if ((entry1
->ie_bits
& MACH_PORT_TYPE(right1
)) == MACH_PORT_TYPE_NONE
) {
225 /* If looking for receive, and the entry used to hold one, give a pass on EXC_GUARD */
226 if ((right1
& MACH_PORT_RIGHT_RECEIVE
) == MACH_PORT_RIGHT_RECEIVE
&&
227 (entry1
->ie_bits
& MACH_PORT_TYPE_EX_RECEIVE
) == MACH_PORT_TYPE_EX_RECEIVE
) {
230 is_read_unlock(space
);
232 mach_port_guard_exception(name1
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
234 return KERN_INVALID_RIGHT
;
237 if ((entry2
->ie_bits
& MACH_PORT_TYPE(right2
)) == MACH_PORT_TYPE_NONE
) {
238 /* If looking for receive, and the entry used to hold one, give a pass on EXC_GUARD */
239 if ((right2
& MACH_PORT_RIGHT_RECEIVE
) == MACH_PORT_RIGHT_RECEIVE
&&
240 (entry2
->ie_bits
& MACH_PORT_TYPE_EX_RECEIVE
) == MACH_PORT_TYPE_EX_RECEIVE
) {
243 is_read_unlock(space
);
245 mach_port_guard_exception(name2
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
247 return KERN_INVALID_RIGHT
;
250 object1
= entry1
->ie_object
;
251 assert(object1
!= IO_NULL
);
253 if (!io_active(object1
)) {
255 is_read_unlock(space
);
256 return KERN_INVALID_NAME
;
259 object2
= entry2
->ie_object
;
260 assert(object2
!= IO_NULL
);
262 if (!io_active(object2
)) {
265 is_read_unlock(space
);
266 return KERN_INVALID_NAME
;
272 is_read_unlock(space
);
277 * Routine: ipc_object_alloc_dead
279 * Allocate a dead-name entry.
283 * KERN_SUCCESS The dead name is allocated.
284 * KERN_INVALID_TASK The space is dead.
285 * KERN_NO_SPACE No room for an entry in the space.
286 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
290 ipc_object_alloc_dead(
292 mach_port_name_t
*namep
)
297 kr
= ipc_entry_alloc(space
, namep
, &entry
);
298 if (kr
!= KERN_SUCCESS
) {
301 /* space is write-locked */
303 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
305 assert(entry
->ie_object
== IO_NULL
);
306 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
307 ipc_entry_modified(space
, *namep
, entry
);
308 is_write_unlock(space
);
313 * Routine: ipc_object_alloc_dead_name
315 * Allocate a dead-name entry, with a specific name.
319 * KERN_SUCCESS The dead name is allocated.
320 * KERN_INVALID_TASK The space is dead.
321 * KERN_NAME_EXISTS The name already denotes a right.
322 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
326 ipc_object_alloc_dead_name(
328 mach_port_name_t name
)
333 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
334 if (kr
!= KERN_SUCCESS
) {
337 /* space is write-locked */
339 if (ipc_right_inuse(space
, name
, entry
)) {
340 return KERN_NAME_EXISTS
;
343 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
345 assert(entry
->ie_object
== IO_NULL
);
346 entry
->ie_bits
|= MACH_PORT_TYPE_DEAD_NAME
| 1;
347 ipc_entry_modified(space
, name
, entry
);
348 is_write_unlock(space
);
353 * Routine: ipc_object_alloc
355 * Allocate an object.
357 * Nothing locked. If successful, the object is returned locked.
358 * The space is write locked on successful return.
359 * The caller doesn't get a reference for the object.
361 * KERN_SUCCESS The object is allocated.
362 * KERN_INVALID_TASK The space is dead.
363 * KERN_NO_SPACE No room for an entry in the space.
364 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
370 ipc_object_type_t otype
,
371 mach_port_type_t type
,
372 mach_port_urefs_t urefs
,
373 mach_port_name_t
*namep
,
374 ipc_object_t
*objectp
)
380 assert(otype
< IOT_NUMBER
);
381 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
382 assert(type
!= MACH_PORT_TYPE_NONE
);
383 assert(urefs
<= MACH_PORT_UREFS_MAX
);
385 object
= io_alloc(otype
);
386 if (object
== IO_NULL
) {
387 return KERN_RESOURCE_SHORTAGE
;
390 if (otype
== IOT_PORT
) {
391 ipc_port_t port
= ip_object_to_port(object
);
393 bzero((char *)port
, sizeof(*port
));
394 } else if (otype
== IOT_PORT_SET
) {
395 ipc_pset_t pset
= ips_object_to_pset(object
);
397 bzero((char *)pset
, sizeof(*pset
));
400 io_lock_init(object
);
401 *namep
= CAST_MACH_PORT_TO_NAME(object
);
402 kr
= ipc_entry_alloc(space
, namep
, &entry
);
403 if (kr
!= KERN_SUCCESS
) {
404 io_free(otype
, object
);
407 /* space is write-locked */
409 entry
->ie_bits
|= type
| urefs
;
410 entry
->ie_object
= object
;
411 ipc_entry_modified(space
, *namep
, entry
);
413 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
416 object
->io_references
= 1; /* for entry, not caller */
423 * Routine: ipc_object_alloc_name
425 * Allocate an object, with a specific name.
427 * Nothing locked. If successful, the object is returned locked.
428 * The caller doesn't get a reference for the object.
430 * KERN_SUCCESS The object is allocated.
431 * KERN_INVALID_TASK The space is dead.
432 * KERN_NAME_EXISTS The name already denotes a right.
433 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
437 ipc_object_alloc_name(
439 ipc_object_type_t otype
,
440 mach_port_type_t type
,
441 mach_port_urefs_t urefs
,
442 mach_port_name_t name
,
443 ipc_object_t
*objectp
)
449 assert(otype
< IOT_NUMBER
);
450 assert((type
& MACH_PORT_TYPE_ALL_RIGHTS
) == type
);
451 assert(type
!= MACH_PORT_TYPE_NONE
);
452 assert(urefs
<= MACH_PORT_UREFS_MAX
);
454 object
= io_alloc(otype
);
455 if (object
== IO_NULL
) {
456 return KERN_RESOURCE_SHORTAGE
;
459 if (otype
== IOT_PORT
) {
460 ipc_port_t port
= ip_object_to_port(object
);
462 bzero((char *)port
, sizeof(*port
));
463 } else if (otype
== IOT_PORT_SET
) {
464 ipc_pset_t pset
= ips_object_to_pset(object
);
466 bzero((char *)pset
, sizeof(*pset
));
469 io_lock_init(object
);
470 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
471 if (kr
!= KERN_SUCCESS
) {
472 io_free(otype
, object
);
475 /* space is write-locked */
477 if (ipc_right_inuse(space
, name
, entry
)) {
478 io_free(otype
, object
);
479 return KERN_NAME_EXISTS
;
482 entry
->ie_bits
|= type
| urefs
;
483 entry
->ie_object
= object
;
484 ipc_entry_modified(space
, name
, entry
);
486 object
->io_bits
= io_makebits(TRUE
, otype
, 0);
489 is_write_unlock(space
);
491 object
->io_references
= 1; /* for entry, not caller */
497 /* Routine: ipc_object_validate
499 * Validates an ipc port or port set as belonging to the correct
507 if (io_otype(object
) != IOT_PORT_SET
) {
508 zone_id_require(ZONE_ID_IPC_PORT
,
509 sizeof(struct ipc_port
), object
);
511 zone_id_require(ZONE_ID_IPC_PORT_SET
,
512 sizeof(struct ipc_pset
), object
);
517 * Routine: ipc_object_copyin_type
519 * Convert a send type name to a received type name.
523 ipc_object_copyin_type(
524 mach_msg_type_name_t msgt_name
)
527 case MACH_MSG_TYPE_MOVE_RECEIVE
:
528 return MACH_MSG_TYPE_PORT_RECEIVE
;
530 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
531 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
532 return MACH_MSG_TYPE_PORT_SEND_ONCE
;
534 case MACH_MSG_TYPE_MOVE_SEND
:
535 case MACH_MSG_TYPE_MAKE_SEND
:
536 case MACH_MSG_TYPE_COPY_SEND
:
537 return MACH_MSG_TYPE_PORT_SEND
;
539 case MACH_MSG_TYPE_DISPOSE_RECEIVE
:
540 case MACH_MSG_TYPE_DISPOSE_SEND
:
541 case MACH_MSG_TYPE_DISPOSE_SEND_ONCE
:
544 return MACH_MSG_TYPE_PORT_NONE
;
549 * Routine: ipc_object_copyin
551 * Copyin a capability from a space.
552 * If successful, the caller gets a ref
553 * for the resulting object, unless it is IO_DEAD.
557 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
558 * KERN_INVALID_TASK The space is dead.
559 * KERN_INVALID_NAME Name doesn't exist in space.
560 * KERN_INVALID_RIGHT Name doesn't denote correct right.
566 mach_port_name_t name
,
567 mach_msg_type_name_t msgt_name
,
568 ipc_object_t
*objectp
,
569 mach_port_context_t context
,
570 mach_msg_guard_flags_t
*guard_flags
,
571 ipc_kmsg_flags_t kmsg_flags
)
575 ipc_port_t release_port
;
579 ipc_right_copyin_flags_t irc_flags
= IPC_RIGHT_COPYIN_FLAGS_DEADOK
;
580 if (kmsg_flags
& IPC_KMSG_FLAGS_ALLOW_IMMOVABLE_SEND
) {
581 irc_flags
|= IPC_RIGHT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
;
585 * Could first try a read lock when doing
586 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
587 * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
590 kr
= ipc_right_lookup_write(space
, name
, &entry
);
591 if (kr
!= KERN_SUCCESS
) {
594 /* space is write-locked and active */
596 release_port
= IP_NULL
;
597 kr
= ipc_right_copyin(space
, name
, entry
,
598 msgt_name
, irc_flags
,
604 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
605 ipc_entry_dealloc(space
, name
, entry
);
607 is_write_unlock(space
);
609 #if IMPORTANCE_INHERITANCE
610 if (0 < assertcnt
&& ipc_importance_task_is_any_receiver_type(current_task()->task_imp_base
)) {
611 ipc_importance_task_drop_internal_assertion(current_task()->task_imp_base
, assertcnt
);
613 #endif /* IMPORTANCE_INHERITANCE */
615 if (release_port
!= IP_NULL
) {
616 ip_release(release_port
);
619 if ((kr
== KERN_SUCCESS
) && (soright
!= IP_NULL
)) {
620 ipc_notify_port_deleted(soright
, name
);
627 * Routine: ipc_object_copyin_from_kernel
629 * Copyin a naked capability from the kernel.
631 * MACH_MSG_TYPE_MOVE_RECEIVE
632 * The receiver must be ipc_space_kernel
633 * or the receive right must already be in limbo.
634 * Consumes the naked receive right.
635 * MACH_MSG_TYPE_COPY_SEND
636 * A naked send right must be supplied.
637 * The port gains a reference, and a send right
638 * if the port is still active.
639 * MACH_MSG_TYPE_MAKE_SEND
640 * The receiver must be ipc_space_kernel.
641 * The port gains a reference and a send right.
642 * MACH_MSG_TYPE_MOVE_SEND
643 * Consumes a naked send right.
644 * MACH_MSG_TYPE_MAKE_SEND_ONCE
645 * The port gains a reference and a send-once right.
646 * Receiver also be the caller of device subsystem,
648 * MACH_MSG_TYPE_MOVE_SEND_ONCE
649 * Consumes a naked send-once right.
655 ipc_object_copyin_from_kernel(
657 mach_msg_type_name_t msgt_name
)
659 assert(IO_VALID(object
));
662 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
663 ipc_port_t port
= ip_object_to_port(object
);
666 imq_lock(&port
->ip_messages
);
667 require_ip_active(port
);
668 if (port
->ip_destination
!= IP_NULL
) {
669 assert(port
->ip_receiver
== ipc_space_kernel
);
670 assert(port
->ip_immovable_receive
== 0);
672 /* relevant part of ipc_port_clear_receiver */
673 port
->ip_mscount
= 0;
674 port
->ip_receiver_name
= MACH_PORT_NULL
;
675 port
->ip_destination
= IP_NULL
;
677 imq_unlock(&port
->ip_messages
);
682 case MACH_MSG_TYPE_COPY_SEND
: {
683 ipc_port_t port
= ip_object_to_port(object
);
686 if (ip_active(port
)) {
687 assert(port
->ip_srights
> 0);
695 case MACH_MSG_TYPE_MAKE_SEND
: {
696 ipc_port_t port
= ip_object_to_port(object
);
699 if (ip_active(port
)) {
700 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
701 assert((port
->ip_receiver
== ipc_space_kernel
) ||
702 (port
->ip_receiver
->is_node_id
!= HOST_LOCAL_NODE
));
712 case MACH_MSG_TYPE_MOVE_SEND
: {
713 /* move naked send right into the message */
714 assert(ip_object_to_port(object
)->ip_srights
);
718 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
719 ipc_port_t port
= ip_object_to_port(object
);
722 if (ip_active(port
)) {
723 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
725 ipc_port_make_sonce_locked(port
);
730 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
731 /* move naked send-once right into the message */
732 assert(ip_object_to_port(object
)->ip_sorights
);
737 panic("ipc_object_copyin_from_kernel: strange rights");
742 * Routine: ipc_object_destroy
744 * Destroys a naked capability.
745 * Consumes a ref for the object.
747 * A receive right should be in limbo or in transit.
755 mach_msg_type_name_t msgt_name
)
757 assert(IO_VALID(object
));
758 assert(io_otype(object
) == IOT_PORT
);
761 case MACH_MSG_TYPE_PORT_SEND
:
762 ipc_port_release_send(ip_object_to_port(object
));
765 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
766 ipc_notify_send_once(ip_object_to_port(object
));
769 case MACH_MSG_TYPE_PORT_RECEIVE
:
770 ipc_port_release_receive(ip_object_to_port(object
));
774 panic("ipc_object_destroy: strange rights");
779 * Routine: ipc_object_destroy_dest
781 * Destroys a naked capability for the destination of
782 * of a message. Consumes a ref for the object.
789 ipc_object_destroy_dest(
791 mach_msg_type_name_t msgt_name
)
793 assert(IO_VALID(object
));
794 assert(io_otype(object
) == IOT_PORT
);
797 case MACH_MSG_TYPE_PORT_SEND
:
798 ipc_port_release_send(ip_object_to_port(object
));
801 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
802 if (io_active(object
) &&
803 !ip_full_kernel(ip_object_to_port(object
))) {
804 ipc_notify_send_once(ip_object_to_port(object
));
806 ipc_port_release_sonce(ip_object_to_port(object
));
811 panic("ipc_object_destroy_dest: strange rights");
816 * Routine: ipc_object_insert_send_right
818 * Insert a send right into an object already in the space.
819 * The specified name must already point to a valid object.
821 * Note: This really is a combined copyin()/copyout(),
822 * that avoids most of the overhead of being implemented that way.
824 * This is the fastpath for mach_port_insert_right.
829 * msgt_name must be MACH_MSG_TYPE_MAKE_SEND_ONCE or
830 * MACH_MSG_TYPE_MOVE_SEND_ONCE.
833 * KERN_SUCCESS Copied out object, consumed ref.
834 * KERN_INVALID_TASK The space is dead.
835 * KERN_INVALID_NAME Name doesn't exist in space.
836 * KERN_INVALID_CAPABILITY The object is dead.
837 * KERN_RIGHT_EXISTS Space has rights under another name.
840 ipc_object_insert_send_right(
842 mach_port_name_t name
,
843 mach_msg_type_name_t msgt_name
)
845 ipc_entry_bits_t bits
;
850 assert(msgt_name
== MACH_MSG_TYPE_MAKE_SEND
||
851 msgt_name
== MACH_MSG_TYPE_COPY_SEND
);
853 kr
= ipc_right_lookup_write(space
, name
, &entry
);
854 if (kr
!= KERN_SUCCESS
) {
857 /* space is write-locked and active */
859 if (!IO_VALID(entry
->ie_object
)) {
860 is_write_unlock(space
);
861 return KERN_INVALID_CAPABILITY
;
864 bits
= entry
->ie_bits
;
865 object
= entry
->ie_object
;
868 if (!io_active(object
)) {
869 kr
= KERN_INVALID_CAPABILITY
;
870 } else if (msgt_name
== MACH_MSG_TYPE_MAKE_SEND
) {
871 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
872 ipc_port_t port
= ip_object_to_port(object
);
874 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
876 bits
|= MACH_PORT_TYPE_SEND
;
878 /* leave urefs pegged to maximum if it overflowed */
879 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
880 bits
+= 1; /* increment urefs */
882 entry
->ie_bits
= bits
;
883 ipc_entry_modified(space
, name
, entry
);
886 kr
= KERN_INVALID_RIGHT
;
888 } else { // MACH_MSG_TYPE_COPY_SEND
889 if (bits
& MACH_PORT_TYPE_SEND
) {
890 /* leave urefs pegged to maximum if it overflowed */
891 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
892 entry
->ie_bits
= bits
+ 1; /* increment urefs */
894 ipc_entry_modified(space
, name
, entry
);
897 kr
= KERN_INVALID_RIGHT
;
902 is_write_unlock(space
);
908 * Routine: ipc_object_copyout
910 * Copyout a capability, placing it into a space.
911 * If successful, consumes a ref for the object.
915 * KERN_SUCCESS Copied out object, consumed ref.
916 * KERN_INVALID_TASK The space is dead.
917 * KERN_INVALID_CAPABILITY The object is dead.
918 * KERN_NO_SPACE No room in space for another right.
919 * KERN_RESOURCE_SHORTAGE No memory available.
920 * KERN_UREFS_OVERFLOW Urefs limit exceeded
921 * and overflow wasn't specified.
928 mach_msg_type_name_t msgt_name
,
929 mach_port_context_t
*context
,
930 mach_msg_guard_flags_t
*guard_flags
,
931 mach_port_name_t
*namep
)
933 struct knote
*kn
= current_thread()->ith_knote
;
934 mach_port_name_t name
;
938 assert(IO_VALID(object
));
939 assert(io_otype(object
) == IOT_PORT
);
941 if (ITH_KNOTE_VALID(kn
, msgt_name
)) {
942 filt_machport_turnstile_prepare_lazily(kn
,
943 msgt_name
, ip_object_to_port(object
));
946 is_write_lock(space
);
949 if (!is_active(space
)) {
950 is_write_unlock(space
);
951 return KERN_INVALID_TASK
;
954 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
955 ipc_right_reverse(space
, object
, &name
, &entry
)) {
956 /* object is locked and active */
958 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
963 name
= CAST_MACH_PORT_TO_NAME(object
);
964 kr
= ipc_entry_get(space
, &name
, &entry
);
965 if (kr
!= KERN_SUCCESS
) {
966 /* unlocks/locks space, so must start again */
968 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
969 if (kr
!= KERN_SUCCESS
) {
970 return kr
; /* space is unlocked */
975 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
976 assert(entry
->ie_object
== IO_NULL
);
979 if (!io_active(object
)) {
981 ipc_entry_dealloc(space
, name
, entry
);
982 is_write_unlock(space
);
983 return KERN_INVALID_CAPABILITY
;
986 /* Don't actually copyout rights we aren't allowed to */
987 if (!ip_label_check(space
, ip_object_to_port(object
), msgt_name
)) {
989 ipc_entry_dealloc(space
, name
, entry
);
990 is_write_unlock(space
);
991 return KERN_INVALID_CAPABILITY
;
994 entry
->ie_object
= object
;
998 /* space is write-locked and active, object is locked and active */
1000 kr
= ipc_right_copyout(space
, name
, entry
,
1001 msgt_name
, context
, guard_flags
, object
);
1003 /* object is unlocked */
1004 is_write_unlock(space
);
1006 if (kr
== KERN_SUCCESS
) {
1013 * Routine: ipc_object_copyout_name
1015 * Copyout a capability, placing it into a space.
1016 * The specified name is used for the capability.
1017 * If successful, consumes a ref for the object.
1021 * KERN_SUCCESS Copied out object, consumed ref.
1022 * KERN_INVALID_TASK The space is dead.
1023 * KERN_INVALID_CAPABILITY The object is dead.
1024 * KERN_RESOURCE_SHORTAGE No memory available.
1025 * KERN_UREFS_OVERFLOW Urefs limit exceeded
1026 * and overflow wasn't specified.
1027 * KERN_RIGHT_EXISTS Space has rights under another name.
1028 * KERN_NAME_EXISTS Name is already used.
1032 ipc_object_copyout_name(
1034 ipc_object_t object
,
1035 mach_msg_type_name_t msgt_name
,
1036 mach_port_name_t name
)
1038 mach_port_name_t oname
;
1043 #if IMPORTANCE_INHERITANCE
1045 ipc_importance_task_t task_imp
= IIT_NULL
;
1046 #endif /* IMPORTANCE_INHERITANCE */
1048 assert(IO_VALID(object
));
1049 assert(io_otype(object
) == IOT_PORT
);
1051 kr
= ipc_entry_alloc_name(space
, name
, &entry
);
1052 if (kr
!= KERN_SUCCESS
) {
1055 /* space is write-locked and active */
1057 if ((msgt_name
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
1058 ipc_right_reverse(space
, object
, &oname
, &oentry
)) {
1059 /* object is locked and active */
1061 if (name
!= oname
) {
1064 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
1065 ipc_entry_dealloc(space
, name
, entry
);
1068 is_write_unlock(space
);
1069 return KERN_RIGHT_EXISTS
;
1072 assert(entry
== oentry
);
1073 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
1075 if (ipc_right_inuse(space
, name
, entry
)) {
1076 return KERN_NAME_EXISTS
;
1079 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
1080 assert(entry
->ie_object
== IO_NULL
);
1083 if (!io_active(object
)) {
1085 ipc_entry_dealloc(space
, name
, entry
);
1086 is_write_unlock(space
);
1087 return KERN_INVALID_CAPABILITY
;
1090 /* Don't actually copyout rights we aren't allowed to */
1091 if (!ip_label_check(space
, ip_object_to_port(object
), msgt_name
)) {
1093 ipc_entry_dealloc(space
, name
, entry
);
1094 is_write_unlock(space
);
1095 return KERN_INVALID_CAPABILITY
;
1098 entry
->ie_object
= object
;
1101 /* space is write-locked and active, object is locked and active */
1103 #if IMPORTANCE_INHERITANCE
1105 * We are slamming a receive right into the space, without
1106 * first having been enqueued on a port destined there. So,
1107 * we have to arrange to boost the task appropriately if this
1108 * port has assertions (and the task wants them).
1110 if (msgt_name
== MACH_MSG_TYPE_PORT_RECEIVE
) {
1111 ipc_port_t port
= ip_object_to_port(object
);
1113 if (space
->is_task
!= TASK_NULL
) {
1114 task_imp
= space
->is_task
->task_imp_base
;
1115 if (ipc_importance_task_is_any_receiver_type(task_imp
)) {
1116 assertcnt
= port
->ip_impcount
;
1117 ipc_importance_task_reference(task_imp
);
1119 task_imp
= IIT_NULL
;
1123 /* take port out of limbo */
1124 assert(port
->ip_tempowner
!= 0);
1125 port
->ip_tempowner
= 0;
1128 #endif /* IMPORTANCE_INHERITANCE */
1130 kr
= ipc_right_copyout(space
, name
, entry
,
1131 msgt_name
, NULL
, NULL
, object
);
1133 /* object is unlocked */
1134 is_write_unlock(space
);
1136 #if IMPORTANCE_INHERITANCE
1138 * Add the assertions to the task that we captured before
1140 if (task_imp
!= IIT_NULL
) {
1141 ipc_importance_task_hold_internal_assertion(task_imp
, assertcnt
);
1142 ipc_importance_task_release(task_imp
);
1144 #endif /* IMPORTANCE_INHERITANCE */
1150 * Routine: ipc_object_copyout_dest
1152 * Translates/consumes the destination right of a message.
1153 * This is unlike normal copyout because the right is consumed
1154 * in a funny way instead of being given to the receiving space.
1155 * The receiver gets his name for the port, if he has receive
1156 * rights, otherwise MACH_PORT_NULL.
1158 * The object is locked and active. Nothing else locked.
1159 * The object is unlocked and loses a reference.
1163 ipc_object_copyout_dest(
1165 ipc_object_t object
,
1166 mach_msg_type_name_t msgt_name
,
1167 mach_port_name_t
*namep
)
1169 mach_port_name_t name
;
1171 assert(IO_VALID(object
));
1172 assert(io_active(object
));
1175 * If the space is the receiver/owner of the object,
1176 * then we quietly consume the right and return
1177 * the space's name for the object. Otherwise
1178 * we destroy the right and return MACH_PORT_NULL.
1181 switch (msgt_name
) {
1182 case MACH_MSG_TYPE_PORT_SEND
: {
1183 ipc_port_t port
= ip_object_to_port(object
);
1184 ipc_port_t nsrequest
= IP_NULL
;
1185 mach_port_mscount_t mscount
;
1187 if (port
->ip_receiver
== space
) {
1188 name
= port
->ip_receiver_name
;
1190 name
= MACH_PORT_NULL
;
1193 assert(port
->ip_srights
> 0);
1194 if (--port
->ip_srights
== 0 &&
1195 port
->ip_nsrequest
!= IP_NULL
) {
1196 nsrequest
= port
->ip_nsrequest
;
1197 port
->ip_nsrequest
= IP_NULL
;
1198 mscount
= port
->ip_mscount
;
1199 ipc_port_clear_sync_rcv_thread_boost_locked(port
);
1201 ipc_notify_no_senders(nsrequest
, mscount
);
1203 ipc_port_clear_sync_rcv_thread_boost_locked(port
);
1211 case MACH_MSG_TYPE_PORT_SEND_ONCE
: {
1212 ipc_port_t port
= ip_object_to_port(object
);
1214 assert(port
->ip_sorights
> 0);
1216 if (port
->ip_receiver
== space
) {
1217 /* quietly consume the send-once right */
1219 port
->ip_sorights
--;
1220 name
= port
->ip_receiver_name
;
1221 ipc_port_clear_sync_rcv_thread_boost_locked(port
);
1226 * A very bizarre case. The message
1227 * was received, but before this copyout
1228 * happened the space lost receive rights.
1229 * We can't quietly consume the soright
1230 * out from underneath some other task,
1231 * so generate a send-once notification.
1236 ipc_notify_send_once(port
);
1237 name
= MACH_PORT_NULL
;
1244 panic("ipc_object_copyout_dest: strange rights");
1245 name
= MACH_PORT_DEAD
;
1254 * Validate, then acquire a lock on an ipc object
1258 io_lock(ipc_object_t io
)
1260 ipc_object_validate(io
);
1261 lck_spin_lock_grp(&(io
)->io_lock_data
, &ipc_lck_grp
);
1265 * Routine: io_lock_try
1267 * Validate, then try to acquire a lock on an object,
1268 * fail if there is an existing busy lock
1272 io_lock_try(ipc_object_t io
)
1274 ipc_object_validate(io
);
1275 return lck_spin_try_lock_grp(&(io
)->io_lock_data
, &ipc_lck_grp
);
1279 * Check whether the object is a port if so, free it. But
1280 * keep track of that fact.
1285 ipc_object_t object
)
1287 if (otype
== IOT_PORT
) {
1288 ipc_port_finalize(ip_object_to_port(object
));
1290 io_lock_destroy(object
);
1291 zfree(ipc_object_zones
[otype
], object
);