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@
29 * @OSF_FREE_COPYRIGHT@
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_right.c
70 * Functions to manipulate IPC capabilities.
73 #include <mach/boolean.h>
74 #include <mach/kern_return.h>
75 #include <mach/port.h>
76 #include <mach/message.h>
77 #include <kern/assert.h>
78 #include <kern/ipc_kobject.h>
79 #include <kern/misc_protos.h>
81 #include <ipc/ipc_entry.h>
82 #include <ipc/ipc_space.h>
83 #include <ipc/ipc_object.h>
84 #include <ipc/ipc_hash.h>
85 #include <ipc/ipc_port.h>
86 #include <ipc/ipc_pset.h>
87 #include <ipc/ipc_right.h>
88 #include <ipc/ipc_notify.h>
89 #include <ipc/ipc_table.h>
90 #include <ipc/ipc_importance.h>
91 #include <security/mac_mach_internal.h>
94 * Routine: ipc_right_lookup_write
96 * Finds an entry in a space, given the name.
98 * Nothing locked. If successful, the space is write-locked.
100 * KERN_SUCCESS Found an entry.
101 * KERN_INVALID_TASK The space is dead.
102 * KERN_INVALID_NAME Name doesn't exist in space.
106 ipc_right_lookup_write(
108 mach_port_name_t name
,
113 assert(space
!= IS_NULL
);
115 is_write_lock(space
);
117 if (!is_active(space
)) {
118 is_write_unlock(space
);
119 return KERN_INVALID_TASK
;
122 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
123 is_write_unlock(space
);
124 return KERN_INVALID_NAME
;
132 * Routine: ipc_right_lookup_two_write
134 * Like ipc_right_lookup except that it returns two
135 * entries for two different names that were looked
136 * up under the same space lock.
138 * Nothing locked. If successful, the space is write-locked.
140 * KERN_INVALID_TASK The space is dead.
141 * KERN_INVALID_NAME Name doesn't exist in space.
145 ipc_right_lookup_two_write(
147 mach_port_name_t name1
,
148 ipc_entry_t
*entryp1
,
149 mach_port_name_t name2
,
150 ipc_entry_t
*entryp2
)
155 assert(space
!= IS_NULL
);
157 is_write_lock(space
);
159 if (!is_active(space
)) {
160 is_write_unlock(space
);
161 return KERN_INVALID_TASK
;
164 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
165 is_write_unlock(space
);
166 mach_port_guard_exception(name1
, 0, 0, kGUARD_EXC_INVALID_NAME
);
167 return KERN_INVALID_NAME
;
169 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
170 is_write_unlock(space
);
171 mach_port_guard_exception(name2
, 0, 0, kGUARD_EXC_INVALID_NAME
);
172 return KERN_INVALID_NAME
;
180 * Routine: ipc_right_reverse
182 * Translate (space, object) -> (name, entry).
183 * Only finds send/receive rights.
184 * Returns TRUE if an entry is found; if so,
187 * The space must be locked (read or write) and active.
188 * The port is locked and active
195 mach_port_name_t
*namep
,
199 mach_port_name_t name
;
202 /* would switch on io_otype to handle multiple types of object */
204 assert(is_active(space
));
205 assert(io_otype(object
) == IOT_PORT
);
207 port
= ip_object_to_port(object
);
208 require_ip_active(port
);
212 if (port
->ip_receiver
== space
) {
213 name
= port
->ip_receiver_name
;
214 assert(name
!= MACH_PORT_NULL
);
216 entry
= ipc_entry_lookup(space
, name
);
218 assert(entry
!= IE_NULL
);
219 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
220 assert(port
== ip_object_to_port(entry
->ie_object
));
227 if (ipc_hash_lookup(space
, ip_to_object(port
), namep
, entryp
)) {
228 assert((entry
= *entryp
) != IE_NULL
);
229 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
230 assert(port
== ip_object_to_port(entry
->ie_object
));
239 * Routine: ipc_right_dnrequest
241 * Make a dead-name request, returning the previously
242 * registered send-once right. If notify is IP_NULL,
243 * just cancels the previously registered request.
246 * Nothing locked. May allocate memory.
247 * Only consumes/returns refs if successful.
249 * KERN_SUCCESS Made/canceled dead-name request.
250 * KERN_INVALID_TASK The space is dead.
251 * KERN_INVALID_NAME Name doesn't exist in space.
252 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
253 * KERN_INVALID_ARGUMENT Name denotes dead name, but
254 * immediate is FALSE or notify is IP_NULL.
255 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
259 ipc_right_request_alloc(
261 mach_port_name_t name
,
263 boolean_t send_possible
,
265 ipc_port_t
*previousp
)
267 ipc_port_request_index_t prev_request
;
268 ipc_port_t previous
= IP_NULL
;
272 #if IMPORTANCE_INHERITANCE
273 boolean_t needboost
= FALSE
;
274 #endif /* IMPORTANCE_INHERITANCE */
277 ipc_port_t port
= IP_NULL
;
279 kr
= ipc_right_lookup_write(space
, name
, &entry
);
280 if (kr
!= KERN_SUCCESS
) {
284 /* space is write-locked and active */
286 prev_request
= entry
->ie_request
;
288 /* if nothing to do or undo, we're done */
289 if (notify
== IP_NULL
&& prev_request
== IE_REQ_NONE
) {
290 is_write_unlock(space
);
291 *previousp
= IP_NULL
;
295 /* see if the entry is of proper type for requests */
296 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
297 ipc_port_request_index_t new_request
;
299 port
= ip_object_to_port(entry
->ie_object
);
300 assert(port
!= IP_NULL
);
302 if (!ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
303 /* port is locked and active */
305 /* if no new request, just cancel previous */
306 if (notify
== IP_NULL
) {
307 if (prev_request
!= IE_REQ_NONE
) {
308 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
311 entry
->ie_request
= IE_REQ_NONE
;
312 ipc_entry_modified(space
, name
, entry
);
313 is_write_unlock(space
);
318 * send-once rights, kernel objects, and non-full other queues
319 * fire immediately (if immediate specified).
321 if (send_possible
&& immediate
&&
322 ((entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
) ||
323 port
->ip_receiver
== ipc_space_kernel
|| !ip_full(port
))) {
324 if (prev_request
!= IE_REQ_NONE
) {
325 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
328 entry
->ie_request
= IE_REQ_NONE
;
329 ipc_entry_modified(space
, name
, entry
);
330 is_write_unlock(space
);
332 ipc_notify_send_possible(notify
, name
);
337 * If there is a previous request, free it. Any subsequent
338 * allocation cannot fail, thus assuring an atomic swap.
340 if (prev_request
!= IE_REQ_NONE
) {
341 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
344 #if IMPORTANCE_INHERITANCE
345 kr
= ipc_port_request_alloc(port
, name
, notify
,
346 send_possible
, immediate
,
347 &new_request
, &needboost
);
349 kr
= ipc_port_request_alloc(port
, name
, notify
,
350 send_possible
, immediate
,
352 #endif /* IMPORTANCE_INHERITANCE */
353 if (kr
!= KERN_SUCCESS
) {
354 assert(previous
== IP_NULL
);
355 is_write_unlock(space
);
357 kr
= ipc_port_request_grow(port
, ITS_SIZE_NONE
);
358 /* port is unlocked */
360 if (kr
!= KERN_SUCCESS
) {
368 assert(new_request
!= IE_REQ_NONE
);
369 entry
->ie_request
= new_request
;
370 ipc_entry_modified(space
, name
, entry
);
371 is_write_unlock(space
);
373 #if IMPORTANCE_INHERITANCE
374 if (needboost
== TRUE
) {
375 if (ipc_port_importance_delta(port
, IPID_OPTION_SENDPOSSIBLE
, 1) == FALSE
) {
379 #endif /* IMPORTANCE_INHERITANCE */
384 /* entry may have changed to dead-name by ipc_right_check() */
387 /* treat send_possible requests as immediate w.r.t. dead-name */
388 if ((send_possible
|| immediate
) && notify
!= IP_NULL
&&
389 (entry
->ie_bits
& MACH_PORT_TYPE_DEAD_NAME
)) {
390 mach_port_urefs_t urefs
= IE_BITS_UREFS(entry
->ie_bits
);
394 /* leave urefs pegged to maximum if it overflowed */
395 if (urefs
< MACH_PORT_UREFS_MAX
) {
396 (entry
->ie_bits
)++; /* increment urefs */
398 ipc_entry_modified(space
, name
, entry
);
400 is_write_unlock(space
);
402 if (port
!= IP_NULL
) {
406 ipc_notify_dead_name(notify
, name
);
411 kr
= (entry
->ie_bits
& MACH_PORT_TYPE_PORT_OR_DEAD
) ?
412 KERN_INVALID_ARGUMENT
: KERN_INVALID_RIGHT
;
414 is_write_unlock(space
);
416 if (port
!= IP_NULL
) {
423 *previousp
= previous
;
428 * Routine: ipc_right_request_cancel
430 * Cancel a notification request and return the send-once right.
431 * Afterwards, entry->ie_request == 0.
433 * The space must be write-locked; the port must be locked.
434 * The port must be active; the space doesn't have to be.
438 ipc_right_request_cancel(
439 __unused ipc_space_t space
,
441 mach_port_name_t name
,
446 require_ip_active(port
);
447 assert(port
== ip_object_to_port(entry
->ie_object
));
449 if (entry
->ie_request
== IE_REQ_NONE
) {
453 previous
= ipc_port_request_cancel(port
, name
, entry
->ie_request
);
454 entry
->ie_request
= IE_REQ_NONE
;
455 ipc_entry_modified(space
, name
, entry
);
460 * Routine: ipc_right_inuse
462 * Check if an entry is being used.
463 * Returns TRUE if it is.
465 * The space is write-locked and active.
472 return IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
;
476 * Routine: ipc_right_check
478 * Check if the port has died. If it has,
479 * and IPC_OBJECT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE is not
480 * passed and it is not a send once right then
481 * clean up the entry and return TRUE.
483 * The space is write-locked; the port is not locked.
484 * If returns FALSE, the port is also locked.
485 * Otherwise, entry is converted to a dead name.
487 * Caller is responsible for a reference to port if it
488 * had died (returns TRUE).
495 mach_port_name_t name
,
497 ipc_object_copyin_flags_t flags
)
499 ipc_entry_bits_t bits
;
501 assert(is_active(space
));
502 assert(port
== ip_object_to_port(entry
->ie_object
));
505 if (ip_active(port
) ||
506 ((flags
& IPC_OBJECT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE
) &&
507 entry
->ie_request
== IE_REQ_NONE
&&
508 (entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
))) {
512 /* this was either a pure send right or a send-once right */
514 bits
= entry
->ie_bits
;
515 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
516 assert(IE_BITS_UREFS(bits
) > 0);
518 if (bits
& MACH_PORT_TYPE_SEND
) {
519 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
520 assert(IE_BITS_UREFS(bits
) > 0);
521 assert(port
->ip_srights
> 0);
524 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
525 assert(IE_BITS_UREFS(bits
) == 1);
526 assert(port
->ip_sorights
> 0);
532 * delete SEND rights from ipc hash.
535 if ((bits
& MACH_PORT_TYPE_SEND
) != 0) {
536 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
);
539 /* convert entry to dead name */
540 bits
= (bits
& ~IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
543 * If there was a notification request outstanding on this
544 * name, and the port went dead, that notification
545 * must already be on its way up from the port layer.
547 * Add the reference that the notification carries. It
548 * is done here, and not in the notification delivery,
549 * because the latter doesn't have a space reference and
550 * trying to actually move a send-right reference would
551 * get short-circuited into a MACH_PORT_DEAD by IPC. Since
552 * all calls that deal with the right eventually come
553 * through here, it has the same result.
555 * Once done, clear the request index so we only account
558 if (entry
->ie_request
!= IE_REQ_NONE
) {
559 if (ipc_port_request_type(port
, name
, entry
->ie_request
) != 0) {
560 /* if urefs are pegged due to overflow, leave them pegged */
561 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
562 bits
++; /* increment urefs */
565 entry
->ie_request
= IE_REQ_NONE
;
567 entry
->ie_bits
= bits
;
568 entry
->ie_object
= IO_NULL
;
569 ipc_entry_modified(space
, name
, entry
);
574 * Routine: ipc_right_terminate
576 * Cleans up an entry in a terminated space.
577 * The entry isn't deallocated or removed
578 * from reverse hash tables.
580 * The space is dead and unlocked.
586 mach_port_name_t name
,
589 ipc_entry_bits_t bits
;
590 mach_port_type_t type
;
592 bits
= entry
->ie_bits
;
593 type
= IE_BITS_TYPE(bits
);
595 assert(!is_active(space
));
598 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
599 * problem, because we check that the port is active. If
600 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
601 * would still work, but dead space refs would accumulate
602 * in ip_dnrequests. They would use up slots in
603 * ip_dnrequests and keep the spaces from being freed.
607 case MACH_PORT_TYPE_DEAD_NAME
:
608 assert(entry
->ie_request
== IE_REQ_NONE
);
609 assert(entry
->ie_object
== IO_NULL
);
612 case MACH_PORT_TYPE_PORT_SET
: {
613 ipc_pset_t pset
= ips_object_to_pset(entry
->ie_object
);
615 assert(entry
->ie_request
== IE_REQ_NONE
);
616 assert(pset
!= IPS_NULL
);
619 assert(ips_active(pset
));
620 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
624 case MACH_PORT_TYPE_SEND
:
625 case MACH_PORT_TYPE_RECEIVE
:
626 case MACH_PORT_TYPE_SEND_RECEIVE
:
627 case MACH_PORT_TYPE_SEND_ONCE
: {
628 ipc_port_t port
= ip_object_to_port(entry
->ie_object
);
630 ipc_port_t nsrequest
= IP_NULL
;
631 mach_port_mscount_t mscount
= 0;
633 assert(port
!= IP_NULL
);
636 if (!ip_active(port
)) {
642 request
= ipc_right_request_cancel_macro(space
, port
,
645 if (type
& MACH_PORT_TYPE_SEND
) {
646 assert(port
->ip_srights
> 0);
647 if (--port
->ip_srights
== 0
649 nsrequest
= port
->ip_nsrequest
;
650 if (nsrequest
!= IP_NULL
) {
651 port
->ip_nsrequest
= IP_NULL
;
652 mscount
= port
->ip_mscount
;
657 if (type
& MACH_PORT_TYPE_RECEIVE
) {
658 assert(port
->ip_receiver_name
== name
);
659 assert(port
->ip_receiver
== space
);
661 ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */
662 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
663 assert(port
->ip_sorights
> 0);
664 port
->ip_reply_context
= 0;
667 ipc_notify_send_once(port
); /* consumes our ref */
669 assert(port
->ip_receiver
!= space
);
675 if (nsrequest
!= IP_NULL
) {
676 ipc_notify_no_senders(nsrequest
, mscount
);
679 if (request
!= IP_NULL
) {
680 ipc_notify_port_deleted(request
, name
);
686 panic("ipc_right_terminate: strange type - 0x%x", type
);
691 * Routine: ipc_right_destroy
693 * Destroys an entry in a space.
695 * The space is write-locked (returns unlocked).
696 * The space must be active.
698 * KERN_SUCCESS The entry was destroyed.
704 mach_port_name_t name
,
706 boolean_t check_guard
,
709 ipc_entry_bits_t bits
;
710 mach_port_type_t type
;
712 bits
= entry
->ie_bits
;
713 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
714 type
= IE_BITS_TYPE(bits
);
716 assert(is_active(space
));
719 case MACH_PORT_TYPE_DEAD_NAME
:
720 assert(entry
->ie_request
== IE_REQ_NONE
);
721 assert(entry
->ie_object
== IO_NULL
);
723 ipc_entry_dealloc(space
, name
, entry
);
724 is_write_unlock(space
);
727 case MACH_PORT_TYPE_PORT_SET
: {
728 ipc_pset_t pset
= ips_object_to_pset(entry
->ie_object
);
730 assert(entry
->ie_request
== IE_REQ_NONE
);
731 assert(pset
!= IPS_NULL
);
733 entry
->ie_object
= IO_NULL
;
734 ipc_entry_dealloc(space
, name
, entry
);
737 is_write_unlock(space
);
739 assert(ips_active(pset
));
740 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
744 case MACH_PORT_TYPE_SEND
:
745 case MACH_PORT_TYPE_RECEIVE
:
746 case MACH_PORT_TYPE_SEND_RECEIVE
:
747 case MACH_PORT_TYPE_SEND_ONCE
: {
748 ipc_port_t port
= ip_object_to_port(entry
->ie_object
);
749 ipc_port_t nsrequest
= IP_NULL
;
750 mach_port_mscount_t mscount
= 0;
753 assert(port
!= IP_NULL
);
755 if (type
== MACH_PORT_TYPE_SEND
) {
756 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
);
761 if (!ip_active(port
)) {
762 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
764 entry
->ie_request
= IE_REQ_NONE
;
765 entry
->ie_object
= IO_NULL
;
766 ipc_entry_dealloc(space
, name
, entry
);
767 is_write_unlock(space
);
772 /* For receive rights, check for guarding */
773 if ((type
& MACH_PORT_TYPE_RECEIVE
) &&
774 (check_guard
) && (port
->ip_guarded
) &&
775 (guard
!= port
->ip_context
)) {
776 /* Guard Violation */
777 uint64_t portguard
= port
->ip_context
;
779 is_write_unlock(space
);
780 /* Raise mach port guard exception */
781 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
782 return KERN_INVALID_RIGHT
;
786 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
788 entry
->ie_object
= IO_NULL
;
789 ipc_entry_dealloc(space
, name
, entry
);
790 is_write_unlock(space
);
792 if (type
& MACH_PORT_TYPE_SEND
) {
793 assert(port
->ip_srights
> 0);
794 if (--port
->ip_srights
== 0) {
795 nsrequest
= port
->ip_nsrequest
;
796 if (nsrequest
!= IP_NULL
) {
797 port
->ip_nsrequest
= IP_NULL
;
798 mscount
= port
->ip_mscount
;
803 if (type
& MACH_PORT_TYPE_RECEIVE
) {
804 require_ip_active(port
);
805 assert(port
->ip_receiver
== space
);
807 ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */
808 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
809 assert(port
->ip_sorights
> 0);
810 port
->ip_reply_context
= 0;
813 ipc_notify_send_once(port
); /* consumes our ref */
815 assert(port
->ip_receiver
!= space
);
821 if (nsrequest
!= IP_NULL
) {
822 ipc_notify_no_senders(nsrequest
, mscount
);
825 if (request
!= IP_NULL
) {
826 ipc_notify_port_deleted(request
, name
);
834 panic("ipc_right_destroy: strange type");
841 * Routine: ipc_right_dealloc
843 * Releases a send/send-once/dead-name/port_set user ref.
844 * Like ipc_right_delta with a delta of -1,
845 * but looks at the entry to determine the right.
847 * The space is write-locked, and is unlocked upon return.
848 * The space must be active.
850 * KERN_SUCCESS A user ref was released.
851 * KERN_INVALID_RIGHT Entry has wrong type.
852 * KERN_INVALID_CAPABILITY Deallocating a pinned right.
858 mach_port_name_t name
,
861 ipc_port_t port
= IP_NULL
;
862 ipc_entry_bits_t bits
;
863 mach_port_type_t type
;
865 bits
= entry
->ie_bits
;
866 type
= IE_BITS_TYPE(bits
);
869 assert(is_active(space
));
872 case MACH_PORT_TYPE_PORT_SET
: {
875 assert(IE_BITS_UREFS(bits
) == 0);
876 assert(entry
->ie_request
== IE_REQ_NONE
);
878 pset
= ips_object_to_pset(entry
->ie_object
);
879 assert(pset
!= IPS_NULL
);
881 entry
->ie_object
= IO_NULL
;
882 ipc_entry_dealloc(space
, name
, entry
);
885 assert(ips_active(pset
));
886 is_write_unlock(space
);
888 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
892 case MACH_PORT_TYPE_DEAD_NAME
: {
895 assert(IE_BITS_UREFS(bits
) > 0);
896 assert(entry
->ie_request
== IE_REQ_NONE
);
897 assert(entry
->ie_object
== IO_NULL
);
899 if (IE_BITS_UREFS(bits
) == 1) {
900 ipc_entry_dealloc(space
, name
, entry
);
902 /* if urefs are pegged due to overflow, leave them pegged */
903 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
904 entry
->ie_bits
= bits
- 1; /* decrement urefs */
906 ipc_entry_modified(space
, name
, entry
);
908 is_write_unlock(space
);
910 /* release any port that got converted to dead name below */
911 if (port
!= IP_NULL
) {
917 case MACH_PORT_TYPE_SEND_ONCE
: {
920 assert(IE_BITS_UREFS(bits
) == 1);
922 port
= ip_object_to_port(entry
->ie_object
);
923 assert(port
!= IP_NULL
);
925 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
926 bits
= entry
->ie_bits
;
927 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
928 goto dead_name
; /* it will release port */
930 /* port is locked and active */
932 assert(port
->ip_sorights
> 0);
935 * clear any reply context:
936 * no one will be sending the response b/c we are destroying
937 * the single, outstanding send once right.
939 port
->ip_reply_context
= 0;
941 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
944 entry
->ie_object
= IO_NULL
;
945 ipc_entry_dealloc(space
, name
, entry
);
947 is_write_unlock(space
);
949 ipc_notify_send_once(port
);
951 if (request
!= IP_NULL
) {
952 ipc_notify_port_deleted(request
, name
);
957 case MACH_PORT_TYPE_SEND
: {
958 ipc_port_t request
= IP_NULL
;
959 ipc_port_t nsrequest
= IP_NULL
;
960 mach_port_mscount_t mscount
= 0;
963 assert(IE_BITS_UREFS(bits
) > 0);
965 port
= ip_object_to_port(entry
->ie_object
);
966 assert(port
!= IP_NULL
);
968 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
969 bits
= entry
->ie_bits
;
970 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
971 goto dead_name
; /* it will release port */
973 /* port is locked and active */
975 assert(port
->ip_srights
> 0);
977 if (IE_BITS_UREFS(bits
) == 1) {
978 if (pinned_control_port_enabled
&& port
->ip_pinned
!= 0) {
980 is_write_unlock(space
);
981 mach_port_guard_exception(name
, 0, MPG_FLAGS_MOD_REFS_PINNED_DEALLOC
,
982 ipc_control_port_options
& IPC_CONTROL_PORT_OPTIONS_PINNED_HARD
?
983 kGUARD_EXC_MOD_REFS
: kGUARD_EXC_MOD_REFS_NON_FATAL
);
984 return KERN_INVALID_CAPABILITY
;
986 if (--port
->ip_srights
== 0) {
987 nsrequest
= port
->ip_nsrequest
;
988 if (nsrequest
!= IP_NULL
) {
989 port
->ip_nsrequest
= IP_NULL
;
990 mscount
= port
->ip_mscount
;
994 request
= ipc_right_request_cancel_macro(space
, port
,
996 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
);
999 entry
->ie_object
= IO_NULL
;
1000 ipc_entry_dealloc(space
, name
, entry
);
1001 is_write_unlock(space
);
1005 /* if urefs are pegged due to overflow, leave them pegged */
1006 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1007 entry
->ie_bits
= bits
- 1; /* decrement urefs */
1009 ipc_entry_modified(space
, name
, entry
);
1010 is_write_unlock(space
);
1013 if (nsrequest
!= IP_NULL
) {
1014 ipc_notify_no_senders(nsrequest
, mscount
);
1017 if (request
!= IP_NULL
) {
1018 ipc_notify_port_deleted(request
, name
);
1023 case MACH_PORT_TYPE_SEND_RECEIVE
: {
1024 ipc_port_t nsrequest
= IP_NULL
;
1025 mach_port_mscount_t mscount
= 0;
1027 assert(IE_BITS_UREFS(bits
) > 0);
1029 port
= ip_object_to_port(entry
->ie_object
);
1030 assert(port
!= IP_NULL
);
1033 require_ip_active(port
);
1034 assert(port
->ip_receiver_name
== name
);
1035 assert(port
->ip_receiver
== space
);
1036 assert(port
->ip_srights
> 0);
1038 if (IE_BITS_UREFS(bits
) == 1) {
1039 if (--port
->ip_srights
== 0) {
1040 nsrequest
= port
->ip_nsrequest
;
1041 if (nsrequest
!= IP_NULL
) {
1042 port
->ip_nsrequest
= IP_NULL
;
1043 mscount
= port
->ip_mscount
;
1047 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1048 MACH_PORT_TYPE_SEND
);
1050 /* if urefs are pegged due to overflow, leave them pegged */
1051 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1052 entry
->ie_bits
= bits
- 1; /* decrement urefs */
1057 ipc_entry_modified(space
, name
, entry
);
1058 is_write_unlock(space
);
1060 if (nsrequest
!= IP_NULL
) {
1061 ipc_notify_no_senders(nsrequest
, mscount
);
1067 is_write_unlock(space
);
1068 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1069 return KERN_INVALID_RIGHT
;
1072 return KERN_SUCCESS
;
1076 * Routine: ipc_right_delta
1078 * Modifies the user-reference count for a right.
1079 * May deallocate the right, if the count goes to zero.
1081 * The space is write-locked, and is unlocked upon return.
1082 * The space must be active.
1084 * KERN_SUCCESS Count was modified.
1085 * KERN_INVALID_RIGHT Entry has wrong type.
1086 * KERN_INVALID_VALUE Bad delta for the right.
1087 * KERN_INVALID_CAPABILITY Deallocating a pinned right.
1093 mach_port_name_t name
,
1095 mach_port_right_t right
,
1096 mach_port_delta_t delta
)
1098 ipc_port_t port
= IP_NULL
;
1099 ipc_entry_bits_t bits
;
1101 bits
= entry
->ie_bits
;
1104 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
1105 * switch below. It is used to keep track of those cases (in DIPC)
1106 * where we have postponed the dropping of a port reference. Since
1107 * the dropping of the reference could cause the port to disappear
1108 * we postpone doing so when we are holding the space lock.
1111 assert(is_active(space
));
1112 assert(right
< MACH_PORT_RIGHT_NUMBER
);
1114 /* Rights-specific restrictions and operations. */
1117 case MACH_PORT_RIGHT_PORT_SET
: {
1120 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1121 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1125 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
1126 assert(IE_BITS_UREFS(bits
) == 0);
1127 assert(entry
->ie_request
== IE_REQ_NONE
);
1137 pset
= ips_object_to_pset(entry
->ie_object
);
1138 assert(pset
!= IPS_NULL
);
1140 entry
->ie_object
= IO_NULL
;
1141 ipc_entry_dealloc(space
, name
, entry
);
1144 assert(ips_active(pset
));
1145 is_write_unlock(space
);
1147 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
1151 case MACH_PORT_RIGHT_RECEIVE
: {
1152 ipc_port_t request
= IP_NULL
;
1154 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1155 if ((bits
& MACH_PORT_TYPE_EX_RECEIVE
) == 0) {
1156 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1169 port
= ip_object_to_port(entry
->ie_object
);
1170 assert(port
!= IP_NULL
);
1173 * The port lock is needed for ipc_right_dncancel;
1174 * otherwise, we wouldn't have to take the lock
1175 * until just before dropping the space lock.
1179 require_ip_active(port
);
1180 assert(port
->ip_receiver_name
== name
);
1181 assert(port
->ip_receiver
== space
);
1183 /* Mach Port Guard Checking */
1184 if (port
->ip_guarded
) {
1185 uint64_t portguard
= port
->ip_context
;
1187 is_write_unlock(space
);
1188 /* Raise mach port guard exception */
1189 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_MOD_REFS
);
1193 if (bits
& MACH_PORT_TYPE_SEND
) {
1194 assert(IE_BITS_TYPE(bits
) ==
1195 MACH_PORT_TYPE_SEND_RECEIVE
);
1196 assert(IE_BITS_UREFS(bits
) > 0);
1197 assert(port
->ip_srights
> 0);
1199 if (port
->ip_pdrequest
!= NULL
) {
1201 * Since another task has requested a
1202 * destroy notification for this port, it
1203 * isn't actually being destroyed - the receive
1204 * right is just being moved to another task.
1205 * Since we still have one or more send rights,
1206 * we need to record the loss of the receive
1207 * right and enter the remaining send right
1208 * into the hash table.
1210 ipc_entry_modified(space
, name
, entry
);
1211 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1212 entry
->ie_bits
|= MACH_PORT_TYPE_EX_RECEIVE
;
1213 ipc_hash_insert(space
, ip_to_object(port
),
1218 * The remaining send right turns into a
1219 * dead name. Notice we don't decrement
1220 * ip_srights, generate a no-senders notif,
1221 * or use ipc_right_dncancel, because the
1222 * port is destroyed "first".
1224 bits
&= ~IE_BITS_TYPE_MASK
;
1225 bits
|= (MACH_PORT_TYPE_DEAD_NAME
| MACH_PORT_TYPE_EX_RECEIVE
);
1226 if (entry
->ie_request
) {
1227 entry
->ie_request
= IE_REQ_NONE
;
1228 /* if urefs are pegged due to overflow, leave them pegged */
1229 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1230 bits
++; /* increment urefs */
1233 entry
->ie_bits
= bits
;
1234 entry
->ie_object
= IO_NULL
;
1235 ipc_entry_modified(space
, name
, entry
);
1238 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1239 assert(IE_BITS_UREFS(bits
) == 0);
1241 request
= ipc_right_request_cancel_macro(space
, port
,
1243 entry
->ie_object
= IO_NULL
;
1244 ipc_entry_dealloc(space
, name
, entry
);
1246 is_write_unlock(space
);
1248 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1250 if (request
!= IP_NULL
) {
1251 ipc_notify_port_deleted(request
, name
);
1256 case MACH_PORT_RIGHT_SEND_ONCE
: {
1259 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1263 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1264 assert(IE_BITS_UREFS(bits
) == 1);
1266 port
= ip_object_to_port(entry
->ie_object
);
1267 assert(port
!= IP_NULL
);
1269 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
1270 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1271 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1274 /* port is locked and active */
1276 assert(port
->ip_sorights
> 0);
1278 if ((delta
> 0) || (delta
< -1)) {
1289 * clear any reply context:
1290 * no one will be sending the response b/c we are destroying
1291 * the single, outstanding send once right.
1293 port
->ip_reply_context
= 0;
1295 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1298 entry
->ie_object
= IO_NULL
;
1299 ipc_entry_dealloc(space
, name
, entry
);
1301 is_write_unlock(space
);
1303 ipc_notify_send_once(port
);
1305 if (request
!= IP_NULL
) {
1306 ipc_notify_port_deleted(request
, name
);
1311 case MACH_PORT_RIGHT_DEAD_NAME
: {
1312 ipc_port_t relport
= IP_NULL
;
1313 mach_port_urefs_t urefs
;
1315 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1316 port
= ip_object_to_port(entry
->ie_object
);
1317 assert(port
!= IP_NULL
);
1319 if (!ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
1320 /* port is locked and active */
1323 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1326 bits
= entry
->ie_bits
;
1329 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0) {
1330 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1334 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1335 assert(IE_BITS_UREFS(bits
) > 0);
1336 assert(entry
->ie_object
== IO_NULL
);
1337 assert(entry
->ie_request
== IE_REQ_NONE
);
1339 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1340 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1344 urefs
= IE_BITS_UREFS(bits
);
1346 if (urefs
== MACH_PORT_UREFS_MAX
) {
1348 * urefs are pegged due to an overflow
1349 * only a delta removing all refs at once can change it
1352 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1356 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1359 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1360 /* leave urefs pegged to maximum if it overflowed */
1361 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1365 if ((urefs
+ delta
) == 0) {
1366 ipc_entry_dealloc(space
, name
, entry
);
1367 } else if (delta
!= 0) {
1368 entry
->ie_bits
= bits
+ delta
;
1369 ipc_entry_modified(space
, name
, entry
);
1372 is_write_unlock(space
);
1374 if (relport
!= IP_NULL
) {
1375 ip_release(relport
);
1381 case MACH_PORT_RIGHT_SEND
: {
1382 mach_port_urefs_t urefs
;
1383 ipc_port_t request
= IP_NULL
;
1384 ipc_port_t nsrequest
= IP_NULL
;
1385 ipc_port_t port_to_release
= IP_NULL
;
1386 mach_port_mscount_t mscount
= 0;
1388 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1389 /* invalid right exception only when not live/dead confusion */
1390 if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0
1391 #if !defined(AE_MAKESENDRIGHT_FIXED)
1393 * AE tries to add single send right without knowing if it already owns one.
1394 * But if it doesn't, it should own the receive right and delta should be 1.
1396 && (((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) || (delta
!= 1))
1399 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1404 /* maximum urefs for send is MACH_PORT_UREFS_MAX */
1406 port
= ip_object_to_port(entry
->ie_object
);
1407 assert(port
!= IP_NULL
);
1409 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
1410 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1413 /* port is locked and active */
1415 assert(port
->ip_srights
> 0);
1417 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1418 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1423 urefs
= IE_BITS_UREFS(bits
);
1425 if (urefs
== MACH_PORT_UREFS_MAX
) {
1427 * urefs are pegged due to an overflow
1428 * only a delta removing all refs at once can change it
1431 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1435 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1439 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1440 /* leave urefs pegged to maximum if it overflowed */
1441 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1445 if ((urefs
+ delta
) == 0) {
1446 if (pinned_control_port_enabled
&& port
->ip_pinned
!= 0) {
1451 if (--port
->ip_srights
== 0) {
1452 nsrequest
= port
->ip_nsrequest
;
1453 if (nsrequest
!= IP_NULL
) {
1454 port
->ip_nsrequest
= IP_NULL
;
1455 mscount
= port
->ip_mscount
;
1459 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1460 assert(port
->ip_receiver_name
== name
);
1461 assert(port
->ip_receiver
== space
);
1463 assert(IE_BITS_TYPE(bits
) ==
1464 MACH_PORT_TYPE_SEND_RECEIVE
);
1466 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1467 MACH_PORT_TYPE_SEND
);
1468 ipc_entry_modified(space
, name
, entry
);
1470 assert(IE_BITS_TYPE(bits
) ==
1471 MACH_PORT_TYPE_SEND
);
1473 request
= ipc_right_request_cancel_macro(space
, port
,
1475 ipc_hash_delete(space
, ip_to_object(port
),
1479 port_to_release
= port
;
1481 entry
->ie_object
= IO_NULL
;
1482 ipc_entry_dealloc(space
, name
, entry
);
1484 } else if (delta
!= 0) {
1486 entry
->ie_bits
= bits
+ delta
;
1487 ipc_entry_modified(space
, name
, entry
);
1492 is_write_unlock(space
);
1494 if (port_to_release
!= IP_NULL
) {
1495 ip_release(port_to_release
);
1498 if (nsrequest
!= IP_NULL
) {
1499 ipc_notify_no_senders(nsrequest
, mscount
);
1502 if (request
!= IP_NULL
) {
1503 ipc_notify_port_deleted(request
, name
);
1508 case MACH_PORT_RIGHT_LABELH
:
1512 panic("ipc_right_delta: strange right %d for 0x%x (%p) in space:%p",
1513 right
, name
, (void *)entry
, (void *)space
);
1516 return KERN_SUCCESS
;
1519 is_write_unlock(space
);
1520 return KERN_SUCCESS
;
1523 is_write_unlock(space
);
1524 if (port
!= IP_NULL
) {
1527 return KERN_INVALID_RIGHT
;
1530 assert(pinned_control_port_enabled
);
1532 is_write_unlock(space
);
1533 mach_port_guard_exception(name
, 0, MPG_FLAGS_MOD_REFS_PINNED_DEALLOC
,
1534 ipc_control_port_options
& IPC_CONTROL_PORT_OPTIONS_PINNED_HARD
?
1535 kGUARD_EXC_MOD_REFS
: kGUARD_EXC_MOD_REFS_NON_FATAL
);
1536 return KERN_INVALID_CAPABILITY
;
1539 is_write_unlock(space
);
1540 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
);
1541 return KERN_INVALID_VALUE
;
1544 return KERN_INVALID_RIGHT
;
1548 * Routine: ipc_right_destruct
1550 * Deallocates the receive right and modifies the
1551 * user-reference count for the send rights as requested.
1553 * The space is write-locked, and is unlocked upon return.
1554 * The space must be active.
1556 * KERN_SUCCESS Count was modified.
1557 * KERN_INVALID_RIGHT Entry has wrong type.
1558 * KERN_INVALID_VALUE Bad delta for the right.
1564 mach_port_name_t name
,
1566 mach_port_delta_t srdelta
,
1569 ipc_port_t port
= IP_NULL
;
1570 ipc_entry_bits_t bits
;
1572 mach_port_urefs_t urefs
;
1573 ipc_port_t request
= IP_NULL
;
1574 ipc_port_t nsrequest
= IP_NULL
;
1575 mach_port_mscount_t mscount
= 0;
1577 bits
= entry
->ie_bits
;
1579 assert(is_active(space
));
1581 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1582 is_write_unlock(space
);
1584 /* No exception if we used to have receive and held entry since */
1585 if ((bits
& MACH_PORT_TYPE_EX_RECEIVE
) == 0) {
1586 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1588 return KERN_INVALID_RIGHT
;
1591 if (srdelta
&& (bits
& MACH_PORT_TYPE_SEND
) == 0) {
1592 is_write_unlock(space
);
1593 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1594 return KERN_INVALID_RIGHT
;
1601 port
= ip_object_to_port(entry
->ie_object
);
1602 assert(port
!= IP_NULL
);
1605 require_ip_active(port
);
1606 assert(port
->ip_receiver_name
== name
);
1607 assert(port
->ip_receiver
== space
);
1609 /* Mach Port Guard Checking */
1610 if (port
->ip_guarded
&& (guard
!= port
->ip_context
)) {
1611 uint64_t portguard
= port
->ip_context
;
1613 is_write_unlock(space
);
1614 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
1615 return KERN_INVALID_ARGUMENT
;
1619 * First reduce the send rights as requested and
1620 * adjust the entry->ie_bits accordingly. The
1621 * ipc_entry_modified() call is made once the receive
1622 * right is destroyed too.
1626 assert(port
->ip_srights
> 0);
1628 urefs
= IE_BITS_UREFS(bits
);
1631 * Since we made sure that srdelta is negative,
1632 * the check for urefs overflow is not required.
1634 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, srdelta
)) {
1639 if (urefs
== MACH_PORT_UREFS_MAX
) {
1641 * urefs are pegged due to an overflow
1642 * only a delta removing all refs at once can change it
1644 if (srdelta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1649 if ((urefs
+ srdelta
) == 0) {
1650 if (--port
->ip_srights
== 0) {
1651 nsrequest
= port
->ip_nsrequest
;
1652 if (nsrequest
!= IP_NULL
) {
1653 port
->ip_nsrequest
= IP_NULL
;
1654 mscount
= port
->ip_mscount
;
1657 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_RECEIVE
);
1658 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1659 MACH_PORT_TYPE_SEND
);
1661 entry
->ie_bits
= bits
+ srdelta
;
1666 * Now destroy the receive right. Update space and
1667 * entry accordingly.
1670 bits
= entry
->ie_bits
;
1671 if (bits
& MACH_PORT_TYPE_SEND
) {
1672 assert(IE_BITS_UREFS(bits
) > 0);
1673 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
1675 if (port
->ip_pdrequest
!= NULL
) {
1677 * Since another task has requested a
1678 * destroy notification for this port, it
1679 * isn't actually being destroyed - the receive
1680 * right is just being moved to another task.
1681 * Since we still have one or more send rights,
1682 * we need to record the loss of the receive
1683 * right and enter the remaining send right
1684 * into the hash table.
1686 ipc_entry_modified(space
, name
, entry
);
1687 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1688 entry
->ie_bits
|= MACH_PORT_TYPE_EX_RECEIVE
;
1689 ipc_hash_insert(space
, ip_to_object(port
),
1694 * The remaining send right turns into a
1695 * dead name. Notice we don't decrement
1696 * ip_srights, generate a no-senders notif,
1697 * or use ipc_right_dncancel, because the
1698 * port is destroyed "first".
1700 bits
&= ~IE_BITS_TYPE_MASK
;
1701 bits
|= (MACH_PORT_TYPE_DEAD_NAME
| MACH_PORT_TYPE_EX_RECEIVE
);
1702 if (entry
->ie_request
) {
1703 entry
->ie_request
= IE_REQ_NONE
;
1704 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1705 bits
++; /* increment urefs */
1708 entry
->ie_bits
= bits
;
1709 entry
->ie_object
= IO_NULL
;
1710 ipc_entry_modified(space
, name
, entry
);
1713 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1714 assert(IE_BITS_UREFS(bits
) == 0);
1715 request
= ipc_right_request_cancel_macro(space
, port
,
1717 entry
->ie_object
= IO_NULL
;
1718 ipc_entry_dealloc(space
, name
, entry
);
1722 is_write_unlock(space
);
1724 if (nsrequest
!= IP_NULL
) {
1725 ipc_notify_no_senders(nsrequest
, mscount
);
1728 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1730 if (request
!= IP_NULL
) {
1731 ipc_notify_port_deleted(request
, name
);
1734 return KERN_SUCCESS
;
1737 is_write_unlock(space
);
1738 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
);
1739 return KERN_INVALID_VALUE
;
1744 * Routine: ipc_right_info
1746 * Retrieves information about the right.
1748 * The space is active and write-locked.
1749 * The space is unlocked upon return.
1751 * KERN_SUCCESS Retrieved info
1757 mach_port_name_t name
,
1759 mach_port_type_t
*typep
,
1760 mach_port_urefs_t
*urefsp
)
1763 ipc_entry_bits_t bits
;
1764 mach_port_type_t type
= 0;
1765 ipc_port_request_index_t request
;
1767 bits
= entry
->ie_bits
;
1768 request
= entry
->ie_request
;
1769 port
= ip_object_to_port(entry
->ie_object
);
1771 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1772 assert(IP_VALID(port
));
1774 if (request
!= IE_REQ_NONE
) {
1776 require_ip_active(port
);
1777 type
|= ipc_port_request_type(port
, name
, request
);
1780 is_write_unlock(space
);
1781 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1783 * validate port is still alive - if so, get request
1784 * types while we still have it locked. Otherwise,
1785 * recapture the (now dead) bits.
1787 if (!ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
1788 if (request
!= IE_REQ_NONE
) {
1789 type
|= ipc_port_request_type(port
, name
, request
);
1792 is_write_unlock(space
);
1794 bits
= entry
->ie_bits
;
1795 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1796 is_write_unlock(space
);
1800 is_write_unlock(space
);
1803 type
|= IE_BITS_TYPE(bits
);
1806 *urefsp
= IE_BITS_UREFS(bits
);
1807 return KERN_SUCCESS
;
1811 * Routine: ipc_right_copyin_check_reply
1813 * Check if a subsequent ipc_right_copyin would succeed. Used only
1814 * by ipc_kmsg_copyin_header to check if reply_port can be copied in.
1815 * If the reply port is an immovable send right, it errors out.
1817 * The space is locked (read or write) and active.
1821 ipc_right_copyin_check_reply(
1822 __assert_only ipc_space_t space
,
1823 mach_port_name_t reply_name
,
1824 ipc_entry_t reply_entry
,
1825 mach_msg_type_name_t reply_type
)
1827 ipc_entry_bits_t bits
;
1828 ipc_port_t reply_port
;
1830 bits
= reply_entry
->ie_bits
;
1831 assert(is_active(space
));
1833 switch (reply_type
) {
1834 case MACH_MSG_TYPE_MAKE_SEND
:
1835 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1840 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1841 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1846 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1847 /* ipc_kmsg_copyin_header already filters it out */
1850 case MACH_MSG_TYPE_COPY_SEND
:
1851 case MACH_MSG_TYPE_MOVE_SEND
:
1852 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1853 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
1857 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
1861 reply_port
= ip_object_to_port(reply_entry
->ie_object
);
1862 assert(reply_port
!= IP_NULL
);
1865 * active status peek to avoid checks that will be skipped
1866 * on copyin for dead ports. Lock not held, so will not be
1867 * atomic (but once dead, there's no going back).
1869 if (!ip_active(reply_port
)) {
1874 * Can't copyin a send right that is marked immovable. This bit
1875 * is set only during port creation and never unset. So it can
1876 * be read without a lock.
1878 if (reply_port
->ip_immovable_send
) {
1879 if (!ip_is_control(reply_port
) || immovable_control_port_enabled
) {
1880 mach_port_guard_exception_immovable(reply_name
, reply_port
, MPG_FLAGS_NONE
);
1885 if (reply_type
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1886 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1890 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1899 panic("ipc_right_copyin_check: strange rights");
1906 * Routine: ipc_right_copyin_check_guard_locked
1908 * Check if the port is guarded and the guard
1909 * value matches the one passed in the arguments.
1910 * If MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND is set,
1911 * check if the port is unguarded.
1913 * The port is locked.
1915 * KERN_SUCCESS Port is either unguarded
1916 * or guarded with expected value
1917 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
1918 * This also raises a EXC_GUARD exception.
1920 static kern_return_t
1921 ipc_right_copyin_check_guard_locked(
1922 mach_port_name_t name
,
1924 mach_port_context_t context
,
1925 mach_msg_guard_flags_t
*guard_flags
)
1927 mach_msg_guard_flags_t flags
= *guard_flags
;
1928 if ((flags
& MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
) && !port
->ip_guarded
&& !context
) {
1929 return KERN_SUCCESS
;
1930 } else if (port
->ip_guarded
&& (port
->ip_context
== context
)) {
1931 return KERN_SUCCESS
;
1934 /* Incorrect guard; Raise exception */
1935 mach_port_guard_exception(name
, context
, port
->ip_context
, kGUARD_EXC_INCORRECT_GUARD
);
1936 return KERN_INVALID_ARGUMENT
;
1940 * Routine: ipc_right_copyin
1942 * Copyin a capability from a space.
1943 * If successful, the caller gets a ref
1944 * for the resulting object, unless it is IO_DEAD,
1945 * and possibly a send-once right which should
1946 * be used in a port-deleted notification.
1948 * If deadok is not TRUE, the copyin operation
1949 * will fail instead of producing IO_DEAD.
1951 * The entry is never deallocated (except
1952 * when KERN_INVALID_NAME), so the caller
1953 * should deallocate the entry if its type
1954 * is MACH_PORT_TYPE_NONE.
1956 * The space is write-locked and active.
1958 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1959 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1960 * KERN_INVALID_CAPABILITY Trying to move an kobject port or an immovable right,
1961 * or moving the last ref of pinned right
1962 * KERN_INVALID_ARGUMENT Port is unguarded or guard mismatch
1968 mach_port_name_t name
,
1970 mach_msg_type_name_t msgt_name
,
1971 ipc_object_copyin_flags_t flags
,
1972 ipc_object_t
*objectp
,
1973 ipc_port_t
*sorightp
,
1974 ipc_port_t
*releasep
,
1976 mach_port_context_t context
,
1977 mach_msg_guard_flags_t
*guard_flags
)
1979 ipc_entry_bits_t bits
;
1982 boolean_t deadok
= !!(flags
& IPC_OBJECT_COPYIN_FLAGS_DEADOK
);
1983 boolean_t allow_imm_send
= !!(flags
& IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
);
1984 boolean_t soft_fail_imm_send
= !!(flags
& IPC_OBJECT_COPYIN_FLAGS_SOFT_FAIL_IMMOVABLE_SEND
);
1986 *releasep
= IP_NULL
;
1989 bits
= entry
->ie_bits
;
1991 assert(is_active(space
));
1993 switch (msgt_name
) {
1994 case MACH_MSG_TYPE_MAKE_SEND
: {
1995 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1999 port
= ip_object_to_port(entry
->ie_object
);
2000 assert(port
!= IP_NULL
);
2003 assert(port
->ip_receiver_name
== name
);
2004 assert(port
->ip_receiver
== space
);
2006 ipc_port_make_send_locked(port
);
2009 *objectp
= ip_to_object(port
);
2010 *sorightp
= IP_NULL
;
2014 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
2015 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
2019 port
= ip_object_to_port(entry
->ie_object
);
2020 assert(port
!= IP_NULL
);
2023 require_ip_active(port
);
2024 assert(port
->ip_receiver_name
== name
);
2025 assert(port
->ip_receiver
== space
);
2027 ipc_port_make_sonce_locked(port
);
2030 *objectp
= ip_to_object(port
);
2031 *sorightp
= IP_NULL
;
2035 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
2036 ipc_port_t request
= IP_NULL
;
2038 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
2043 * Disallow moving receive-right kobjects/kolabel, e.g. mk_timer ports
2044 * The ipc_port structure uses the kdata union of kobject and
2045 * imp_task exclusively. Thus, general use of a kobject port as
2046 * a receive right can cause type confusion in the importance
2049 if (io_is_kobject(entry
->ie_object
) ||
2050 io_is_kolabeled(entry
->ie_object
)) {
2052 * Distinguish an invalid right, e.g., trying to move
2053 * a send right as a receive right, from this
2054 * situation which is, "This is a valid receive right,
2055 * but it's also a kobject and you can't move it."
2057 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
2058 return KERN_INVALID_CAPABILITY
;
2061 port
= ip_object_to_port(entry
->ie_object
);
2062 assert(port
!= IP_NULL
);
2065 require_ip_active(port
);
2066 assert(port
->ip_receiver_name
== name
);
2067 assert(port
->ip_receiver
== space
);
2069 if (port
->ip_immovable_receive
|| port
->ip_specialreply
) {
2070 assert(port
->ip_receiver
!= ipc_space_kernel
);
2072 assert(current_task() != kernel_task
);
2073 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
2074 return KERN_INVALID_CAPABILITY
;
2077 if (guard_flags
!= NULL
) {
2078 kr
= ipc_right_copyin_check_guard_locked(name
, port
, context
, guard_flags
);
2079 if (kr
!= KERN_SUCCESS
) {
2085 if (bits
& MACH_PORT_TYPE_SEND
) {
2086 assert(IE_BITS_TYPE(bits
) ==
2087 MACH_PORT_TYPE_SEND_RECEIVE
);
2088 assert(IE_BITS_UREFS(bits
) > 0);
2089 assert(port
->ip_srights
> 0);
2091 ipc_hash_insert(space
, ip_to_object(port
),
2095 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2096 assert(IE_BITS_UREFS(bits
) == 0);
2098 request
= ipc_right_request_cancel_macro(space
, port
,
2100 entry
->ie_object
= IO_NULL
;
2102 entry
->ie_bits
= bits
& ~MACH_PORT_TYPE_RECEIVE
;
2103 entry
->ie_bits
|= MACH_PORT_TYPE_EX_RECEIVE
;
2104 ipc_entry_modified(space
, name
, entry
);
2106 /* ipc_port_clear_receiver unguards the port and clears the ip_immovable_receive bit */
2107 (void)ipc_port_clear_receiver(port
, FALSE
); /* don't destroy the port/mqueue */
2108 if (guard_flags
!= NULL
) {
2109 /* this flag will be cleared during copyout */
2110 *guard_flags
= *guard_flags
| MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
;
2113 #if IMPORTANCE_INHERITANCE
2115 * Account for boosts the current task is going to lose when
2116 * copying this right in. Tempowner ports have either not
2117 * been accounting to any task (and therefore are already in
2118 * "limbo" state w.r.t. assertions) or to some other specific
2119 * task. As we have no way to drop the latter task's assertions
2120 * here, We'll deduct those when we enqueue it on its
2121 * destination port (see ipc_port_check_circularity()).
2123 if (port
->ip_tempowner
== 0) {
2124 assert(IIT_NULL
== port
->ip_imp_task
);
2126 /* ports in limbo have to be tempowner */
2127 port
->ip_tempowner
= 1;
2128 *assertcntp
= port
->ip_impcount
;
2130 #endif /* IMPORTANCE_INHERITANCE */
2134 *objectp
= ip_to_object(port
);
2135 *sorightp
= request
;
2139 case MACH_MSG_TYPE_COPY_SEND
: {
2140 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2144 /* allow for dead send-once rights */
2146 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2150 assert(IE_BITS_UREFS(bits
) > 0);
2152 port
= ip_object_to_port(entry
->ie_object
);
2153 assert(port
!= IP_NULL
);
2155 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
2156 bits
= entry
->ie_bits
;
2160 /* port is locked and active */
2162 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2163 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2164 assert(port
->ip_sorights
> 0);
2170 if (!allow_imm_send
&& port
->ip_immovable_send
) {
2171 if (!ip_is_control(port
) || immovable_control_port_enabled
) {
2173 if (!soft_fail_imm_send
) {
2174 mach_port_guard_exception_immovable(name
, port
, MPG_FLAGS_NONE
);
2176 return KERN_INVALID_CAPABILITY
;
2180 ipc_port_copy_send_locked(port
);
2183 *objectp
= ip_to_object(port
);
2184 *sorightp
= IP_NULL
;
2188 case MACH_MSG_TYPE_MOVE_SEND
: {
2189 ipc_port_t request
= IP_NULL
;
2191 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2195 /* allow for dead send-once rights */
2197 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2201 assert(IE_BITS_UREFS(bits
) > 0);
2203 port
= ip_object_to_port(entry
->ie_object
);
2204 assert(port
!= IP_NULL
);
2206 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
2207 bits
= entry
->ie_bits
;
2211 /* port is locked and active */
2213 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2214 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2215 assert(port
->ip_sorights
> 0);
2220 if (!allow_imm_send
&& port
->ip_immovable_send
) {
2221 if (!ip_is_control(port
) || immovable_control_port_enabled
) {
2223 if (!soft_fail_imm_send
) {
2224 mach_port_guard_exception_immovable(name
, port
, MPG_FLAGS_NONE
);
2226 return KERN_INVALID_CAPABILITY
;
2230 if (IE_BITS_UREFS(bits
) == 1) {
2231 assert(port
->ip_srights
> 0);
2232 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2233 assert(port
->ip_receiver_name
== name
);
2234 assert(port
->ip_receiver
== space
);
2235 assert(IE_BITS_TYPE(bits
) ==
2236 MACH_PORT_TYPE_SEND_RECEIVE
);
2237 assert(port
->ip_pinned
== 0);
2241 assert(IE_BITS_TYPE(bits
) ==
2242 MACH_PORT_TYPE_SEND
);
2244 request
= ipc_right_request_cancel_macro(space
, port
,
2246 ipc_hash_delete(space
, ip_to_object(port
),
2248 entry
->ie_object
= IO_NULL
;
2249 /* transfer entry's reference to caller */
2251 entry
->ie_bits
= bits
& ~
2252 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND
);
2254 ipc_port_copy_send_locked(port
);
2255 /* if urefs are pegged due to overflow, leave them pegged */
2256 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2257 entry
->ie_bits
= bits
- 1; /* decrement urefs */
2261 ipc_entry_modified(space
, name
, entry
);
2264 *objectp
= ip_to_object(port
);
2265 *sorightp
= request
;
2269 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
2272 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2276 /* allow for dead send rights */
2278 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2282 assert(IE_BITS_UREFS(bits
) > 0);
2284 port
= ip_object_to_port(entry
->ie_object
);
2285 assert(port
!= IP_NULL
);
2287 if (ipc_right_check(space
, port
, name
, entry
, flags
)) {
2288 bits
= entry
->ie_bits
;
2293 * port is locked, but may not be active:
2294 * Allow copyin of inactive ports with no dead name request and treat it
2295 * as if the copyin of the port was successful and port became inactive
2299 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
2300 assert(bits
& MACH_PORT_TYPE_SEND
);
2301 assert(port
->ip_srights
> 0);
2307 if (!allow_imm_send
&& port
->ip_immovable_send
) {
2308 if (!ip_is_control(port
) || immovable_control_port_enabled
) {
2310 if (!soft_fail_imm_send
) {
2311 mach_port_guard_exception_immovable(name
, port
, MPG_FLAGS_NONE
);
2313 return KERN_INVALID_CAPABILITY
;
2317 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2318 assert(IE_BITS_UREFS(bits
) == 1);
2319 assert(port
->ip_sorights
> 0);
2321 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
2324 entry
->ie_object
= IO_NULL
;
2325 entry
->ie_bits
= bits
& ~
2326 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
2327 ipc_entry_modified(space
, name
, entry
);
2328 *objectp
= ip_to_object(port
);
2329 *sorightp
= request
;
2335 return KERN_INVALID_RIGHT
;
2338 return KERN_SUCCESS
;
2341 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2342 assert(IE_BITS_UREFS(bits
) > 0);
2343 assert(entry
->ie_request
== IE_REQ_NONE
);
2344 assert(entry
->ie_object
== 0);
2351 *sorightp
= IP_NULL
;
2352 return KERN_SUCCESS
;
2355 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2356 assert(IE_BITS_UREFS(bits
) > 0);
2357 assert(entry
->ie_request
== IE_REQ_NONE
);
2358 assert(entry
->ie_object
== 0);
2364 if (IE_BITS_UREFS(bits
) == 1) {
2365 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
2367 /* if urefs are pegged due to overflow, leave them pegged */
2368 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2369 entry
->ie_bits
= bits
- 1; /* decrement urefs */
2371 ipc_entry_modified(space
, name
, entry
);
2373 *sorightp
= IP_NULL
;
2374 return KERN_SUCCESS
;
2378 * Routine: ipc_right_copyin_two_move_sends
2380 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
2381 * and deadok == FALSE, except that this moves two
2382 * send rights at once.
2384 * The space is write-locked and active.
2385 * The object is returned with two refs/send rights.
2387 * KERN_SUCCESS Acquired an object.
2388 * KERN_INVALID_RIGHT Name doesn't denote correct right.
2392 ipc_right_copyin_two_move_sends(
2394 mach_port_name_t name
,
2396 ipc_object_t
*objectp
,
2397 ipc_port_t
*sorightp
,
2398 ipc_port_t
*releasep
)
2400 ipc_entry_bits_t bits
;
2401 mach_port_urefs_t urefs
;
2403 ipc_port_t request
= IP_NULL
;
2405 *releasep
= IP_NULL
;
2407 assert(is_active(space
));
2409 bits
= entry
->ie_bits
;
2411 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2415 urefs
= IE_BITS_UREFS(bits
);
2420 port
= ip_object_to_port(entry
->ie_object
);
2421 assert(port
!= IP_NULL
);
2423 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) {
2427 /* port is locked and active */
2431 * We are moving 2 urefs as naked send rights, which is decomposed as:
2432 * - two copy sends (which doesn't affect the make send count)
2433 * - decrementing the local urefs twice.
2435 ipc_port_copy_send_locked(port
);
2436 ipc_port_copy_send_locked(port
);
2437 /* if urefs are pegged due to overflow, leave them pegged */
2438 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2439 entry
->ie_bits
= bits
- 2; /* decrement urefs */
2443 * We have exactly 2 send rights for this port in this space,
2444 * which means that we will liberate the naked send right held
2447 * However refcounting rules around entries are that naked send rights
2448 * on behalf of spaces do not have an associated port reference,
2449 * so we need to donate one ...
2451 ipc_port_copy_send_locked(port
);
2453 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2454 assert(port
->ip_receiver_name
== name
);
2455 assert(port
->ip_receiver
== space
);
2456 assert(IE_BITS_TYPE(bits
) ==
2457 MACH_PORT_TYPE_SEND_RECEIVE
);
2459 /* ... that we inject manually when the entry stays alive */
2462 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2464 /* ... that we steal from the entry when it dies */
2465 request
= ipc_right_request_cancel_macro(space
, port
,
2468 ipc_hash_delete(space
, ip_to_object(port
),
2470 entry
->ie_object
= IO_NULL
;
2473 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND
);
2475 ipc_entry_modified(space
, name
, entry
);
2479 *objectp
= ip_to_object(port
);
2480 *sorightp
= request
;
2481 return KERN_SUCCESS
;
2484 return KERN_INVALID_RIGHT
;
2489 * Routine: ipc_right_copyin_two
2491 * Like ipc_right_copyin with two dispositions,
2492 * each of which results in a send or send-once right,
2493 * and deadok = FALSE.
2495 * The space is write-locked and active.
2496 * The object is returned with two refs/rights.
2497 * Msgt_one refers to the dest_type
2499 * KERN_SUCCESS Acquired an object.
2500 * KERN_INVALID_RIGHT Name doesn't denote correct right(s).
2501 * KERN_INVALID_CAPABILITY Name doesn't denote correct right for msgt_two.
2504 ipc_right_copyin_two(
2506 mach_port_name_t name
,
2508 mach_msg_type_name_t msgt_one
,
2509 mach_msg_type_name_t msgt_two
,
2510 ipc_object_t
*objectp
,
2511 ipc_port_t
*sorightp
,
2512 ipc_port_t
*releasep
)
2517 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one
));
2518 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two
));
2521 * This is a little tedious to make atomic, because
2522 * there are 25 combinations of valid dispositions.
2523 * However, most are easy.
2527 * If either is move-sonce, then there must be an error.
2529 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND_ONCE
||
2530 msgt_two
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
2531 return KERN_INVALID_RIGHT
;
2534 if ((msgt_one
== MACH_MSG_TYPE_MAKE_SEND
) ||
2535 (msgt_one
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) ||
2536 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND
) ||
2537 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) {
2539 * One of the dispositions needs a receive right.
2541 * If the copyin below succeeds, we know the receive
2542 * right is there (because the pre-validation of
2543 * the second disposition already succeeded in our
2546 * Hence the port is not in danger of dying.
2548 ipc_object_t object_two
;
2550 kr
= ipc_right_copyin(space
, name
, entry
,
2551 msgt_one
, IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
,
2552 objectp
, sorightp
, releasep
,
2553 &assertcnt
, 0, NULL
);
2554 assert(assertcnt
== 0);
2555 if (kr
!= KERN_SUCCESS
) {
2559 assert(IO_VALID(*objectp
));
2560 assert(*sorightp
== IP_NULL
);
2561 assert(*releasep
== IP_NULL
);
2564 * Now copyin the second (previously validated)
2565 * disposition. The result can't be a dead port,
2566 * as no valid disposition can make us lose our
2569 kr
= ipc_right_copyin(space
, name
, entry
,
2570 msgt_two
, IPC_OBJECT_COPYIN_FLAGS_NONE
,
2571 &object_two
, sorightp
, releasep
,
2572 &assertcnt
, 0, NULL
);
2573 assert(assertcnt
== 0);
2574 assert(kr
== KERN_SUCCESS
);
2575 assert(*sorightp
== IP_NULL
);
2576 assert(*releasep
== IP_NULL
);
2577 assert(object_two
== *objectp
);
2578 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
2579 } else if ((msgt_one
== MACH_MSG_TYPE_MOVE_SEND
) &&
2580 (msgt_two
== MACH_MSG_TYPE_MOVE_SEND
)) {
2582 * This is an easy case. Just use our
2583 * handy-dandy special-purpose copyin call
2584 * to get two send rights for the price of one.
2586 kr
= ipc_right_copyin_two_move_sends(space
, name
, entry
,
2589 if (kr
!= KERN_SUCCESS
) {
2593 mach_msg_type_name_t msgt_name
;
2596 * Must be either a single move-send and a
2597 * copy-send, or two copy-send dispositions.
2598 * Use the disposition with the greatest side
2599 * effects for the actual copyin - then just
2600 * duplicate the send right you get back.
2602 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND
||
2603 msgt_two
== MACH_MSG_TYPE_MOVE_SEND
) {
2604 msgt_name
= MACH_MSG_TYPE_MOVE_SEND
;
2606 msgt_name
= MACH_MSG_TYPE_COPY_SEND
;
2609 kr
= ipc_right_copyin(space
, name
, entry
,
2610 msgt_name
, IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
,
2611 objectp
, sorightp
, releasep
,
2612 &assertcnt
, 0, NULL
);
2613 assert(assertcnt
== 0);
2614 if (kr
!= KERN_SUCCESS
) {
2619 * Copy the right we got back. If it is dead now,
2620 * that's OK. Neither right will be usable to send
2623 (void)ipc_port_copy_send(ip_object_to_port(*objectp
));
2626 return KERN_SUCCESS
;
2631 * Routine: ipc_right_copyout
2633 * Copyout a capability to a space.
2634 * If successful, consumes a ref for the object.
2636 * Always succeeds when given a newly-allocated entry,
2637 * because user-reference overflow isn't a possibility.
2639 * If copying out the object would cause the user-reference
2640 * count in the entry to overflow, then the user-reference
2641 * count is left pegged to its maximum value and the copyout
2644 * The space is write-locked and active.
2645 * The object is locked and active.
2646 * The object is unlocked; the space isn't.
2648 * KERN_SUCCESS Copied out capability.
2654 mach_port_name_t name
,
2656 mach_msg_type_name_t msgt_name
,
2657 ipc_object_copyout_flags_t flags
,
2658 mach_port_context_t
*context
,
2659 mach_msg_guard_flags_t
*guard_flags
,
2660 ipc_object_t object
)
2662 ipc_entry_bits_t bits
;
2665 bits
= entry
->ie_bits
;
2667 assert(IO_VALID(object
));
2668 assert(io_otype(object
) == IOT_PORT
);
2669 assert(io_active(object
));
2670 assert(entry
->ie_object
== object
);
2672 port
= ip_object_to_port(object
);
2674 if (pinned_control_port_enabled
&& (flags
& IPC_OBJECT_COPYOUT_FLAGS_PINNED
)) {
2675 assert(!port
->ip_pinned
);
2676 assert(port
->ip_immovable_send
);
2677 port
->ip_pinned
= 1;
2680 switch (msgt_name
) {
2681 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
2683 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2684 assert(IE_BITS_UREFS(bits
) == 0);
2685 assert(port
->ip_sorights
> 0);
2687 if (port
->ip_specialreply
) {
2688 ipc_port_adjust_special_reply_port_locked(port
,
2689 current_thread()->ith_knote
, IPC_PORT_ADJUST_SR_LINK_WORKLOOP
, FALSE
);
2690 /* port unlocked on return */
2695 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1); /* set urefs to 1 */
2696 ipc_entry_modified(space
, name
, entry
);
2699 case MACH_MSG_TYPE_PORT_SEND
:
2700 assert(port
->ip_srights
> 0);
2702 if (bits
& MACH_PORT_TYPE_SEND
) {
2703 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
2705 assert(port
->ip_srights
> 1);
2707 assert(urefs
<= MACH_PORT_UREFS_MAX
);
2709 if (urefs
== MACH_PORT_UREFS_MAX
) {
2711 * leave urefs pegged to maximum,
2712 * consume send right and ref
2718 return KERN_SUCCESS
;
2721 /* consume send right and ref */
2725 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2726 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2727 assert(IE_BITS_UREFS(bits
) == 0);
2729 /* transfer send right to entry, consume ref */
2733 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2734 assert(IE_BITS_UREFS(bits
) == 0);
2736 /* transfer send right and ref to entry */
2739 /* entry is locked holding ref, so can use port */
2741 ipc_hash_insert(space
, ip_to_object(port
), name
, entry
);
2744 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1; /* increment urefs */
2745 ipc_entry_modified(space
, name
, entry
);
2748 case MACH_MSG_TYPE_PORT_RECEIVE
: {
2750 #if IMPORTANCE_INHERITANCE
2751 natural_t assertcnt
= port
->ip_impcount
;
2752 #endif /* IMPORTANCE_INHERITANCE */
2754 assert(port
->ip_mscount
== 0);
2755 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
2758 * Don't copyout kobjects or kolabels as receive right
2760 if (io_is_kobject(entry
->ie_object
) ||
2761 io_is_kolabeled(entry
->ie_object
)) {
2762 panic("ipc_right_copyout: Copyout kobject/kolabel as receive right");
2765 imq_lock(&port
->ip_messages
);
2766 dest
= port
->ip_destination
;
2768 port
->ip_receiver_name
= name
;
2769 port
->ip_receiver
= space
;
2771 struct knote
*kn
= current_thread()->ith_knote
;
2773 if ((guard_flags
!= NULL
) && ((*guard_flags
& MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE
) != 0)) {
2774 assert(port
->ip_immovable_receive
== 0);
2775 port
->ip_guarded
= 1;
2776 port
->ip_strict_guard
= 0;
2777 /* pseudo receive shouldn't set the receive right as immovable in the sender's space */
2778 if (kn
!= ITH_KNOTE_PSEUDO
) {
2779 port
->ip_immovable_receive
= 1;
2781 port
->ip_context
= current_thread()->ith_msg_addr
;
2782 *context
= port
->ip_context
;
2783 *guard_flags
= *guard_flags
& ~MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
;
2786 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
2787 if (bits
& MACH_PORT_TYPE_SEND
) {
2788 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2789 assert(IE_BITS_UREFS(bits
) > 0);
2790 assert(port
->ip_srights
> 0);
2792 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2793 assert(IE_BITS_UREFS(bits
) == 0);
2796 boolean_t sync_bootstrap_checkin
= FALSE
;
2797 if (kn
!= ITH_KNOTE_PSEUDO
&& port
->ip_sync_bootstrap_checkin
) {
2798 sync_bootstrap_checkin
= TRUE
;
2800 if (!ITH_KNOTE_VALID(kn
, MACH_MSG_TYPE_PORT_RECEIVE
)) {
2803 ipc_port_adjust_port_locked(port
, kn
, sync_bootstrap_checkin
);
2804 /* port & message queue are unlocked */
2806 if (bits
& MACH_PORT_TYPE_SEND
) {
2809 /* entry is locked holding ref, so can use port */
2810 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
);
2812 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2813 ipc_entry_modified(space
, name
, entry
);
2815 if (dest
!= IP_NULL
) {
2816 #if IMPORTANCE_INHERITANCE
2818 * Deduct the assertion counts we contributed to
2819 * the old destination port. They've already
2820 * been reflected into the task as a result of
2824 ipc_port_impcount_delta(dest
, 0 - assertcnt
, IP_NULL
);
2826 #endif /* IMPORTANCE_INHERITANCE */
2828 /* Drop turnstile ref on dest */
2829 ipc_port_send_turnstile_complete(dest
);
2836 panic("ipc_right_copyout: strange rights");
2838 return KERN_SUCCESS
;