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>
93 /* Allow IPC to generate mach port guard exceptions */
95 mach_port_guard_exception(
96 mach_port_name_t name
,
101 * Routine: ipc_right_lookup_write
103 * Finds an entry in a space, given the name.
105 * Nothing locked. If successful, the space is write-locked.
107 * KERN_SUCCESS Found an entry.
108 * KERN_INVALID_TASK The space is dead.
109 * KERN_INVALID_NAME Name doesn't exist in space.
113 ipc_right_lookup_write(
115 mach_port_name_t name
,
120 assert(space
!= IS_NULL
);
122 is_write_lock(space
);
124 if (!is_active(space
)) {
125 is_write_unlock(space
);
126 return KERN_INVALID_TASK
;
129 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
130 is_write_unlock(space
);
131 return KERN_INVALID_NAME
;
139 * Routine: ipc_right_lookup_two_write
141 * Like ipc_right_lookup except that it returns two
142 * entries for two different names that were looked
143 * up under the same space lock.
145 * Nothing locked. If successful, the space is write-locked.
147 * KERN_INVALID_TASK The space is dead.
148 * KERN_INVALID_NAME Name doesn't exist in space.
152 ipc_right_lookup_two_write(
154 mach_port_name_t name1
,
155 ipc_entry_t
*entryp1
,
156 mach_port_name_t name2
,
157 ipc_entry_t
*entryp2
)
162 assert(space
!= IS_NULL
);
164 is_write_lock(space
);
166 if (!is_active(space
)) {
167 is_write_unlock(space
);
168 return KERN_INVALID_TASK
;
171 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
172 is_write_unlock(space
);
173 return KERN_INVALID_NAME
;
175 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
176 is_write_unlock(space
);
177 return KERN_INVALID_NAME
;
185 * Routine: ipc_right_reverse
187 * Translate (space, object) -> (name, entry).
188 * Only finds send/receive rights.
189 * Returns TRUE if an entry is found; if so,
190 * the object is locked and active.
192 * The space must be locked (read or write) and active.
193 * Nothing else locked.
200 mach_port_name_t
*namep
,
204 mach_port_name_t name
;
207 /* would switch on io_otype to handle multiple types of object */
209 assert(is_active(space
));
210 assert(io_otype(object
) == IOT_PORT
);
212 port
= (ipc_port_t
) object
;
215 if (!ip_active(port
)) {
221 if (port
->ip_receiver
== space
) {
222 name
= port
->ip_receiver_name
;
223 assert(name
!= MACH_PORT_NULL
);
225 entry
= ipc_entry_lookup(space
, name
);
227 assert(entry
!= IE_NULL
);
228 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
229 assert(port
== (ipc_port_t
) entry
->ie_object
);
236 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
237 assert((entry
= *entryp
) != IE_NULL
);
238 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
239 assert(port
== (ipc_port_t
) entry
->ie_object
);
249 * Routine: ipc_right_dnrequest
251 * Make a dead-name request, returning the previously
252 * registered send-once right. If notify is IP_NULL,
253 * just cancels the previously registered request.
256 * Nothing locked. May allocate memory.
257 * Only consumes/returns refs if successful.
259 * KERN_SUCCESS Made/canceled dead-name request.
260 * KERN_INVALID_TASK The space is dead.
261 * KERN_INVALID_NAME Name doesn't exist in space.
262 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
263 * KERN_INVALID_ARGUMENT Name denotes dead name, but
264 * immediate is FALSE or notify is IP_NULL.
265 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
269 ipc_right_request_alloc(
271 mach_port_name_t name
,
273 boolean_t send_possible
,
275 ipc_port_t
*previousp
)
277 ipc_port_request_index_t prev_request
;
278 ipc_port_t previous
= IP_NULL
;
282 #if IMPORTANCE_INHERITANCE
283 boolean_t needboost
= FALSE
;
284 #endif /* IMPORTANCE_INHERITANCE */
287 ipc_port_t port
= IP_NULL
;
289 kr
= ipc_right_lookup_write(space
, name
, &entry
);
290 if (kr
!= KERN_SUCCESS
)
293 /* space is write-locked and active */
295 prev_request
= entry
->ie_request
;
297 /* if nothing to do or undo, we're done */
298 if (notify
== IP_NULL
&& prev_request
== IE_REQ_NONE
) {
299 is_write_unlock(space
);
300 *previousp
= IP_NULL
;
304 /* see if the entry is of proper type for requests */
305 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
306 ipc_port_request_index_t new_request
;
308 port
= (ipc_port_t
) entry
->ie_object
;
309 assert(port
!= IP_NULL
);
311 if (!ipc_right_check(space
, port
, name
, entry
)) {
312 /* port is locked and active */
314 /* if no new request, just cancel previous */
315 if (notify
== IP_NULL
) {
316 if (prev_request
!= IE_REQ_NONE
)
317 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
319 entry
->ie_request
= IE_REQ_NONE
;
320 ipc_entry_modified(space
, name
, entry
);
321 is_write_unlock(space
);
326 * send-once rights, kernel objects, and non-full other queues
327 * fire immediately (if immediate specified).
329 if (send_possible
&& immediate
&&
330 ((entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
) ||
331 port
->ip_receiver
== ipc_space_kernel
|| !ip_full(port
))) {
332 if (prev_request
!= IE_REQ_NONE
)
333 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
335 entry
->ie_request
= IE_REQ_NONE
;
336 ipc_entry_modified(space
, name
, entry
);
337 is_write_unlock(space
);
339 ipc_notify_send_possible(notify
, name
);
344 * If there is a previous request, free it. Any subsequent
345 * allocation cannot fail, thus assuring an atomic swap.
347 if (prev_request
!= IE_REQ_NONE
)
348 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
350 #if IMPORTANCE_INHERITANCE
351 kr
= ipc_port_request_alloc(port
, name
, notify
,
352 send_possible
, immediate
,
353 &new_request
, &needboost
);
355 kr
= ipc_port_request_alloc(port
, name
, notify
,
356 send_possible
, immediate
,
358 #endif /* IMPORTANCE_INHERITANCE */
359 if (kr
!= KERN_SUCCESS
) {
360 assert(previous
== IP_NULL
);
361 is_write_unlock(space
);
363 kr
= ipc_port_request_grow(port
, ITS_SIZE_NONE
);
364 /* port is unlocked */
366 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
)
383 #endif /* IMPORTANCE_INHERITANCE */
388 /* 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
);
410 ipc_notify_dead_name(notify
, name
);
415 kr
= (entry
->ie_bits
& MACH_PORT_TYPE_PORT_OR_DEAD
) ?
416 KERN_INVALID_ARGUMENT
: KERN_INVALID_RIGHT
;
418 is_write_unlock(space
);
426 *previousp
= previous
;
431 * Routine: ipc_right_request_cancel
433 * Cancel a notification request and return the send-once right.
434 * Afterwards, entry->ie_request == 0.
436 * The space must be write-locked; the port must be locked.
437 * The port must be active; the space doesn't have to be.
441 ipc_right_request_cancel(
442 __unused ipc_space_t space
,
444 mach_port_name_t name
,
449 assert(ip_active(port
));
450 assert(port
== (ipc_port_t
) entry
->ie_object
);
452 if (entry
->ie_request
== IE_REQ_NONE
)
455 previous
= ipc_port_request_cancel(port
, name
, entry
->ie_request
);
456 entry
->ie_request
= IE_REQ_NONE
;
457 ipc_entry_modified(space
, name
, entry
);
462 * Routine: ipc_right_inuse
464 * Check if an entry is being used.
465 * Returns TRUE if it is.
467 * The space is write-locked and active.
468 * It is unlocked if the entry is inuse.
474 __unused mach_port_name_t name
,
477 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
478 is_write_unlock(space
);
485 * Routine: ipc_right_check
487 * Check if the port has died. If it has,
488 * clean up the entry and return TRUE.
490 * The space is write-locked; the port is not locked.
491 * If returns FALSE, the port is also locked and active.
492 * Otherwise, entry is converted to a dead name.
494 * Caller is responsible for a reference to port if it
495 * had died (returns TRUE).
502 mach_port_name_t name
,
505 ipc_entry_bits_t bits
;
507 assert(is_active(space
));
508 assert(port
== (ipc_port_t
) entry
->ie_object
);
514 /* this was either a pure send right or a send-once right */
516 bits
= entry
->ie_bits
;
517 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
518 assert(IE_BITS_UREFS(bits
) > 0);
520 if (bits
& MACH_PORT_TYPE_SEND
) {
521 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
522 assert(IE_BITS_UREFS(bits
) > 0);
523 assert(port
->ip_srights
> 0);
526 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
527 assert(IE_BITS_UREFS(bits
) == 1);
528 assert(port
->ip_sorights
> 0);
534 * delete SEND rights from ipc hash.
537 if ((bits
& MACH_PORT_TYPE_SEND
) != 0) {
538 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
541 /* convert entry to dead name */
542 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
545 * If there was a notification request outstanding on this
546 * name, and the port went dead, that notification
547 * must already be on its way up from the port layer.
549 * Add the reference that the notification carries. It
550 * is done here, and not in the notification delivery,
551 * because the latter doesn't have a space reference and
552 * trying to actually move a send-right reference would
553 * get short-circuited into a MACH_PORT_DEAD by IPC. Since
554 * all calls that deal with the right eventually come
555 * through here, it has the same result.
557 * Once done, clear the request index so we only account
560 if (entry
->ie_request
!= IE_REQ_NONE
) {
561 if (ipc_port_request_type(port
, name
, entry
->ie_request
) != 0) {
562 /* if urefs are pegged due to overflow, leave them pegged */
563 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
564 bits
++; /* increment urefs */
566 entry
->ie_request
= IE_REQ_NONE
;
568 entry
->ie_bits
= bits
;
569 entry
->ie_object
= IO_NULL
;
570 ipc_entry_modified(space
, name
, entry
);
575 * Routine: ipc_right_terminate
577 * Cleans up an entry in a terminated space.
578 * The entry isn't deallocated or removed
579 * from reverse hash tables.
581 * The space is dead and unlocked.
587 mach_port_name_t name
,
590 ipc_entry_bits_t bits
;
591 mach_port_type_t type
;
593 bits
= entry
->ie_bits
;
594 type
= IE_BITS_TYPE(bits
);
596 assert(!is_active(space
));
599 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
600 * problem, because we check that the port is active. If
601 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
602 * would still work, but dead space refs would accumulate
603 * in ip_dnrequests. They would use up slots in
604 * ip_dnrequests and keep the spaces from being freed.
608 case MACH_PORT_TYPE_DEAD_NAME
:
609 assert(entry
->ie_request
== IE_REQ_NONE
);
610 assert(entry
->ie_object
== IO_NULL
);
613 case MACH_PORT_TYPE_PORT_SET
: {
614 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
616 assert(entry
->ie_request
== IE_REQ_NONE
);
617 assert(pset
!= IPS_NULL
);
620 assert(ips_active(pset
));
621 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
625 case MACH_PORT_TYPE_SEND
:
626 case MACH_PORT_TYPE_RECEIVE
:
627 case MACH_PORT_TYPE_SEND_RECEIVE
:
628 case MACH_PORT_TYPE_SEND_ONCE
: {
629 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
631 ipc_port_t nsrequest
= IP_NULL
;
632 mach_port_mscount_t mscount
= 0;
634 assert(port
!= IP_NULL
);
637 if (!ip_active(port
)) {
643 request
= ipc_right_request_cancel_macro(space
, port
,
646 if (type
& MACH_PORT_TYPE_SEND
) {
647 assert(port
->ip_srights
> 0);
648 if (--port
->ip_srights
== 0
650 nsrequest
= port
->ip_nsrequest
;
651 if (nsrequest
!= IP_NULL
) {
652 port
->ip_nsrequest
= IP_NULL
;
653 mscount
= port
->ip_mscount
;
658 if (type
& MACH_PORT_TYPE_RECEIVE
) {
659 assert(port
->ip_receiver_name
== name
);
660 assert(port
->ip_receiver
== space
);
662 ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */
664 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
665 assert(port
->ip_sorights
> 0);
668 ipc_notify_send_once(port
); /* consumes our ref */
670 assert(port
->ip_receiver
!= space
);
676 if (nsrequest
!= IP_NULL
)
677 ipc_notify_no_senders(nsrequest
, mscount
);
679 if (request
!= IP_NULL
)
680 ipc_notify_port_deleted(request
, name
);
685 panic("ipc_right_terminate: strange type - 0x%x", type
);
690 * Routine: ipc_right_destroy
692 * Destroys an entry in a space.
694 * The space is write-locked (returns unlocked).
695 * The space must be active.
697 * KERN_SUCCESS The entry was destroyed.
703 mach_port_name_t name
,
705 boolean_t check_guard
,
708 ipc_entry_bits_t bits
;
709 mach_port_type_t type
;
711 bits
= entry
->ie_bits
;
712 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
713 type
= IE_BITS_TYPE(bits
);
715 assert(is_active(space
));
718 case MACH_PORT_TYPE_DEAD_NAME
:
719 assert(entry
->ie_request
== IE_REQ_NONE
);
720 assert(entry
->ie_object
== IO_NULL
);
722 ipc_entry_dealloc(space
, name
, entry
);
723 is_write_unlock(space
);
726 case MACH_PORT_TYPE_PORT_SET
: {
727 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
729 assert(entry
->ie_request
== IE_REQ_NONE
);
730 assert(pset
!= IPS_NULL
);
732 entry
->ie_object
= IO_NULL
;
733 ipc_entry_dealloc(space
, name
, entry
);
736 is_write_unlock(space
);
738 assert(ips_active(pset
));
739 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
743 case MACH_PORT_TYPE_SEND
:
744 case MACH_PORT_TYPE_RECEIVE
:
745 case MACH_PORT_TYPE_SEND_RECEIVE
:
746 case MACH_PORT_TYPE_SEND_ONCE
: {
747 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
748 ipc_port_t nsrequest
= IP_NULL
;
749 mach_port_mscount_t mscount
= 0;
752 assert(port
!= IP_NULL
);
754 if (type
== MACH_PORT_TYPE_SEND
)
755 ipc_hash_delete(space
, (ipc_object_t
) port
,
760 if (!ip_active(port
)) {
761 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
763 entry
->ie_request
= IE_REQ_NONE
;
764 entry
->ie_object
= IO_NULL
;
765 ipc_entry_dealloc(space
, name
, entry
);
766 is_write_unlock(space
);
771 /* For receive rights, check for guarding */
772 if ((type
& MACH_PORT_TYPE_RECEIVE
) &&
773 (check_guard
) && (port
->ip_guarded
) &&
774 (guard
!= port
->ip_context
)) {
775 /* Guard Violation */
776 uint64_t portguard
= port
->ip_context
;
778 is_write_unlock(space
);
779 /* Raise mach port guard exception */
780 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
781 return KERN_INVALID_RIGHT
;
785 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
787 entry
->ie_object
= IO_NULL
;
788 ipc_entry_dealloc(space
, name
, entry
);
789 is_write_unlock(space
);
791 if (type
& MACH_PORT_TYPE_SEND
) {
792 assert(port
->ip_srights
> 0);
793 if (--port
->ip_srights
== 0) {
794 nsrequest
= port
->ip_nsrequest
;
795 if (nsrequest
!= IP_NULL
) {
796 port
->ip_nsrequest
= IP_NULL
;
797 mscount
= port
->ip_mscount
;
802 if (type
& MACH_PORT_TYPE_RECEIVE
) {
803 assert(ip_active(port
));
804 assert(port
->ip_receiver
== space
);
806 ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */
808 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
809 assert(port
->ip_sorights
> 0);
812 ipc_notify_send_once(port
); /* consumes our ref */
814 assert(port
->ip_receiver
!= space
);
820 if (nsrequest
!= IP_NULL
)
821 ipc_notify_no_senders(nsrequest
, mscount
);
823 if (request
!= IP_NULL
)
824 ipc_notify_port_deleted(request
, name
);
831 panic("ipc_right_destroy: strange type");
838 * Routine: ipc_right_dealloc
840 * Releases a send/send-once/dead-name/port_set user ref.
841 * Like ipc_right_delta with a delta of -1,
842 * but looks at the entry to determine the right.
844 * The space is write-locked, and is unlocked upon return.
845 * The space must be active.
847 * KERN_SUCCESS A user ref was released.
848 * KERN_INVALID_RIGHT Entry has wrong type.
854 mach_port_name_t name
,
857 ipc_port_t port
= IP_NULL
;
858 ipc_entry_bits_t bits
;
859 mach_port_type_t type
;
861 bits
= entry
->ie_bits
;
862 type
= IE_BITS_TYPE(bits
);
865 assert(is_active(space
));
868 case MACH_PORT_TYPE_PORT_SET
: {
871 assert(IE_BITS_UREFS(bits
) == 0);
872 assert(entry
->ie_request
== IE_REQ_NONE
);
874 pset
= (ipc_pset_t
) entry
->ie_object
;
875 assert(pset
!= IPS_NULL
);
877 entry
->ie_object
= IO_NULL
;
878 ipc_entry_dealloc(space
, name
, entry
);
881 assert(ips_active(pset
));
882 is_write_unlock(space
);
884 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
888 case MACH_PORT_TYPE_DEAD_NAME
: {
891 assert(IE_BITS_UREFS(bits
) > 0);
892 assert(entry
->ie_request
== IE_REQ_NONE
);
893 assert(entry
->ie_object
== IO_NULL
);
895 if (IE_BITS_UREFS(bits
) == 1) {
896 ipc_entry_dealloc(space
, name
, entry
);
898 /* if urefs are pegged due to overflow, leave them pegged */
899 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
900 entry
->ie_bits
= bits
-1; /* decrement urefs */
901 ipc_entry_modified(space
, name
, entry
);
903 is_write_unlock(space
);
905 /* release any port that got converted to dead name below */
911 case MACH_PORT_TYPE_SEND_ONCE
: {
914 assert(IE_BITS_UREFS(bits
) == 1);
916 port
= (ipc_port_t
) entry
->ie_object
;
917 assert(port
!= IP_NULL
);
919 if (ipc_right_check(space
, port
, name
, entry
)) {
921 bits
= entry
->ie_bits
;
922 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
923 goto dead_name
; /* it will release port */
925 /* port is locked and active */
927 assert(port
->ip_sorights
> 0);
929 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
932 entry
->ie_object
= IO_NULL
;
933 ipc_entry_dealloc(space
, name
, entry
);
935 is_write_unlock(space
);
937 ipc_notify_send_once(port
);
939 if (request
!= IP_NULL
)
940 ipc_notify_port_deleted(request
, name
);
944 case MACH_PORT_TYPE_SEND
: {
945 ipc_port_t request
= IP_NULL
;
946 ipc_port_t nsrequest
= IP_NULL
;
947 mach_port_mscount_t mscount
= 0;
950 assert(IE_BITS_UREFS(bits
) > 0);
952 port
= (ipc_port_t
) entry
->ie_object
;
953 assert(port
!= IP_NULL
);
955 if (ipc_right_check(space
, port
, name
, entry
)) {
956 bits
= entry
->ie_bits
;
957 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
958 goto dead_name
; /* it will release port */
960 /* port is locked and active */
962 assert(port
->ip_srights
> 0);
964 if (IE_BITS_UREFS(bits
) == 1) {
965 if (--port
->ip_srights
== 0) {
966 nsrequest
= port
->ip_nsrequest
;
967 if (nsrequest
!= IP_NULL
) {
968 port
->ip_nsrequest
= IP_NULL
;
969 mscount
= port
->ip_mscount
;
973 request
= ipc_right_request_cancel_macro(space
, port
,
975 ipc_hash_delete(space
, (ipc_object_t
) port
,
979 entry
->ie_object
= IO_NULL
;
980 ipc_entry_dealloc(space
, name
, entry
);
981 is_write_unlock(space
);
986 /* if urefs are pegged due to overflow, leave them pegged */
987 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
988 entry
->ie_bits
= bits
-1; /* decrement urefs */
989 ipc_entry_modified(space
, name
, entry
);
990 is_write_unlock(space
);
993 if (nsrequest
!= IP_NULL
)
994 ipc_notify_no_senders(nsrequest
, mscount
);
996 if (request
!= IP_NULL
)
997 ipc_notify_port_deleted(request
, name
);
1001 case MACH_PORT_TYPE_SEND_RECEIVE
: {
1002 ipc_port_t nsrequest
= IP_NULL
;
1003 mach_port_mscount_t mscount
= 0;
1005 assert(IE_BITS_UREFS(bits
) > 0);
1007 port
= (ipc_port_t
) entry
->ie_object
;
1008 assert(port
!= IP_NULL
);
1011 assert(ip_active(port
));
1012 assert(port
->ip_receiver_name
== name
);
1013 assert(port
->ip_receiver
== space
);
1014 assert(port
->ip_srights
> 0);
1016 if (IE_BITS_UREFS(bits
) == 1) {
1017 if (--port
->ip_srights
== 0) {
1018 nsrequest
= port
->ip_nsrequest
;
1019 if (nsrequest
!= IP_NULL
) {
1020 port
->ip_nsrequest
= IP_NULL
;
1021 mscount
= port
->ip_mscount
;
1025 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1026 MACH_PORT_TYPE_SEND
);
1028 /* if urefs are pegged due to overflow, leave them pegged */
1029 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) {
1030 entry
->ie_bits
= bits
-1; /* decrement urefs */
1035 ipc_entry_modified(space
, name
, entry
);
1036 is_write_unlock(space
);
1038 if (nsrequest
!= IP_NULL
)
1039 ipc_notify_no_senders(nsrequest
, mscount
);
1044 is_write_unlock(space
);
1045 return KERN_INVALID_RIGHT
;
1048 return KERN_SUCCESS
;
1052 * Routine: ipc_right_delta
1054 * Modifies the user-reference count for a right.
1055 * May deallocate the right, if the count goes to zero.
1057 * The space is write-locked, and is unlocked upon return.
1058 * The space must be active.
1060 * KERN_SUCCESS Count was modified.
1061 * KERN_INVALID_RIGHT Entry has wrong type.
1062 * KERN_INVALID_VALUE Bad delta for the right.
1068 mach_port_name_t name
,
1070 mach_port_right_t right
,
1071 mach_port_delta_t delta
)
1073 ipc_port_t port
= IP_NULL
;
1074 ipc_entry_bits_t bits
;
1076 bits
= entry
->ie_bits
;
1080 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
1081 * switch below. It is used to keep track of those cases (in DIPC)
1082 * where we have postponed the dropping of a port reference. Since
1083 * the dropping of the reference could cause the port to disappear
1084 * we postpone doing so when we are holding the space lock.
1087 assert(is_active(space
));
1088 assert(right
< MACH_PORT_RIGHT_NUMBER
);
1090 /* Rights-specific restrictions and operations. */
1093 case MACH_PORT_RIGHT_PORT_SET
: {
1096 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0)
1099 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
1100 assert(IE_BITS_UREFS(bits
) == 0);
1101 assert(entry
->ie_request
== IE_REQ_NONE
);
1109 pset
= (ipc_pset_t
) entry
->ie_object
;
1110 assert(pset
!= IPS_NULL
);
1112 entry
->ie_object
= IO_NULL
;
1113 ipc_entry_dealloc(space
, name
, entry
);
1116 assert(ips_active(pset
));
1117 is_write_unlock(space
);
1119 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
1123 case MACH_PORT_RIGHT_RECEIVE
: {
1124 ipc_port_t request
= IP_NULL
;
1126 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1135 port
= (ipc_port_t
) entry
->ie_object
;
1136 assert(port
!= IP_NULL
);
1139 * The port lock is needed for ipc_right_dncancel;
1140 * otherwise, we wouldn't have to take the lock
1141 * until just before dropping the space lock.
1145 assert(ip_active(port
));
1146 assert(port
->ip_receiver_name
== name
);
1147 assert(port
->ip_receiver
== space
);
1149 /* Mach Port Guard Checking */
1150 if(port
->ip_guarded
) {
1151 uint64_t portguard
= port
->ip_context
;
1153 is_write_unlock(space
);
1154 /* Raise mach port guard exception */
1155 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_MOD_REFS
);
1159 if (bits
& MACH_PORT_TYPE_SEND
) {
1160 assert(IE_BITS_TYPE(bits
) ==
1161 MACH_PORT_TYPE_SEND_RECEIVE
);
1162 assert(IE_BITS_UREFS(bits
) > 0);
1163 assert(port
->ip_srights
> 0);
1165 if (port
->ip_pdrequest
!= NULL
) {
1167 * Since another task has requested a
1168 * destroy notification for this port, it
1169 * isn't actually being destroyed - the receive
1170 * right is just being moved to another task.
1171 * Since we still have one or more send rights,
1172 * we need to record the loss of the receive
1173 * right and enter the remaining send right
1174 * into the hash table.
1176 ipc_entry_modified(space
, name
, entry
);
1177 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1178 ipc_hash_insert(space
, (ipc_object_t
) port
,
1183 * The remaining send right turns into a
1184 * dead name. Notice we don't decrement
1185 * ip_srights, generate a no-senders notif,
1186 * or use ipc_right_dncancel, because the
1187 * port is destroyed "first".
1189 bits
&= ~IE_BITS_TYPE_MASK
;
1190 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1191 if (entry
->ie_request
) {
1192 entry
->ie_request
= IE_REQ_NONE
;
1193 /* if urefs are pegged due to overflow, leave them pegged */
1194 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
1195 bits
++; /* increment urefs */
1197 entry
->ie_bits
= bits
;
1198 entry
->ie_object
= IO_NULL
;
1199 ipc_entry_modified(space
, name
, entry
);
1202 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1203 assert(IE_BITS_UREFS(bits
) == 0);
1205 request
= ipc_right_request_cancel_macro(space
, port
,
1207 entry
->ie_object
= IO_NULL
;
1208 ipc_entry_dealloc(space
, name
, entry
);
1210 is_write_unlock(space
);
1212 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1214 if (request
!= IP_NULL
)
1215 ipc_notify_port_deleted(request
, name
);
1219 case MACH_PORT_RIGHT_SEND_ONCE
: {
1222 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1225 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1226 assert(IE_BITS_UREFS(bits
) == 1);
1228 port
= (ipc_port_t
) entry
->ie_object
;
1229 assert(port
!= IP_NULL
);
1231 if (ipc_right_check(space
, port
, name
, entry
)) {
1232 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1235 /* port is locked and active */
1237 assert(port
->ip_sorights
> 0);
1239 if ((delta
> 0) || (delta
< -1)) {
1249 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1252 entry
->ie_object
= IO_NULL
;
1253 ipc_entry_dealloc(space
, name
, entry
);
1255 is_write_unlock(space
);
1257 ipc_notify_send_once(port
);
1259 if (request
!= IP_NULL
)
1260 ipc_notify_port_deleted(request
, name
);
1264 case MACH_PORT_RIGHT_DEAD_NAME
: {
1265 ipc_port_t relport
= IP_NULL
;
1266 mach_port_urefs_t urefs
;
1268 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1270 port
= (ipc_port_t
) entry
->ie_object
;
1271 assert(port
!= IP_NULL
);
1273 if (!ipc_right_check(space
, port
, name
, entry
)) {
1274 /* port is locked and active */
1279 bits
= entry
->ie_bits
;
1282 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0) {
1286 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1287 assert(IE_BITS_UREFS(bits
) > 0);
1288 assert(entry
->ie_object
== IO_NULL
);
1289 assert(entry
->ie_request
== IE_REQ_NONE
);
1291 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1292 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1296 urefs
= IE_BITS_UREFS(bits
);
1298 if (urefs
== MACH_PORT_UREFS_MAX
) {
1300 * urefs are pegged due to an overflow
1301 * only a delta removing all refs at once can change it
1304 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
)))
1307 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1309 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1310 /* leave urefs pegged to maximum if it overflowed */
1311 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1315 if ((urefs
+ delta
) == 0) {
1316 ipc_entry_dealloc(space
, name
, entry
);
1317 } else if (delta
!= 0) {
1318 entry
->ie_bits
= bits
+ delta
;
1319 ipc_entry_modified(space
, name
, entry
);
1322 is_write_unlock(space
);
1324 if (relport
!= IP_NULL
)
1325 ip_release(relport
);
1330 case MACH_PORT_RIGHT_SEND
: {
1331 mach_port_urefs_t urefs
;
1332 ipc_port_t request
= IP_NULL
;
1333 ipc_port_t nsrequest
= IP_NULL
;
1334 ipc_port_t port_to_release
= IP_NULL
;
1335 mach_port_mscount_t mscount
= 0;
1337 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1340 /* maximum urefs for send is MACH_PORT_UREFS_MAX */
1342 port
= (ipc_port_t
) entry
->ie_object
;
1343 assert(port
!= IP_NULL
);
1345 if (ipc_right_check(space
, port
, name
, entry
)) {
1346 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1349 /* port is locked and active */
1351 assert(port
->ip_srights
> 0);
1353 if (delta
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) ||
1354 delta
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) {
1359 urefs
= IE_BITS_UREFS(bits
);
1361 if (urefs
== MACH_PORT_UREFS_MAX
) {
1363 * urefs are pegged due to an overflow
1364 * only a delta removing all refs at once can change it
1367 if (delta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
)))
1370 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1374 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) {
1375 /* leave urefs pegged to maximum if it overflowed */
1376 delta
= MACH_PORT_UREFS_MAX
- urefs
;
1380 if ((urefs
+ delta
) == 0) {
1381 if (--port
->ip_srights
== 0) {
1382 nsrequest
= port
->ip_nsrequest
;
1383 if (nsrequest
!= IP_NULL
) {
1384 port
->ip_nsrequest
= IP_NULL
;
1385 mscount
= port
->ip_mscount
;
1389 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1390 assert(port
->ip_receiver_name
== name
);
1391 assert(port
->ip_receiver
== space
);
1393 assert(IE_BITS_TYPE(bits
) ==
1394 MACH_PORT_TYPE_SEND_RECEIVE
);
1396 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1397 MACH_PORT_TYPE_SEND
);
1398 ipc_entry_modified(space
, name
, entry
);
1400 assert(IE_BITS_TYPE(bits
) ==
1401 MACH_PORT_TYPE_SEND
);
1403 request
= ipc_right_request_cancel_macro(space
, port
,
1405 ipc_hash_delete(space
, (ipc_object_t
) port
,
1409 port_to_release
= port
;
1411 entry
->ie_object
= IO_NULL
;
1412 ipc_entry_dealloc(space
, name
, entry
);
1414 } else if (delta
!= 0) {
1416 entry
->ie_bits
= bits
+ delta
;
1417 ipc_entry_modified(space
, name
, entry
);
1422 is_write_unlock(space
);
1424 if (port_to_release
!= IP_NULL
)
1425 ip_release(port_to_release
);
1427 if (nsrequest
!= IP_NULL
)
1428 ipc_notify_no_senders(nsrequest
, mscount
);
1430 if (request
!= IP_NULL
)
1431 ipc_notify_port_deleted(request
, name
);
1435 case MACH_PORT_RIGHT_LABELH
:
1439 panic("ipc_right_delta: strange right %d for 0x%x (%p) in space:%p",
1440 right
, name
, (void *)entry
, (void *)space
);
1443 return KERN_SUCCESS
;
1446 is_write_unlock(space
);
1447 return KERN_SUCCESS
;
1450 is_write_unlock(space
);
1451 if (port
!= IP_NULL
)
1453 return KERN_INVALID_RIGHT
;
1456 is_write_unlock(space
);
1457 return KERN_INVALID_VALUE
;
1460 return KERN_INVALID_RIGHT
;
1464 * Routine: ipc_right_destruct
1466 * Deallocates the receive right and modifies the
1467 * user-reference count for the send rights as requested.
1469 * The space is write-locked, and is unlocked upon return.
1470 * The space must be active.
1472 * KERN_SUCCESS Count was modified.
1473 * KERN_INVALID_RIGHT Entry has wrong type.
1474 * KERN_INVALID_VALUE Bad delta for the right.
1480 mach_port_name_t name
,
1482 mach_port_delta_t srdelta
,
1485 ipc_port_t port
= IP_NULL
;
1486 ipc_entry_bits_t bits
;
1488 mach_port_urefs_t urefs
;
1489 ipc_port_t request
= IP_NULL
;
1490 ipc_port_t nsrequest
= IP_NULL
;
1491 mach_port_mscount_t mscount
= 0;
1493 bits
= entry
->ie_bits
;
1495 assert(is_active(space
));
1497 if (((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) ||
1498 (srdelta
&& ((bits
& MACH_PORT_TYPE_SEND
) == 0))) {
1499 is_write_unlock(space
);
1500 return KERN_INVALID_RIGHT
;
1506 port
= (ipc_port_t
) entry
->ie_object
;
1507 assert(port
!= IP_NULL
);
1510 assert(ip_active(port
));
1511 assert(port
->ip_receiver_name
== name
);
1512 assert(port
->ip_receiver
== space
);
1514 /* Mach Port Guard Checking */
1515 if(port
->ip_guarded
&& (guard
!= port
->ip_context
)) {
1516 uint64_t portguard
= port
->ip_context
;
1518 is_write_unlock(space
);
1519 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
1520 return KERN_INVALID_ARGUMENT
;
1524 * First reduce the send rights as requested and
1525 * adjust the entry->ie_bits accordingly. The
1526 * ipc_entry_modified() call is made once the receive
1527 * right is destroyed too.
1532 assert(port
->ip_srights
> 0);
1534 urefs
= IE_BITS_UREFS(bits
);
1537 * Since we made sure that srdelta is negative,
1538 * the check for urefs overflow is not required.
1540 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, srdelta
)) {
1545 if (urefs
== MACH_PORT_UREFS_MAX
) {
1547 * urefs are pegged due to an overflow
1548 * only a delta removing all refs at once can change it
1550 if (srdelta
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
)))
1554 if ((urefs
+ srdelta
) == 0) {
1555 if (--port
->ip_srights
== 0) {
1556 nsrequest
= port
->ip_nsrequest
;
1557 if (nsrequest
!= IP_NULL
) {
1558 port
->ip_nsrequest
= IP_NULL
;
1559 mscount
= port
->ip_mscount
;
1562 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_RECEIVE
);
1563 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1564 MACH_PORT_TYPE_SEND
);
1566 entry
->ie_bits
= bits
+ srdelta
;
1571 * Now destroy the receive right. Update space and
1572 * entry accordingly.
1575 bits
= entry
->ie_bits
;
1576 if (bits
& MACH_PORT_TYPE_SEND
) {
1577 assert(IE_BITS_UREFS(bits
) > 0);
1578 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
1580 if (port
->ip_pdrequest
!= NULL
) {
1582 * Since another task has requested a
1583 * destroy notification for this port, it
1584 * isn't actually being destroyed - the receive
1585 * right is just being moved to another task.
1586 * Since we still have one or more send rights,
1587 * we need to record the loss of the receive
1588 * right and enter the remaining send right
1589 * into the hash table.
1591 ipc_entry_modified(space
, name
, entry
);
1592 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1593 ipc_hash_insert(space
, (ipc_object_t
) port
,
1598 * The remaining send right turns into a
1599 * dead name. Notice we don't decrement
1600 * ip_srights, generate a no-senders notif,
1601 * or use ipc_right_dncancel, because the
1602 * port is destroyed "first".
1604 bits
&= ~IE_BITS_TYPE_MASK
;
1605 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1606 if (entry
->ie_request
) {
1607 entry
->ie_request
= IE_REQ_NONE
;
1608 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
1609 bits
++; /* increment urefs */
1611 entry
->ie_bits
= bits
;
1612 entry
->ie_object
= IO_NULL
;
1613 ipc_entry_modified(space
, name
, entry
);
1616 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1617 assert(IE_BITS_UREFS(bits
) == 0);
1618 request
= ipc_right_request_cancel_macro(space
, port
,
1620 entry
->ie_object
= IO_NULL
;
1621 ipc_entry_dealloc(space
, name
, entry
);
1625 is_write_unlock(space
);
1627 if (nsrequest
!= IP_NULL
)
1628 ipc_notify_no_senders(nsrequest
, mscount
);
1630 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */
1632 if (request
!= IP_NULL
)
1633 ipc_notify_port_deleted(request
, name
);
1635 return KERN_SUCCESS
;
1638 is_write_unlock(space
);
1639 return KERN_INVALID_VALUE
;
1645 * Routine: ipc_right_info
1647 * Retrieves information about the right.
1649 * The space is active and write-locked.
1650 * The space is unlocked upon return.
1652 * KERN_SUCCESS Retrieved info
1658 mach_port_name_t name
,
1660 mach_port_type_t
*typep
,
1661 mach_port_urefs_t
*urefsp
)
1664 ipc_entry_bits_t bits
;
1665 mach_port_type_t type
= 0;
1666 ipc_port_request_index_t request
;
1668 bits
= entry
->ie_bits
;
1669 request
= entry
->ie_request
;
1670 port
= (ipc_port_t
) entry
->ie_object
;
1672 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1673 assert(IP_VALID(port
));
1675 if (request
!= IE_REQ_NONE
) {
1677 assert(ip_active(port
));
1678 type
|= ipc_port_request_type(port
, name
, request
);
1681 is_write_unlock(space
);
1683 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1685 * validate port is still alive - if so, get request
1686 * types while we still have it locked. Otherwise,
1687 * recapture the (now dead) bits.
1689 if (!ipc_right_check(space
, port
, name
, entry
)) {
1690 if (request
!= IE_REQ_NONE
)
1691 type
|= ipc_port_request_type(port
, name
, request
);
1693 is_write_unlock(space
);
1695 bits
= entry
->ie_bits
;
1696 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1697 is_write_unlock(space
);
1701 is_write_unlock(space
);
1704 type
|= IE_BITS_TYPE(bits
);
1707 *urefsp
= IE_BITS_UREFS(bits
);
1708 return KERN_SUCCESS
;
1712 * Routine: ipc_right_copyin_check
1714 * Check if a subsequent ipc_right_copyin would succeed.
1716 * The space is locked (read or write) and active.
1720 ipc_right_copyin_check(
1721 __assert_only ipc_space_t space
,
1722 __unused mach_port_name_t name
,
1724 mach_msg_type_name_t msgt_name
)
1726 ipc_entry_bits_t bits
;
1729 bits
= entry
->ie_bits
;
1730 assert(is_active(space
));
1732 switch (msgt_name
) {
1733 case MACH_MSG_TYPE_MAKE_SEND
:
1734 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1738 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1739 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1743 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1744 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1746 if (io_kotype(entry
->ie_object
) != IKOT_NONE
)
1748 port
= (ipc_port_t
) entry
->ie_object
;
1749 if (port
->ip_specialreply
)
1753 case MACH_MSG_TYPE_COPY_SEND
:
1754 case MACH_MSG_TYPE_MOVE_SEND
:
1755 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1757 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1760 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1763 port
= (ipc_port_t
) entry
->ie_object
;
1764 assert(port
!= IP_NULL
);
1767 * active status peek to avoid checks that will be skipped
1768 * on copyin for dead ports. Lock not held, so will not be
1769 * atomic (but once dead, there's no going back).
1771 if (!ip_active(port
)) {
1775 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1776 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1779 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1787 panic("ipc_right_copyin_check: strange rights");
1794 * Routine: ipc_right_copyin
1796 * Copyin a capability from a space.
1797 * If successful, the caller gets a ref
1798 * for the resulting object, unless it is IO_DEAD,
1799 * and possibly a send-once right which should
1800 * be used in a port-deleted notification.
1802 * If deadok is not TRUE, the copyin operation
1803 * will fail instead of producing IO_DEAD.
1805 * The entry is never deallocated (except
1806 * when KERN_INVALID_NAME), so the caller
1807 * should deallocate the entry if its type
1808 * is MACH_PORT_TYPE_NONE.
1810 * The space is write-locked and active.
1812 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1813 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1819 mach_port_name_t name
,
1821 mach_msg_type_name_t msgt_name
,
1823 ipc_object_t
*objectp
,
1824 ipc_port_t
*sorightp
,
1825 ipc_port_t
*releasep
,
1828 ipc_entry_bits_t bits
;
1831 *releasep
= IP_NULL
;
1834 bits
= entry
->ie_bits
;
1836 assert(is_active(space
));
1838 switch (msgt_name
) {
1839 case MACH_MSG_TYPE_MAKE_SEND
: {
1841 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1844 port
= (ipc_port_t
) entry
->ie_object
;
1845 assert(port
!= IP_NULL
);
1848 assert(ip_active(port
));
1849 assert(port
->ip_receiver_name
== name
);
1850 assert(port
->ip_receiver
== space
);
1857 *objectp
= (ipc_object_t
) port
;
1858 *sorightp
= IP_NULL
;
1862 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1864 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1867 port
= (ipc_port_t
) entry
->ie_object
;
1868 assert(port
!= IP_NULL
);
1871 assert(ip_active(port
));
1872 assert(port
->ip_receiver_name
== name
);
1873 assert(port
->ip_receiver
== space
);
1875 port
->ip_sorights
++;
1879 *objectp
= (ipc_object_t
) port
;
1880 *sorightp
= IP_NULL
;
1884 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1885 ipc_port_t request
= IP_NULL
;
1887 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1891 * Disallow moving receive-right kobjects, e.g. mk_timer ports
1892 * The ipc_port structure uses the kdata union of kobject and
1893 * imp_task exclusively. Thus, general use of a kobject port as
1894 * a receive right can cause type confusion in the importance
1897 if (io_kotype(entry
->ie_object
) != IKOT_NONE
) {
1899 * Distinguish an invalid right, e.g., trying to move
1900 * a send right as a receive right, from this
1901 * situation which is, "This is a valid receive right,
1902 * but it's also a kobject and you can't move it."
1904 return KERN_INVALID_CAPABILITY
;
1907 port
= (ipc_port_t
) entry
->ie_object
;
1908 assert(port
!= IP_NULL
);
1911 assert(ip_active(port
));
1912 assert(port
->ip_receiver_name
== name
);
1913 assert(port
->ip_receiver
== space
);
1915 if (bits
& MACH_PORT_TYPE_SEND
) {
1916 assert(IE_BITS_TYPE(bits
) ==
1917 MACH_PORT_TYPE_SEND_RECEIVE
);
1918 assert(IE_BITS_UREFS(bits
) > 0);
1919 assert(port
->ip_srights
> 0);
1921 ipc_hash_insert(space
, (ipc_object_t
) port
,
1925 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1926 assert(IE_BITS_UREFS(bits
) == 0);
1928 request
= ipc_right_request_cancel_macro(space
, port
,
1930 entry
->ie_object
= IO_NULL
;
1932 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1933 ipc_entry_modified(space
, name
, entry
);
1935 (void)ipc_port_clear_receiver(port
, FALSE
); /* don't destroy the port/mqueue */
1936 port
->ip_receiver_name
= MACH_PORT_NULL
;
1937 port
->ip_destination
= IP_NULL
;
1939 #if IMPORTANCE_INHERITANCE
1941 * Account for boosts the current task is going to lose when
1942 * copying this right in. Tempowner ports have either not
1943 * been accounting to any task (and therefore are already in
1944 * "limbo" state w.r.t. assertions) or to some other specific
1945 * task. As we have no way to drop the latter task's assertions
1946 * here, We'll deduct those when we enqueue it on its
1947 * destination port (see ipc_port_check_circularity()).
1949 if (port
->ip_tempowner
== 0) {
1950 assert(IIT_NULL
== port
->ip_imp_task
);
1952 /* ports in limbo have to be tempowner */
1953 port
->ip_tempowner
= 1;
1954 *assertcntp
= port
->ip_impcount
;
1956 #endif /* IMPORTANCE_INHERITANCE */
1960 *objectp
= (ipc_object_t
) port
;
1961 *sorightp
= request
;
1965 case MACH_MSG_TYPE_COPY_SEND
: {
1967 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1970 /* allow for dead send-once rights */
1972 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1975 assert(IE_BITS_UREFS(bits
) > 0);
1977 port
= (ipc_port_t
) entry
->ie_object
;
1978 assert(port
!= IP_NULL
);
1980 if (ipc_right_check(space
, port
, name
, entry
)) {
1981 bits
= entry
->ie_bits
;
1985 /* port is locked and active */
1987 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1988 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1989 assert(port
->ip_sorights
> 0);
1995 assert(port
->ip_srights
> 0);
2001 *objectp
= (ipc_object_t
) port
;
2002 *sorightp
= IP_NULL
;
2006 case MACH_MSG_TYPE_MOVE_SEND
: {
2007 ipc_port_t request
= IP_NULL
;
2009 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
2012 /* allow for dead send-once rights */
2014 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
2017 assert(IE_BITS_UREFS(bits
) > 0);
2019 port
= (ipc_port_t
) entry
->ie_object
;
2020 assert(port
!= IP_NULL
);
2022 if (ipc_right_check(space
, port
, name
, entry
)) {
2023 bits
= entry
->ie_bits
;
2027 /* port is locked and active */
2029 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2030 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2031 assert(port
->ip_sorights
> 0);
2037 assert(port
->ip_srights
> 0);
2039 if (IE_BITS_UREFS(bits
) == 1) {
2040 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2041 assert(port
->ip_receiver_name
== name
);
2042 assert(port
->ip_receiver
== space
);
2043 assert(IE_BITS_TYPE(bits
) ==
2044 MACH_PORT_TYPE_SEND_RECEIVE
);
2048 assert(IE_BITS_TYPE(bits
) ==
2049 MACH_PORT_TYPE_SEND
);
2051 request
= ipc_right_request_cancel_macro(space
, port
,
2053 ipc_hash_delete(space
, (ipc_object_t
) port
,
2055 entry
->ie_object
= IO_NULL
;
2056 /* transfer entry's reference to caller */
2058 entry
->ie_bits
= bits
&~
2059 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
2063 /* if urefs are pegged due to overflow, leave them pegged */
2064 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
2065 entry
->ie_bits
= bits
-1; /* decrement urefs */
2068 ipc_entry_modified(space
, name
, entry
);
2071 *objectp
= (ipc_object_t
) port
;
2072 *sorightp
= request
;
2076 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
2079 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
2082 /* allow for dead send rights */
2084 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
2087 assert(IE_BITS_UREFS(bits
) > 0);
2089 port
= (ipc_port_t
) entry
->ie_object
;
2090 assert(port
!= IP_NULL
);
2092 if (ipc_right_check(space
, port
, name
, entry
)) {
2093 bits
= entry
->ie_bits
;
2097 /* port is locked and active */
2099 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
2100 assert(bits
& MACH_PORT_TYPE_SEND
);
2101 assert(port
->ip_srights
> 0);
2107 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2108 assert(IE_BITS_UREFS(bits
) == 1);
2109 assert(port
->ip_sorights
> 0);
2111 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
2114 entry
->ie_object
= IO_NULL
;
2115 entry
->ie_bits
= bits
&~
2116 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
2117 ipc_entry_modified(space
, name
, entry
);
2118 *objectp
= (ipc_object_t
) port
;
2119 *sorightp
= request
;
2125 return KERN_INVALID_RIGHT
;
2128 return KERN_SUCCESS
;
2131 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2132 assert(IE_BITS_UREFS(bits
) > 0);
2133 assert(entry
->ie_request
== IE_REQ_NONE
);
2134 assert(entry
->ie_object
== 0);
2140 *sorightp
= IP_NULL
;
2141 return KERN_SUCCESS
;
2144 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2145 assert(IE_BITS_UREFS(bits
) > 0);
2146 assert(entry
->ie_request
== IE_REQ_NONE
);
2147 assert(entry
->ie_object
== 0);
2152 if (IE_BITS_UREFS(bits
) == 1) {
2153 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
2155 /* if urefs are pegged due to overflow, leave them pegged */
2156 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
2157 entry
->ie_bits
= bits
-1; /* decrement urefs */
2159 ipc_entry_modified(space
, name
, entry
);
2161 *sorightp
= IP_NULL
;
2162 return KERN_SUCCESS
;
2167 * Routine: ipc_right_copyin_undo
2169 * Undoes the effects of an ipc_right_copyin
2170 * of a send/send-once right that is dead.
2171 * (Object is either IO_DEAD or a dead port.)
2173 * The space is write-locked and active.
2177 ipc_right_copyin_undo(
2179 mach_port_name_t name
,
2181 mach_msg_type_name_t msgt_name
,
2182 ipc_object_t object
,
2185 ipc_entry_bits_t bits
;
2187 bits
= entry
->ie_bits
;
2189 assert(is_active(space
));
2191 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2192 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
2193 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2195 if (soright
!= IP_NULL
) {
2196 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2197 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2198 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2199 assert(object
!= IO_DEAD
);
2201 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
2202 MACH_PORT_TYPE_DEAD_NAME
| 2);
2204 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
2205 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2206 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2208 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
2209 MACH_PORT_TYPE_DEAD_NAME
| 1);
2210 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
2211 assert(object
== IO_DEAD
);
2212 assert(IE_BITS_UREFS(bits
) > 0);
2214 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2215 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
2216 /* if urefs are pegged due to overflow, leave them pegged */
2217 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
2218 entry
->ie_bits
= bits
+1; /* increment urefs */
2221 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2222 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
2223 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2224 assert(object
!= IO_DEAD
);
2225 assert(entry
->ie_object
== object
);
2226 assert(IE_BITS_UREFS(bits
) > 0);
2228 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2229 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
);
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; /* increment urefs */
2236 * May as well convert the entry to a dead name.
2237 * (Or if it is a compat entry, destroy it.)
2240 (void) ipc_right_check(space
, (ipc_port_t
) object
,
2242 /* object is dead so it is not locked */
2244 ipc_entry_modified(space
, name
, entry
);
2245 /* release the reference acquired by copyin */
2247 if (object
!= IO_DEAD
)
2252 * Routine: ipc_right_copyin_two_move_sends
2254 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
2255 * and deadok == FALSE, except that this moves two
2256 * send rights at once.
2258 * The space is write-locked and active.
2259 * The object is returned with two refs/send rights.
2261 * KERN_SUCCESS Acquired an object.
2262 * KERN_INVALID_RIGHT Name doesn't denote correct right.
2266 ipc_right_copyin_two_move_sends(
2268 mach_port_name_t name
,
2270 ipc_object_t
*objectp
,
2271 ipc_port_t
*sorightp
,
2272 ipc_port_t
*releasep
)
2274 ipc_entry_bits_t bits
;
2275 mach_port_urefs_t urefs
;
2277 ipc_port_t request
= IP_NULL
;
2279 *releasep
= IP_NULL
;
2281 assert(is_active(space
));
2283 bits
= entry
->ie_bits
;
2285 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
2288 urefs
= IE_BITS_UREFS(bits
);
2292 port
= (ipc_port_t
) entry
->ie_object
;
2293 assert(port
!= IP_NULL
);
2295 if (ipc_right_check(space
, port
, name
, entry
)) {
2299 /* port is locked and active */
2301 assert(port
->ip_srights
> 0);
2304 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2305 assert(port
->ip_receiver_name
== name
);
2306 assert(port
->ip_receiver
== space
);
2307 assert(IE_BITS_TYPE(bits
) ==
2308 MACH_PORT_TYPE_SEND_RECEIVE
);
2314 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2316 request
= ipc_right_request_cancel_macro(space
, port
,
2321 ipc_hash_delete(space
, (ipc_object_t
) port
,
2323 entry
->ie_object
= IO_NULL
;
2325 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
2327 port
->ip_srights
+= 2;
2330 /* if urefs are pegged due to overflow, leave them pegged */
2331 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
)
2332 entry
->ie_bits
= bits
-2; /* decrement urefs */
2334 ipc_entry_modified(space
, name
, entry
);
2338 *objectp
= (ipc_object_t
) port
;
2339 *sorightp
= request
;
2340 return KERN_SUCCESS
;
2343 return KERN_INVALID_RIGHT
;
2348 * Routine: ipc_right_copyin_two
2350 * Like ipc_right_copyin with two dispositions,
2351 * each of which results in a send or send-once right,
2352 * and deadok = FALSE.
2354 * The space is write-locked and active.
2355 * The object is returned with two refs/rights.
2357 * KERN_SUCCESS Acquired an object.
2358 * KERN_INVALID_RIGHT Name doesn't denote correct right(s).
2359 * KERN_INVALID_CAPABILITY Name doesn't denote correct right for msgt_two.
2362 ipc_right_copyin_two(
2364 mach_port_name_t name
,
2366 mach_msg_type_name_t msgt_one
,
2367 mach_msg_type_name_t msgt_two
,
2368 ipc_object_t
*objectp
,
2369 ipc_port_t
*sorightp
,
2370 ipc_port_t
*releasep
)
2375 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one
));
2376 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two
));
2380 * Pre-validate the second disposition is possible all by itself.
2382 if (!ipc_right_copyin_check(space
, name
, entry
, msgt_two
)) {
2383 return KERN_INVALID_CAPABILITY
;
2387 * This is a little tedious to make atomic, because
2388 * there are 25 combinations of valid dispositions.
2389 * However, most are easy.
2393 * If either is move-sonce, then there must be an error.
2395 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND_ONCE
||
2396 msgt_two
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
2397 return KERN_INVALID_RIGHT
;
2400 if ((msgt_one
== MACH_MSG_TYPE_MAKE_SEND
) ||
2401 (msgt_one
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) ||
2402 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND
) ||
2403 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) {
2405 * One of the dispositions needs a receive right.
2407 * If the copyin below succeeds, we know the receive
2408 * right is there (because the pre-validation of
2409 * the second disposition already succeeded in our
2412 * Hence the port is not in danger of dying.
2414 ipc_object_t object_two
;
2416 kr
= ipc_right_copyin(space
, name
, entry
,
2418 objectp
, sorightp
, releasep
,
2420 assert(assertcnt
== 0);
2421 if (kr
!= KERN_SUCCESS
) {
2425 assert(IO_VALID(*objectp
));
2426 assert(*sorightp
== IP_NULL
);
2427 assert(*releasep
== IP_NULL
);
2430 * Now copyin the second (previously validated)
2431 * disposition. The result can't be a dead port,
2432 * as no valid disposition can make us lose our
2435 kr
= ipc_right_copyin(space
, name
, entry
,
2437 &object_two
, sorightp
, releasep
,
2439 assert(assertcnt
== 0);
2440 assert(kr
== KERN_SUCCESS
);
2441 assert(*sorightp
== IP_NULL
);
2442 assert(*releasep
== IP_NULL
);
2443 assert(object_two
== *objectp
);
2444 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
2446 } else if ((msgt_one
== MACH_MSG_TYPE_MOVE_SEND
) &&
2447 (msgt_two
== MACH_MSG_TYPE_MOVE_SEND
)) {
2449 * This is an easy case. Just use our
2450 * handy-dandy special-purpose copyin call
2451 * to get two send rights for the price of one.
2453 kr
= ipc_right_copyin_two_move_sends(space
, name
, entry
,
2456 if (kr
!= KERN_SUCCESS
) {
2461 mach_msg_type_name_t msgt_name
;
2464 * Must be either a single move-send and a
2465 * copy-send, or two copy-send dispositions.
2466 * Use the disposition with the greatest side
2467 * effects for the actual copyin - then just
2468 * duplicate the send right you get back.
2470 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND
||
2471 msgt_two
== MACH_MSG_TYPE_MOVE_SEND
) {
2472 msgt_name
= MACH_MSG_TYPE_MOVE_SEND
;
2474 msgt_name
= MACH_MSG_TYPE_COPY_SEND
;
2477 kr
= ipc_right_copyin(space
, name
, entry
,
2479 objectp
, sorightp
, releasep
,
2481 assert(assertcnt
== 0);
2482 if (kr
!= KERN_SUCCESS
) {
2487 * Copy the right we got back. If it is dead now,
2488 * that's OK. Neither right will be usable to send
2491 (void)ipc_port_copy_send((ipc_port_t
)*objectp
);
2494 return KERN_SUCCESS
;
2499 * Routine: ipc_right_copyout
2501 * Copyout a capability to a space.
2502 * If successful, consumes a ref for the object.
2504 * Always succeeds when given a newly-allocated entry,
2505 * because user-reference overflow isn't a possibility.
2507 * If copying out the object would cause the user-reference
2508 * count in the entry to overflow, and overflow is TRUE,
2509 * then instead the user-reference count is left pegged
2510 * to its maximum value and the copyout succeeds anyway.
2512 * The space is write-locked and active.
2513 * The object is locked and active.
2514 * The object is unlocked; the space isn't.
2516 * KERN_SUCCESS Copied out capability.
2522 mach_port_name_t name
,
2524 mach_msg_type_name_t msgt_name
,
2525 __unused boolean_t overflow
,
2526 ipc_object_t object
)
2528 ipc_entry_bits_t bits
;
2531 bits
= entry
->ie_bits
;
2533 assert(IO_VALID(object
));
2534 assert(io_otype(object
) == IOT_PORT
);
2535 assert(io_active(object
));
2536 assert(entry
->ie_object
== object
);
2538 port
= (ipc_port_t
) object
;
2540 switch (msgt_name
) {
2541 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
2543 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2544 assert(IE_BITS_UREFS(bits
) == 0);
2545 assert(port
->ip_sorights
> 0);
2547 if (port
->ip_specialreply
) {
2548 ipc_port_unlink_special_reply_port_locked(port
,
2549 current_thread()->ith_knote
, IPC_PORT_UNLINK_SR_NONE
);
2550 /* port unlocked on return */
2555 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1); /* set urefs to 1 */
2556 ipc_entry_modified(space
, name
, entry
);
2559 case MACH_MSG_TYPE_PORT_SEND
:
2560 assert(port
->ip_srights
> 0);
2562 if (bits
& MACH_PORT_TYPE_SEND
) {
2563 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
2565 assert(port
->ip_srights
> 1);
2567 assert(urefs
<= MACH_PORT_UREFS_MAX
);
2569 if (urefs
== MACH_PORT_UREFS_MAX
) {
2571 * leave urefs pegged to maximum,
2572 * consume send right and ref
2578 return KERN_SUCCESS
;
2581 /* consume send right and ref */
2586 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2587 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2588 assert(IE_BITS_UREFS(bits
) == 0);
2590 /* transfer send right to entry, consume ref */
2595 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2596 assert(IE_BITS_UREFS(bits
) == 0);
2598 /* transfer send right and ref to entry */
2601 /* entry is locked holding ref, so can use port */
2603 ipc_hash_insert(space
, (ipc_object_t
) port
,
2607 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1; /* increment urefs */
2608 ipc_entry_modified(space
, name
, entry
);
2611 case MACH_MSG_TYPE_PORT_RECEIVE
: {
2613 sync_qos_count_t max_sync_qos
= THREAD_QOS_UNSPECIFIED
;
2614 sync_qos_count_t sync_qos_delta_add
[THREAD_QOS_LAST
] = {0};
2615 sync_qos_count_t sync_qos_delta_sub
[THREAD_QOS_LAST
] = {0};
2617 #if IMPORTANCE_INHERITANCE
2618 natural_t assertcnt
= port
->ip_impcount
;
2619 #endif /* IMPORTANCE_INHERITANCE */
2620 /* Capture the sync qos count delta */
2621 for (int i
= 0; i
< THREAD_QOS_LAST
; i
++) {
2622 sync_qos_delta_sub
[i
] = port_sync_qos(port
, i
);
2623 if (sync_qos_delta_sub
[i
] != 0) {
2628 assert(port
->ip_mscount
== 0);
2629 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
2630 dest
= port
->ip_destination
;
2632 port
->ip_receiver_name
= name
;
2633 port
->ip_receiver
= space
;
2635 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
2637 if (bits
& MACH_PORT_TYPE_SEND
) {
2638 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2639 assert(IE_BITS_UREFS(bits
) > 0);
2640 assert(port
->ip_srights
> 0);
2645 /* entry is locked holding ref, so can use port */
2647 ipc_hash_delete(space
, (ipc_object_t
) port
,
2650 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2651 assert(IE_BITS_UREFS(bits
) == 0);
2653 /* transfer ref to entry */
2656 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2657 ipc_entry_modified(space
, name
, entry
);
2659 /* update the sync qos count on knote */
2660 if (ITH_KNOTE_VALID(current_thread()->ith_knote
)) {
2661 knote_adjust_sync_qos(current_thread()->ith_knote
, max_sync_qos
, TRUE
);
2664 if (dest
!= IP_NULL
) {
2665 #if IMPORTANCE_INHERITANCE
2667 * Deduct the assertion counts we contributed to
2668 * the old destination port. They've already
2669 * been reflected into the task as a result of
2673 ipc_port_impcount_delta(dest
, 0 - assertcnt
, IP_NULL
);
2675 #endif /* IMPORTANCE_INHERITANCE */
2676 /* Adjust the sync qos of destination */
2677 ipc_port_adjust_sync_qos(dest
, sync_qos_delta_add
, sync_qos_delta_sub
);
2684 panic("ipc_right_copyout: strange rights");
2686 return KERN_SUCCESS
;
2690 * Routine: ipc_right_rename
2692 * Transfer an entry from one name to another.
2693 * The old entry is deallocated.
2695 * The space is write-locked and active.
2696 * The new entry is unused. Upon return,
2697 * the space is unlocked.
2699 * KERN_SUCCESS Moved entry to new name.
2705 mach_port_name_t oname
,
2707 mach_port_name_t nname
,
2710 ipc_port_request_index_t request
= oentry
->ie_request
;
2711 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2712 ipc_object_t object
= oentry
->ie_object
;
2713 ipc_port_t release_port
= IP_NULL
;
2715 assert(is_active(space
));
2716 assert(oname
!= nname
);
2719 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2720 * if the port is dead. (This would foil ipc_port_destroy.)
2721 * Instead we should fail because oentry shouldn't exist.
2722 * Note IE_BITS_COMPAT implies ie_request != 0.
2725 if (request
!= IE_REQ_NONE
) {
2728 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2729 port
= (ipc_port_t
) object
;
2730 assert(port
!= IP_NULL
);
2732 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2733 request
= IE_REQ_NONE
;
2735 bits
= oentry
->ie_bits
;
2736 release_port
= port
;
2737 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2738 assert(oentry
->ie_request
== IE_REQ_NONE
);
2740 /* port is locked and active */
2742 ipc_port_request_rename(port
, request
, oname
, nname
);
2744 oentry
->ie_request
= IE_REQ_NONE
;
2748 /* initialize nentry before letting ipc_hash_insert see it */
2750 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2751 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2752 nentry
->ie_request
= request
;
2753 nentry
->ie_object
= object
;
2755 switch (IE_BITS_TYPE(bits
)) {
2756 case MACH_PORT_TYPE_SEND
: {
2759 port
= (ipc_port_t
) object
;
2760 assert(port
!= IP_NULL
);
2762 /* remember, there are no other share entries possible */
2763 /* or we can't do the rename. Therefore we do not need */
2764 /* to check the other subspaces */
2765 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2766 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2770 case MACH_PORT_TYPE_RECEIVE
:
2771 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2774 port
= (ipc_port_t
) object
;
2775 assert(port
!= IP_NULL
);
2778 assert(ip_active(port
));
2779 assert(port
->ip_receiver_name
== oname
);
2780 assert(port
->ip_receiver
== space
);
2782 port
->ip_receiver_name
= nname
;
2787 case MACH_PORT_TYPE_PORT_SET
: {
2790 pset
= (ipc_pset_t
) object
;
2791 assert(pset
!= IPS_NULL
);
2794 assert(ips_active(pset
));
2800 case MACH_PORT_TYPE_SEND_ONCE
:
2801 case MACH_PORT_TYPE_DEAD_NAME
:
2805 panic("ipc_right_rename: strange rights");
2808 assert(oentry
->ie_request
== IE_REQ_NONE
);
2809 oentry
->ie_object
= IO_NULL
;
2810 ipc_entry_dealloc(space
, oname
, oentry
);
2811 ipc_entry_modified(space
, nname
, nentry
);
2812 is_write_unlock(space
);
2814 if (release_port
!= IP_NULL
)
2815 ip_release(release_port
);
2817 return KERN_SUCCESS
;