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,
185 * the object is locked and active.
187 * The space must be locked (read or write) and active.
188 * Nothing else locked.
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
= (ipc_port_t
) object
;
210 if (!ip_active(port
)) {
216 if (port
->ip_receiver
== space
) {
217 name
= port
->ip_receiver_name
;
218 assert(name
!= MACH_PORT_NULL
);
220 entry
= ipc_entry_lookup(space
, name
);
222 assert(entry
!= IE_NULL
);
223 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
224 assert(port
== (ipc_port_t
) entry
->ie_object
);
231 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
232 assert((entry
= *entryp
) != IE_NULL
);
233 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
234 assert(port
== (ipc_port_t
) entry
->ie_object
);
244 * Routine: ipc_right_dnrequest
246 * Make a dead-name request, returning the previously
247 * registered send-once right. If notify is IP_NULL,
248 * just cancels the previously registered request.
251 * Nothing locked. May allocate memory.
252 * Only consumes/returns refs if successful.
254 * KERN_SUCCESS Made/canceled dead-name request.
255 * KERN_INVALID_TASK The space is dead.
256 * KERN_INVALID_NAME Name doesn't exist in space.
257 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
258 * KERN_INVALID_ARGUMENT Name denotes dead name, but
259 * immediate is FALSE or notify is IP_NULL.
260 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
264 ipc_right_request_alloc(
266 mach_port_name_t name
,
268 boolean_t send_possible
,
270 ipc_port_t
*previousp
)
272 ipc_port_request_index_t prev_request
;
273 ipc_port_t previous
= IP_NULL
;
277 #if IMPORTANCE_INHERITANCE
278 boolean_t needboost
= FALSE
;
279 #endif /* IMPORTANCE_INHERITANCE */
282 ipc_port_t port
= IP_NULL
;
284 kr
= ipc_right_lookup_write(space
, name
, &entry
);
285 if (kr
!= KERN_SUCCESS
) {
289 /* space is write-locked and active */
291 prev_request
= entry
->ie_request
;
293 /* if nothing to do or undo, we're done */
294 if (notify
== IP_NULL
&& prev_request
== IE_REQ_NONE
) {
295 is_write_unlock(space
);
296 *previousp
= IP_NULL
;
300 /* see if the entry is of proper type for requests */
301 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
302 ipc_port_request_index_t new_request
;
304 port
= (ipc_port_t
) entry
->ie_object
;
305 assert(port
!= IP_NULL
);
307 if (!ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
308 /* port is locked and active */
310 /* if no new request, just cancel previous */
311 if (notify
== IP_NULL
) {
312 if (prev_request
!= IE_REQ_NONE
) {
313 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
316 entry
->ie_request
= IE_REQ_NONE
;
317 ipc_entry_modified(space
, name
, entry
);
318 is_write_unlock(space
);
323 * send-once rights, kernel objects, and non-full other queues
324 * fire immediately (if immediate specified).
326 if (send_possible
&& immediate
&&
327 ((entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
) ||
328 port
->ip_receiver
== ipc_space_kernel
|| !ip_full(port
))) {
329 if (prev_request
!= IE_REQ_NONE
) {
330 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
333 entry
->ie_request
= IE_REQ_NONE
;
334 ipc_entry_modified(space
, name
, entry
);
335 is_write_unlock(space
);
337 ipc_notify_send_possible(notify
, name
);
342 * If there is a previous request, free it. Any subsequent
343 * allocation cannot fail, thus assuring an atomic swap.
345 if (prev_request
!= IE_REQ_NONE
) {
346 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
349 #if IMPORTANCE_INHERITANCE
350 kr
= ipc_port_request_alloc(port
, name
, notify
,
351 send_possible
, immediate
,
352 &new_request
, &needboost
);
354 kr
= ipc_port_request_alloc(port
, name
, notify
,
355 send_possible
, immediate
,
357 #endif /* IMPORTANCE_INHERITANCE */
358 if (kr
!= KERN_SUCCESS
) {
359 assert(previous
== IP_NULL
);
360 is_write_unlock(space
);
362 kr
= ipc_port_request_grow(port
, ITS_SIZE_NONE
);
363 /* port is unlocked */
365 if (kr
!= KERN_SUCCESS
) {
373 assert(new_request
!= IE_REQ_NONE
);
374 entry
->ie_request
= new_request
;
375 ipc_entry_modified(space
, name
, entry
);
376 is_write_unlock(space
);
378 #if IMPORTANCE_INHERITANCE
379 if (needboost
== TRUE
) {
380 if (ipc_port_importance_delta(port
, IPID_OPTION_SENDPOSSIBLE
, 1) == FALSE
) {
384 #endif /* IMPORTANCE_INHERITANCE */
389 /* entry may have changed to dead-name by ipc_right_check() */
392 /* treat send_possible requests as immediate w.r.t. dead-name */
393 if ((send_possible
|| immediate
) && notify
!= IP_NULL
&&
394 (entry
->ie_bits
& MACH_PORT_TYPE_DEAD_NAME
)) {
395 mach_port_urefs_t urefs
= IE_BITS_UREFS(entry
->ie_bits
);
399 /* leave urefs pegged to maximum if it overflowed */
400 if (urefs
< MACH_PORT_UREFS_MAX
) {
401 (entry
->ie_bits
)++; /* increment urefs */
403 ipc_entry_modified(space
, name
, entry
);
405 is_write_unlock(space
);
407 if (port
!= IP_NULL
) {
411 ipc_notify_dead_name(notify
, name
);
416 kr
= (entry
->ie_bits
& MACH_PORT_TYPE_PORT_OR_DEAD
) ?
417 KERN_INVALID_ARGUMENT
: KERN_INVALID_RIGHT
;
419 is_write_unlock(space
);
421 if (port
!= IP_NULL
) {
428 *previousp
= previous
;
433 * Routine: ipc_right_request_cancel
435 * Cancel a notification request and return the send-once right.
436 * Afterwards, entry->ie_request == 0.
438 * The space must be write-locked; the port must be locked.
439 * The port must be active; the space doesn't have to be.
443 ipc_right_request_cancel(
444 __unused ipc_space_t space
,
446 mach_port_name_t name
,
451 assert(ip_active(port
));
452 assert(port
== (ipc_port_t
) entry
->ie_object
);
454 if (entry
->ie_request
== IE_REQ_NONE
) {
458 previous
= ipc_port_request_cancel(port
, name
, entry
->ie_request
);
459 entry
->ie_request
= IE_REQ_NONE
;
460 ipc_entry_modified(space
, name
, entry
);
465 * Routine: ipc_right_inuse
467 * Check if an entry is being used.
468 * Returns TRUE if it is.
470 * The space is write-locked and active.
471 * It is unlocked if the entry is inuse.
477 __unused mach_port_name_t name
,
480 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
481 is_write_unlock(space
);
488 * Routine: ipc_right_check
490 * Check if the port has died. If it has,
491 * and IPC_RIGHT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE is not
492 * passed and it is not a send once right then
493 * clean up the entry and return TRUE.
495 * The space is write-locked; the port is not locked.
496 * If returns FALSE, the port is also locked.
497 * Otherwise, entry is converted to a dead name.
499 * Caller is responsible for a reference to port if it
500 * had died (returns TRUE).
507 mach_port_name_t name
,
509 ipc_right_copyin_flags_t flags
)
511 ipc_entry_bits_t bits
;
513 assert(is_active(space
));
514 assert(port
== (ipc_port_t
) entry
->ie_object
);
517 if (ip_active(port
) ||
518 ((flags
& IPC_RIGHT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE
) &&
519 entry
->ie_request
== IE_REQ_NONE
&&
520 (entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
))) {
524 /* this was either a pure send right or a send-once right */
526 bits
= entry
->ie_bits
;
527 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
528 assert(IE_BITS_UREFS(bits
) > 0);
530 if (bits
& MACH_PORT_TYPE_SEND
) {
531 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
532 assert(IE_BITS_UREFS(bits
) > 0);
533 assert(port
->ip_srights
> 0);
536 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
537 assert(IE_BITS_UREFS(bits
) == 1);
538 assert(port
->ip_sorights
> 0);
544 * delete SEND rights from ipc hash.
547 if ((bits
& MACH_PORT_TYPE_SEND
) != 0) {
548 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
551 /* convert entry to dead name */
552 bits
= (bits
& ~IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
555 * If there was a notification request outstanding on this
556 * name, and the port went dead, that notification
557 * must already be on its way up from the port layer.
559 * Add the reference that the notification carries. It
560 * is done here, and not in the notification delivery,
561 * because the latter doesn't have a space reference and
562 * trying to actually move a send-right reference would
563 * get short-circuited into a MACH_PORT_DEAD by IPC. Since
564 * all calls that deal with the right eventually come
565 * through here, it has the same result.
567 * Once done, clear the request index so we only account
570 if (entry
->ie_request
!= IE_REQ_NONE
) {
571 if (ipc_port_request_type(port
, name
, entry
->ie_request
) != 0) {
572 /* if urefs are pegged due to overflow, leave them pegged */
573 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
574 bits
++; /* increment urefs */
577 entry
->ie_request
= IE_REQ_NONE
;
579 entry
->ie_bits
= bits
;
580 entry
->ie_object
= IO_NULL
;
581 ipc_entry_modified(space
, name
, entry
);
586 * Routine: ipc_right_terminate
588 * Cleans up an entry in a terminated space.
589 * The entry isn't deallocated or removed
590 * from reverse hash tables.
592 * The space is dead and unlocked.
598 mach_port_name_t name
,
601 ipc_entry_bits_t bits
;
602 mach_port_type_t type
;
604 bits
= entry
->ie_bits
;
605 type
= IE_BITS_TYPE(bits
);
607 assert(!is_active(space
));
610 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
611 * problem, because we check that the port is active. If
612 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
613 * would still work, but dead space refs would accumulate
614 * in ip_dnrequests. They would use up slots in
615 * ip_dnrequests and keep the spaces from being freed.
619 case MACH_PORT_TYPE_DEAD_NAME
:
620 assert(entry
->ie_request
== IE_REQ_NONE
);
621 assert(entry
->ie_object
== IO_NULL
);
624 case MACH_PORT_TYPE_PORT_SET
: {
625 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
627 assert(entry
->ie_request
== IE_REQ_NONE
);
628 assert(pset
!= IPS_NULL
);
631 assert(ips_active(pset
));
632 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
636 case MACH_PORT_TYPE_SEND
:
637 case MACH_PORT_TYPE_RECEIVE
:
638 case MACH_PORT_TYPE_SEND_RECEIVE
:
639 case MACH_PORT_TYPE_SEND_ONCE
: {
640 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
642 ipc_port_t nsrequest
= IP_NULL
;
643 mach_port_mscount_t mscount
= 0;
645 assert(port
!= IP_NULL
);
648 if (!ip_active(port
)) {
654 request
= ipc_right_request_cancel_macro(space
, port
,
657 if (type
& MACH_PORT_TYPE_SEND
) {
658 assert(port
->ip_srights
> 0);
659 if (--port
->ip_srights
== 0
661 nsrequest
= port
->ip_nsrequest
;
662 if (nsrequest
!= IP_NULL
) {
663 port
->ip_nsrequest
= IP_NULL
;
664 mscount
= port
->ip_mscount
;
669 if (type
& MACH_PORT_TYPE_RECEIVE
) {
670 assert(port
->ip_receiver_name
== name
);
671 assert(port
->ip_receiver
== space
);
673 ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */
674 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
675 assert(port
->ip_sorights
> 0);
678 ipc_notify_send_once(port
); /* consumes our ref */
680 assert(port
->ip_receiver
!= space
);
686 if (nsrequest
!= IP_NULL
) {
687 ipc_notify_no_senders(nsrequest
, mscount
);
690 if (request
!= IP_NULL
) {
691 ipc_notify_port_deleted(request
, name
);
697 panic("ipc_right_terminate: strange type - 0x%x", type
);
702 * Routine: ipc_right_destroy
704 * Destroys an entry in a space.
706 * The space is write-locked (returns unlocked).
707 * The space must be active.
709 * KERN_SUCCESS The entry was destroyed.
715 mach_port_name_t name
,
717 boolean_t check_guard
,
720 ipc_entry_bits_t bits
;
721 mach_port_type_t type
;
723 bits
= entry
->ie_bits
;
724 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
725 type
= IE_BITS_TYPE(bits
);
727 assert(is_active(space
));
730 case MACH_PORT_TYPE_DEAD_NAME
:
731 assert(entry
->ie_request
== IE_REQ_NONE
);
732 assert(entry
->ie_object
== IO_NULL
);
734 ipc_entry_dealloc(space
, name
, entry
);
735 is_write_unlock(space
);
738 case MACH_PORT_TYPE_PORT_SET
: {
739 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
741 assert(entry
->ie_request
== IE_REQ_NONE
);
742 assert(pset
!= IPS_NULL
);
744 entry
->ie_object
= IO_NULL
;
745 ipc_entry_dealloc(space
, name
, entry
);
748 is_write_unlock(space
);
750 assert(ips_active(pset
));
751 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
755 case MACH_PORT_TYPE_SEND
:
756 case MACH_PORT_TYPE_RECEIVE
:
757 case MACH_PORT_TYPE_SEND_RECEIVE
:
758 case MACH_PORT_TYPE_SEND_ONCE
: {
759 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
760 ipc_port_t nsrequest
= IP_NULL
;
761 mach_port_mscount_t mscount
= 0;
764 assert(port
!= IP_NULL
);
766 if (type
== MACH_PORT_TYPE_SEND
) {
767 ipc_hash_delete(space
, (ipc_object_t
) port
,
773 if (!ip_active(port
)) {
774 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
776 entry
->ie_request
= IE_REQ_NONE
;
777 entry
->ie_object
= IO_NULL
;
778 ipc_entry_dealloc(space
, name
, entry
);
779 is_write_unlock(space
);
784 /* For receive rights, check for guarding */
785 if ((type
& MACH_PORT_TYPE_RECEIVE
) &&
786 (check_guard
) && (port
->ip_guarded
) &&
787 (guard
!= port
->ip_context
)) {
788 /* Guard Violation */
789 uint64_t portguard
= port
->ip_context
;
791 is_write_unlock(space
);
792 /* Raise mach port guard exception */
793 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
794 return KERN_INVALID_RIGHT
;
798 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
800 entry
->ie_object
= IO_NULL
;
801 ipc_entry_dealloc(space
, name
, entry
);
802 is_write_unlock(space
);
804 if (type
& MACH_PORT_TYPE_SEND
) {
805 assert(port
->ip_srights
> 0);
806 if (--port
->ip_srights
== 0) {
807 nsrequest
= port
->ip_nsrequest
;
808 if (nsrequest
!= IP_NULL
) {
809 port
->ip_nsrequest
= IP_NULL
;
810 mscount
= port
->ip_mscount
;
815 if (type
& MACH_PORT_TYPE_RECEIVE
) {
816 assert(ip_active(port
));
817 assert(port
->ip_receiver
== space
);
819 ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */
820 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
821 assert(port
->ip_sorights
> 0);
824 ipc_notify_send_once(port
); /* consumes our ref */
826 assert(port
->ip_receiver
!= space
);
832 if (nsrequest
!= IP_NULL
) {
833 ipc_notify_no_senders(nsrequest
, mscount
);
836 if (request
!= IP_NULL
) {
837 ipc_notify_port_deleted(request
, name
);
845 panic("ipc_right_destroy: strange type");
852 * Routine: ipc_right_dealloc
854 * Releases a send/send-once/dead-name/port_set user ref.
855 * Like ipc_right_delta with a delta of -1,
856 * but looks at the entry to determine the right.
858 * The space is write-locked, and is unlocked upon return.
859 * The space must be active.
861 * KERN_SUCCESS A user ref was released.
862 * KERN_INVALID_RIGHT Entry has wrong type.
868 mach_port_name_t name
,
871 ipc_port_t port
= IP_NULL
;
872 ipc_entry_bits_t bits
;
873 mach_port_type_t type
;
875 bits
= entry
->ie_bits
;
876 type
= IE_BITS_TYPE(bits
);
879 assert(is_active(space
));
882 case MACH_PORT_TYPE_PORT_SET
: {
885 assert(IE_BITS_UREFS(bits
) == 0);
886 assert(entry
->ie_request
== IE_REQ_NONE
);
888 pset
= (ipc_pset_t
) entry
->ie_object
;
889 assert(pset
!= IPS_NULL
);
891 entry
->ie_object
= IO_NULL
;
892 ipc_entry_dealloc(space
, name
, entry
);
895 assert(ips_active(pset
));
896 is_write_unlock(space
);
898 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
902 case MACH_PORT_TYPE_DEAD_NAME
: {
905 assert(IE_BITS_UREFS(bits
) > 0);
906 assert(entry
->ie_request
== IE_REQ_NONE
);
907 assert(entry
->ie_object
== IO_NULL
);
909 if (IE_BITS_UREFS(bits
) == 1) {
910 ipc_entry_dealloc(space
, name
, entry
);
912 /* if urefs are pegged due to overflow, leave them pegged */
913 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
914 entry
->ie_bits
= bits
- 1; /* decrement urefs */
916 ipc_entry_modified(space
, name
, entry
);
918 is_write_unlock(space
);
920 /* release any port that got converted to dead name below */
921 if (port
!= IP_NULL
) {
927 case MACH_PORT_TYPE_SEND_ONCE
: {
930 assert(IE_BITS_UREFS(bits
) == 1);
932 port
= (ipc_port_t
) entry
->ie_object
;
933 assert(port
!= IP_NULL
);
935 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
936 bits
= entry
->ie_bits
;
937 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
938 goto dead_name
; /* it will release port */
940 /* port is locked and active */
942 assert(port
->ip_sorights
> 0);
944 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
947 entry
->ie_object
= IO_NULL
;
948 ipc_entry_dealloc(space
, name
, entry
);
950 is_write_unlock(space
);
952 ipc_notify_send_once(port
);
954 if (request
!= IP_NULL
) {
955 ipc_notify_port_deleted(request
, name
);
960 case MACH_PORT_TYPE_SEND
: {
961 ipc_port_t request
= IP_NULL
;
962 ipc_port_t nsrequest
= IP_NULL
;
963 mach_port_mscount_t mscount
= 0;
966 assert(IE_BITS_UREFS(bits
) > 0);
968 port
= (ipc_port_t
) entry
->ie_object
;
969 assert(port
!= IP_NULL
);
971 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
972 bits
= entry
->ie_bits
;
973 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
974 goto dead_name
; /* it will release port */
976 /* port is locked and active */
978 assert(port
->ip_srights
> 0);
980 if (IE_BITS_UREFS(bits
) == 1) {
981 if (--port
->ip_srights
== 0) {
982 nsrequest
= port
->ip_nsrequest
;
983 if (nsrequest
!= IP_NULL
) {
984 port
->ip_nsrequest
= IP_NULL
;
985 mscount
= port
->ip_mscount
;
989 request
= ipc_right_request_cancel_macro(space
, port
,
991 ipc_hash_delete(space
, (ipc_object_t
) port
,
995 entry
->ie_object
= IO_NULL
;
996 ipc_entry_dealloc(space
, name
, entry
);
997 is_write_unlock(space
);
1001 /* if urefs are pegged due to overflow, leave them pegged */
1002 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1003 entry
->ie_bits
= bits
- 1; /* decrement urefs */
1005 ipc_entry_modified(space
, name
, entry
);
1006 is_write_unlock(space
);
1009 if (nsrequest
!= IP_NULL
) {
1010 ipc_notify_no_senders(nsrequest
, mscount
);
1013 if (request
!= IP_NULL
) {
1014 ipc_notify_port_deleted(request
, name
);
1019 case MACH_PORT_TYPE_SEND_RECEIVE
: {
1020 ipc_port_t nsrequest
= IP_NULL
;
1021 mach_port_mscount_t mscount
= 0;
1023 assert(IE_BITS_UREFS(bits
) > 0);
1025 port
= (ipc_port_t
) entry
->ie_object
;
1026 assert(port
!= IP_NULL
);
1029 assert(ip_active(port
));
1030 assert(port
->ip_receiver_name
== name
);
1031 assert(port
->ip_receiver
== space
);
1032 assert(port
->ip_srights
> 0);
1034 if (IE_BITS_UREFS(bits
) == 1) {
1035 if (--port
->ip_srights
== 0) {
1036 nsrequest
= port
->ip_nsrequest
;
1037 if (nsrequest
!= IP_NULL
) {
1038 port
->ip_nsrequest
= IP_NULL
;
1039 mscount
= port
->ip_mscount
;
1043 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1044 MACH_PORT_TYPE_SEND
);
1046 /* if urefs are pegged due to overflow, leave them pegged */
1047 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1048 entry
->ie_bits
= bits
- 1; /* decrement urefs */
1053 ipc_entry_modified(space
, name
, entry
);
1054 is_write_unlock(space
);
1056 if (nsrequest
!= IP_NULL
) {
1057 ipc_notify_no_senders(nsrequest
, mscount
);
1063 is_write_unlock(space
);
1064 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1065 return KERN_INVALID_RIGHT
;
1068 return KERN_SUCCESS
;
1072 * Routine: ipc_right_delta
1074 * Modifies the user-reference count for a right.
1075 * May deallocate the right, if the count goes to zero.
1077 * The space is write-locked, and is unlocked upon return.
1078 * The space must be active.
1080 * KERN_SUCCESS Count was modified.
1081 * KERN_INVALID_RIGHT Entry has wrong type.
1082 * KERN_INVALID_VALUE Bad delta for the right.
1088 mach_port_name_t name
,
1090 mach_port_right_t right
,
1091 mach_port_delta_t delta
)
1093 ipc_port_t port
= IP_NULL
;
1094 ipc_entry_bits_t bits
;
1096 bits
= entry
->ie_bits
;
1099 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
1100 * switch below. It is used to keep track of those cases (in DIPC)
1101 * where we have postponed the dropping of a port reference. Since
1102 * the dropping of the reference could cause the port to disappear
1103 * we postpone doing so when we are holding the space lock.
1106 assert(is_active(space
));
1107 assert(right
< MACH_PORT_RIGHT_NUMBER
);
1109 /* Rights-specific restrictions and operations. */
1112 case MACH_PORT_RIGHT_PORT_SET
: {
1115 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1116 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1120 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
1121 assert(IE_BITS_UREFS(bits
) == 0);
1122 assert(entry
->ie_request
== IE_REQ_NONE
);
1132 pset
= (ipc_pset_t
) entry
->ie_object
;
1133 assert(pset
!= IPS_NULL
);
1135 entry
->ie_object
= IO_NULL
;
1136 ipc_entry_dealloc(space
, name
, entry
);
1139 assert(ips_active(pset
));
1140 is_write_unlock(space
);
1142 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
1146 case MACH_PORT_RIGHT_RECEIVE
: {
1147 ipc_port_t request
= IP_NULL
;
1149 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1150 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1162 port
= (ipc_port_t
) entry
->ie_object
;
1163 assert(port
!= IP_NULL
);
1166 * The port lock is needed for ipc_right_dncancel;
1167 * otherwise, we wouldn't have to take the lock
1168 * until just before dropping the space lock.
1172 assert(ip_active(port
));
1173 assert(port
->ip_receiver_name
== name
);
1174 assert(port
->ip_receiver
== space
);
1176 /* Mach Port Guard Checking */
1177 if (port
->ip_guarded
) {
1178 uint64_t portguard
= port
->ip_context
;
1180 is_write_unlock(space
);
1181 /* Raise mach port guard exception */
1182 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_MOD_REFS
);
1186 if (bits
& MACH_PORT_TYPE_SEND
) {
1187 assert(IE_BITS_TYPE(bits
) ==
1188 MACH_PORT_TYPE_SEND_RECEIVE
);
1189 assert(IE_BITS_UREFS(bits
) > 0);
1190 assert(port
->ip_srights
> 0);
1192 if (port
->ip_pdrequest
!= NULL
) {
1194 * Since another task has requested a
1195 * destroy notification for this port, it
1196 * isn't actually being destroyed - the receive
1197 * right is just being moved to another task.
1198 * Since we still have one or more send rights,
1199 * we need to record the loss of the receive
1200 * right and enter the remaining send right
1201 * into the hash table.
1203 ipc_entry_modified(space
, name
, entry
);
1204 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1205 ipc_hash_insert(space
, (ipc_object_t
) port
,
1210 * The remaining send right turns into a
1211 * dead name. Notice we don't decrement
1212 * ip_srights, generate a no-senders notif,
1213 * or use ipc_right_dncancel, because the
1214 * port is destroyed "first".
1216 bits
&= ~IE_BITS_TYPE_MASK
;
1217 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1218 if (entry
->ie_request
) {
1219 entry
->ie_request
= IE_REQ_NONE
;
1220 /* if urefs are pegged due to overflow, leave them pegged */
1221 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1222 bits
++; /* increment urefs */
1225 entry
->ie_bits
= bits
;
1226 entry
->ie_object
= IO_NULL
;
1227 ipc_entry_modified(space
, name
, entry
);
1230 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1231 assert(IE_BITS_UREFS(bits
) == 0);
1233 request
= ipc_right_request_cancel_macro(space
, port
,
1235 entry
->ie_object
= IO_NULL
;
1236 ipc_entry_dealloc(space
, name
, entry
);
1238 is_write_unlock(space
);
1240 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1242 if (request
!= IP_NULL
) {
1243 ipc_notify_port_deleted(request
, name
);
1248 case MACH_PORT_RIGHT_SEND_ONCE
: {
1251 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1255 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1256 assert(IE_BITS_UREFS(bits
) == 1);
1258 port
= (ipc_port_t
) entry
->ie_object
;
1259 assert(port
!= IP_NULL
);
1261 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1262 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1263 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1266 /* port is locked and active */
1268 assert(port
->ip_sorights
> 0);
1270 if ((delta
> 0) || (delta
< -1)) {
1280 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1283 entry
->ie_object
= IO_NULL
;
1284 ipc_entry_dealloc(space
, name
, entry
);
1286 is_write_unlock(space
);
1288 ipc_notify_send_once(port
);
1290 if (request
!= IP_NULL
) {
1291 ipc_notify_port_deleted(request
, name
);
1296 case MACH_PORT_RIGHT_DEAD_NAME
: {
1297 ipc_port_t relport
= IP_NULL
;
1298 mach_port_urefs_t urefs
;
1300 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1301 port
= (ipc_port_t
) entry
->ie_object
;
1302 assert(port
!= IP_NULL
);
1304 if (!ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1305 /* port is locked and active */
1308 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1311 bits
= entry
->ie_bits
;
1314 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0) {
1315 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1319 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1320 assert(IE_BITS_UREFS(bits
) > 0);
1321 assert(entry
->ie_object
== IO_NULL
);
1322 assert(entry
->ie_request
== IE_REQ_NONE
);
1324 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1325 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1329 urefs
= IE_BITS_UREFS(bits
);
1331 if (urefs
== MACH_PORT_UREFS_MAX
) {
1333 * urefs are pegged due to an overflow
1334 * only a delta removing all refs at once can change it
1337 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1341 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1344 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1345 /* leave urefs pegged to maximum if it overflowed */
1346 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1350 if ((urefs
+ delta
) == 0) {
1351 ipc_entry_dealloc(space
, name
, entry
);
1352 } else if (delta
!= 0) {
1353 entry
->ie_bits
= bits
+ delta
;
1354 ipc_entry_modified(space
, name
, entry
);
1357 is_write_unlock(space
);
1359 if (relport
!= IP_NULL
) {
1360 ip_release(relport
);
1366 case MACH_PORT_RIGHT_SEND
: {
1367 mach_port_urefs_t urefs
;
1368 ipc_port_t request
= IP_NULL
;
1369 ipc_port_t nsrequest
= IP_NULL
;
1370 ipc_port_t port_to_release
= IP_NULL
;
1371 mach_port_mscount_t mscount
= 0;
1373 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1374 /* invalid right exception only when not live/dead confusion */
1375 if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0) {
1376 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1381 /* maximum urefs for send is MACH_PORT_UREFS_MAX */
1383 port
= (ipc_port_t
) entry
->ie_object
;
1384 assert(port
!= IP_NULL
);
1386 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1387 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1390 /* port is locked and active */
1392 assert(port
->ip_srights
> 0);
1394 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1395 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1400 urefs
= IE_BITS_UREFS(bits
);
1402 if (urefs
== MACH_PORT_UREFS_MAX
) {
1404 * urefs are pegged due to an overflow
1405 * only a delta removing all refs at once can change it
1408 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1412 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1416 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1417 /* leave urefs pegged to maximum if it overflowed */
1418 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1422 if ((urefs
+ delta
) == 0) {
1423 if (--port
->ip_srights
== 0) {
1424 nsrequest
= port
->ip_nsrequest
;
1425 if (nsrequest
!= IP_NULL
) {
1426 port
->ip_nsrequest
= IP_NULL
;
1427 mscount
= port
->ip_mscount
;
1431 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1432 assert(port
->ip_receiver_name
== name
);
1433 assert(port
->ip_receiver
== space
);
1435 assert(IE_BITS_TYPE(bits
) ==
1436 MACH_PORT_TYPE_SEND_RECEIVE
);
1438 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1439 MACH_PORT_TYPE_SEND
);
1440 ipc_entry_modified(space
, name
, entry
);
1442 assert(IE_BITS_TYPE(bits
) ==
1443 MACH_PORT_TYPE_SEND
);
1445 request
= ipc_right_request_cancel_macro(space
, port
,
1447 ipc_hash_delete(space
, (ipc_object_t
) port
,
1451 port_to_release
= port
;
1453 entry
->ie_object
= IO_NULL
;
1454 ipc_entry_dealloc(space
, name
, entry
);
1456 } else if (delta
!= 0) {
1458 entry
->ie_bits
= bits
+ delta
;
1459 ipc_entry_modified(space
, name
, entry
);
1464 is_write_unlock(space
);
1466 if (port_to_release
!= IP_NULL
) {
1467 ip_release(port_to_release
);
1470 if (nsrequest
!= IP_NULL
) {
1471 ipc_notify_no_senders(nsrequest
, mscount
);
1474 if (request
!= IP_NULL
) {
1475 ipc_notify_port_deleted(request
, name
);
1480 case MACH_PORT_RIGHT_LABELH
:
1484 panic("ipc_right_delta: strange right %d for 0x%x (%p) in space:%p",
1485 right
, name
, (void *)entry
, (void *)space
);
1488 return KERN_SUCCESS
;
1491 is_write_unlock(space
);
1492 return KERN_SUCCESS
;
1495 is_write_unlock(space
);
1496 if (port
!= IP_NULL
) {
1499 return KERN_INVALID_RIGHT
;
1502 is_write_unlock(space
);
1503 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
);
1504 return KERN_INVALID_VALUE
;
1507 return KERN_INVALID_RIGHT
;
1511 * Routine: ipc_right_destruct
1513 * Deallocates the receive right and modifies the
1514 * user-reference count for the send rights as requested.
1516 * The space is write-locked, and is unlocked upon return.
1517 * The space must be active.
1519 * KERN_SUCCESS Count was modified.
1520 * KERN_INVALID_RIGHT Entry has wrong type.
1521 * KERN_INVALID_VALUE Bad delta for the right.
1527 mach_port_name_t name
,
1529 mach_port_delta_t srdelta
,
1532 ipc_port_t port
= IP_NULL
;
1533 ipc_entry_bits_t bits
;
1535 mach_port_urefs_t urefs
;
1536 ipc_port_t request
= IP_NULL
;
1537 ipc_port_t nsrequest
= IP_NULL
;
1538 mach_port_mscount_t mscount
= 0;
1540 bits
= entry
->ie_bits
;
1542 assert(is_active(space
));
1544 if (((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) ||
1545 (srdelta
&& ((bits
& MACH_PORT_TYPE_SEND
) == 0))) {
1546 is_write_unlock(space
);
1547 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1548 return KERN_INVALID_RIGHT
;
1555 port
= (ipc_port_t
) entry
->ie_object
;
1556 assert(port
!= IP_NULL
);
1559 assert(ip_active(port
));
1560 assert(port
->ip_receiver_name
== name
);
1561 assert(port
->ip_receiver
== space
);
1563 /* Mach Port Guard Checking */
1564 if (port
->ip_guarded
&& (guard
!= port
->ip_context
)) {
1565 uint64_t portguard
= port
->ip_context
;
1567 is_write_unlock(space
);
1568 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
1569 return KERN_INVALID_ARGUMENT
;
1573 * First reduce the send rights as requested and
1574 * adjust the entry->ie_bits accordingly. The
1575 * ipc_entry_modified() call is made once the receive
1576 * right is destroyed too.
1580 assert(port
->ip_srights
> 0);
1582 urefs
= IE_BITS_UREFS(bits
);
1585 * Since we made sure that srdelta is negative,
1586 * the check for urefs overflow is not required.
1588 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, srdelta
)) {
1593 if (urefs
== MACH_PORT_UREFS_MAX
) {
1595 * urefs are pegged due to an overflow
1596 * only a delta removing all refs at once can change it
1598 if (srdelta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1603 if ((urefs
+ srdelta
) == 0) {
1604 if (--port
->ip_srights
== 0) {
1605 nsrequest
= port
->ip_nsrequest
;
1606 if (nsrequest
!= IP_NULL
) {
1607 port
->ip_nsrequest
= IP_NULL
;
1608 mscount
= port
->ip_mscount
;
1611 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_RECEIVE
);
1612 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1613 MACH_PORT_TYPE_SEND
);
1615 entry
->ie_bits
= bits
+ srdelta
;
1620 * Now destroy the receive right. Update space and
1621 * entry accordingly.
1624 bits
= entry
->ie_bits
;
1625 if (bits
& MACH_PORT_TYPE_SEND
) {
1626 assert(IE_BITS_UREFS(bits
) > 0);
1627 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
1629 if (port
->ip_pdrequest
!= NULL
) {
1631 * Since another task has requested a
1632 * destroy notification for this port, it
1633 * isn't actually being destroyed - the receive
1634 * right is just being moved to another task.
1635 * Since we still have one or more send rights,
1636 * we need to record the loss of the receive
1637 * right and enter the remaining send right
1638 * into the hash table.
1640 ipc_entry_modified(space
, name
, entry
);
1641 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1642 ipc_hash_insert(space
, (ipc_object_t
) port
,
1647 * The remaining send right turns into a
1648 * dead name. Notice we don't decrement
1649 * ip_srights, generate a no-senders notif,
1650 * or use ipc_right_dncancel, because the
1651 * port is destroyed "first".
1653 bits
&= ~IE_BITS_TYPE_MASK
;
1654 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1655 if (entry
->ie_request
) {
1656 entry
->ie_request
= IE_REQ_NONE
;
1657 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1658 bits
++; /* increment urefs */
1661 entry
->ie_bits
= bits
;
1662 entry
->ie_object
= IO_NULL
;
1663 ipc_entry_modified(space
, name
, entry
);
1666 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1667 assert(IE_BITS_UREFS(bits
) == 0);
1668 request
= ipc_right_request_cancel_macro(space
, port
,
1670 entry
->ie_object
= IO_NULL
;
1671 ipc_entry_dealloc(space
, name
, entry
);
1675 is_write_unlock(space
);
1677 if (nsrequest
!= IP_NULL
) {
1678 ipc_notify_no_senders(nsrequest
, mscount
);
1681 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1683 if (request
!= IP_NULL
) {
1684 ipc_notify_port_deleted(request
, name
);
1687 return KERN_SUCCESS
;
1690 is_write_unlock(space
);
1691 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
);
1692 return KERN_INVALID_VALUE
;
1697 * Routine: ipc_right_info
1699 * Retrieves information about the right.
1701 * The space is active and write-locked.
1702 * The space is unlocked upon return.
1704 * KERN_SUCCESS Retrieved info
1710 mach_port_name_t name
,
1712 mach_port_type_t
*typep
,
1713 mach_port_urefs_t
*urefsp
)
1716 ipc_entry_bits_t bits
;
1717 mach_port_type_t type
= 0;
1718 ipc_port_request_index_t request
;
1720 bits
= entry
->ie_bits
;
1721 request
= entry
->ie_request
;
1722 port
= (ipc_port_t
) entry
->ie_object
;
1724 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1725 assert(IP_VALID(port
));
1727 if (request
!= IE_REQ_NONE
) {
1729 assert(ip_active(port
));
1730 type
|= ipc_port_request_type(port
, name
, request
);
1733 is_write_unlock(space
);
1734 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1736 * validate port is still alive - if so, get request
1737 * types while we still have it locked. Otherwise,
1738 * recapture the (now dead) bits.
1740 if (!ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1741 if (request
!= IE_REQ_NONE
) {
1742 type
|= ipc_port_request_type(port
, name
, request
);
1745 is_write_unlock(space
);
1747 bits
= entry
->ie_bits
;
1748 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1749 is_write_unlock(space
);
1753 is_write_unlock(space
);
1756 type
|= IE_BITS_TYPE(bits
);
1759 *urefsp
= IE_BITS_UREFS(bits
);
1760 return KERN_SUCCESS
;
1764 * Routine: ipc_right_copyin_check
1766 * Check if a subsequent ipc_right_copyin would succeed.
1768 * The space is locked (read or write) and active.
1772 ipc_right_copyin_check(
1773 __assert_only ipc_space_t space
,
1774 __unused mach_port_name_t name
,
1776 mach_msg_type_name_t msgt_name
)
1778 ipc_entry_bits_t bits
;
1781 bits
= entry
->ie_bits
;
1782 assert(is_active(space
));
1784 switch (msgt_name
) {
1785 case MACH_MSG_TYPE_MAKE_SEND
:
1786 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1791 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1792 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1797 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1798 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1801 if (io_kotype(entry
->ie_object
) != IKOT_NONE
) {
1804 port
= (ipc_port_t
) entry
->ie_object
;
1805 if (port
->ip_specialreply
) {
1810 case MACH_MSG_TYPE_COPY_SEND
:
1811 case MACH_MSG_TYPE_MOVE_SEND
:
1812 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1813 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
1817 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
1821 port
= (ipc_port_t
) entry
->ie_object
;
1822 assert(port
!= IP_NULL
);
1825 * active status peek to avoid checks that will be skipped
1826 * on copyin for dead ports. Lock not held, so will not be
1827 * atomic (but once dead, there's no going back).
1829 if (!ip_active(port
)) {
1833 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1834 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1838 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1847 panic("ipc_right_copyin_check: strange rights");
1854 * Routine: ipc_right_copyin
1856 * Copyin a capability from a space.
1857 * If successful, the caller gets a ref
1858 * for the resulting object, unless it is IO_DEAD,
1859 * and possibly a send-once right which should
1860 * be used in a port-deleted notification.
1862 * If deadok is not TRUE, the copyin operation
1863 * will fail instead of producing IO_DEAD.
1865 * The entry is never deallocated (except
1866 * when KERN_INVALID_NAME), so the caller
1867 * should deallocate the entry if its type
1868 * is MACH_PORT_TYPE_NONE.
1870 * The space is write-locked and active.
1872 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1873 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1879 mach_port_name_t name
,
1881 mach_msg_type_name_t msgt_name
,
1882 ipc_right_copyin_flags_t flags
,
1883 ipc_object_t
*objectp
,
1884 ipc_port_t
*sorightp
,
1885 ipc_port_t
*releasep
,
1888 ipc_entry_bits_t bits
;
1891 *releasep
= IP_NULL
;
1893 boolean_t deadok
= (flags
& IPC_RIGHT_COPYIN_FLAGS_DEADOK
) ? TRUE
: FALSE
;
1895 bits
= entry
->ie_bits
;
1897 assert(is_active(space
));
1899 switch (msgt_name
) {
1900 case MACH_MSG_TYPE_MAKE_SEND
: {
1901 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1905 port
= (ipc_port_t
) entry
->ie_object
;
1906 assert(port
!= IP_NULL
);
1909 assert(ip_active(port
));
1910 assert(port
->ip_receiver_name
== name
);
1911 assert(port
->ip_receiver
== space
);
1918 *objectp
= (ipc_object_t
) port
;
1919 *sorightp
= IP_NULL
;
1923 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1924 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1928 port
= (ipc_port_t
) entry
->ie_object
;
1929 assert(port
!= IP_NULL
);
1932 assert(ip_active(port
));
1933 assert(port
->ip_receiver_name
== name
);
1934 assert(port
->ip_receiver
== space
);
1936 port
->ip_sorights
++;
1940 *objectp
= (ipc_object_t
) port
;
1941 *sorightp
= IP_NULL
;
1945 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1946 ipc_port_t request
= IP_NULL
;
1948 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1953 * Disallow moving receive-right kobjects, e.g. mk_timer ports
1954 * The ipc_port structure uses the kdata union of kobject and
1955 * imp_task exclusively. Thus, general use of a kobject port as
1956 * a receive right can cause type confusion in the importance
1959 if (io_kotype(entry
->ie_object
) != IKOT_NONE
) {
1961 * Distinguish an invalid right, e.g., trying to move
1962 * a send right as a receive right, from this
1963 * situation which is, "This is a valid receive right,
1964 * but it's also a kobject and you can't move it."
1966 return KERN_INVALID_CAPABILITY
;
1969 port
= (ipc_port_t
) entry
->ie_object
;
1970 assert(port
!= IP_NULL
);
1973 assert(ip_active(port
));
1974 assert(port
->ip_receiver_name
== name
);
1975 assert(port
->ip_receiver
== space
);
1977 if (bits
& MACH_PORT_TYPE_SEND
) {
1978 assert(IE_BITS_TYPE(bits
) ==
1979 MACH_PORT_TYPE_SEND_RECEIVE
);
1980 assert(IE_BITS_UREFS(bits
) > 0);
1981 assert(port
->ip_srights
> 0);
1983 ipc_hash_insert(space
, (ipc_object_t
) port
,
1987 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1988 assert(IE_BITS_UREFS(bits
) == 0);
1990 request
= ipc_right_request_cancel_macro(space
, port
,
1992 entry
->ie_object
= IO_NULL
;
1994 entry
->ie_bits
= bits
& ~MACH_PORT_TYPE_RECEIVE
;
1995 ipc_entry_modified(space
, name
, entry
);
1997 (void)ipc_port_clear_receiver(port
, FALSE
); /* don't destroy the port/mqueue */
1999 #if IMPORTANCE_INHERITANCE
2001 * Account for boosts the current task is going to lose when
2002 * copying this right in. Tempowner ports have either not
2003 * been accounting to any task (and therefore are already in
2004 * "limbo" state w.r.t. assertions) or to some other specific
2005 * task. As we have no way to drop the latter task's assertions
2006 * here, We'll deduct those when we enqueue it on its
2007 * destination port (see ipc_port_check_circularity()).
2009 if (port
->ip_tempowner
== 0) {
2010 assert(IIT_NULL
== port
->ip_imp_task
);
2012 /* ports in limbo have to be tempowner */
2013 port
->ip_tempowner
= 1;
2014 *assertcntp
= port
->ip_impcount
;
2016 #endif /* IMPORTANCE_INHERITANCE */
2020 *objectp
= (ipc_object_t
) port
;
2021 *sorightp
= request
;
2025 case MACH_MSG_TYPE_COPY_SEND
: {
2026 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2030 /* allow for dead send-once rights */
2032 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2036 assert(IE_BITS_UREFS(bits
) > 0);
2038 port
= (ipc_port_t
) entry
->ie_object
;
2039 assert(port
!= IP_NULL
);
2041 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
2042 bits
= entry
->ie_bits
;
2046 /* port is locked and active */
2048 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2049 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2050 assert(port
->ip_sorights
> 0);
2056 assert(port
->ip_srights
> 0);
2062 *objectp
= (ipc_object_t
) port
;
2063 *sorightp
= IP_NULL
;
2067 case MACH_MSG_TYPE_MOVE_SEND
: {
2068 ipc_port_t request
= IP_NULL
;
2070 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2074 /* allow for dead send-once rights */
2076 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2080 assert(IE_BITS_UREFS(bits
) > 0);
2082 port
= (ipc_port_t
) entry
->ie_object
;
2083 assert(port
!= IP_NULL
);
2085 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
2086 bits
= entry
->ie_bits
;
2090 /* port is locked and active */
2092 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2093 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2094 assert(port
->ip_sorights
> 0);
2100 assert(port
->ip_srights
> 0);
2102 if (IE_BITS_UREFS(bits
) == 1) {
2103 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2104 assert(port
->ip_receiver_name
== name
);
2105 assert(port
->ip_receiver
== space
);
2106 assert(IE_BITS_TYPE(bits
) ==
2107 MACH_PORT_TYPE_SEND_RECEIVE
);
2111 assert(IE_BITS_TYPE(bits
) ==
2112 MACH_PORT_TYPE_SEND
);
2114 request
= ipc_right_request_cancel_macro(space
, port
,
2116 ipc_hash_delete(space
, (ipc_object_t
) port
,
2118 entry
->ie_object
= IO_NULL
;
2119 /* transfer entry's reference to caller */
2121 entry
->ie_bits
= bits
& ~
2122 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND
);
2126 /* if urefs are pegged due to overflow, leave them pegged */
2127 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2128 entry
->ie_bits
= bits
- 1; /* decrement urefs */
2132 ipc_entry_modified(space
, name
, entry
);
2135 *objectp
= (ipc_object_t
) port
;
2136 *sorightp
= request
;
2140 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
2143 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2147 /* allow for dead send rights */
2149 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2153 assert(IE_BITS_UREFS(bits
) > 0);
2155 port
= (ipc_port_t
) entry
->ie_object
;
2156 assert(port
!= IP_NULL
);
2158 if (ipc_right_check(space
, port
, name
, entry
, flags
)) {
2159 bits
= entry
->ie_bits
;
2164 * port is locked, but may not be active:
2165 * Allow copyin of inactive ports with no dead name request and treat it
2166 * as if the copyin of the port was successful and port became inactive
2170 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
2171 assert(bits
& MACH_PORT_TYPE_SEND
);
2172 assert(port
->ip_srights
> 0);
2178 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2179 assert(IE_BITS_UREFS(bits
) == 1);
2180 assert(port
->ip_sorights
> 0);
2182 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
2185 entry
->ie_object
= IO_NULL
;
2186 entry
->ie_bits
= bits
& ~
2187 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
2188 ipc_entry_modified(space
, name
, entry
);
2189 *objectp
= (ipc_object_t
) port
;
2190 *sorightp
= request
;
2196 return KERN_INVALID_RIGHT
;
2199 return KERN_SUCCESS
;
2202 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2203 assert(IE_BITS_UREFS(bits
) > 0);
2204 assert(entry
->ie_request
== IE_REQ_NONE
);
2205 assert(entry
->ie_object
== 0);
2212 *sorightp
= IP_NULL
;
2213 return KERN_SUCCESS
;
2216 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2217 assert(IE_BITS_UREFS(bits
) > 0);
2218 assert(entry
->ie_request
== IE_REQ_NONE
);
2219 assert(entry
->ie_object
== 0);
2225 if (IE_BITS_UREFS(bits
) == 1) {
2226 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
2228 /* if urefs are pegged due to overflow, leave them pegged */
2229 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2230 entry
->ie_bits
= bits
- 1; /* decrement urefs */
2232 ipc_entry_modified(space
, name
, entry
);
2234 *sorightp
= IP_NULL
;
2235 return KERN_SUCCESS
;
2239 * Routine: ipc_right_copyin_undo
2241 * Undoes the effects of an ipc_right_copyin
2242 * of a send/send-once right that is dead.
2243 * (Object is either IO_DEAD or a dead port.)
2245 * The space is write-locked and active.
2249 ipc_right_copyin_undo(
2251 mach_port_name_t name
,
2253 mach_msg_type_name_t msgt_name
,
2254 ipc_object_t object
,
2257 ipc_entry_bits_t bits
;
2259 bits
= entry
->ie_bits
;
2261 assert(is_active(space
));
2263 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2264 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
2265 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2267 if (soright
!= IP_NULL
) {
2268 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2269 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2270 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2271 assert(object
!= IO_DEAD
);
2273 entry
->ie_bits
= ((bits
& ~IE_BITS_RIGHT_MASK
) |
2274 MACH_PORT_TYPE_DEAD_NAME
| 2);
2275 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
2276 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2277 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2279 entry
->ie_bits
= ((bits
& ~IE_BITS_RIGHT_MASK
) |
2280 MACH_PORT_TYPE_DEAD_NAME
| 1);
2281 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
2282 assert(object
== IO_DEAD
);
2283 assert(IE_BITS_UREFS(bits
) > 0);
2285 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2286 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
2287 /* if urefs are pegged due to overflow, leave them pegged */
2288 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2289 entry
->ie_bits
= bits
+ 1; /* increment urefs */
2293 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2294 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
2295 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2296 assert(object
!= IO_DEAD
);
2297 assert(entry
->ie_object
== object
);
2298 assert(IE_BITS_UREFS(bits
) > 0);
2300 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2301 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
2302 /* if urefs are pegged due to overflow, leave them pegged */
2303 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2304 entry
->ie_bits
= bits
+ 1; /* increment urefs */
2309 * May as well convert the entry to a dead name.
2310 * (Or if it is a compat entry, destroy it.)
2313 (void) ipc_right_check(space
, (ipc_port_t
) object
,
2314 name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
);
2315 /* object is dead so it is not locked */
2317 ipc_entry_modified(space
, name
, entry
);
2318 /* release the reference acquired by copyin */
2320 if (object
!= IO_DEAD
) {
2326 * Routine: ipc_right_copyin_two_move_sends
2328 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
2329 * and deadok == FALSE, except that this moves two
2330 * send rights at once.
2332 * The space is write-locked and active.
2333 * The object is returned with two refs/send rights.
2335 * KERN_SUCCESS Acquired an object.
2336 * KERN_INVALID_RIGHT Name doesn't denote correct right.
2340 ipc_right_copyin_two_move_sends(
2342 mach_port_name_t name
,
2344 ipc_object_t
*objectp
,
2345 ipc_port_t
*sorightp
,
2346 ipc_port_t
*releasep
)
2348 ipc_entry_bits_t bits
;
2349 mach_port_urefs_t urefs
;
2351 ipc_port_t request
= IP_NULL
;
2353 *releasep
= IP_NULL
;
2355 assert(is_active(space
));
2357 bits
= entry
->ie_bits
;
2359 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2363 urefs
= IE_BITS_UREFS(bits
);
2368 port
= (ipc_port_t
) entry
->ie_object
;
2369 assert(port
!= IP_NULL
);
2371 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
2375 /* port is locked and active */
2377 assert(port
->ip_srights
> 0);
2380 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2381 assert(port
->ip_receiver_name
== name
);
2382 assert(port
->ip_receiver
== space
);
2383 assert(IE_BITS_TYPE(bits
) ==
2384 MACH_PORT_TYPE_SEND_RECEIVE
);
2390 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2392 request
= ipc_right_request_cancel_macro(space
, port
,
2397 ipc_hash_delete(space
, (ipc_object_t
) port
,
2399 entry
->ie_object
= IO_NULL
;
2401 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND
);
2403 port
->ip_srights
+= 2;
2406 /* if urefs are pegged due to overflow, leave them pegged */
2407 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2408 entry
->ie_bits
= bits
- 2; /* decrement urefs */
2411 ipc_entry_modified(space
, name
, entry
);
2415 *objectp
= (ipc_object_t
) port
;
2416 *sorightp
= request
;
2417 return KERN_SUCCESS
;
2420 return KERN_INVALID_RIGHT
;
2425 * Routine: ipc_right_copyin_two
2427 * Like ipc_right_copyin with two dispositions,
2428 * each of which results in a send or send-once right,
2429 * and deadok = FALSE.
2431 * The space is write-locked and active.
2432 * The object is returned with two refs/rights.
2434 * KERN_SUCCESS Acquired an object.
2435 * KERN_INVALID_RIGHT Name doesn't denote correct right(s).
2436 * KERN_INVALID_CAPABILITY Name doesn't denote correct right for msgt_two.
2439 ipc_right_copyin_two(
2441 mach_port_name_t name
,
2443 mach_msg_type_name_t msgt_one
,
2444 mach_msg_type_name_t msgt_two
,
2445 ipc_object_t
*objectp
,
2446 ipc_port_t
*sorightp
,
2447 ipc_port_t
*releasep
)
2452 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one
));
2453 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two
));
2457 * Pre-validate the second disposition is possible all by itself.
2459 if (!ipc_right_copyin_check(space
, name
, entry
, msgt_two
)) {
2460 return KERN_INVALID_CAPABILITY
;
2464 * This is a little tedious to make atomic, because
2465 * there are 25 combinations of valid dispositions.
2466 * However, most are easy.
2470 * If either is move-sonce, then there must be an error.
2472 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND_ONCE
||
2473 msgt_two
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
2474 return KERN_INVALID_RIGHT
;
2477 if ((msgt_one
== MACH_MSG_TYPE_MAKE_SEND
) ||
2478 (msgt_one
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) ||
2479 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND
) ||
2480 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) {
2482 * One of the dispositions needs a receive right.
2484 * If the copyin below succeeds, we know the receive
2485 * right is there (because the pre-validation of
2486 * the second disposition already succeeded in our
2489 * Hence the port is not in danger of dying.
2491 ipc_object_t object_two
;
2493 kr
= ipc_right_copyin(space
, name
, entry
,
2494 msgt_one
, IPC_RIGHT_COPYIN_FLAGS_NONE
,
2495 objectp
, sorightp
, releasep
,
2497 assert(assertcnt
== 0);
2498 if (kr
!= KERN_SUCCESS
) {
2502 assert(IO_VALID(*objectp
));
2503 assert(*sorightp
== IP_NULL
);
2504 assert(*releasep
== IP_NULL
);
2507 * Now copyin the second (previously validated)
2508 * disposition. The result can't be a dead port,
2509 * as no valid disposition can make us lose our
2512 kr
= ipc_right_copyin(space
, name
, entry
,
2513 msgt_two
, IPC_RIGHT_COPYIN_FLAGS_NONE
,
2514 &object_two
, sorightp
, releasep
,
2516 assert(assertcnt
== 0);
2517 assert(kr
== KERN_SUCCESS
);
2518 assert(*sorightp
== IP_NULL
);
2519 assert(*releasep
== IP_NULL
);
2520 assert(object_two
== *objectp
);
2521 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
2522 } else if ((msgt_one
== MACH_MSG_TYPE_MOVE_SEND
) &&
2523 (msgt_two
== MACH_MSG_TYPE_MOVE_SEND
)) {
2525 * This is an easy case. Just use our
2526 * handy-dandy special-purpose copyin call
2527 * to get two send rights for the price of one.
2529 kr
= ipc_right_copyin_two_move_sends(space
, name
, entry
,
2532 if (kr
!= KERN_SUCCESS
) {
2536 mach_msg_type_name_t msgt_name
;
2539 * Must be either a single move-send and a
2540 * copy-send, or two copy-send dispositions.
2541 * Use the disposition with the greatest side
2542 * effects for the actual copyin - then just
2543 * duplicate the send right you get back.
2545 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND
||
2546 msgt_two
== MACH_MSG_TYPE_MOVE_SEND
) {
2547 msgt_name
= MACH_MSG_TYPE_MOVE_SEND
;
2549 msgt_name
= MACH_MSG_TYPE_COPY_SEND
;
2552 kr
= ipc_right_copyin(space
, name
, entry
,
2553 msgt_name
, IPC_RIGHT_COPYIN_FLAGS_NONE
,
2554 objectp
, sorightp
, releasep
,
2556 assert(assertcnt
== 0);
2557 if (kr
!= KERN_SUCCESS
) {
2562 * Copy the right we got back. If it is dead now,
2563 * that's OK. Neither right will be usable to send
2566 (void)ipc_port_copy_send((ipc_port_t
)*objectp
);
2569 return KERN_SUCCESS
;
2574 * Routine: ipc_right_copyout
2576 * Copyout a capability to a space.
2577 * If successful, consumes a ref for the object.
2579 * Always succeeds when given a newly-allocated entry,
2580 * because user-reference overflow isn't a possibility.
2582 * If copying out the object would cause the user-reference
2583 * count in the entry to overflow, and overflow is TRUE,
2584 * then instead the user-reference count is left pegged
2585 * to its maximum value and the copyout succeeds anyway.
2587 * The space is write-locked and active.
2588 * The object is locked and active.
2589 * The object is unlocked; the space isn't.
2591 * KERN_SUCCESS Copied out capability.
2597 mach_port_name_t name
,
2599 mach_msg_type_name_t msgt_name
,
2600 __unused boolean_t overflow
,
2601 ipc_object_t object
)
2603 ipc_entry_bits_t bits
;
2606 bits
= entry
->ie_bits
;
2608 assert(IO_VALID(object
));
2609 assert(io_otype(object
) == IOT_PORT
);
2610 assert(io_active(object
));
2611 assert(entry
->ie_object
== object
);
2613 port
= (ipc_port_t
) object
;
2615 switch (msgt_name
) {
2616 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
2618 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2619 assert(IE_BITS_UREFS(bits
) == 0);
2620 assert(port
->ip_sorights
> 0);
2622 if (port
->ip_specialreply
) {
2623 ipc_port_adjust_special_reply_port_locked(port
,
2624 current_thread()->ith_knote
, IPC_PORT_ADJUST_SR_LINK_WORKLOOP
, FALSE
);
2625 /* port unlocked on return */
2630 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1); /* set urefs to 1 */
2631 ipc_entry_modified(space
, name
, entry
);
2634 case MACH_MSG_TYPE_PORT_SEND
:
2635 assert(port
->ip_srights
> 0);
2637 if (bits
& MACH_PORT_TYPE_SEND
) {
2638 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
2640 assert(port
->ip_srights
> 1);
2642 assert(urefs
<= MACH_PORT_UREFS_MAX
);
2644 if (urefs
== MACH_PORT_UREFS_MAX
) {
2646 * leave urefs pegged to maximum,
2647 * consume send right and ref
2653 return KERN_SUCCESS
;
2656 /* consume send right and ref */
2660 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2661 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2662 assert(IE_BITS_UREFS(bits
) == 0);
2664 /* transfer send right to entry, consume ref */
2668 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2669 assert(IE_BITS_UREFS(bits
) == 0);
2671 /* transfer send right and ref to entry */
2674 /* entry is locked holding ref, so can use port */
2676 ipc_hash_insert(space
, (ipc_object_t
) port
,
2680 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1; /* increment urefs */
2681 ipc_entry_modified(space
, name
, entry
);
2684 case MACH_MSG_TYPE_PORT_RECEIVE
: {
2686 turnstile_inheritor_t inheritor
= TURNSTILE_INHERITOR_NULL
;
2687 struct turnstile
*ts
= TURNSTILE_NULL
;
2689 #if IMPORTANCE_INHERITANCE
2690 natural_t assertcnt
= port
->ip_impcount
;
2691 #endif /* IMPORTANCE_INHERITANCE */
2693 assert(port
->ip_mscount
== 0);
2694 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
2696 imq_lock(&port
->ip_messages
);
2697 dest
= port
->ip_destination
;
2699 port
->ip_receiver_name
= name
;
2700 port
->ip_receiver
= space
;
2702 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
2704 /* Update the port's turnstile linkage to WL turnstile */
2705 ts
= port_send_turnstile(port
);
2707 struct knote
*kn
= current_thread()->ith_knote
;
2708 if (ITH_KNOTE_VALID(kn
, MACH_MSG_TYPE_PORT_RECEIVE
)) {
2709 inheritor
= filt_machport_stash_port(kn
, port
, NULL
);
2711 turnstile_reference(inheritor
);
2712 IMQ_SET_INHERITOR(&port
->ip_messages
, inheritor
);
2715 turnstile_reference(ts
);
2716 turnstile_update_inheritor(ts
, inheritor
,
2717 (TURNSTILE_IMMEDIATE_UPDATE
| TURNSTILE_INHERITOR_TURNSTILE
));
2720 imq_unlock(&port
->ip_messages
);
2722 if (bits
& MACH_PORT_TYPE_SEND
) {
2723 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2724 assert(IE_BITS_UREFS(bits
) > 0);
2725 assert(port
->ip_srights
> 0);
2730 /* entry is locked holding ref, so can use port */
2731 ipc_hash_delete(space
, (ipc_object_t
) port
, name
, entry
);
2733 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2734 assert(IE_BITS_UREFS(bits
) == 0);
2736 /* transfer ref to entry */
2739 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2740 ipc_entry_modified(space
, name
, entry
);
2743 turnstile_update_inheritor_complete(ts
, TURNSTILE_INTERLOCK_NOT_HELD
);
2744 turnstile_deallocate_safe(ts
);
2747 if (dest
!= IP_NULL
) {
2748 #if IMPORTANCE_INHERITANCE
2750 * Deduct the assertion counts we contributed to
2751 * the old destination port. They've already
2752 * been reflected into the task as a result of
2756 ipc_port_impcount_delta(dest
, 0 - assertcnt
, IP_NULL
);
2758 #endif /* IMPORTANCE_INHERITANCE */
2760 /* Drop turnstile ref on dest */
2761 ipc_port_send_turnstile_complete(dest
);
2768 panic("ipc_right_copyout: strange rights");
2770 return KERN_SUCCESS
;
2774 * Routine: ipc_right_rename
2776 * Transfer an entry from one name to another.
2777 * The old entry is deallocated.
2779 * The space is write-locked and active.
2780 * The new entry is unused. Upon return,
2781 * the space is unlocked.
2783 * KERN_SUCCESS Moved entry to new name.
2789 mach_port_name_t oname
,
2791 mach_port_name_t nname
,
2794 ipc_port_request_index_t request
= oentry
->ie_request
;
2795 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2796 ipc_object_t object
= oentry
->ie_object
;
2797 ipc_port_t release_port
= IP_NULL
;
2799 assert(is_active(space
));
2800 assert(oname
!= nname
);
2803 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2804 * if the port is dead. (This would foil ipc_port_destroy.)
2805 * Instead we should fail because oentry shouldn't exist.
2806 * Note IE_BITS_COMPAT implies ie_request != 0.
2809 if (request
!= IE_REQ_NONE
) {
2812 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2813 port
= (ipc_port_t
) object
;
2814 assert(port
!= IP_NULL
);
2816 if (ipc_right_check(space
, port
, oname
, oentry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
2817 request
= IE_REQ_NONE
;
2819 bits
= oentry
->ie_bits
;
2820 release_port
= port
;
2821 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2822 assert(oentry
->ie_request
== IE_REQ_NONE
);
2824 /* port is locked and active */
2826 ipc_port_request_rename(port
, request
, oname
, nname
);
2828 oentry
->ie_request
= IE_REQ_NONE
;
2832 /* initialize nentry before letting ipc_hash_insert see it */
2834 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2835 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2836 nentry
->ie_request
= request
;
2837 nentry
->ie_object
= object
;
2839 switch (IE_BITS_TYPE(bits
)) {
2840 case MACH_PORT_TYPE_SEND
: {
2843 port
= (ipc_port_t
) object
;
2844 assert(port
!= IP_NULL
);
2846 /* remember, there are no other share entries possible */
2847 /* or we can't do the rename. Therefore we do not need */
2848 /* to check the other subspaces */
2849 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2850 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2854 case MACH_PORT_TYPE_RECEIVE
:
2855 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2858 port
= (ipc_port_t
) object
;
2859 assert(port
!= IP_NULL
);
2862 imq_lock(&port
->ip_messages
);
2863 assert(ip_active(port
));
2864 assert(port
->ip_receiver_name
== oname
);
2865 assert(port
->ip_receiver
== space
);
2867 port
->ip_receiver_name
= nname
;
2868 imq_unlock(&port
->ip_messages
);
2873 case MACH_PORT_TYPE_PORT_SET
: {
2876 pset
= (ipc_pset_t
) object
;
2877 assert(pset
!= IPS_NULL
);
2880 assert(ips_active(pset
));
2886 case MACH_PORT_TYPE_SEND_ONCE
:
2887 case MACH_PORT_TYPE_DEAD_NAME
:
2891 panic("ipc_right_rename: strange rights");
2894 assert(oentry
->ie_request
== IE_REQ_NONE
);
2895 oentry
->ie_object
= IO_NULL
;
2896 ipc_entry_dealloc(space
, oname
, oentry
);
2897 ipc_entry_modified(space
, nname
, nentry
);
2898 is_write_unlock(space
);
2900 if (release_port
!= IP_NULL
) {
2901 ip_release(release_port
);
2904 return KERN_SUCCESS
;