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/misc_protos.h>
80 #include <ipc/ipc_entry.h>
81 #include <ipc/ipc_space.h>
82 #include <ipc/ipc_object.h>
83 #include <ipc/ipc_hash.h>
84 #include <ipc/ipc_port.h>
85 #include <ipc/ipc_pset.h>
86 #include <ipc/ipc_right.h>
87 #include <ipc/ipc_notify.h>
88 #include <ipc/ipc_table.h>
89 #include <ipc/ipc_importance.h>
90 #include <security/mac_mach_internal.h>
92 /* Allow IPC to generate mach port guard exceptions */
94 mach_port_guard_exception(
95 mach_port_name_t name
,
100 * Routine: ipc_right_lookup_write
102 * Finds an entry in a space, given the name.
104 * Nothing locked. If successful, the space is write-locked.
106 * KERN_SUCCESS Found an entry.
107 * KERN_INVALID_TASK The space is dead.
108 * KERN_INVALID_NAME Name doesn't exist in space.
112 ipc_right_lookup_write(
114 mach_port_name_t name
,
119 assert(space
!= IS_NULL
);
121 is_write_lock(space
);
123 if (!is_active(space
)) {
124 is_write_unlock(space
);
125 return KERN_INVALID_TASK
;
128 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
129 is_write_unlock(space
);
130 return KERN_INVALID_NAME
;
138 * Routine: ipc_right_lookup_two_write
140 * Like ipc_right_lookup except that it returns two
141 * entries for two different names that were looked
142 * up under the same space lock.
144 * Nothing locked. If successful, the space is write-locked.
146 * KERN_INVALID_TASK The space is dead.
147 * KERN_INVALID_NAME Name doesn't exist in space.
151 ipc_right_lookup_two_write(
153 mach_port_name_t name1
,
154 ipc_entry_t
*entryp1
,
155 mach_port_name_t name2
,
156 ipc_entry_t
*entryp2
)
161 assert(space
!= IS_NULL
);
163 is_write_lock(space
);
165 if (!is_active(space
)) {
166 is_write_unlock(space
);
167 return KERN_INVALID_TASK
;
170 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
171 is_write_unlock(space
);
172 return KERN_INVALID_NAME
;
174 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
175 is_write_unlock(space
);
176 return KERN_INVALID_NAME
;
184 * Routine: ipc_right_reverse
186 * Translate (space, object) -> (name, entry).
187 * Only finds send/receive rights.
188 * Returns TRUE if an entry is found; if so,
189 * the object is locked and active.
191 * The space must be locked (read or write) and active.
192 * Nothing else locked.
199 mach_port_name_t
*namep
,
203 mach_port_name_t name
;
206 /* would switch on io_otype to handle multiple types of object */
208 assert(is_active(space
));
209 assert(io_otype(object
) == IOT_PORT
);
211 port
= (ipc_port_t
) object
;
214 if (!ip_active(port
)) {
220 if (port
->ip_receiver
== space
) {
221 name
= port
->ip_receiver_name
;
222 assert(name
!= MACH_PORT_NULL
);
224 entry
= ipc_entry_lookup(space
, name
);
226 assert(entry
!= IE_NULL
);
227 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
228 assert(port
== (ipc_port_t
) entry
->ie_object
);
235 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
236 assert((entry
= *entryp
) != IE_NULL
);
237 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
238 assert(port
== (ipc_port_t
) entry
->ie_object
);
248 * Routine: ipc_right_dnrequest
250 * Make a dead-name request, returning the previously
251 * registered send-once right. If notify is IP_NULL,
252 * just cancels the previously registered request.
255 * Nothing locked. May allocate memory.
256 * Only consumes/returns refs if successful.
258 * KERN_SUCCESS Made/canceled dead-name request.
259 * KERN_INVALID_TASK The space is dead.
260 * KERN_INVALID_NAME Name doesn't exist in space.
261 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
262 * KERN_INVALID_ARGUMENT Name denotes dead name, but
263 * immediate is FALSE or notify is IP_NULL.
264 * KERN_UREFS_OVERFLOW Name denotes dead name, but
265 * generating immediate notif. would overflow urefs.
266 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
270 ipc_right_request_alloc(
272 mach_port_name_t name
,
274 boolean_t send_possible
,
276 ipc_port_t
*previousp
)
278 ipc_port_request_index_t prev_request
;
279 ipc_port_t previous
= IP_NULL
;
283 #if IMPORTANCE_INHERITANCE
284 boolean_t needboost
= FALSE
;
285 #endif /* IMPORTANCE_INHERITANCE */
288 ipc_port_t port
= IP_NULL
;
290 kr
= ipc_right_lookup_write(space
, name
, &entry
);
291 if (kr
!= KERN_SUCCESS
)
294 /* space is write-locked and active */
296 prev_request
= entry
->ie_request
;
298 /* if nothing to do or undo, we're done */
299 if (notify
== IP_NULL
&& prev_request
== IE_REQ_NONE
) {
300 is_write_unlock(space
);
301 *previousp
= IP_NULL
;
305 /* see if the entry is of proper type for requests */
306 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
307 ipc_port_request_index_t new_request
;
309 port
= (ipc_port_t
) entry
->ie_object
;
310 assert(port
!= IP_NULL
);
312 if (!ipc_right_check(space
, port
, name
, entry
)) {
313 /* port is locked and active */
315 /* if no new request, just cancel previous */
316 if (notify
== IP_NULL
) {
317 if (prev_request
!= IE_REQ_NONE
)
318 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
320 entry
->ie_request
= IE_REQ_NONE
;
321 ipc_entry_modified(space
, name
, entry
);
322 is_write_unlock(space
);
327 * send-once rights, kernel objects, and non-full other queues
328 * fire immediately (if immediate specified).
330 if (send_possible
&& immediate
&&
331 ((entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
) ||
332 port
->ip_receiver
== ipc_space_kernel
|| !ip_full(port
))) {
333 if (prev_request
!= IE_REQ_NONE
)
334 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
336 entry
->ie_request
= IE_REQ_NONE
;
337 ipc_entry_modified(space
, name
, entry
);
338 is_write_unlock(space
);
340 ipc_notify_send_possible(notify
, name
);
345 * If there is a previous request, free it. Any subsequent
346 * allocation cannot fail, thus assuring an atomic swap.
348 if (prev_request
!= IE_REQ_NONE
)
349 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
351 #if IMPORTANCE_INHERITANCE
352 kr
= ipc_port_request_alloc(port
, name
, notify
,
353 send_possible
, immediate
,
354 &new_request
, &needboost
);
356 kr
= ipc_port_request_alloc(port
, name
, notify
,
357 send_possible
, immediate
,
359 #endif /* IMPORTANCE_INHERITANCE */
360 if (kr
!= KERN_SUCCESS
) {
361 assert(previous
== IP_NULL
);
362 is_write_unlock(space
);
364 kr
= ipc_port_request_grow(port
, ITS_SIZE_NONE
);
365 /* port is unlocked */
367 if (kr
!= KERN_SUCCESS
)
374 assert(new_request
!= IE_REQ_NONE
);
375 entry
->ie_request
= new_request
;
376 ipc_entry_modified(space
, name
, entry
);
377 is_write_unlock(space
);
379 #if IMPORTANCE_INHERITANCE
380 if (needboost
== TRUE
) {
381 if (ipc_port_importance_delta(port
, 1) == FALSE
)
384 #endif /* IMPORTANCE_INHERITANCE */
389 /* entry may have changed to dead-name by ipc_right_check() */
393 /* treat send_possible requests as immediate w.r.t. dead-name */
394 if ((send_possible
|| immediate
) && notify
!= IP_NULL
&&
395 (entry
->ie_bits
& MACH_PORT_TYPE_DEAD_NAME
)) {
396 mach_port_urefs_t urefs
= IE_BITS_UREFS(entry
->ie_bits
);
400 if (MACH_PORT_UREFS_OVERFLOW(urefs
, 1)) {
401 is_write_unlock(space
);
404 return KERN_UREFS_OVERFLOW
;
407 (entry
->ie_bits
)++; /* increment urefs */
408 ipc_entry_modified(space
, name
, entry
);
409 is_write_unlock(space
);
414 ipc_notify_dead_name(notify
, name
);
419 is_write_unlock(space
);
424 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_OR_DEAD
)
425 return KERN_INVALID_ARGUMENT
;
427 return KERN_INVALID_RIGHT
;
430 *previousp
= previous
;
435 * Routine: ipc_right_request_cancel
437 * Cancel a notification request and return the send-once right.
438 * Afterwards, entry->ie_request == 0.
440 * The space must be write-locked; the port must be locked.
441 * The port must be active; the space doesn't have to be.
445 ipc_right_request_cancel(
446 __unused ipc_space_t space
,
448 mach_port_name_t name
,
453 assert(ip_active(port
));
454 assert(port
== (ipc_port_t
) entry
->ie_object
);
456 if (entry
->ie_request
== IE_REQ_NONE
)
459 previous
= ipc_port_request_cancel(port
, name
, entry
->ie_request
);
460 entry
->ie_request
= IE_REQ_NONE
;
461 ipc_entry_modified(space
, name
, entry
);
466 * Routine: ipc_right_inuse
468 * Check if an entry is being used.
469 * Returns TRUE if it is.
471 * The space is write-locked and active.
472 * It is unlocked if the entry is inuse.
478 __unused mach_port_name_t name
,
481 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
482 is_write_unlock(space
);
489 * Routine: ipc_right_check
491 * Check if the port has died. If it has,
492 * clean up the entry and return TRUE.
494 * The space is write-locked; the port is not locked.
495 * If returns FALSE, the port is also locked and active.
496 * Otherwise, entry is converted to a dead name.
498 * Caller is responsible for a reference to port if it
499 * had died (returns TRUE).
506 mach_port_name_t name
,
509 ipc_entry_bits_t bits
;
511 assert(is_active(space
));
512 assert(port
== (ipc_port_t
) entry
->ie_object
);
518 /* this was either a pure send right or a send-once right */
520 bits
= entry
->ie_bits
;
521 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
522 assert(IE_BITS_UREFS(bits
) > 0);
524 if (bits
& MACH_PORT_TYPE_SEND
) {
525 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
526 assert(IE_BITS_UREFS(bits
) > 0);
527 assert(port
->ip_srights
> 0);
530 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
531 assert(IE_BITS_UREFS(bits
) == 1);
532 assert(port
->ip_sorights
> 0);
538 * delete SEND rights from ipc hash.
541 if ((bits
& MACH_PORT_TYPE_SEND
) != 0) {
542 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
545 /* convert entry to dead name */
546 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
549 * If there was a notification request outstanding on this
550 * name, and the port went dead, that notification
551 * must already be on its way up from the port layer.
553 * Add the reference that the notification carries. It
554 * is done here, and not in the notification delivery,
555 * because the latter doesn't have a space reference and
556 * trying to actually move a send-right reference would
557 * get short-circuited into a MACH_PORT_DEAD by IPC. Since
558 * all calls that deal with the right eventually come
559 * through here, it has the same result.
561 * Once done, clear the request index so we only account
564 if (entry
->ie_request
!= IE_REQ_NONE
) {
565 if (ipc_port_request_type(port
, name
, entry
->ie_request
) != 0) {
566 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
569 entry
->ie_request
= IE_REQ_NONE
;
571 entry
->ie_bits
= bits
;
572 entry
->ie_object
= IO_NULL
;
573 ipc_entry_modified(space
, name
, entry
);
578 * Routine: ipc_right_terminate
580 * Cleans up an entry in a terminated space.
581 * The entry isn't deallocated or removed
582 * from reverse hash tables.
584 * The space is dead and unlocked.
590 mach_port_name_t name
,
593 ipc_entry_bits_t bits
;
594 mach_port_type_t type
;
596 bits
= entry
->ie_bits
;
597 type
= IE_BITS_TYPE(bits
);
599 assert(!is_active(space
));
602 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
603 * problem, because we check that the port is active. If
604 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
605 * would still work, but dead space refs would accumulate
606 * in ip_dnrequests. They would use up slots in
607 * ip_dnrequests and keep the spaces from being freed.
611 case MACH_PORT_TYPE_DEAD_NAME
:
612 assert(entry
->ie_request
== IE_REQ_NONE
);
613 assert(entry
->ie_object
== IO_NULL
);
616 case MACH_PORT_TYPE_PORT_SET
: {
617 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
619 assert(entry
->ie_request
== IE_REQ_NONE
);
620 assert(pset
!= IPS_NULL
);
623 assert(ips_active(pset
));
624 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
628 case MACH_PORT_TYPE_SEND
:
629 case MACH_PORT_TYPE_RECEIVE
:
630 case MACH_PORT_TYPE_SEND_RECEIVE
:
631 case MACH_PORT_TYPE_SEND_ONCE
: {
632 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
634 ipc_port_t nsrequest
= IP_NULL
;
635 mach_port_mscount_t mscount
= 0;
637 assert(port
!= IP_NULL
);
640 if (!ip_active(port
)) {
646 request
= ipc_right_request_cancel_macro(space
, port
,
649 if (type
& MACH_PORT_TYPE_SEND
) {
650 assert(port
->ip_srights
> 0);
651 if (--port
->ip_srights
== 0
653 nsrequest
= port
->ip_nsrequest
;
654 if (nsrequest
!= IP_NULL
) {
655 port
->ip_nsrequest
= IP_NULL
;
656 mscount
= port
->ip_mscount
;
661 if (type
& MACH_PORT_TYPE_RECEIVE
) {
662 wait_queue_link_t wql
;
663 queue_head_t links_data
;
664 queue_t links
= &links_data
;
666 assert(port
->ip_receiver_name
== name
);
667 assert(port
->ip_receiver
== space
);
670 ipc_port_clear_receiver(port
, links
);
671 ipc_port_destroy(port
); /* consumes our ref, unlocks */
672 while(!queue_empty(links
)) {
673 wql
= (wait_queue_link_t
) dequeue(links
);
674 wait_queue_link_free(wql
);
677 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
678 assert(port
->ip_sorights
> 0);
681 ipc_notify_send_once(port
); /* consumes our ref */
683 assert(port
->ip_receiver
!= space
);
689 if (nsrequest
!= IP_NULL
)
690 ipc_notify_no_senders(nsrequest
, mscount
);
692 if (request
!= IP_NULL
)
693 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
= (ipc_pset_t
) 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(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
= (ipc_port_t
) 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
, (ipc_object_t
) port
,
773 if (!ip_active(port
)) {
774 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
776 entry
->ie_request
= IE_REQ_NONE
;
777 entry
->ie_object
= IO_NULL
;
778 ipc_entry_dealloc(space
, name
, entry
);
779 is_write_unlock(space
);
784 /* For receive rights, check for guarding */
785 if ((type
& MACH_PORT_TYPE_RECEIVE
) &&
786 (check_guard
) && (port
->ip_guarded
) &&
787 (guard
!= port
->ip_context
)) {
788 /* Guard Violation */
789 uint64_t portguard
= port
->ip_context
;
791 is_write_unlock(space
);
792 /* Raise mach port guard exception */
793 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
794 return KERN_INVALID_RIGHT
;
798 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
800 entry
->ie_object
= IO_NULL
;
801 ipc_entry_dealloc(space
, name
, entry
);
802 is_write_unlock(space
);
804 if (type
& MACH_PORT_TYPE_SEND
) {
805 assert(port
->ip_srights
> 0);
806 if (--port
->ip_srights
== 0) {
807 nsrequest
= port
->ip_nsrequest
;
808 if (nsrequest
!= IP_NULL
) {
809 port
->ip_nsrequest
= IP_NULL
;
810 mscount
= port
->ip_mscount
;
815 if (type
& MACH_PORT_TYPE_RECEIVE
) {
816 queue_head_t links_data
;
817 queue_t links
= &links_data
;
818 wait_queue_link_t wql
;
820 assert(ip_active(port
));
821 assert(port
->ip_receiver
== space
);
825 ipc_port_clear_receiver(port
, links
);
826 ipc_port_destroy(port
); /* consumes our ref, unlocks */
828 while(!queue_empty(links
)) {
829 wql
= (wait_queue_link_t
) dequeue(links
);
830 wait_queue_link_free(wql
);
833 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
834 assert(port
->ip_sorights
> 0);
837 ipc_notify_send_once(port
); /* consumes our ref */
839 assert(port
->ip_receiver
!= space
);
845 if (nsrequest
!= IP_NULL
)
846 ipc_notify_no_senders(nsrequest
, mscount
);
848 if (request
!= IP_NULL
)
849 ipc_notify_port_deleted(request
, name
);
856 panic("ipc_right_destroy: strange type");
863 * Routine: ipc_right_dealloc
865 * Releases a send/send-once/dead-name user ref.
866 * Like ipc_right_delta with a delta of -1,
867 * but looks at the entry to determine the right.
869 * The space is write-locked, and is unlocked upon return.
870 * The space must be active.
872 * KERN_SUCCESS A user ref was released.
873 * KERN_INVALID_RIGHT Entry has wrong type.
879 mach_port_name_t name
,
882 ipc_port_t port
= IP_NULL
;
883 ipc_entry_bits_t bits
;
884 mach_port_type_t type
;
886 bits
= entry
->ie_bits
;
887 type
= IE_BITS_TYPE(bits
);
890 assert(is_active(space
));
893 case MACH_PORT_TYPE_DEAD_NAME
: {
896 assert(IE_BITS_UREFS(bits
) > 0);
897 assert(entry
->ie_request
== IE_REQ_NONE
);
898 assert(entry
->ie_object
== IO_NULL
);
900 if (IE_BITS_UREFS(bits
) == 1) {
901 ipc_entry_dealloc(space
, name
, entry
);
903 entry
->ie_bits
= bits
-1; /* decrement urefs */
904 ipc_entry_modified(space
, name
, entry
);
906 is_write_unlock(space
);
908 /* release any port that got converted to dead name below */
914 case MACH_PORT_TYPE_SEND_ONCE
: {
917 assert(IE_BITS_UREFS(bits
) == 1);
919 port
= (ipc_port_t
) entry
->ie_object
;
920 assert(port
!= IP_NULL
);
922 if (ipc_right_check(space
, port
, name
, entry
)) {
924 bits
= entry
->ie_bits
;
925 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
926 goto dead_name
; /* it will release port */
928 /* port is locked and active */
930 assert(port
->ip_sorights
> 0);
932 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
935 entry
->ie_object
= IO_NULL
;
936 ipc_entry_dealloc(space
, name
, entry
);
938 is_write_unlock(space
);
940 ipc_notify_send_once(port
);
942 if (request
!= IP_NULL
)
943 ipc_notify_port_deleted(request
, name
);
947 case MACH_PORT_TYPE_SEND
: {
948 ipc_port_t request
= IP_NULL
;
949 ipc_port_t nsrequest
= IP_NULL
;
950 mach_port_mscount_t mscount
= 0;
953 assert(IE_BITS_UREFS(bits
) > 0);
955 port
= (ipc_port_t
) entry
->ie_object
;
956 assert(port
!= IP_NULL
);
958 if (ipc_right_check(space
, port
, name
, entry
)) {
959 bits
= entry
->ie_bits
;
960 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
961 goto dead_name
; /* it will release port */
963 /* port is locked and active */
965 assert(port
->ip_srights
> 0);
967 if (IE_BITS_UREFS(bits
) == 1) {
968 if (--port
->ip_srights
== 0) {
969 nsrequest
= port
->ip_nsrequest
;
970 if (nsrequest
!= IP_NULL
) {
971 port
->ip_nsrequest
= IP_NULL
;
972 mscount
= port
->ip_mscount
;
976 request
= ipc_right_request_cancel_macro(space
, port
,
978 ipc_hash_delete(space
, (ipc_object_t
) port
,
982 entry
->ie_object
= IO_NULL
;
983 ipc_entry_dealloc(space
, name
, entry
);
984 is_write_unlock(space
);
989 entry
->ie_bits
= bits
-1; /* decrement urefs */
990 ipc_entry_modified(space
, name
, entry
);
991 is_write_unlock(space
);
995 if (nsrequest
!= IP_NULL
)
996 ipc_notify_no_senders(nsrequest
, mscount
);
998 if (request
!= IP_NULL
)
999 ipc_notify_port_deleted(request
, name
);
1003 case MACH_PORT_TYPE_SEND_RECEIVE
: {
1004 ipc_port_t nsrequest
= IP_NULL
;
1005 mach_port_mscount_t mscount
= 0;
1007 assert(IE_BITS_UREFS(bits
) > 0);
1009 port
= (ipc_port_t
) entry
->ie_object
;
1010 assert(port
!= IP_NULL
);
1013 assert(ip_active(port
));
1014 assert(port
->ip_receiver_name
== name
);
1015 assert(port
->ip_receiver
== space
);
1016 assert(port
->ip_srights
> 0);
1018 if (IE_BITS_UREFS(bits
) == 1) {
1019 if (--port
->ip_srights
== 0) {
1020 nsrequest
= port
->ip_nsrequest
;
1021 if (nsrequest
!= IP_NULL
) {
1022 port
->ip_nsrequest
= IP_NULL
;
1023 mscount
= port
->ip_mscount
;
1027 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1028 MACH_PORT_TYPE_SEND
);
1030 entry
->ie_bits
= bits
-1; /* decrement urefs */
1034 ipc_entry_modified(space
, name
, entry
);
1035 is_write_unlock(space
);
1037 if (nsrequest
!= IP_NULL
)
1038 ipc_notify_no_senders(nsrequest
, mscount
);
1043 is_write_unlock(space
);
1044 return KERN_INVALID_RIGHT
;
1047 return KERN_SUCCESS
;
1051 * Routine: ipc_right_delta
1053 * Modifies the user-reference count for a right.
1054 * May deallocate the right, if the count goes to zero.
1056 * The space is write-locked, and is unlocked upon return.
1057 * The space must be active.
1059 * KERN_SUCCESS Count was modified.
1060 * KERN_INVALID_RIGHT Entry has wrong type.
1061 * KERN_INVALID_VALUE Bad delta for the right.
1062 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
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
;
1125 queue_head_t links_data
;
1126 queue_t links
= &links_data
;
1127 wait_queue_link_t wql
;
1129 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1138 port
= (ipc_port_t
) entry
->ie_object
;
1139 assert(port
!= IP_NULL
);
1142 * The port lock is needed for ipc_right_dncancel;
1143 * otherwise, we wouldn't have to take the lock
1144 * until just before dropping the space lock.
1148 assert(ip_active(port
));
1149 assert(port
->ip_receiver_name
== name
);
1150 assert(port
->ip_receiver
== space
);
1152 /* Mach Port Guard Checking */
1153 if(port
->ip_guarded
) {
1154 uint64_t portguard
= port
->ip_context
;
1156 is_write_unlock(space
);
1157 /* Raise mach port guard exception */
1158 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_MOD_REFS
);
1162 if (bits
& MACH_PORT_TYPE_SEND
) {
1163 assert(IE_BITS_TYPE(bits
) ==
1164 MACH_PORT_TYPE_SEND_RECEIVE
);
1165 assert(IE_BITS_UREFS(bits
) > 0);
1166 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1167 assert(port
->ip_srights
> 0);
1169 if (port
->ip_pdrequest
!= NULL
) {
1171 * Since another task has requested a
1172 * destroy notification for this port, it
1173 * isn't actually being destroyed - the receive
1174 * right is just being moved to another task.
1175 * Since we still have one or more send rights,
1176 * we need to record the loss of the receive
1177 * right and enter the remaining send right
1178 * into the hash table.
1180 ipc_entry_modified(space
, name
, entry
);
1181 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1182 ipc_hash_insert(space
, (ipc_object_t
) port
,
1187 * The remaining send right turns into a
1188 * dead name. Notice we don't decrement
1189 * ip_srights, generate a no-senders notif,
1190 * or use ipc_right_dncancel, because the
1191 * port is destroyed "first".
1193 bits
&= ~IE_BITS_TYPE_MASK
;
1194 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1195 if (entry
->ie_request
) {
1196 entry
->ie_request
= IE_REQ_NONE
;
1199 entry
->ie_bits
= bits
;
1200 entry
->ie_object
= IO_NULL
;
1201 ipc_entry_modified(space
, name
, entry
);
1204 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1205 assert(IE_BITS_UREFS(bits
) == 0);
1207 request
= ipc_right_request_cancel_macro(space
, port
,
1209 entry
->ie_object
= IO_NULL
;
1210 ipc_entry_dealloc(space
, name
, entry
);
1212 is_write_unlock(space
);
1215 ipc_port_clear_receiver(port
, links
);
1216 ipc_port_destroy(port
); /* consumes ref, unlocks */
1218 while(!queue_empty(links
)) {
1219 wql
= (wait_queue_link_t
) dequeue(links
);
1220 wait_queue_link_free(wql
);
1223 if (request
!= IP_NULL
)
1224 ipc_notify_port_deleted(request
, name
);
1228 case MACH_PORT_RIGHT_SEND_ONCE
: {
1231 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1234 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1235 assert(IE_BITS_UREFS(bits
) == 1);
1237 port
= (ipc_port_t
) entry
->ie_object
;
1238 assert(port
!= IP_NULL
);
1240 if (ipc_right_check(space
, port
, name
, entry
)) {
1241 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1244 /* port is locked and active */
1246 assert(port
->ip_sorights
> 0);
1248 if ((delta
> 0) || (delta
< -1)) {
1258 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1261 entry
->ie_object
= IO_NULL
;
1262 ipc_entry_dealloc(space
, name
, entry
);
1264 is_write_unlock(space
);
1266 ipc_notify_send_once(port
);
1268 if (request
!= IP_NULL
)
1269 ipc_notify_port_deleted(request
, name
);
1273 case MACH_PORT_RIGHT_DEAD_NAME
: {
1274 ipc_port_t relport
= IP_NULL
;
1275 mach_port_urefs_t urefs
;
1277 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1279 port
= (ipc_port_t
) entry
->ie_object
;
1280 assert(port
!= IP_NULL
);
1282 if (!ipc_right_check(space
, port
, name
, entry
)) {
1283 /* port is locked and active */
1288 bits
= entry
->ie_bits
;
1291 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0)
1294 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1295 assert(IE_BITS_UREFS(bits
) > 0);
1296 assert(entry
->ie_object
== IO_NULL
);
1297 assert(entry
->ie_request
== IE_REQ_NONE
);
1299 urefs
= IE_BITS_UREFS(bits
);
1300 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1302 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
))
1303 goto urefs_overflow
;
1305 if ((urefs
+ delta
) == 0) {
1306 ipc_entry_dealloc(space
, name
, entry
);
1308 entry
->ie_bits
= bits
+ delta
;
1309 ipc_entry_modified(space
, name
, entry
);
1311 is_write_unlock(space
);
1313 if (relport
!= IP_NULL
)
1314 ip_release(relport
);
1319 case MACH_PORT_RIGHT_SEND
: {
1320 mach_port_urefs_t urefs
;
1321 ipc_port_t request
= IP_NULL
;
1322 ipc_port_t nsrequest
= IP_NULL
;
1323 mach_port_mscount_t mscount
= 0;
1325 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1328 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1330 port
= (ipc_port_t
) entry
->ie_object
;
1331 assert(port
!= IP_NULL
);
1333 if (ipc_right_check(space
, port
, name
, entry
)) {
1334 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1337 /* port is locked and active */
1339 assert(port
->ip_srights
> 0);
1341 urefs
= IE_BITS_UREFS(bits
);
1342 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1346 if (MACH_PORT_UREFS_OVERFLOW(urefs
+1, delta
)) {
1348 goto urefs_overflow
;
1351 if ((urefs
+ delta
) == 0) {
1352 if (--port
->ip_srights
== 0) {
1353 nsrequest
= port
->ip_nsrequest
;
1354 if (nsrequest
!= IP_NULL
) {
1355 port
->ip_nsrequest
= IP_NULL
;
1356 mscount
= port
->ip_mscount
;
1360 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1361 assert(port
->ip_receiver_name
== name
);
1362 assert(port
->ip_receiver
== space
);
1364 assert(IE_BITS_TYPE(bits
) ==
1365 MACH_PORT_TYPE_SEND_RECEIVE
);
1367 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1368 MACH_PORT_TYPE_SEND
);
1369 ipc_entry_modified(space
, name
, entry
);
1371 assert(IE_BITS_TYPE(bits
) ==
1372 MACH_PORT_TYPE_SEND
);
1374 request
= ipc_right_request_cancel_macro(space
, port
,
1376 ipc_hash_delete(space
, (ipc_object_t
) port
,
1382 entry
->ie_object
= IO_NULL
;
1383 ipc_entry_dealloc(space
, name
, entry
);
1387 entry
->ie_bits
= bits
+ delta
;
1388 ipc_entry_modified(space
, name
, entry
);
1391 is_write_unlock(space
);
1393 if (nsrequest
!= IP_NULL
)
1394 ipc_notify_no_senders(nsrequest
, mscount
);
1396 if (request
!= IP_NULL
)
1397 ipc_notify_port_deleted(request
, name
);
1402 panic("ipc_right_delta: strange right");
1405 return KERN_SUCCESS
;
1408 is_write_unlock(space
);
1409 return KERN_SUCCESS
;
1412 is_write_unlock(space
);
1413 if (port
!= IP_NULL
)
1415 return KERN_INVALID_RIGHT
;
1418 is_write_unlock(space
);
1419 return KERN_INVALID_VALUE
;
1422 is_write_unlock(space
);
1423 return KERN_UREFS_OVERFLOW
;
1426 return KERN_INVALID_RIGHT
;
1430 * Routine: ipc_right_destruct
1432 * Deallocates the receive right and modifies the
1433 * user-reference count for the send rights as requested.
1435 * The space is write-locked, and is unlocked upon return.
1436 * The space must be active.
1438 * KERN_SUCCESS Count was modified.
1439 * KERN_INVALID_RIGHT Entry has wrong type.
1440 * KERN_INVALID_VALUE Bad delta for the right.
1446 mach_port_name_t name
,
1448 mach_port_delta_t srdelta
,
1451 ipc_port_t port
= IP_NULL
;
1452 ipc_entry_bits_t bits
;
1454 queue_head_t links_data
;
1455 queue_t links
= &links_data
;
1456 wait_queue_link_t wql
;
1458 mach_port_urefs_t urefs
;
1459 ipc_port_t request
= IP_NULL
;
1460 ipc_port_t nsrequest
= IP_NULL
;
1461 mach_port_mscount_t mscount
= 0;
1463 bits
= entry
->ie_bits
;
1465 assert(is_active(space
));
1467 if (((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) ||
1468 (srdelta
&& ((bits
& MACH_PORT_TYPE_SEND
) == 0))) {
1469 is_write_unlock(space
);
1470 return KERN_INVALID_RIGHT
;
1476 port
= (ipc_port_t
) entry
->ie_object
;
1477 assert(port
!= IP_NULL
);
1480 assert(ip_active(port
));
1481 assert(port
->ip_receiver_name
== name
);
1482 assert(port
->ip_receiver
== space
);
1484 /* Mach Port Guard Checking */
1485 if(port
->ip_guarded
&& (guard
!= port
->ip_context
)) {
1486 uint64_t portguard
= port
->ip_context
;
1488 is_write_unlock(space
);
1489 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
1490 return KERN_INVALID_ARGUMENT
;
1494 * First reduce the send rights as requested and
1495 * adjust the entry->ie_bits accordingly. The
1496 * ipc_entry_modified() call is made once the receive
1497 * right is destroyed too.
1502 assert(port
->ip_srights
> 0);
1504 urefs
= IE_BITS_UREFS(bits
);
1506 * Since we made sure that srdelta is negative,
1507 * the check for urefs overflow is not required.
1509 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, srdelta
)) {
1513 if ((urefs
+ srdelta
) == 0) {
1514 if (--port
->ip_srights
== 0) {
1515 nsrequest
= port
->ip_nsrequest
;
1516 if (nsrequest
!= IP_NULL
) {
1517 port
->ip_nsrequest
= IP_NULL
;
1518 mscount
= port
->ip_mscount
;
1521 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_RECEIVE
);
1522 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1523 MACH_PORT_TYPE_SEND
);
1525 entry
->ie_bits
= bits
+ srdelta
;
1530 * Now destroy the receive right. Update space and
1531 * entry accordingly.
1534 bits
= entry
->ie_bits
;
1535 if (bits
& MACH_PORT_TYPE_SEND
) {
1536 assert(IE_BITS_UREFS(bits
) > 0);
1537 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1539 if (port
->ip_pdrequest
!= NULL
) {
1541 * Since another task has requested a
1542 * destroy notification for this port, it
1543 * isn't actually being destroyed - the receive
1544 * right is just being moved to another task.
1545 * Since we still have one or more send rights,
1546 * we need to record the loss of the receive
1547 * right and enter the remaining send right
1548 * into the hash table.
1550 ipc_entry_modified(space
, name
, entry
);
1551 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1552 ipc_hash_insert(space
, (ipc_object_t
) port
,
1557 * The remaining send right turns into a
1558 * dead name. Notice we don't decrement
1559 * ip_srights, generate a no-senders notif,
1560 * or use ipc_right_dncancel, because the
1561 * port is destroyed "first".
1563 bits
&= ~IE_BITS_TYPE_MASK
;
1564 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1565 if (entry
->ie_request
) {
1566 entry
->ie_request
= IE_REQ_NONE
;
1569 entry
->ie_bits
= bits
;
1570 entry
->ie_object
= IO_NULL
;
1571 ipc_entry_modified(space
, name
, entry
);
1574 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1575 assert(IE_BITS_UREFS(bits
) == 0);
1576 request
= ipc_right_request_cancel_macro(space
, port
,
1578 entry
->ie_object
= IO_NULL
;
1579 ipc_entry_dealloc(space
, name
, entry
);
1583 is_write_unlock(space
);
1585 if (nsrequest
!= IP_NULL
)
1586 ipc_notify_no_senders(nsrequest
, mscount
);
1589 ipc_port_clear_receiver(port
, links
);
1590 ipc_port_destroy(port
); /* consumes ref, unlocks */
1592 while(!queue_empty(links
)) {
1593 wql
= (wait_queue_link_t
) dequeue(links
);
1594 wait_queue_link_free(wql
);
1597 if (request
!= IP_NULL
)
1598 ipc_notify_port_deleted(request
, name
);
1600 return KERN_SUCCESS
;
1603 is_write_unlock(space
);
1604 return KERN_INVALID_VALUE
;
1610 * Routine: ipc_right_info
1612 * Retrieves information about the right.
1614 * The space is active and write-locked.
1615 * The space is unlocked upon return.
1617 * KERN_SUCCESS Retrieved info
1623 mach_port_name_t name
,
1625 mach_port_type_t
*typep
,
1626 mach_port_urefs_t
*urefsp
)
1629 ipc_entry_bits_t bits
;
1630 mach_port_type_t type
= 0;
1631 ipc_port_request_index_t request
;
1633 bits
= entry
->ie_bits
;
1634 request
= entry
->ie_request
;
1635 port
= (ipc_port_t
) entry
->ie_object
;
1637 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1638 assert(IP_VALID(port
));
1640 if (request
!= IE_REQ_NONE
) {
1642 assert(ip_active(port
));
1643 type
|= ipc_port_request_type(port
, name
, request
);
1646 is_write_unlock(space
);
1648 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1650 * validate port is still alive - if so, get request
1651 * types while we still have it locked. Otherwise,
1652 * recapture the (now dead) bits.
1654 if (!ipc_right_check(space
, port
, name
, entry
)) {
1655 if (request
!= IE_REQ_NONE
)
1656 type
|= ipc_port_request_type(port
, name
, request
);
1658 is_write_unlock(space
);
1660 bits
= entry
->ie_bits
;
1661 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1662 is_write_unlock(space
);
1666 is_write_unlock(space
);
1669 type
|= IE_BITS_TYPE(bits
);
1672 *urefsp
= IE_BITS_UREFS(bits
);
1673 return KERN_SUCCESS
;
1677 * Routine: ipc_right_copyin_check
1679 * Check if a subsequent ipc_right_copyin would succeed.
1681 * The space is locked (read or write) and active.
1685 ipc_right_copyin_check(
1686 __assert_only ipc_space_t space
,
1687 __unused mach_port_name_t name
,
1689 mach_msg_type_name_t msgt_name
)
1691 ipc_entry_bits_t bits
;
1694 bits
= entry
->ie_bits
;
1695 assert(is_active(space
));
1697 switch (msgt_name
) {
1698 case MACH_MSG_TYPE_MAKE_SEND
:
1699 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1703 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1704 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1708 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1709 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1713 case MACH_MSG_TYPE_COPY_SEND
:
1714 case MACH_MSG_TYPE_MOVE_SEND
:
1715 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1717 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1720 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1723 port
= (ipc_port_t
) entry
->ie_object
;
1724 assert(port
!= IP_NULL
);
1727 * active status peek to avoid checks that will be skipped
1728 * on copyin for dead ports. Lock not held, so will not be
1729 * atomic (but once dead, there's no going back).
1731 if (!ip_active(port
)) {
1735 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1736 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1739 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1747 panic("ipc_right_copyin_check: strange rights");
1754 * Routine: ipc_right_copyin
1756 * Copyin a capability from a space.
1757 * If successful, the caller gets a ref
1758 * for the resulting object, unless it is IO_DEAD,
1759 * and possibly a send-once right which should
1760 * be used in a port-deleted notification.
1762 * If deadok is not TRUE, the copyin operation
1763 * will fail instead of producing IO_DEAD.
1765 * The entry is never deallocated (except
1766 * when KERN_INVALID_NAME), so the caller
1767 * should deallocate the entry if its type
1768 * is MACH_PORT_TYPE_NONE.
1770 * The space is write-locked and active.
1772 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1773 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1779 mach_port_name_t name
,
1781 mach_msg_type_name_t msgt_name
,
1783 ipc_object_t
*objectp
,
1784 ipc_port_t
*sorightp
,
1785 ipc_port_t
*releasep
,
1786 #if IMPORTANCE_INHERITANCE
1788 #endif /* IMPORTANCE_INHERITANCE */
1791 ipc_entry_bits_t bits
;
1794 *releasep
= IP_NULL
;
1796 #if IMPORTANCE_INHERITANCE
1800 bits
= entry
->ie_bits
;
1802 assert(is_active(space
));
1804 switch (msgt_name
) {
1805 case MACH_MSG_TYPE_MAKE_SEND
: {
1807 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1810 port
= (ipc_port_t
) entry
->ie_object
;
1811 assert(port
!= IP_NULL
);
1814 assert(ip_active(port
));
1815 assert(port
->ip_receiver_name
== name
);
1816 assert(port
->ip_receiver
== space
);
1823 *objectp
= (ipc_object_t
) port
;
1824 *sorightp
= IP_NULL
;
1828 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1830 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1833 port
= (ipc_port_t
) entry
->ie_object
;
1834 assert(port
!= IP_NULL
);
1837 assert(ip_active(port
));
1838 assert(port
->ip_receiver_name
== name
);
1839 assert(port
->ip_receiver
== space
);
1841 port
->ip_sorights
++;
1845 *objectp
= (ipc_object_t
) port
;
1846 *sorightp
= IP_NULL
;
1850 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1851 ipc_port_t request
= IP_NULL
;
1853 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1856 port
= (ipc_port_t
) entry
->ie_object
;
1857 assert(port
!= IP_NULL
);
1860 assert(ip_active(port
));
1861 assert(port
->ip_receiver_name
== name
);
1862 assert(port
->ip_receiver
== space
);
1864 if (bits
& MACH_PORT_TYPE_SEND
) {
1865 assert(IE_BITS_TYPE(bits
) ==
1866 MACH_PORT_TYPE_SEND_RECEIVE
);
1867 assert(IE_BITS_UREFS(bits
) > 0);
1868 assert(port
->ip_srights
> 0);
1870 ipc_hash_insert(space
, (ipc_object_t
) port
,
1874 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1875 assert(IE_BITS_UREFS(bits
) == 0);
1877 request
= ipc_right_request_cancel_macro(space
, port
,
1879 entry
->ie_object
= IO_NULL
;
1881 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1882 ipc_entry_modified(space
, name
, entry
);
1884 ipc_port_clear_receiver(port
, links
);
1885 port
->ip_receiver_name
= MACH_PORT_NULL
;
1886 port
->ip_destination
= IP_NULL
;
1888 #if IMPORTANCE_INHERITANCE
1890 * Account for boosts the current task is going to lose when
1891 * copying this right in. Tempowner ports have either not
1892 * been accounting to any task (and therefore are already in
1893 * "limbo" state w.r.t. assertions) or to some other specific
1894 * task. As we have no way to drop the latter task's assertions
1895 * here, We'll deduct those when we enqueue it on its
1896 * destination port (see ipc_port_check_circularity()).
1898 if (port
->ip_tempowner
== 0) {
1899 assert(IIT_NULL
== port
->ip_imp_task
);
1901 /* ports in limbo have to be tempowner */
1902 port
->ip_tempowner
= 1;
1903 *assertcntp
= port
->ip_impcount
;
1905 #endif /* IMPORTANCE_INHERITANCE */
1909 *objectp
= (ipc_object_t
) port
;
1910 *sorightp
= request
;
1914 case MACH_MSG_TYPE_COPY_SEND
: {
1916 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1919 /* allow for dead send-once rights */
1921 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1924 assert(IE_BITS_UREFS(bits
) > 0);
1926 port
= (ipc_port_t
) entry
->ie_object
;
1927 assert(port
!= IP_NULL
);
1929 if (ipc_right_check(space
, port
, name
, entry
)) {
1930 bits
= entry
->ie_bits
;
1934 /* port is locked and active */
1936 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1937 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1938 assert(port
->ip_sorights
> 0);
1944 assert(port
->ip_srights
> 0);
1950 *objectp
= (ipc_object_t
) port
;
1951 *sorightp
= IP_NULL
;
1955 case MACH_MSG_TYPE_MOVE_SEND
: {
1956 ipc_port_t request
= IP_NULL
;
1958 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1961 /* allow for dead send-once rights */
1963 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1966 assert(IE_BITS_UREFS(bits
) > 0);
1968 port
= (ipc_port_t
) entry
->ie_object
;
1969 assert(port
!= IP_NULL
);
1971 if (ipc_right_check(space
, port
, name
, entry
)) {
1972 bits
= entry
->ie_bits
;
1976 /* port is locked and active */
1978 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1979 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1980 assert(port
->ip_sorights
> 0);
1986 assert(port
->ip_srights
> 0);
1988 if (IE_BITS_UREFS(bits
) == 1) {
1989 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1990 assert(port
->ip_receiver_name
== name
);
1991 assert(port
->ip_receiver
== space
);
1992 assert(IE_BITS_TYPE(bits
) ==
1993 MACH_PORT_TYPE_SEND_RECEIVE
);
1997 assert(IE_BITS_TYPE(bits
) ==
1998 MACH_PORT_TYPE_SEND
);
2000 request
= ipc_right_request_cancel_macro(space
, port
,
2002 ipc_hash_delete(space
, (ipc_object_t
) port
,
2004 entry
->ie_object
= IO_NULL
;
2006 entry
->ie_bits
= bits
&~
2007 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
2011 entry
->ie_bits
= bits
-1; /* decrement urefs */
2013 ipc_entry_modified(space
, name
, entry
);
2016 *objectp
= (ipc_object_t
) port
;
2017 *sorightp
= request
;
2021 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
2024 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
2027 /* allow for dead send rights */
2029 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
2032 assert(IE_BITS_UREFS(bits
) > 0);
2034 port
= (ipc_port_t
) entry
->ie_object
;
2035 assert(port
!= IP_NULL
);
2037 if (ipc_right_check(space
, port
, name
, entry
)) {
2038 bits
= entry
->ie_bits
;
2041 /* port is locked and active */
2043 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
2044 assert(bits
& MACH_PORT_TYPE_SEND
);
2045 assert(port
->ip_srights
> 0);
2051 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2052 assert(IE_BITS_UREFS(bits
) == 1);
2053 assert(port
->ip_sorights
> 0);
2055 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
2058 entry
->ie_object
= IO_NULL
;
2059 entry
->ie_bits
= bits
&~
2060 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
2061 ipc_entry_modified(space
, name
, entry
);
2062 *objectp
= (ipc_object_t
) port
;
2063 *sorightp
= request
;
2069 return KERN_INVALID_RIGHT
;
2072 return KERN_SUCCESS
;
2075 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2076 assert(IE_BITS_UREFS(bits
) > 0);
2077 assert(entry
->ie_request
== IE_REQ_NONE
);
2078 assert(entry
->ie_object
== 0);
2084 *sorightp
= IP_NULL
;
2085 return KERN_SUCCESS
;
2088 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2089 assert(IE_BITS_UREFS(bits
) > 0);
2090 assert(entry
->ie_request
== IE_REQ_NONE
);
2091 assert(entry
->ie_object
== 0);
2096 if (IE_BITS_UREFS(bits
) == 1) {
2097 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
2099 entry
->ie_bits
= bits
-1; /* decrement urefs */
2100 ipc_entry_modified(space
, name
, entry
);
2102 *sorightp
= IP_NULL
;
2103 return KERN_SUCCESS
;
2108 * Routine: ipc_right_copyin_undo
2110 * Undoes the effects of an ipc_right_copyin
2111 * of a send/send-once right that is dead.
2112 * (Object is either IO_DEAD or a dead port.)
2114 * The space is write-locked and active.
2118 ipc_right_copyin_undo(
2120 mach_port_name_t name
,
2122 mach_msg_type_name_t msgt_name
,
2123 ipc_object_t object
,
2126 ipc_entry_bits_t bits
;
2128 bits
= entry
->ie_bits
;
2130 assert(is_active(space
));
2132 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2133 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
2134 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2136 if (soright
!= IP_NULL
) {
2137 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2138 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2139 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2140 assert(object
!= IO_DEAD
);
2142 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
2143 MACH_PORT_TYPE_DEAD_NAME
| 2);
2145 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
2146 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2147 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2149 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
2150 MACH_PORT_TYPE_DEAD_NAME
| 1);
2151 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
2152 assert(object
== IO_DEAD
);
2153 assert(IE_BITS_UREFS(bits
) > 0);
2155 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2156 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
2157 entry
->ie_bits
= bits
+1; /* increment urefs */
2160 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2161 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
2162 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2163 assert(object
!= IO_DEAD
);
2164 assert(entry
->ie_object
== object
);
2165 assert(IE_BITS_UREFS(bits
) > 0);
2167 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2168 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
-1);
2169 entry
->ie_bits
= bits
+1; /* increment urefs */
2173 * May as well convert the entry to a dead name.
2174 * (Or if it is a compat entry, destroy it.)
2177 (void) ipc_right_check(space
, (ipc_port_t
) object
,
2179 /* object is dead so it is not locked */
2181 ipc_entry_modified(space
, name
, entry
);
2182 /* release the reference acquired by copyin */
2184 if (object
!= IO_DEAD
)
2189 * Routine: ipc_right_copyin_two_move_sends
2191 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
2192 * and deadok == FALSE, except that this moves two
2193 * send rights at once.
2195 * The space is write-locked and active.
2196 * The object is returned with two refs/send rights.
2198 * KERN_SUCCESS Acquired an object.
2199 * KERN_INVALID_RIGHT Name doesn't denote correct right.
2203 ipc_right_copyin_two_move_sends(
2205 mach_port_name_t name
,
2207 ipc_object_t
*objectp
,
2208 ipc_port_t
*sorightp
,
2209 ipc_port_t
*releasep
)
2211 ipc_entry_bits_t bits
;
2212 mach_port_urefs_t urefs
;
2214 ipc_port_t request
= IP_NULL
;
2216 *releasep
= IP_NULL
;
2218 assert(is_active(space
));
2220 bits
= entry
->ie_bits
;
2222 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
2225 urefs
= IE_BITS_UREFS(bits
);
2229 port
= (ipc_port_t
) entry
->ie_object
;
2230 assert(port
!= IP_NULL
);
2232 if (ipc_right_check(space
, port
, name
, entry
)) {
2236 /* port is locked and active */
2238 assert(port
->ip_srights
> 0);
2241 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2242 assert(port
->ip_receiver_name
== name
);
2243 assert(port
->ip_receiver
== space
);
2244 assert(IE_BITS_TYPE(bits
) ==
2245 MACH_PORT_TYPE_SEND_RECEIVE
);
2251 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2253 request
= ipc_right_request_cancel_macro(space
, port
,
2258 ipc_hash_delete(space
, (ipc_object_t
) port
,
2260 entry
->ie_object
= IO_NULL
;
2262 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
2264 port
->ip_srights
+= 2;
2267 entry
->ie_bits
= bits
-2; /* decrement urefs */
2269 ipc_entry_modified(space
, name
, entry
);
2273 *objectp
= (ipc_object_t
) port
;
2274 *sorightp
= request
;
2275 return KERN_SUCCESS
;
2278 return KERN_INVALID_RIGHT
;
2283 * Routine: ipc_right_copyin_two
2285 * Like ipc_right_copyin with two dispositions,
2286 * each of which results in a send or send-once right,
2287 * and deadok = FALSE.
2289 * The space is write-locked and active.
2290 * The object is returned with two refs/rights.
2292 * KERN_SUCCESS Acquired an object.
2293 * KERN_INVALID_RIGHT Name doesn't denote correct right(s).
2294 * KERN_INVALID_CAPABILITY Name doesn't denote correct right for msgt_two.
2297 ipc_right_copyin_two(
2299 mach_port_name_t name
,
2301 mach_msg_type_name_t msgt_one
,
2302 mach_msg_type_name_t msgt_two
,
2303 ipc_object_t
*objectp
,
2304 ipc_port_t
*sorightp
,
2305 ipc_port_t
*releasep
)
2307 queue_head_t links_data
;
2308 queue_t links
= &links_data
;
2311 #if IMPORTANCE_INHERITANCE
2317 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one
));
2318 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two
));
2322 * Pre-validate the second disposition is possible all by itself.
2324 if (!ipc_right_copyin_check(space
, name
, entry
, msgt_two
)) {
2325 return KERN_INVALID_CAPABILITY
;
2329 * This is a little tedious to make atomic, because
2330 * there are 25 combinations of valid dispositions.
2331 * However, most are easy.
2335 * If either is move-sonce, then there must be an error.
2337 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND_ONCE
||
2338 msgt_two
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
2339 return KERN_INVALID_RIGHT
;
2342 if ((msgt_one
== MACH_MSG_TYPE_MAKE_SEND
) ||
2343 (msgt_one
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) ||
2344 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND
) ||
2345 (msgt_two
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) {
2347 * One of the dispositions needs a receive right.
2349 * If the copyin below succeeds, we know the receive
2350 * right is there (because the pre-validation of
2351 * the second disposition already succeeded in our
2354 * Hence the port is not in danger of dying.
2356 ipc_object_t object_two
;
2358 #if IMPORTANCE_INHERITANCE
2359 kr
= ipc_right_copyin(space
, name
, entry
,
2361 objectp
, sorightp
, releasep
,
2363 assert(assertcnt
== 0);
2365 kr
= ipc_right_copyin(space
, name
, entry
,
2367 objectp
, sorightp
, releasep
,
2369 #endif /* IMPORTANCE_INHERITANCE */
2370 if (kr
!= KERN_SUCCESS
) {
2374 assert(IO_VALID(*objectp
));
2375 assert(*sorightp
== IP_NULL
);
2376 assert(*releasep
== IP_NULL
);
2379 * Now copyin the second (previously validated)
2380 * disposition. The result can't be a dead port,
2381 * as no valid disposition can make us lose our
2384 #if IMPORTANCE_INHERITANCE
2385 kr
= ipc_right_copyin(space
, name
, entry
,
2387 &object_two
, sorightp
, releasep
,
2389 assert(assertcnt
== 0);
2391 kr
= ipc_right_copyin(space
, name
, entry
,
2393 &object_two
, sorightp
, releasep
,
2395 #endif /* IMPORTANCE_INHERITANCE */
2396 assert(kr
== KERN_SUCCESS
);
2397 assert(*sorightp
== IP_NULL
);
2398 assert(*releasep
== IP_NULL
);
2399 assert(object_two
== *objectp
);
2400 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
2402 } else if ((msgt_one
== MACH_MSG_TYPE_MOVE_SEND
) &&
2403 (msgt_two
== MACH_MSG_TYPE_MOVE_SEND
)) {
2405 * This is an easy case. Just use our
2406 * handy-dandy special-purpose copyin call
2407 * to get two send rights for the price of one.
2409 kr
= ipc_right_copyin_two_move_sends(space
, name
, entry
,
2412 if (kr
!= KERN_SUCCESS
) {
2417 mach_msg_type_name_t msgt_name
;
2420 * Must be either a single move-send and a
2421 * copy-send, or two copy-send dispositions.
2422 * Use the disposition with the greatest side
2423 * effects for the actual copyin - then just
2424 * duplicate the send right you get back.
2426 if (msgt_one
== MACH_MSG_TYPE_MOVE_SEND
||
2427 msgt_two
== MACH_MSG_TYPE_MOVE_SEND
) {
2428 msgt_name
= MACH_MSG_TYPE_MOVE_SEND
;
2430 msgt_name
= MACH_MSG_TYPE_COPY_SEND
;
2433 #if IMPORTANCE_INHERITANCE
2434 kr
= ipc_right_copyin(space
, name
, entry
,
2436 objectp
, sorightp
, releasep
,
2438 assert(assertcnt
== 0);
2440 kr
= ipc_right_copyin(space
, name
, entry
,
2442 objectp
, sorightp
, releasep
,
2444 #endif /* IMPORTANCE_INHERITANCE */
2445 if (kr
!= KERN_SUCCESS
) {
2450 * Copy the right we got back. If it is dead now,
2451 * that's OK. Neither right will be usable to send
2454 (void)ipc_port_copy_send((ipc_port_t
)*objectp
);
2457 assert(queue_empty(links
));
2459 return KERN_SUCCESS
;
2464 * Routine: ipc_right_copyout
2466 * Copyout a capability to a space.
2467 * If successful, consumes a ref for the object.
2469 * Always succeeds when given a newly-allocated entry,
2470 * because user-reference overflow isn't a possibility.
2472 * If copying out the object would cause the user-reference
2473 * count in the entry to overflow, and overflow is TRUE,
2474 * then instead the user-reference count is left pegged
2475 * to its maximum value and the copyout succeeds anyway.
2477 * The space is write-locked and active.
2478 * The object is locked and active.
2479 * The object is unlocked; the space isn't.
2481 * KERN_SUCCESS Copied out capability.
2482 * KERN_UREFS_OVERFLOW User-refs would overflow;
2483 * guaranteed not to happen with a fresh entry
2484 * or if overflow=TRUE was specified.
2490 mach_port_name_t name
,
2492 mach_msg_type_name_t msgt_name
,
2494 ipc_object_t object
)
2496 ipc_entry_bits_t bits
;
2499 bits
= entry
->ie_bits
;
2501 assert(IO_VALID(object
));
2502 assert(io_otype(object
) == IOT_PORT
);
2503 assert(io_active(object
));
2504 assert(entry
->ie_object
== object
);
2506 port
= (ipc_port_t
) object
;
2508 switch (msgt_name
) {
2509 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
2511 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2512 assert(port
->ip_sorights
> 0);
2514 /* transfer send-once right and ref to entry */
2517 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1);
2518 ipc_entry_modified(space
, name
, entry
);
2521 case MACH_MSG_TYPE_PORT_SEND
:
2522 assert(port
->ip_srights
> 0);
2524 if (bits
& MACH_PORT_TYPE_SEND
) {
2525 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
2527 assert(port
->ip_srights
> 1);
2529 assert(urefs
< MACH_PORT_UREFS_MAX
);
2531 if (urefs
+1 == MACH_PORT_UREFS_MAX
) {
2533 /* leave urefs pegged to maximum */
2538 return KERN_SUCCESS
;
2542 return KERN_UREFS_OVERFLOW
;
2548 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2549 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2550 assert(IE_BITS_UREFS(bits
) == 0);
2552 /* transfer send right to entry */
2557 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2558 assert(IE_BITS_UREFS(bits
) == 0);
2560 /* transfer send right and ref to entry */
2563 /* entry is locked holding ref, so can use port */
2565 ipc_hash_insert(space
, (ipc_object_t
) port
,
2569 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1;
2570 ipc_entry_modified(space
, name
, entry
);
2573 case MACH_MSG_TYPE_PORT_RECEIVE
: {
2576 #if IMPORTANCE_INHERITANCE
2577 natural_t assertcnt
= port
->ip_impcount
;
2578 #endif /* IMPORTANCE_INHERITANCE */
2580 assert(port
->ip_mscount
== 0);
2581 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
2582 dest
= port
->ip_destination
;
2584 port
->ip_receiver_name
= name
;
2585 port
->ip_receiver
= space
;
2587 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
2589 if (bits
& MACH_PORT_TYPE_SEND
) {
2590 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2591 assert(IE_BITS_UREFS(bits
) > 0);
2592 assert(port
->ip_srights
> 0);
2597 /* entry is locked holding ref, so can use port */
2599 ipc_hash_delete(space
, (ipc_object_t
) port
,
2602 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2603 assert(IE_BITS_UREFS(bits
) == 0);
2605 /* transfer ref to entry */
2608 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2609 ipc_entry_modified(space
, name
, entry
);
2611 if (dest
!= IP_NULL
) {
2612 #if IMPORTANCE_INHERITANCE
2614 * Deduct the assertion counts we contributed to
2615 * the old destination port. They've already
2616 * been reflected into the task as a result of
2620 ipc_port_impcount_delta(dest
, 0 - assertcnt
, IP_NULL
);
2622 #endif /* IMPORTANCE_INHERITANCE */
2629 panic("ipc_right_copyout: strange rights");
2631 return KERN_SUCCESS
;
2635 * Routine: ipc_right_rename
2637 * Transfer an entry from one name to another.
2638 * The old entry is deallocated.
2640 * The space is write-locked and active.
2641 * The new entry is unused. Upon return,
2642 * the space is unlocked.
2644 * KERN_SUCCESS Moved entry to new name.
2650 mach_port_name_t oname
,
2652 mach_port_name_t nname
,
2655 ipc_port_request_index_t request
= oentry
->ie_request
;
2656 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2657 ipc_object_t object
= oentry
->ie_object
;
2658 ipc_port_t release_port
= IP_NULL
;
2660 assert(is_active(space
));
2661 assert(oname
!= nname
);
2664 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2665 * if the port is dead. (This would foil ipc_port_destroy.)
2666 * Instead we should fail because oentry shouldn't exist.
2667 * Note IE_BITS_COMPAT implies ie_request != 0.
2670 if (request
!= IE_REQ_NONE
) {
2673 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2674 port
= (ipc_port_t
) object
;
2675 assert(port
!= IP_NULL
);
2677 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2678 request
= IE_REQ_NONE
;
2680 bits
= oentry
->ie_bits
;
2681 release_port
= port
;
2682 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2683 assert(oentry
->ie_request
== IE_REQ_NONE
);
2685 /* port is locked and active */
2687 ipc_port_request_rename(port
, request
, oname
, nname
);
2689 oentry
->ie_request
= IE_REQ_NONE
;
2693 /* initialize nentry before letting ipc_hash_insert see it */
2695 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2696 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2697 nentry
->ie_request
= request
;
2698 nentry
->ie_object
= object
;
2700 switch (IE_BITS_TYPE(bits
)) {
2701 case MACH_PORT_TYPE_SEND
: {
2704 port
= (ipc_port_t
) object
;
2705 assert(port
!= IP_NULL
);
2707 /* remember, there are no other share entries possible */
2708 /* or we can't do the rename. Therefore we do not need */
2709 /* to check the other subspaces */
2710 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2711 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2715 case MACH_PORT_TYPE_RECEIVE
:
2716 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2719 port
= (ipc_port_t
) object
;
2720 assert(port
!= IP_NULL
);
2723 assert(ip_active(port
));
2724 assert(port
->ip_receiver_name
== oname
);
2725 assert(port
->ip_receiver
== space
);
2727 port
->ip_receiver_name
= nname
;
2732 case MACH_PORT_TYPE_PORT_SET
: {
2735 pset
= (ipc_pset_t
) object
;
2736 assert(pset
!= IPS_NULL
);
2739 assert(ips_active(pset
));
2740 assert(pset
->ips_local_name
== oname
);
2742 pset
->ips_local_name
= nname
;
2747 case MACH_PORT_TYPE_SEND_ONCE
:
2748 case MACH_PORT_TYPE_DEAD_NAME
:
2752 panic("ipc_right_rename: strange rights");
2755 assert(oentry
->ie_request
== IE_REQ_NONE
);
2756 oentry
->ie_object
= IO_NULL
;
2757 ipc_entry_dealloc(space
, oname
, oentry
);
2758 ipc_entry_modified(space
, nname
, nentry
);
2759 is_write_unlock(space
);
2761 if (release_port
!= IP_NULL
)
2762 ip_release(release_port
);
2764 return KERN_SUCCESS
;