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
= ip_object_to_port(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
== ip_object_to_port(entry
->ie_object
));
231 if (ipc_hash_lookup(space
, ip_to_object(port
), namep
, entryp
)) {
232 assert((entry
= *entryp
) != IE_NULL
);
233 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
234 assert(port
== ip_object_to_port(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
= ip_object_to_port(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 require_ip_active(port
);
452 assert(port
== ip_object_to_port(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
== ip_object_to_port(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
, ip_to_object(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
= ips_object_to_pset(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
= ip_object_to_port(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);
676 port
->ip_reply_context
= 0;
679 ipc_notify_send_once(port
); /* consumes our ref */
681 assert(port
->ip_receiver
!= space
);
687 if (nsrequest
!= IP_NULL
) {
688 ipc_notify_no_senders(nsrequest
, mscount
);
691 if (request
!= IP_NULL
) {
692 ipc_notify_port_deleted(request
, name
);
698 panic("ipc_right_terminate: strange type - 0x%x", type
);
703 * Routine: ipc_right_destroy
705 * Destroys an entry in a space.
707 * The space is write-locked (returns unlocked).
708 * The space must be active.
710 * KERN_SUCCESS The entry was destroyed.
716 mach_port_name_t name
,
718 boolean_t check_guard
,
721 ipc_entry_bits_t bits
;
722 mach_port_type_t type
;
724 bits
= entry
->ie_bits
;
725 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
726 type
= IE_BITS_TYPE(bits
);
728 assert(is_active(space
));
731 case MACH_PORT_TYPE_DEAD_NAME
:
732 assert(entry
->ie_request
== IE_REQ_NONE
);
733 assert(entry
->ie_object
== IO_NULL
);
735 ipc_entry_dealloc(space
, name
, entry
);
736 is_write_unlock(space
);
739 case MACH_PORT_TYPE_PORT_SET
: {
740 ipc_pset_t pset
= ips_object_to_pset(entry
->ie_object
);
742 assert(entry
->ie_request
== IE_REQ_NONE
);
743 assert(pset
!= IPS_NULL
);
745 entry
->ie_object
= IO_NULL
;
746 ipc_entry_dealloc(space
, name
, entry
);
749 is_write_unlock(space
);
751 assert(ips_active(pset
));
752 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
756 case MACH_PORT_TYPE_SEND
:
757 case MACH_PORT_TYPE_RECEIVE
:
758 case MACH_PORT_TYPE_SEND_RECEIVE
:
759 case MACH_PORT_TYPE_SEND_ONCE
: {
760 ipc_port_t port
= ip_object_to_port(entry
->ie_object
);
761 ipc_port_t nsrequest
= IP_NULL
;
762 mach_port_mscount_t mscount
= 0;
765 assert(port
!= IP_NULL
);
767 if (type
== MACH_PORT_TYPE_SEND
) {
768 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
);
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 require_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);
822 port
->ip_reply_context
= 0;
825 ipc_notify_send_once(port
); /* consumes our ref */
827 assert(port
->ip_receiver
!= space
);
833 if (nsrequest
!= IP_NULL
) {
834 ipc_notify_no_senders(nsrequest
, mscount
);
837 if (request
!= IP_NULL
) {
838 ipc_notify_port_deleted(request
, name
);
846 panic("ipc_right_destroy: strange type");
853 * Routine: ipc_right_dealloc
855 * Releases a send/send-once/dead-name/port_set user ref.
856 * Like ipc_right_delta with a delta of -1,
857 * but looks at the entry to determine the right.
859 * The space is write-locked, and is unlocked upon return.
860 * The space must be active.
862 * KERN_SUCCESS A user ref was released.
863 * KERN_INVALID_RIGHT Entry has wrong type.
869 mach_port_name_t name
,
872 ipc_port_t port
= IP_NULL
;
873 ipc_entry_bits_t bits
;
874 mach_port_type_t type
;
876 bits
= entry
->ie_bits
;
877 type
= IE_BITS_TYPE(bits
);
880 assert(is_active(space
));
883 case MACH_PORT_TYPE_PORT_SET
: {
886 assert(IE_BITS_UREFS(bits
) == 0);
887 assert(entry
->ie_request
== IE_REQ_NONE
);
889 pset
= ips_object_to_pset(entry
->ie_object
);
890 assert(pset
!= IPS_NULL
);
892 entry
->ie_object
= IO_NULL
;
893 ipc_entry_dealloc(space
, name
, entry
);
896 assert(ips_active(pset
));
897 is_write_unlock(space
);
899 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
903 case MACH_PORT_TYPE_DEAD_NAME
: {
906 assert(IE_BITS_UREFS(bits
) > 0);
907 assert(entry
->ie_request
== IE_REQ_NONE
);
908 assert(entry
->ie_object
== IO_NULL
);
910 if (IE_BITS_UREFS(bits
) == 1) {
911 ipc_entry_dealloc(space
, name
, entry
);
913 /* if urefs are pegged due to overflow, leave them pegged */
914 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
915 entry
->ie_bits
= bits
- 1; /* decrement urefs */
917 ipc_entry_modified(space
, name
, entry
);
919 is_write_unlock(space
);
921 /* release any port that got converted to dead name below */
922 if (port
!= IP_NULL
) {
928 case MACH_PORT_TYPE_SEND_ONCE
: {
931 assert(IE_BITS_UREFS(bits
) == 1);
933 port
= ip_object_to_port(entry
->ie_object
);
934 assert(port
!= IP_NULL
);
936 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
937 bits
= entry
->ie_bits
;
938 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
939 goto dead_name
; /* it will release port */
941 /* port is locked and active */
943 assert(port
->ip_sorights
> 0);
946 * clear any reply context:
947 * no one will be sending the response b/c we are destroying
948 * the single, outstanding send once right.
950 port
->ip_reply_context
= 0;
952 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
955 entry
->ie_object
= IO_NULL
;
956 ipc_entry_dealloc(space
, name
, entry
);
958 is_write_unlock(space
);
960 ipc_notify_send_once(port
);
962 if (request
!= IP_NULL
) {
963 ipc_notify_port_deleted(request
, name
);
968 case MACH_PORT_TYPE_SEND
: {
969 ipc_port_t request
= IP_NULL
;
970 ipc_port_t nsrequest
= IP_NULL
;
971 mach_port_mscount_t mscount
= 0;
974 assert(IE_BITS_UREFS(bits
) > 0);
976 port
= ip_object_to_port(entry
->ie_object
);
977 assert(port
!= IP_NULL
);
979 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
980 bits
= entry
->ie_bits
;
981 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
982 goto dead_name
; /* it will release port */
984 /* port is locked and active */
986 assert(port
->ip_srights
> 0);
988 if (IE_BITS_UREFS(bits
) == 1) {
989 if (--port
->ip_srights
== 0) {
990 nsrequest
= port
->ip_nsrequest
;
991 if (nsrequest
!= IP_NULL
) {
992 port
->ip_nsrequest
= IP_NULL
;
993 mscount
= port
->ip_mscount
;
997 request
= ipc_right_request_cancel_macro(space
, port
,
999 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
);
1002 entry
->ie_object
= IO_NULL
;
1003 ipc_entry_dealloc(space
, name
, entry
);
1004 is_write_unlock(space
);
1008 /* if urefs are pegged due to overflow, leave them pegged */
1009 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1010 entry
->ie_bits
= bits
- 1; /* decrement urefs */
1012 ipc_entry_modified(space
, name
, entry
);
1013 is_write_unlock(space
);
1016 if (nsrequest
!= IP_NULL
) {
1017 ipc_notify_no_senders(nsrequest
, mscount
);
1020 if (request
!= IP_NULL
) {
1021 ipc_notify_port_deleted(request
, name
);
1026 case MACH_PORT_TYPE_SEND_RECEIVE
: {
1027 ipc_port_t nsrequest
= IP_NULL
;
1028 mach_port_mscount_t mscount
= 0;
1030 assert(IE_BITS_UREFS(bits
) > 0);
1032 port
= ip_object_to_port(entry
->ie_object
);
1033 assert(port
!= IP_NULL
);
1036 require_ip_active(port
);
1037 assert(port
->ip_receiver_name
== name
);
1038 assert(port
->ip_receiver
== space
);
1039 assert(port
->ip_srights
> 0);
1041 if (IE_BITS_UREFS(bits
) == 1) {
1042 if (--port
->ip_srights
== 0) {
1043 nsrequest
= port
->ip_nsrequest
;
1044 if (nsrequest
!= IP_NULL
) {
1045 port
->ip_nsrequest
= IP_NULL
;
1046 mscount
= port
->ip_mscount
;
1050 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1051 MACH_PORT_TYPE_SEND
);
1053 /* if urefs are pegged due to overflow, leave them pegged */
1054 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1055 entry
->ie_bits
= bits
- 1; /* decrement urefs */
1060 ipc_entry_modified(space
, name
, entry
);
1061 is_write_unlock(space
);
1063 if (nsrequest
!= IP_NULL
) {
1064 ipc_notify_no_senders(nsrequest
, mscount
);
1070 is_write_unlock(space
);
1071 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1072 return KERN_INVALID_RIGHT
;
1075 return KERN_SUCCESS
;
1079 * Routine: ipc_right_delta
1081 * Modifies the user-reference count for a right.
1082 * May deallocate the right, if the count goes to zero.
1084 * The space is write-locked, and is unlocked upon return.
1085 * The space must be active.
1087 * KERN_SUCCESS Count was modified.
1088 * KERN_INVALID_RIGHT Entry has wrong type.
1089 * KERN_INVALID_VALUE Bad delta for the right.
1095 mach_port_name_t name
,
1097 mach_port_right_t right
,
1098 mach_port_delta_t delta
)
1100 ipc_port_t port
= IP_NULL
;
1101 ipc_entry_bits_t bits
;
1103 bits
= entry
->ie_bits
;
1106 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
1107 * switch below. It is used to keep track of those cases (in DIPC)
1108 * where we have postponed the dropping of a port reference. Since
1109 * the dropping of the reference could cause the port to disappear
1110 * we postpone doing so when we are holding the space lock.
1113 assert(is_active(space
));
1114 assert(right
< MACH_PORT_RIGHT_NUMBER
);
1116 /* Rights-specific restrictions and operations. */
1119 case MACH_PORT_RIGHT_PORT_SET
: {
1122 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1123 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1127 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
1128 assert(IE_BITS_UREFS(bits
) == 0);
1129 assert(entry
->ie_request
== IE_REQ_NONE
);
1139 pset
= ips_object_to_pset(entry
->ie_object
);
1140 assert(pset
!= IPS_NULL
);
1142 entry
->ie_object
= IO_NULL
;
1143 ipc_entry_dealloc(space
, name
, entry
);
1146 assert(ips_active(pset
));
1147 is_write_unlock(space
);
1149 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */
1153 case MACH_PORT_RIGHT_RECEIVE
: {
1154 ipc_port_t request
= IP_NULL
;
1156 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1157 if ((bits
& MACH_PORT_TYPE_EX_RECEIVE
) == 0) {
1158 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1171 port
= ip_object_to_port(entry
->ie_object
);
1172 assert(port
!= IP_NULL
);
1175 * The port lock is needed for ipc_right_dncancel;
1176 * otherwise, we wouldn't have to take the lock
1177 * until just before dropping the space lock.
1181 require_ip_active(port
);
1182 assert(port
->ip_receiver_name
== name
);
1183 assert(port
->ip_receiver
== space
);
1185 /* Mach Port Guard Checking */
1186 if (port
->ip_guarded
) {
1187 uint64_t portguard
= port
->ip_context
;
1189 is_write_unlock(space
);
1190 /* Raise mach port guard exception */
1191 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_MOD_REFS
);
1195 if (bits
& MACH_PORT_TYPE_SEND
) {
1196 assert(IE_BITS_TYPE(bits
) ==
1197 MACH_PORT_TYPE_SEND_RECEIVE
);
1198 assert(IE_BITS_UREFS(bits
) > 0);
1199 assert(port
->ip_srights
> 0);
1201 if (port
->ip_pdrequest
!= NULL
) {
1203 * Since another task has requested a
1204 * destroy notification for this port, it
1205 * isn't actually being destroyed - the receive
1206 * right is just being moved to another task.
1207 * Since we still have one or more send rights,
1208 * we need to record the loss of the receive
1209 * right and enter the remaining send right
1210 * into the hash table.
1212 ipc_entry_modified(space
, name
, entry
);
1213 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1214 entry
->ie_bits
|= MACH_PORT_TYPE_EX_RECEIVE
;
1215 ipc_hash_insert(space
, ip_to_object(port
),
1220 * The remaining send right turns into a
1221 * dead name. Notice we don't decrement
1222 * ip_srights, generate a no-senders notif,
1223 * or use ipc_right_dncancel, because the
1224 * port is destroyed "first".
1226 bits
&= ~IE_BITS_TYPE_MASK
;
1227 bits
|= (MACH_PORT_TYPE_DEAD_NAME
| MACH_PORT_TYPE_EX_RECEIVE
);
1228 if (entry
->ie_request
) {
1229 entry
->ie_request
= IE_REQ_NONE
;
1230 /* if urefs are pegged due to overflow, leave them pegged */
1231 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1232 bits
++; /* increment urefs */
1235 entry
->ie_bits
= bits
;
1236 entry
->ie_object
= IO_NULL
;
1237 ipc_entry_modified(space
, name
, entry
);
1240 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1241 assert(IE_BITS_UREFS(bits
) == 0);
1243 request
= ipc_right_request_cancel_macro(space
, port
,
1245 entry
->ie_object
= IO_NULL
;
1246 ipc_entry_dealloc(space
, name
, entry
);
1248 is_write_unlock(space
);
1250 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1252 if (request
!= IP_NULL
) {
1253 ipc_notify_port_deleted(request
, name
);
1258 case MACH_PORT_RIGHT_SEND_ONCE
: {
1261 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1265 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1266 assert(IE_BITS_UREFS(bits
) == 1);
1268 port
= ip_object_to_port(entry
->ie_object
);
1269 assert(port
!= IP_NULL
);
1271 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1272 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1273 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1276 /* port is locked and active */
1278 assert(port
->ip_sorights
> 0);
1280 if ((delta
> 0) || (delta
< -1)) {
1291 * clear any reply context:
1292 * no one will be sending the response b/c we are destroying
1293 * the single, outstanding send once right.
1295 port
->ip_reply_context
= 0;
1297 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1300 entry
->ie_object
= IO_NULL
;
1301 ipc_entry_dealloc(space
, name
, entry
);
1303 is_write_unlock(space
);
1305 ipc_notify_send_once(port
);
1307 if (request
!= IP_NULL
) {
1308 ipc_notify_port_deleted(request
, name
);
1313 case MACH_PORT_RIGHT_DEAD_NAME
: {
1314 ipc_port_t relport
= IP_NULL
;
1315 mach_port_urefs_t urefs
;
1317 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1318 port
= ip_object_to_port(entry
->ie_object
);
1319 assert(port
!= IP_NULL
);
1321 if (!ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1322 /* port is locked and active */
1325 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1328 bits
= entry
->ie_bits
;
1331 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0) {
1332 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1336 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1337 assert(IE_BITS_UREFS(bits
) > 0);
1338 assert(entry
->ie_object
== IO_NULL
);
1339 assert(entry
->ie_request
== IE_REQ_NONE
);
1341 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1342 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1346 urefs
= IE_BITS_UREFS(bits
);
1348 if (urefs
== MACH_PORT_UREFS_MAX
) {
1350 * urefs are pegged due to an overflow
1351 * only a delta removing all refs at once can change it
1354 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1358 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1361 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1362 /* leave urefs pegged to maximum if it overflowed */
1363 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1367 if ((urefs
+ delta
) == 0) {
1368 ipc_entry_dealloc(space
, name
, entry
);
1369 } else if (delta
!= 0) {
1370 entry
->ie_bits
= bits
+ delta
;
1371 ipc_entry_modified(space
, name
, entry
);
1374 is_write_unlock(space
);
1376 if (relport
!= IP_NULL
) {
1377 ip_release(relport
);
1383 case MACH_PORT_RIGHT_SEND
: {
1384 mach_port_urefs_t urefs
;
1385 ipc_port_t request
= IP_NULL
;
1386 ipc_port_t nsrequest
= IP_NULL
;
1387 ipc_port_t port_to_release
= IP_NULL
;
1388 mach_port_mscount_t mscount
= 0;
1390 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1391 /* invalid right exception only when not live/dead confusion */
1392 if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0
1393 #if !defined(AE_MAKESENDRIGHT_FIXED)
1395 * AE tries to add single send right without knowing if it already owns one.
1396 * But if it doesn't, it should own the receive right and delta should be 1.
1398 && (((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) || (delta
!= 1))
1401 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1406 /* maximum urefs for send is MACH_PORT_UREFS_MAX */
1408 port
= ip_object_to_port(entry
->ie_object
);
1409 assert(port
!= IP_NULL
);
1411 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1412 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1415 /* port is locked and active */
1417 assert(port
->ip_srights
> 0);
1419 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1420 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1425 urefs
= IE_BITS_UREFS(bits
);
1427 if (urefs
== MACH_PORT_UREFS_MAX
) {
1429 * urefs are pegged due to an overflow
1430 * only a delta removing all refs at once can change it
1433 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1437 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1441 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1442 /* leave urefs pegged to maximum if it overflowed */
1443 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1447 if ((urefs
+ delta
) == 0) {
1448 if (--port
->ip_srights
== 0) {
1449 nsrequest
= port
->ip_nsrequest
;
1450 if (nsrequest
!= IP_NULL
) {
1451 port
->ip_nsrequest
= IP_NULL
;
1452 mscount
= port
->ip_mscount
;
1456 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1457 assert(port
->ip_receiver_name
== name
);
1458 assert(port
->ip_receiver
== space
);
1460 assert(IE_BITS_TYPE(bits
) ==
1461 MACH_PORT_TYPE_SEND_RECEIVE
);
1463 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1464 MACH_PORT_TYPE_SEND
);
1465 ipc_entry_modified(space
, name
, entry
);
1467 assert(IE_BITS_TYPE(bits
) ==
1468 MACH_PORT_TYPE_SEND
);
1470 request
= ipc_right_request_cancel_macro(space
, port
,
1472 ipc_hash_delete(space
, ip_to_object(port
),
1476 port_to_release
= port
;
1478 entry
->ie_object
= IO_NULL
;
1479 ipc_entry_dealloc(space
, name
, entry
);
1481 } else if (delta
!= 0) {
1483 entry
->ie_bits
= bits
+ delta
;
1484 ipc_entry_modified(space
, name
, entry
);
1489 is_write_unlock(space
);
1491 if (port_to_release
!= IP_NULL
) {
1492 ip_release(port_to_release
);
1495 if (nsrequest
!= IP_NULL
) {
1496 ipc_notify_no_senders(nsrequest
, mscount
);
1499 if (request
!= IP_NULL
) {
1500 ipc_notify_port_deleted(request
, name
);
1505 case MACH_PORT_RIGHT_LABELH
:
1509 panic("ipc_right_delta: strange right %d for 0x%x (%p) in space:%p",
1510 right
, name
, (void *)entry
, (void *)space
);
1513 return KERN_SUCCESS
;
1516 is_write_unlock(space
);
1517 return KERN_SUCCESS
;
1520 is_write_unlock(space
);
1521 if (port
!= IP_NULL
) {
1524 return KERN_INVALID_RIGHT
;
1527 is_write_unlock(space
);
1528 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
);
1529 return KERN_INVALID_VALUE
;
1532 return KERN_INVALID_RIGHT
;
1536 * Routine: ipc_right_destruct
1538 * Deallocates the receive right and modifies the
1539 * user-reference count for the send rights as requested.
1541 * The space is write-locked, and is unlocked upon return.
1542 * The space must be active.
1544 * KERN_SUCCESS Count was modified.
1545 * KERN_INVALID_RIGHT Entry has wrong type.
1546 * KERN_INVALID_VALUE Bad delta for the right.
1552 mach_port_name_t name
,
1554 mach_port_delta_t srdelta
,
1557 ipc_port_t port
= IP_NULL
;
1558 ipc_entry_bits_t bits
;
1560 mach_port_urefs_t urefs
;
1561 ipc_port_t request
= IP_NULL
;
1562 ipc_port_t nsrequest
= IP_NULL
;
1563 mach_port_mscount_t mscount
= 0;
1565 bits
= entry
->ie_bits
;
1567 assert(is_active(space
));
1569 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1570 is_write_unlock(space
);
1572 /* No exception if we used to have receive and held entry since */
1573 if ((bits
& MACH_PORT_TYPE_EX_RECEIVE
) == 0) {
1574 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1576 return KERN_INVALID_RIGHT
;
1579 if (srdelta
&& (bits
& MACH_PORT_TYPE_SEND
) == 0) {
1580 is_write_unlock(space
);
1581 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
);
1582 return KERN_INVALID_RIGHT
;
1589 port
= ip_object_to_port(entry
->ie_object
);
1590 assert(port
!= IP_NULL
);
1593 require_ip_active(port
);
1594 assert(port
->ip_receiver_name
== name
);
1595 assert(port
->ip_receiver
== space
);
1597 /* Mach Port Guard Checking */
1598 if (port
->ip_guarded
&& (guard
!= port
->ip_context
)) {
1599 uint64_t portguard
= port
->ip_context
;
1601 is_write_unlock(space
);
1602 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
1603 return KERN_INVALID_ARGUMENT
;
1607 * First reduce the send rights as requested and
1608 * adjust the entry->ie_bits accordingly. The
1609 * ipc_entry_modified() call is made once the receive
1610 * right is destroyed too.
1614 assert(port
->ip_srights
> 0);
1616 urefs
= IE_BITS_UREFS(bits
);
1619 * Since we made sure that srdelta is negative,
1620 * the check for urefs overflow is not required.
1622 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, srdelta
)) {
1627 if (urefs
== MACH_PORT_UREFS_MAX
) {
1629 * urefs are pegged due to an overflow
1630 * only a delta removing all refs at once can change it
1632 if (srdelta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1637 if ((urefs
+ srdelta
) == 0) {
1638 if (--port
->ip_srights
== 0) {
1639 nsrequest
= port
->ip_nsrequest
;
1640 if (nsrequest
!= IP_NULL
) {
1641 port
->ip_nsrequest
= IP_NULL
;
1642 mscount
= port
->ip_mscount
;
1645 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_RECEIVE
);
1646 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
|
1647 MACH_PORT_TYPE_SEND
);
1649 entry
->ie_bits
= bits
+ srdelta
;
1654 * Now destroy the receive right. Update space and
1655 * entry accordingly.
1658 bits
= entry
->ie_bits
;
1659 if (bits
& MACH_PORT_TYPE_SEND
) {
1660 assert(IE_BITS_UREFS(bits
) > 0);
1661 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
1663 if (port
->ip_pdrequest
!= NULL
) {
1665 * Since another task has requested a
1666 * destroy notification for this port, it
1667 * isn't actually being destroyed - the receive
1668 * right is just being moved to another task.
1669 * Since we still have one or more send rights,
1670 * we need to record the loss of the receive
1671 * right and enter the remaining send right
1672 * into the hash table.
1674 ipc_entry_modified(space
, name
, entry
);
1675 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1676 entry
->ie_bits
|= MACH_PORT_TYPE_EX_RECEIVE
;
1677 ipc_hash_insert(space
, ip_to_object(port
),
1682 * The remaining send right turns into a
1683 * dead name. Notice we don't decrement
1684 * ip_srights, generate a no-senders notif,
1685 * or use ipc_right_dncancel, because the
1686 * port is destroyed "first".
1688 bits
&= ~IE_BITS_TYPE_MASK
;
1689 bits
|= (MACH_PORT_TYPE_DEAD_NAME
| MACH_PORT_TYPE_EX_RECEIVE
);
1690 if (entry
->ie_request
) {
1691 entry
->ie_request
= IE_REQ_NONE
;
1692 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1693 bits
++; /* increment urefs */
1696 entry
->ie_bits
= bits
;
1697 entry
->ie_object
= IO_NULL
;
1698 ipc_entry_modified(space
, name
, entry
);
1701 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1702 assert(IE_BITS_UREFS(bits
) == 0);
1703 request
= ipc_right_request_cancel_macro(space
, port
,
1705 entry
->ie_object
= IO_NULL
;
1706 ipc_entry_dealloc(space
, name
, entry
);
1710 is_write_unlock(space
);
1712 if (nsrequest
!= IP_NULL
) {
1713 ipc_notify_no_senders(nsrequest
, mscount
);
1716 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1718 if (request
!= IP_NULL
) {
1719 ipc_notify_port_deleted(request
, name
);
1722 return KERN_SUCCESS
;
1725 is_write_unlock(space
);
1726 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
);
1727 return KERN_INVALID_VALUE
;
1732 * Routine: ipc_right_info
1734 * Retrieves information about the right.
1736 * The space is active and write-locked.
1737 * The space is unlocked upon return.
1739 * KERN_SUCCESS Retrieved info
1745 mach_port_name_t name
,
1747 mach_port_type_t
*typep
,
1748 mach_port_urefs_t
*urefsp
)
1751 ipc_entry_bits_t bits
;
1752 mach_port_type_t type
= 0;
1753 ipc_port_request_index_t request
;
1755 bits
= entry
->ie_bits
;
1756 request
= entry
->ie_request
;
1757 port
= ip_object_to_port(entry
->ie_object
);
1759 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1760 assert(IP_VALID(port
));
1762 if (request
!= IE_REQ_NONE
) {
1764 require_ip_active(port
);
1765 type
|= ipc_port_request_type(port
, name
, request
);
1768 is_write_unlock(space
);
1769 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1771 * validate port is still alive - if so, get request
1772 * types while we still have it locked. Otherwise,
1773 * recapture the (now dead) bits.
1775 if (!ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
1776 if (request
!= IE_REQ_NONE
) {
1777 type
|= ipc_port_request_type(port
, name
, request
);
1780 is_write_unlock(space
);
1782 bits
= entry
->ie_bits
;
1783 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1784 is_write_unlock(space
);
1788 is_write_unlock(space
);
1791 type
|= IE_BITS_TYPE(bits
);
1794 *urefsp
= IE_BITS_UREFS(bits
);
1795 return KERN_SUCCESS
;
1799 * Routine: ipc_right_copyin_check_reply
1801 * Check if a subsequent ipc_right_copyin would succeed. Used only
1802 * by ipc_kmsg_copyin_header to check if reply_port can be copied in.
1803 * If the reply port is an immovable send right, it errors out.
1805 * The space is locked (read or write) and active.
1809 ipc_right_copyin_check_reply(
1810 __assert_only ipc_space_t space
,
1811 mach_port_name_t reply_name
,
1812 ipc_entry_t reply_entry
,
1813 mach_msg_type_name_t reply_type
)
1815 ipc_entry_bits_t bits
;
1816 ipc_port_t reply_port
;
1818 bits
= reply_entry
->ie_bits
;
1819 assert(is_active(space
));
1821 switch (reply_type
) {
1822 case MACH_MSG_TYPE_MAKE_SEND
:
1823 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1828 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1829 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1834 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1835 /* ipc_kmsg_copyin_header already filters it out */
1838 case MACH_MSG_TYPE_COPY_SEND
:
1839 case MACH_MSG_TYPE_MOVE_SEND
:
1840 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1841 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
1845 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
1849 reply_port
= ip_object_to_port(reply_entry
->ie_object
);
1850 assert(reply_port
!= IP_NULL
);
1853 * active status peek to avoid checks that will be skipped
1854 * on copyin for dead ports. Lock not held, so will not be
1855 * atomic (but once dead, there's no going back).
1857 if (!ip_active(reply_port
)) {
1862 * Can't copyin a send right that is marked immovable. This bit
1863 * is set only during port creation and never unset. So it can
1864 * be read without a lock.
1866 if (reply_port
->ip_immovable_send
) {
1867 mach_port_guard_exception(reply_name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
1871 if (reply_type
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1872 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1876 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1885 panic("ipc_right_copyin_check: strange rights");
1892 * Routine: ipc_right_copyin_check_guard_locked
1894 * Check if the port is guarded and the guard
1895 * value matches the one passed in the arguments.
1896 * If MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND is set,
1897 * check if the port is unguarded.
1899 * The port is locked.
1901 * KERN_SUCCESS Port is either unguarded
1902 * or guarded with expected value
1903 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch.
1904 * This also raises a EXC_GUARD exception.
1906 static kern_return_t
1907 ipc_right_copyin_check_guard_locked(
1908 mach_port_name_t name
,
1910 mach_port_context_t context
,
1911 mach_msg_guard_flags_t
*guard_flags
)
1913 mach_msg_guard_flags_t flags
= *guard_flags
;
1914 if ((flags
& MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
) && !port
->ip_guarded
&& !context
) {
1915 return KERN_SUCCESS
;
1916 } else if (port
->ip_guarded
&& (port
->ip_context
== context
)) {
1917 return KERN_SUCCESS
;
1920 /* Incorrect guard; Raise exception */
1921 mach_port_guard_exception(name
, context
, port
->ip_context
, kGUARD_EXC_INCORRECT_GUARD
);
1922 return KERN_INVALID_ARGUMENT
;
1926 * Routine: ipc_right_copyin
1928 * Copyin a capability from a space.
1929 * If successful, the caller gets a ref
1930 * for the resulting object, unless it is IO_DEAD,
1931 * and possibly a send-once right which should
1932 * be used in a port-deleted notification.
1934 * If deadok is not TRUE, the copyin operation
1935 * will fail instead of producing IO_DEAD.
1937 * The entry is never deallocated (except
1938 * when KERN_INVALID_NAME), so the caller
1939 * should deallocate the entry if its type
1940 * is MACH_PORT_TYPE_NONE.
1942 * The space is write-locked and active.
1944 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1945 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1946 * KERN_INVALID_CAPABILITY Trying to move an kobject port or an immovable right
1947 * KERN_INVALID_ARGUMENT Port is unguarded or guard mismatch
1953 mach_port_name_t name
,
1955 mach_msg_type_name_t msgt_name
,
1956 ipc_right_copyin_flags_t flags
,
1957 ipc_object_t
*objectp
,
1958 ipc_port_t
*sorightp
,
1959 ipc_port_t
*releasep
,
1961 mach_port_context_t context
,
1962 mach_msg_guard_flags_t
*guard_flags
)
1964 ipc_entry_bits_t bits
;
1967 boolean_t deadok
= flags
& IPC_RIGHT_COPYIN_FLAGS_DEADOK
? TRUE
: FALSE
;
1968 boolean_t allow_imm_send
= flags
& IPC_RIGHT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
? TRUE
: FALSE
;
1970 *releasep
= IP_NULL
;
1973 bits
= entry
->ie_bits
;
1975 assert(is_active(space
));
1977 switch (msgt_name
) {
1978 case MACH_MSG_TYPE_MAKE_SEND
: {
1979 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1983 port
= ip_object_to_port(entry
->ie_object
);
1984 assert(port
!= IP_NULL
);
1987 assert(port
->ip_receiver_name
== name
);
1988 assert(port
->ip_receiver
== space
);
1990 ipc_port_make_send_locked(port
);
1993 *objectp
= ip_to_object(port
);
1994 *sorightp
= IP_NULL
;
1998 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1999 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
2003 port
= ip_object_to_port(entry
->ie_object
);
2004 assert(port
!= IP_NULL
);
2007 require_ip_active(port
);
2008 assert(port
->ip_receiver_name
== name
);
2009 assert(port
->ip_receiver
== space
);
2011 ipc_port_make_sonce_locked(port
);
2014 *objectp
= ip_to_object(port
);
2015 *sorightp
= IP_NULL
;
2019 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
2020 ipc_port_t request
= IP_NULL
;
2022 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
2027 * Disallow moving receive-right kobjects, e.g. mk_timer ports
2028 * The ipc_port structure uses the kdata union of kobject and
2029 * imp_task exclusively. Thus, general use of a kobject port as
2030 * a receive right can cause type confusion in the importance
2033 if (io_kotype(entry
->ie_object
) != IKOT_NONE
) {
2035 * Distinguish an invalid right, e.g., trying to move
2036 * a send right as a receive right, from this
2037 * situation which is, "This is a valid receive right,
2038 * but it's also a kobject and you can't move it."
2040 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
2041 return KERN_INVALID_CAPABILITY
;
2044 port
= ip_object_to_port(entry
->ie_object
);
2045 assert(port
!= IP_NULL
);
2048 require_ip_active(port
);
2049 assert(port
->ip_receiver_name
== name
);
2050 assert(port
->ip_receiver
== space
);
2052 if (port
->ip_immovable_receive
) {
2053 assert(port
->ip_receiver
!= ipc_space_kernel
);
2055 assert(current_task() != kernel_task
);
2056 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
2057 return KERN_INVALID_CAPABILITY
;
2060 if (guard_flags
!= NULL
) {
2061 kr
= ipc_right_copyin_check_guard_locked(name
, port
, context
, guard_flags
);
2062 if (kr
!= KERN_SUCCESS
) {
2068 if (bits
& MACH_PORT_TYPE_SEND
) {
2069 assert(IE_BITS_TYPE(bits
) ==
2070 MACH_PORT_TYPE_SEND_RECEIVE
);
2071 assert(IE_BITS_UREFS(bits
) > 0);
2072 assert(port
->ip_srights
> 0);
2074 ipc_hash_insert(space
, ip_to_object(port
),
2078 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2079 assert(IE_BITS_UREFS(bits
) == 0);
2081 request
= ipc_right_request_cancel_macro(space
, port
,
2083 entry
->ie_object
= IO_NULL
;
2085 entry
->ie_bits
= bits
& ~MACH_PORT_TYPE_RECEIVE
;
2086 entry
->ie_bits
|= MACH_PORT_TYPE_EX_RECEIVE
;
2087 ipc_entry_modified(space
, name
, entry
);
2089 /* ipc_port_clear_receiver unguards the port and clears the ip_immovable_receive bit */
2090 (void)ipc_port_clear_receiver(port
, FALSE
); /* don't destroy the port/mqueue */
2091 if (guard_flags
!= NULL
) {
2092 /* this flag will be cleared during copyout */
2093 *guard_flags
= *guard_flags
| MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
;
2096 #if IMPORTANCE_INHERITANCE
2098 * Account for boosts the current task is going to lose when
2099 * copying this right in. Tempowner ports have either not
2100 * been accounting to any task (and therefore are already in
2101 * "limbo" state w.r.t. assertions) or to some other specific
2102 * task. As we have no way to drop the latter task's assertions
2103 * here, We'll deduct those when we enqueue it on its
2104 * destination port (see ipc_port_check_circularity()).
2106 if (port
->ip_tempowner
== 0) {
2107 assert(IIT_NULL
== port
->ip_imp_task
);
2109 /* ports in limbo have to be tempowner */
2110 port
->ip_tempowner
= 1;
2111 *assertcntp
= port
->ip_impcount
;
2113 #endif /* IMPORTANCE_INHERITANCE */
2117 *objectp
= ip_to_object(port
);
2118 *sorightp
= request
;
2122 case MACH_MSG_TYPE_COPY_SEND
: {
2123 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2127 /* allow for dead send-once rights */
2129 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2133 assert(IE_BITS_UREFS(bits
) > 0);
2135 port
= ip_object_to_port(entry
->ie_object
);
2136 assert(port
!= IP_NULL
);
2138 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
2139 bits
= entry
->ie_bits
;
2143 /* port is locked and active */
2145 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2146 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2147 assert(port
->ip_sorights
> 0);
2153 if (!allow_imm_send
&& port
->ip_immovable_send
) {
2155 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
2156 return KERN_INVALID_CAPABILITY
;
2159 ipc_port_copy_send_locked(port
);
2162 *objectp
= ip_to_object(port
);
2163 *sorightp
= IP_NULL
;
2167 case MACH_MSG_TYPE_MOVE_SEND
: {
2168 ipc_port_t request
= IP_NULL
;
2170 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2174 /* allow for dead send-once rights */
2176 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2180 assert(IE_BITS_UREFS(bits
) > 0);
2182 port
= ip_object_to_port(entry
->ie_object
);
2183 assert(port
!= IP_NULL
);
2185 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
2186 bits
= entry
->ie_bits
;
2190 /* port is locked and active */
2192 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2193 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2194 assert(port
->ip_sorights
> 0);
2200 if (!allow_imm_send
&& port
->ip_immovable_send
) {
2202 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
2203 return KERN_INVALID_CAPABILITY
;
2206 if (IE_BITS_UREFS(bits
) == 1) {
2207 assert(port
->ip_srights
> 0);
2208 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2209 assert(port
->ip_receiver_name
== name
);
2210 assert(port
->ip_receiver
== space
);
2211 assert(IE_BITS_TYPE(bits
) ==
2212 MACH_PORT_TYPE_SEND_RECEIVE
);
2216 assert(IE_BITS_TYPE(bits
) ==
2217 MACH_PORT_TYPE_SEND
);
2219 request
= ipc_right_request_cancel_macro(space
, port
,
2221 ipc_hash_delete(space
, ip_to_object(port
),
2223 entry
->ie_object
= IO_NULL
;
2224 /* transfer entry's reference to caller */
2226 entry
->ie_bits
= bits
& ~
2227 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND
);
2229 ipc_port_copy_send_locked(port
);
2230 /* if urefs are pegged due to overflow, leave them pegged */
2231 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2232 entry
->ie_bits
= bits
- 1; /* decrement urefs */
2236 ipc_entry_modified(space
, name
, entry
);
2239 *objectp
= ip_to_object(port
);
2240 *sorightp
= request
;
2244 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
2247 if (bits
& MACH_PORT_TYPE_DEAD_NAME
) {
2251 /* allow for dead send rights */
2253 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) {
2257 assert(IE_BITS_UREFS(bits
) > 0);
2259 port
= ip_object_to_port(entry
->ie_object
);
2260 assert(port
!= IP_NULL
);
2262 if (ipc_right_check(space
, port
, name
, entry
, flags
)) {
2263 bits
= entry
->ie_bits
;
2268 * port is locked, but may not be active:
2269 * Allow copyin of inactive ports with no dead name request and treat it
2270 * as if the copyin of the port was successful and port became inactive
2274 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
2275 assert(bits
& MACH_PORT_TYPE_SEND
);
2276 assert(port
->ip_srights
> 0);
2282 if (!allow_imm_send
&& port
->ip_immovable_send
) {
2284 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
);
2285 return KERN_INVALID_CAPABILITY
;
2288 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2289 assert(IE_BITS_UREFS(bits
) == 1);
2290 assert(port
->ip_sorights
> 0);
2292 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
2295 entry
->ie_object
= IO_NULL
;
2296 entry
->ie_bits
= bits
& ~
2297 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
2298 ipc_entry_modified(space
, name
, entry
);
2299 *objectp
= ip_to_object(port
);
2300 *sorightp
= request
;
2306 return KERN_INVALID_RIGHT
;
2309 return KERN_SUCCESS
;
2312 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2313 assert(IE_BITS_UREFS(bits
) > 0);
2314 assert(entry
->ie_request
== IE_REQ_NONE
);
2315 assert(entry
->ie_object
== 0);
2322 *sorightp
= IP_NULL
;
2323 return KERN_SUCCESS
;
2326 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2327 assert(IE_BITS_UREFS(bits
) > 0);
2328 assert(entry
->ie_request
== IE_REQ_NONE
);
2329 assert(entry
->ie_object
== 0);
2335 if (IE_BITS_UREFS(bits
) == 1) {
2336 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
2338 /* if urefs are pegged due to overflow, leave them pegged */
2339 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2340 entry
->ie_bits
= bits
- 1; /* decrement urefs */
2342 ipc_entry_modified(space
, name
, entry
);
2344 *sorightp
= IP_NULL
;
2345 return KERN_SUCCESS
;
2349 * Routine: ipc_right_copyin_two_move_sends
2351 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
2352 * and deadok == FALSE, except that this moves two
2353 * send rights at once.
2355 * The space is write-locked and active.
2356 * The object is returned with two refs/send rights.
2358 * KERN_SUCCESS Acquired an object.
2359 * KERN_INVALID_RIGHT Name doesn't denote correct right.
2363 ipc_right_copyin_two_move_sends(
2365 mach_port_name_t name
,
2367 ipc_object_t
*objectp
,
2368 ipc_port_t
*sorightp
,
2369 ipc_port_t
*releasep
)
2371 ipc_entry_bits_t bits
;
2372 mach_port_urefs_t urefs
;
2374 ipc_port_t request
= IP_NULL
;
2376 *releasep
= IP_NULL
;
2378 assert(is_active(space
));
2380 bits
= entry
->ie_bits
;
2382 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2386 urefs
= IE_BITS_UREFS(bits
);
2391 port
= ip_object_to_port(entry
->ie_object
);
2392 assert(port
!= IP_NULL
);
2394 if (ipc_right_check(space
, port
, name
, entry
, IPC_RIGHT_COPYIN_FLAGS_NONE
)) {
2398 /* port is locked and active */
2402 * We are moving 2 urefs as naked send rights, which is decomposed as:
2403 * - two copy sends (which doesn't affect the make send count)
2404 * - decrementing the local urefs twice.
2406 ipc_port_copy_send_locked(port
);
2407 ipc_port_copy_send_locked(port
);
2408 /* if urefs are pegged due to overflow, leave them pegged */
2409 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
2410 entry
->ie_bits
= bits
- 2; /* decrement urefs */
2414 * We have exactly 2 send rights for this port in this space,
2415 * which means that we will liberate the naked send right held
2418 * However refcounting rules around entries are that naked send rights
2419 * on behalf of spaces do not have an associated port reference,
2420 * so we need to donate one ...
2422 ipc_port_copy_send_locked(port
);
2424 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2425 assert(port
->ip_receiver_name
== name
);
2426 assert(port
->ip_receiver
== space
);
2427 assert(IE_BITS_TYPE(bits
) ==
2428 MACH_PORT_TYPE_SEND_RECEIVE
);
2430 /* ... that we inject manually when the entry stays alive */
2433 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2435 /* ... that we steal from the entry when it dies */
2436 request
= ipc_right_request_cancel_macro(space
, port
,
2439 ipc_hash_delete(space
, ip_to_object(port
),
2441 entry
->ie_object
= IO_NULL
;
2444 entry
->ie_bits
= bits
& ~(IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND
);
2446 ipc_entry_modified(space
, name
, entry
);
2450 *objectp
= ip_to_object(port
);
2451 *sorightp
= request
;
2452 return KERN_SUCCESS
;
2455 return KERN_INVALID_RIGHT
;
2460 * Routine: ipc_right_copyin_two
2462 * Like ipc_right_copyin with two dispositions,
2463 * each of which results in a send or send-once right,
2464 * and deadok = FALSE.
2466 * The space is write-locked and active.
2467 * The object is returned with two refs/rights.
2468 * Msgt_one refers to the dest_type
2470 * KERN_SUCCESS Acquired an object.
2471 * KERN_INVALID_RIGHT Name doesn't denote correct right(s).
2472 * KERN_INVALID_CAPABILITY Name doesn't denote correct right for msgt_two.
2475 ipc_right_copyin_two(
2477 mach_port_name_t name
,
2479 mach_msg_type_name_t msgt_one
,
2480 mach_msg_type_name_t msgt_two
,
2481 ipc_object_t
*objectp
,
2482 ipc_port_t
*sorightp
,
2483 ipc_port_t
*releasep
)
2488 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one
));
2489 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two
));
2492 * This is a little tedious to make atomic, because
2493 * there are 25 combinations of valid dispositions.
2494 * However, most are easy.
2498 * If either is move-sonce, then there must be an error.
2500 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND_ONCE
||
2501 msgt_two
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
2502 return KERN_INVALID_RIGHT
;
2505 if ((msgt_one
== MACH_MSG_TYPE_MAKE_SEND
) ||
2506 (msgt_one
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) ||
2507 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND
) ||
2508 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) {
2510 * One of the dispositions needs a receive right.
2512 * If the copyin below succeeds, we know the receive
2513 * right is there (because the pre-validation of
2514 * the second disposition already succeeded in our
2517 * Hence the port is not in danger of dying.
2519 ipc_object_t object_two
;
2521 kr
= ipc_right_copyin(space
, name
, entry
,
2522 msgt_one
, IPC_RIGHT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
,
2523 objectp
, sorightp
, releasep
,
2524 &assertcnt
, 0, NULL
);
2525 assert(assertcnt
== 0);
2526 if (kr
!= KERN_SUCCESS
) {
2530 assert(IO_VALID(*objectp
));
2531 assert(*sorightp
== IP_NULL
);
2532 assert(*releasep
== IP_NULL
);
2535 * Now copyin the second (previously validated)
2536 * disposition. The result can't be a dead port,
2537 * as no valid disposition can make us lose our
2540 kr
= ipc_right_copyin(space
, name
, entry
,
2541 msgt_two
, IPC_RIGHT_COPYIN_FLAGS_NONE
,
2542 &object_two
, sorightp
, releasep
,
2543 &assertcnt
, 0, NULL
);
2544 assert(assertcnt
== 0);
2545 assert(kr
== KERN_SUCCESS
);
2546 assert(*sorightp
== IP_NULL
);
2547 assert(*releasep
== IP_NULL
);
2548 assert(object_two
== *objectp
);
2549 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
2550 } else if ((msgt_one
== MACH_MSG_TYPE_MOVE_SEND
) &&
2551 (msgt_two
== MACH_MSG_TYPE_MOVE_SEND
)) {
2553 * This is an easy case. Just use our
2554 * handy-dandy special-purpose copyin call
2555 * to get two send rights for the price of one.
2557 kr
= ipc_right_copyin_two_move_sends(space
, name
, entry
,
2560 if (kr
!= KERN_SUCCESS
) {
2564 mach_msg_type_name_t msgt_name
;
2567 * Must be either a single move-send and a
2568 * copy-send, or two copy-send dispositions.
2569 * Use the disposition with the greatest side
2570 * effects for the actual copyin - then just
2571 * duplicate the send right you get back.
2573 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND
||
2574 msgt_two
== MACH_MSG_TYPE_MOVE_SEND
) {
2575 msgt_name
= MACH_MSG_TYPE_MOVE_SEND
;
2577 msgt_name
= MACH_MSG_TYPE_COPY_SEND
;
2580 kr
= ipc_right_copyin(space
, name
, entry
,
2581 msgt_name
, IPC_RIGHT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
,
2582 objectp
, sorightp
, releasep
,
2583 &assertcnt
, 0, NULL
);
2584 assert(assertcnt
== 0);
2585 if (kr
!= KERN_SUCCESS
) {
2590 * Copy the right we got back. If it is dead now,
2591 * that's OK. Neither right will be usable to send
2594 (void)ipc_port_copy_send(ip_object_to_port(*objectp
));
2597 return KERN_SUCCESS
;
2602 * Routine: ipc_right_copyout
2604 * Copyout a capability to a space.
2605 * If successful, consumes a ref for the object.
2607 * Always succeeds when given a newly-allocated entry,
2608 * because user-reference overflow isn't a possibility.
2610 * If copying out the object would cause the user-reference
2611 * count in the entry to overflow, then the user-reference
2612 * count is left pegged to its maximum value and the copyout
2615 * The space is write-locked and active.
2616 * The object is locked and active.
2617 * The object is unlocked; the space isn't.
2619 * KERN_SUCCESS Copied out capability.
2625 mach_port_name_t name
,
2627 mach_msg_type_name_t msgt_name
,
2628 mach_port_context_t
*context
,
2629 mach_msg_guard_flags_t
*guard_flags
,
2630 ipc_object_t object
)
2632 ipc_entry_bits_t bits
;
2635 bits
= entry
->ie_bits
;
2637 assert(IO_VALID(object
));
2638 assert(io_otype(object
) == IOT_PORT
);
2639 assert(io_active(object
));
2640 assert(entry
->ie_object
== object
);
2642 port
= ip_object_to_port(object
);
2644 switch (msgt_name
) {
2645 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
2647 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2648 assert(IE_BITS_UREFS(bits
) == 0);
2649 assert(port
->ip_sorights
> 0);
2651 if (port
->ip_specialreply
) {
2652 ipc_port_adjust_special_reply_port_locked(port
,
2653 current_thread()->ith_knote
, IPC_PORT_ADJUST_SR_LINK_WORKLOOP
, FALSE
);
2654 /* port unlocked on return */
2659 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1); /* set urefs to 1 */
2660 ipc_entry_modified(space
, name
, entry
);
2663 case MACH_MSG_TYPE_PORT_SEND
:
2664 assert(port
->ip_srights
> 0);
2666 if (bits
& MACH_PORT_TYPE_SEND
) {
2667 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
2669 assert(port
->ip_srights
> 1);
2671 assert(urefs
<= MACH_PORT_UREFS_MAX
);
2673 if (urefs
== MACH_PORT_UREFS_MAX
) {
2675 * leave urefs pegged to maximum,
2676 * consume send right and ref
2682 return KERN_SUCCESS
;
2685 /* consume send right and ref */
2689 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2690 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2691 assert(IE_BITS_UREFS(bits
) == 0);
2693 /* transfer send right to entry, consume ref */
2697 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2698 assert(IE_BITS_UREFS(bits
) == 0);
2700 /* transfer send right and ref to entry */
2703 /* entry is locked holding ref, so can use port */
2705 ipc_hash_insert(space
, ip_to_object(port
), name
, entry
);
2708 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1; /* increment urefs */
2709 ipc_entry_modified(space
, name
, entry
);
2712 case MACH_MSG_TYPE_PORT_RECEIVE
: {
2714 #if IMPORTANCE_INHERITANCE
2715 natural_t assertcnt
= port
->ip_impcount
;
2716 #endif /* IMPORTANCE_INHERITANCE */
2718 assert(port
->ip_mscount
== 0);
2719 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
2721 imq_lock(&port
->ip_messages
);
2722 dest
= port
->ip_destination
;
2724 port
->ip_receiver_name
= name
;
2725 port
->ip_receiver
= space
;
2727 struct knote
*kn
= current_thread()->ith_knote
;
2729 if ((guard_flags
!= NULL
) && ((*guard_flags
& MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE
) != 0)) {
2730 assert(port
->ip_immovable_receive
== 0);
2731 port
->ip_guarded
= 1;
2732 port
->ip_strict_guard
= 0;
2733 /* pseudo receive shouldn't set the receive right as immovable in the sender's space */
2734 if (kn
!= ITH_KNOTE_PSEUDO
) {
2735 port
->ip_immovable_receive
= 1;
2737 port
->ip_context
= current_thread()->ith_msg_addr
;
2738 *context
= port
->ip_context
;
2739 *guard_flags
= *guard_flags
& ~MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
;
2742 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
2743 if (bits
& MACH_PORT_TYPE_SEND
) {
2744 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2745 assert(IE_BITS_UREFS(bits
) > 0);
2746 assert(port
->ip_srights
> 0);
2748 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2749 assert(IE_BITS_UREFS(bits
) == 0);
2752 boolean_t sync_bootstrap_checkin
= FALSE
;
2753 if (kn
!= ITH_KNOTE_PSEUDO
&& port
->ip_sync_bootstrap_checkin
) {
2754 sync_bootstrap_checkin
= TRUE
;
2756 if (!ITH_KNOTE_VALID(kn
, MACH_MSG_TYPE_PORT_RECEIVE
)) {
2759 ipc_port_adjust_port_locked(port
, kn
, sync_bootstrap_checkin
);
2760 /* port & message queue are unlocked */
2762 if (bits
& MACH_PORT_TYPE_SEND
) {
2765 /* entry is locked holding ref, so can use port */
2766 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
);
2768 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2769 ipc_entry_modified(space
, name
, entry
);
2771 if (dest
!= IP_NULL
) {
2772 #if IMPORTANCE_INHERITANCE
2774 * Deduct the assertion counts we contributed to
2775 * the old destination port. They've already
2776 * been reflected into the task as a result of
2780 ipc_port_impcount_delta(dest
, 0 - assertcnt
, IP_NULL
);
2782 #endif /* IMPORTANCE_INHERITANCE */
2784 /* Drop turnstile ref on dest */
2785 ipc_port_send_turnstile_complete(dest
);
2792 panic("ipc_right_copyout: strange rights");
2794 return KERN_SUCCESS
;