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 <security/mac_mach_internal.h>
91 /* Allow IPC to generate mach port guard exceptions */
93 mach_port_guard_exception(
94 mach_port_name_t name
,
99 * Routine: ipc_right_lookup_write
101 * Finds an entry in a space, given the name.
103 * Nothing locked. If successful, the space is write-locked.
105 * KERN_SUCCESS Found an entry.
106 * KERN_INVALID_TASK The space is dead.
107 * KERN_INVALID_NAME Name doesn't exist in space.
111 ipc_right_lookup_write(
113 mach_port_name_t name
,
118 assert(space
!= IS_NULL
);
120 is_write_lock(space
);
122 if (!is_active(space
)) {
123 is_write_unlock(space
);
124 return KERN_INVALID_TASK
;
127 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
128 is_write_unlock(space
);
129 return KERN_INVALID_NAME
;
137 * Routine: ipc_right_lookup_two_write
139 * Like ipc_right_lookup except that it returns two
140 * entries for two different names that were looked
141 * up under the same space lock.
143 * Nothing locked. If successful, the space is write-locked.
145 * KERN_INVALID_TASK The space is dead.
146 * KERN_INVALID_NAME Name doesn't exist in space.
150 ipc_right_lookup_two_write(
152 mach_port_name_t name1
,
153 ipc_entry_t
*entryp1
,
154 mach_port_name_t name2
,
155 ipc_entry_t
*entryp2
)
160 assert(space
!= IS_NULL
);
162 is_write_lock(space
);
164 if (!is_active(space
)) {
165 is_write_unlock(space
);
166 return KERN_INVALID_TASK
;
169 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
170 is_write_unlock(space
);
171 return KERN_INVALID_NAME
;
173 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
174 is_write_unlock(space
);
175 return KERN_INVALID_NAME
;
183 * Routine: ipc_right_reverse
185 * Translate (space, object) -> (name, entry).
186 * Only finds send/receive rights.
187 * Returns TRUE if an entry is found; if so,
188 * the object is locked and active.
190 * The space must be locked (read or write) and active.
191 * Nothing else locked.
198 mach_port_name_t
*namep
,
202 mach_port_name_t name
;
205 /* would switch on io_otype to handle multiple types of object */
207 assert(is_active(space
));
208 assert(io_otype(object
) == IOT_PORT
);
210 port
= (ipc_port_t
) object
;
213 if (!ip_active(port
)) {
219 if (port
->ip_receiver
== space
) {
220 name
= port
->ip_receiver_name
;
221 assert(name
!= MACH_PORT_NULL
);
223 entry
= ipc_entry_lookup(space
, name
);
225 assert(entry
!= IE_NULL
);
226 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
227 assert(port
== (ipc_port_t
) entry
->ie_object
);
234 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
235 assert((entry
= *entryp
) != IE_NULL
);
236 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
237 assert(port
== (ipc_port_t
) entry
->ie_object
);
247 * Routine: ipc_right_dnrequest
249 * Make a dead-name request, returning the previously
250 * registered send-once right. If notify is IP_NULL,
251 * just cancels the previously registered request.
254 * Nothing locked. May allocate memory.
255 * Only consumes/returns refs if successful.
257 * KERN_SUCCESS Made/canceled dead-name request.
258 * KERN_INVALID_TASK The space is dead.
259 * KERN_INVALID_NAME Name doesn't exist in space.
260 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
261 * KERN_INVALID_ARGUMENT Name denotes dead name, but
262 * immediate is FALSE or notify is IP_NULL.
263 * KERN_UREFS_OVERFLOW Name denotes dead name, but
264 * generating immediate notif. would overflow urefs.
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
, 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 if (MACH_PORT_UREFS_OVERFLOW(urefs
, 1)) {
400 is_write_unlock(space
);
403 return KERN_UREFS_OVERFLOW
;
406 (entry
->ie_bits
)++; /* increment urefs */
407 ipc_entry_modified(space
, name
, entry
);
408 is_write_unlock(space
);
413 ipc_notify_dead_name(notify
, name
);
418 is_write_unlock(space
);
423 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_OR_DEAD
)
424 return KERN_INVALID_ARGUMENT
;
426 return KERN_INVALID_RIGHT
;
429 *previousp
= previous
;
434 * Routine: ipc_right_request_cancel
436 * Cancel a notification request and return the send-once right.
437 * Afterwards, entry->ie_request == 0.
439 * The space must be write-locked; the port must be locked.
440 * The port must be active; the space doesn't have to be.
444 ipc_right_request_cancel(
445 __unused ipc_space_t space
,
447 mach_port_name_t name
,
452 assert(ip_active(port
));
453 assert(port
== (ipc_port_t
) entry
->ie_object
);
455 if (entry
->ie_request
== IE_REQ_NONE
)
458 previous
= ipc_port_request_cancel(port
, name
, entry
->ie_request
);
459 entry
->ie_request
= IE_REQ_NONE
;
460 ipc_entry_modified(space
, name
, entry
);
465 * Routine: ipc_right_inuse
467 * Check if an entry is being used.
468 * Returns TRUE if it is.
470 * The space is write-locked and active.
471 * It is unlocked if the entry is inuse.
477 __unused mach_port_name_t name
,
480 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
481 is_write_unlock(space
);
488 * Routine: ipc_right_check
490 * Check if the port has died. If it has,
491 * clean up the entry and return TRUE.
493 * The space is write-locked; the port is not locked.
494 * If returns FALSE, the port is also locked and active.
495 * Otherwise, entry is converted to a dead name.
497 * Caller is responsible for a reference to port if it
498 * had died (returns TRUE).
505 mach_port_name_t name
,
508 ipc_entry_bits_t bits
;
510 assert(is_active(space
));
511 assert(port
== (ipc_port_t
) entry
->ie_object
);
517 /* this was either a pure send right or a send-once right */
519 bits
= entry
->ie_bits
;
520 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
521 assert(IE_BITS_UREFS(bits
) > 0);
523 if (bits
& MACH_PORT_TYPE_SEND
) {
524 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
525 assert(IE_BITS_UREFS(bits
) > 0);
526 assert(port
->ip_srights
> 0);
529 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
530 assert(IE_BITS_UREFS(bits
) == 1);
531 assert(port
->ip_sorights
> 0);
537 * delete SEND rights from ipc hash.
540 if ((bits
& MACH_PORT_TYPE_SEND
) != 0) {
541 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
544 /* convert entry to dead name */
545 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
548 * If there was a notification request outstanding on this
549 * name, and the port went dead, that notification
550 * must already be on its way up from the port layer.
552 * Add the reference that the notification carries. It
553 * is done here, and not in the notification delivery,
554 * because the latter doesn't have a space reference and
555 * trying to actually move a send-right reference would
556 * get short-circuited into a MACH_PORT_DEAD by IPC. Since
557 * all calls that deal with the right eventually come
558 * through here, it has the same result.
560 * Once done, clear the request index so we only account
563 if (entry
->ie_request
!= IE_REQ_NONE
) {
564 if (ipc_port_request_type(port
, name
, entry
->ie_request
) != 0) {
565 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
568 entry
->ie_request
= IE_REQ_NONE
;
570 entry
->ie_bits
= bits
;
571 entry
->ie_object
= IO_NULL
;
572 ipc_entry_modified(space
, name
, entry
);
577 * Routine: ipc_right_terminate
579 * Cleans up an entry in a terminated space.
580 * The entry isn't deallocated or removed
581 * from reverse hash tables.
583 * The space is dead and unlocked.
589 mach_port_name_t name
,
592 ipc_entry_bits_t bits
;
593 mach_port_type_t type
;
595 bits
= entry
->ie_bits
;
596 type
= IE_BITS_TYPE(bits
);
598 assert(!is_active(space
));
601 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
602 * problem, because we check that the port is active. If
603 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
604 * would still work, but dead space refs would accumulate
605 * in ip_dnrequests. They would use up slots in
606 * ip_dnrequests and keep the spaces from being freed.
610 case MACH_PORT_TYPE_DEAD_NAME
:
611 assert(entry
->ie_request
== IE_REQ_NONE
);
612 assert(entry
->ie_object
== IO_NULL
);
615 case MACH_PORT_TYPE_PORT_SET
: {
616 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
618 assert(entry
->ie_request
== IE_REQ_NONE
);
619 assert(pset
!= IPS_NULL
);
622 assert(ips_active(pset
));
623 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
627 case MACH_PORT_TYPE_SEND
:
628 case MACH_PORT_TYPE_RECEIVE
:
629 case MACH_PORT_TYPE_SEND_RECEIVE
:
630 case MACH_PORT_TYPE_SEND_ONCE
: {
631 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
633 ipc_port_t nsrequest
= IP_NULL
;
634 mach_port_mscount_t mscount
= 0;
636 assert(port
!= IP_NULL
);
639 if (!ip_active(port
)) {
645 request
= ipc_right_request_cancel_macro(space
, port
,
648 if (type
& MACH_PORT_TYPE_SEND
) {
649 assert(port
->ip_srights
> 0);
650 if (--port
->ip_srights
== 0
652 nsrequest
= port
->ip_nsrequest
;
653 if (nsrequest
!= IP_NULL
) {
654 port
->ip_nsrequest
= IP_NULL
;
655 mscount
= port
->ip_mscount
;
660 if (type
& MACH_PORT_TYPE_RECEIVE
) {
661 wait_queue_link_t wql
;
662 queue_head_t links_data
;
663 queue_t links
= &links_data
;
665 assert(port
->ip_receiver_name
== name
);
666 assert(port
->ip_receiver
== space
);
669 ipc_port_clear_receiver(port
, links
);
670 ipc_port_destroy(port
); /* consumes our ref, unlocks */
671 while(!queue_empty(links
)) {
672 wql
= (wait_queue_link_t
) dequeue(links
);
673 wait_queue_link_free(wql
);
676 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
677 assert(port
->ip_sorights
> 0);
680 ipc_notify_send_once(port
); /* consumes our ref */
682 assert(port
->ip_receiver
!= space
);
688 if (nsrequest
!= IP_NULL
)
689 ipc_notify_no_senders(nsrequest
, mscount
);
691 if (request
!= IP_NULL
)
692 ipc_notify_port_deleted(request
, name
);
697 panic("ipc_right_terminate: strange type - 0x%x", type
);
702 * Routine: ipc_right_destroy
704 * Destroys an entry in a space.
706 * The space is write-locked (returns unlocked).
707 * The space must be active.
709 * KERN_SUCCESS The entry was destroyed.
715 mach_port_name_t name
,
717 boolean_t check_guard
,
720 ipc_entry_bits_t bits
;
721 mach_port_type_t type
;
723 bits
= entry
->ie_bits
;
724 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
725 type
= IE_BITS_TYPE(bits
);
727 assert(is_active(space
));
730 case MACH_PORT_TYPE_DEAD_NAME
:
731 assert(entry
->ie_request
== IE_REQ_NONE
);
732 assert(entry
->ie_object
== IO_NULL
);
734 ipc_entry_dealloc(space
, name
, entry
);
735 is_write_unlock(space
);
738 case MACH_PORT_TYPE_PORT_SET
: {
739 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
741 assert(entry
->ie_request
== IE_REQ_NONE
);
742 assert(pset
!= IPS_NULL
);
744 entry
->ie_object
= IO_NULL
;
745 ipc_entry_dealloc(space
, name
, entry
);
748 is_write_unlock(space
);
750 assert(ips_active(pset
));
751 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
755 case MACH_PORT_TYPE_SEND
:
756 case MACH_PORT_TYPE_RECEIVE
:
757 case MACH_PORT_TYPE_SEND_RECEIVE
:
758 case MACH_PORT_TYPE_SEND_ONCE
: {
759 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
760 ipc_port_t nsrequest
= IP_NULL
;
761 mach_port_mscount_t mscount
= 0;
764 assert(port
!= IP_NULL
);
766 if (type
== MACH_PORT_TYPE_SEND
)
767 ipc_hash_delete(space
, (ipc_object_t
) port
,
772 if (!ip_active(port
)) {
773 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
775 entry
->ie_request
= IE_REQ_NONE
;
776 entry
->ie_object
= IO_NULL
;
777 ipc_entry_dealloc(space
, name
, entry
);
778 is_write_unlock(space
);
783 /* For receive rights, check for guarding */
784 if ((type
& MACH_PORT_TYPE_RECEIVE
) &&
785 (check_guard
) && (port
->ip_guarded
) &&
786 (guard
!= port
->ip_context
)) {
787 /* Guard Violation */
788 uint64_t portguard
= port
->ip_context
;
790 is_write_unlock(space
);
791 /* Raise mach port guard exception */
792 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
793 return KERN_INVALID_RIGHT
;
797 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
799 entry
->ie_object
= IO_NULL
;
800 ipc_entry_dealloc(space
, name
, entry
);
801 is_write_unlock(space
);
803 if (type
& MACH_PORT_TYPE_SEND
) {
804 assert(port
->ip_srights
> 0);
805 if (--port
->ip_srights
== 0) {
806 nsrequest
= port
->ip_nsrequest
;
807 if (nsrequest
!= IP_NULL
) {
808 port
->ip_nsrequest
= IP_NULL
;
809 mscount
= port
->ip_mscount
;
814 if (type
& MACH_PORT_TYPE_RECEIVE
) {
815 queue_head_t links_data
;
816 queue_t links
= &links_data
;
817 wait_queue_link_t wql
;
819 assert(ip_active(port
));
820 assert(port
->ip_receiver
== space
);
824 ipc_port_clear_receiver(port
, links
);
825 ipc_port_destroy(port
); /* consumes our ref, unlocks */
827 while(!queue_empty(links
)) {
828 wql
= (wait_queue_link_t
) dequeue(links
);
829 wait_queue_link_free(wql
);
832 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
833 assert(port
->ip_sorights
> 0);
836 ipc_notify_send_once(port
); /* consumes our ref */
838 assert(port
->ip_receiver
!= space
);
844 if (nsrequest
!= IP_NULL
)
845 ipc_notify_no_senders(nsrequest
, mscount
);
847 if (request
!= IP_NULL
)
848 ipc_notify_port_deleted(request
, name
);
855 panic("ipc_right_destroy: strange type");
862 * Routine: ipc_right_dealloc
864 * Releases a send/send-once/dead-name user ref.
865 * Like ipc_right_delta with a delta of -1,
866 * but looks at the entry to determine the right.
868 * The space is write-locked, and is unlocked upon return.
869 * The space must be active.
871 * KERN_SUCCESS A user ref was released.
872 * KERN_INVALID_RIGHT Entry has wrong type.
878 mach_port_name_t name
,
881 ipc_port_t port
= IP_NULL
;
882 ipc_entry_bits_t bits
;
883 mach_port_type_t type
;
885 bits
= entry
->ie_bits
;
886 type
= IE_BITS_TYPE(bits
);
889 assert(is_active(space
));
892 case MACH_PORT_TYPE_DEAD_NAME
: {
895 assert(IE_BITS_UREFS(bits
) > 0);
896 assert(entry
->ie_request
== IE_REQ_NONE
);
897 assert(entry
->ie_object
== IO_NULL
);
899 if (IE_BITS_UREFS(bits
) == 1) {
900 ipc_entry_dealloc(space
, name
, entry
);
902 entry
->ie_bits
= bits
-1; /* decrement urefs */
903 ipc_entry_modified(space
, name
, entry
);
905 is_write_unlock(space
);
907 /* release any port that got converted to dead name below */
913 case MACH_PORT_TYPE_SEND_ONCE
: {
916 assert(IE_BITS_UREFS(bits
) == 1);
918 port
= (ipc_port_t
) entry
->ie_object
;
919 assert(port
!= IP_NULL
);
921 if (ipc_right_check(space
, port
, name
, entry
)) {
923 bits
= entry
->ie_bits
;
924 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
925 goto dead_name
; /* it will release port */
927 /* port is locked and active */
929 assert(port
->ip_sorights
> 0);
931 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
934 entry
->ie_object
= IO_NULL
;
935 ipc_entry_dealloc(space
, name
, entry
);
937 is_write_unlock(space
);
939 ipc_notify_send_once(port
);
941 if (request
!= IP_NULL
)
942 ipc_notify_port_deleted(request
, name
);
946 case MACH_PORT_TYPE_SEND
: {
947 ipc_port_t request
= IP_NULL
;
948 ipc_port_t nsrequest
= IP_NULL
;
949 mach_port_mscount_t mscount
= 0;
952 assert(IE_BITS_UREFS(bits
) > 0);
954 port
= (ipc_port_t
) entry
->ie_object
;
955 assert(port
!= IP_NULL
);
957 if (ipc_right_check(space
, port
, name
, entry
)) {
958 bits
= entry
->ie_bits
;
959 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
960 goto dead_name
; /* it will release port */
962 /* port is locked and active */
964 assert(port
->ip_srights
> 0);
966 if (IE_BITS_UREFS(bits
) == 1) {
967 if (--port
->ip_srights
== 0) {
968 nsrequest
= port
->ip_nsrequest
;
969 if (nsrequest
!= IP_NULL
) {
970 port
->ip_nsrequest
= IP_NULL
;
971 mscount
= port
->ip_mscount
;
975 request
= ipc_right_request_cancel_macro(space
, port
,
977 ipc_hash_delete(space
, (ipc_object_t
) port
,
981 entry
->ie_object
= IO_NULL
;
982 ipc_entry_dealloc(space
, name
, entry
);
983 is_write_unlock(space
);
988 entry
->ie_bits
= bits
-1; /* decrement urefs */
989 ipc_entry_modified(space
, name
, entry
);
990 is_write_unlock(space
);
994 if (nsrequest
!= IP_NULL
)
995 ipc_notify_no_senders(nsrequest
, mscount
);
997 if (request
!= IP_NULL
)
998 ipc_notify_port_deleted(request
, name
);
1002 case MACH_PORT_TYPE_SEND_RECEIVE
: {
1003 ipc_port_t nsrequest
= IP_NULL
;
1004 mach_port_mscount_t mscount
= 0;
1006 assert(IE_BITS_UREFS(bits
) > 0);
1008 port
= (ipc_port_t
) entry
->ie_object
;
1009 assert(port
!= IP_NULL
);
1012 assert(ip_active(port
));
1013 assert(port
->ip_receiver_name
== name
);
1014 assert(port
->ip_receiver
== space
);
1015 assert(port
->ip_srights
> 0);
1017 if (IE_BITS_UREFS(bits
) == 1) {
1018 if (--port
->ip_srights
== 0) {
1019 nsrequest
= port
->ip_nsrequest
;
1020 if (nsrequest
!= IP_NULL
) {
1021 port
->ip_nsrequest
= IP_NULL
;
1022 mscount
= port
->ip_mscount
;
1026 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1027 MACH_PORT_TYPE_SEND
);
1029 entry
->ie_bits
= bits
-1; /* decrement urefs */
1033 ipc_entry_modified(space
, name
, entry
);
1034 is_write_unlock(space
);
1036 if (nsrequest
!= IP_NULL
)
1037 ipc_notify_no_senders(nsrequest
, mscount
);
1042 is_write_unlock(space
);
1043 return KERN_INVALID_RIGHT
;
1046 return KERN_SUCCESS
;
1050 * Routine: ipc_right_delta
1052 * Modifies the user-reference count for a right.
1053 * May deallocate the right, if the count goes to zero.
1055 * The space is write-locked, and is unlocked upon return.
1056 * The space must be active.
1058 * KERN_SUCCESS Count was modified.
1059 * KERN_INVALID_RIGHT Entry has wrong type.
1060 * KERN_INVALID_VALUE Bad delta for the right.
1061 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
1067 mach_port_name_t name
,
1069 mach_port_right_t right
,
1070 mach_port_delta_t delta
)
1072 ipc_port_t port
= IP_NULL
;
1073 ipc_entry_bits_t bits
;
1075 bits
= entry
->ie_bits
;
1079 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
1080 * switch below. It is used to keep track of those cases (in DIPC)
1081 * where we have postponed the dropping of a port reference. Since
1082 * the dropping of the reference could cause the port to disappear
1083 * we postpone doing so when we are holding the space lock.
1086 assert(is_active(space
));
1087 assert(right
< MACH_PORT_RIGHT_NUMBER
);
1089 /* Rights-specific restrictions and operations. */
1092 case MACH_PORT_RIGHT_PORT_SET
: {
1095 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0)
1098 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
1099 assert(IE_BITS_UREFS(bits
) == 0);
1100 assert(entry
->ie_request
== IE_REQ_NONE
);
1108 pset
= (ipc_pset_t
) entry
->ie_object
;
1109 assert(pset
!= IPS_NULL
);
1111 entry
->ie_object
= IO_NULL
;
1112 ipc_entry_dealloc(space
, name
, entry
);
1115 assert(ips_active(pset
));
1116 is_write_unlock(space
);
1118 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
1122 case MACH_PORT_RIGHT_RECEIVE
: {
1123 ipc_port_t request
= IP_NULL
;
1124 queue_head_t links_data
;
1125 queue_t links
= &links_data
;
1126 wait_queue_link_t wql
;
1128 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1137 port
= (ipc_port_t
) entry
->ie_object
;
1138 assert(port
!= IP_NULL
);
1141 * The port lock is needed for ipc_right_dncancel;
1142 * otherwise, we wouldn't have to take the lock
1143 * until just before dropping the space lock.
1147 assert(ip_active(port
));
1148 assert(port
->ip_receiver_name
== name
);
1149 assert(port
->ip_receiver
== space
);
1151 /* Mach Port Guard Checking */
1152 if(port
->ip_guarded
) {
1153 uint64_t portguard
= port
->ip_context
;
1155 is_write_unlock(space
);
1156 /* Raise mach port guard exception */
1157 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_MOD_REFS
);
1161 if (bits
& MACH_PORT_TYPE_SEND
) {
1162 assert(IE_BITS_TYPE(bits
) ==
1163 MACH_PORT_TYPE_SEND_RECEIVE
);
1164 assert(IE_BITS_UREFS(bits
) > 0);
1165 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1166 assert(port
->ip_srights
> 0);
1168 if (port
->ip_pdrequest
!= NULL
) {
1170 * Since another task has requested a
1171 * destroy notification for this port, it
1172 * isn't actually being destroyed - the receive
1173 * right is just being moved to another task.
1174 * Since we still have one or more send rights,
1175 * we need to record the loss of the receive
1176 * right and enter the remaining send right
1177 * into the hash table.
1179 ipc_entry_modified(space
, name
, entry
);
1180 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1181 ipc_hash_insert(space
, (ipc_object_t
) port
,
1186 * The remaining send right turns into a
1187 * dead name. Notice we don't decrement
1188 * ip_srights, generate a no-senders notif,
1189 * or use ipc_right_dncancel, because the
1190 * port is destroyed "first".
1192 bits
&= ~IE_BITS_TYPE_MASK
;
1193 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1194 if (entry
->ie_request
) {
1195 entry
->ie_request
= IE_REQ_NONE
;
1198 entry
->ie_bits
= bits
;
1199 entry
->ie_object
= IO_NULL
;
1200 ipc_entry_modified(space
, name
, entry
);
1203 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1204 assert(IE_BITS_UREFS(bits
) == 0);
1206 request
= ipc_right_request_cancel_macro(space
, port
,
1208 entry
->ie_object
= IO_NULL
;
1209 ipc_entry_dealloc(space
, name
, entry
);
1211 is_write_unlock(space
);
1214 ipc_port_clear_receiver(port
, links
);
1215 ipc_port_destroy(port
); /* consumes ref, unlocks */
1217 while(!queue_empty(links
)) {
1218 wql
= (wait_queue_link_t
) dequeue(links
);
1219 wait_queue_link_free(wql
);
1222 if (request
!= IP_NULL
)
1223 ipc_notify_port_deleted(request
, name
);
1227 case MACH_PORT_RIGHT_SEND_ONCE
: {
1230 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1233 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1234 assert(IE_BITS_UREFS(bits
) == 1);
1236 port
= (ipc_port_t
) entry
->ie_object
;
1237 assert(port
!= IP_NULL
);
1239 if (ipc_right_check(space
, port
, name
, entry
)) {
1240 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1243 /* port is locked and active */
1245 assert(port
->ip_sorights
> 0);
1247 if ((delta
> 0) || (delta
< -1)) {
1257 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1260 entry
->ie_object
= IO_NULL
;
1261 ipc_entry_dealloc(space
, name
, entry
);
1263 is_write_unlock(space
);
1265 ipc_notify_send_once(port
);
1267 if (request
!= IP_NULL
)
1268 ipc_notify_port_deleted(request
, name
);
1272 case MACH_PORT_RIGHT_DEAD_NAME
: {
1273 ipc_port_t relport
= IP_NULL
;
1274 mach_port_urefs_t urefs
;
1276 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1278 port
= (ipc_port_t
) entry
->ie_object
;
1279 assert(port
!= IP_NULL
);
1281 if (!ipc_right_check(space
, port
, name
, entry
)) {
1282 /* port is locked and active */
1287 bits
= entry
->ie_bits
;
1290 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0)
1293 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1294 assert(IE_BITS_UREFS(bits
) > 0);
1295 assert(entry
->ie_object
== IO_NULL
);
1296 assert(entry
->ie_request
== IE_REQ_NONE
);
1298 urefs
= IE_BITS_UREFS(bits
);
1299 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1301 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
))
1302 goto urefs_overflow
;
1304 if ((urefs
+ delta
) == 0) {
1305 ipc_entry_dealloc(space
, name
, entry
);
1307 entry
->ie_bits
= bits
+ delta
;
1308 ipc_entry_modified(space
, name
, entry
);
1310 is_write_unlock(space
);
1312 if (relport
!= IP_NULL
)
1313 ip_release(relport
);
1318 case MACH_PORT_RIGHT_SEND
: {
1319 mach_port_urefs_t urefs
;
1320 ipc_port_t request
= IP_NULL
;
1321 ipc_port_t nsrequest
= IP_NULL
;
1322 mach_port_mscount_t mscount
= 0;
1324 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1327 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1329 port
= (ipc_port_t
) entry
->ie_object
;
1330 assert(port
!= IP_NULL
);
1332 if (ipc_right_check(space
, port
, name
, entry
)) {
1333 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1336 /* port is locked and active */
1338 assert(port
->ip_srights
> 0);
1340 urefs
= IE_BITS_UREFS(bits
);
1341 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1345 if (MACH_PORT_UREFS_OVERFLOW(urefs
+1, delta
)) {
1347 goto urefs_overflow
;
1350 if ((urefs
+ delta
) == 0) {
1351 if (--port
->ip_srights
== 0) {
1352 nsrequest
= port
->ip_nsrequest
;
1353 if (nsrequest
!= IP_NULL
) {
1354 port
->ip_nsrequest
= IP_NULL
;
1355 mscount
= port
->ip_mscount
;
1359 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1360 assert(port
->ip_receiver_name
== name
);
1361 assert(port
->ip_receiver
== space
);
1363 assert(IE_BITS_TYPE(bits
) ==
1364 MACH_PORT_TYPE_SEND_RECEIVE
);
1366 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1367 MACH_PORT_TYPE_SEND
);
1368 ipc_entry_modified(space
, name
, entry
);
1370 assert(IE_BITS_TYPE(bits
) ==
1371 MACH_PORT_TYPE_SEND
);
1373 request
= ipc_right_request_cancel_macro(space
, port
,
1375 ipc_hash_delete(space
, (ipc_object_t
) port
,
1381 entry
->ie_object
= IO_NULL
;
1382 ipc_entry_dealloc(space
, name
, entry
);
1386 entry
->ie_bits
= bits
+ delta
;
1387 ipc_entry_modified(space
, name
, entry
);
1390 is_write_unlock(space
);
1392 if (nsrequest
!= IP_NULL
)
1393 ipc_notify_no_senders(nsrequest
, mscount
);
1395 if (request
!= IP_NULL
)
1396 ipc_notify_port_deleted(request
, name
);
1401 panic("ipc_right_delta: strange right");
1404 return KERN_SUCCESS
;
1407 is_write_unlock(space
);
1408 return KERN_SUCCESS
;
1411 is_write_unlock(space
);
1412 if (port
!= IP_NULL
)
1414 return KERN_INVALID_RIGHT
;
1417 is_write_unlock(space
);
1418 return KERN_INVALID_VALUE
;
1421 is_write_unlock(space
);
1422 return KERN_UREFS_OVERFLOW
;
1425 return KERN_INVALID_RIGHT
;
1429 * Routine: ipc_right_destruct
1431 * Deallocates the receive right and modifies the
1432 * user-reference count for the send rights as requested.
1434 * The space is write-locked, and is unlocked upon return.
1435 * The space must be active.
1437 * KERN_SUCCESS Count was modified.
1438 * KERN_INVALID_RIGHT Entry has wrong type.
1439 * KERN_INVALID_VALUE Bad delta for the right.
1445 mach_port_name_t name
,
1447 mach_port_delta_t srdelta
,
1450 ipc_port_t port
= IP_NULL
;
1451 ipc_entry_bits_t bits
;
1453 queue_head_t links_data
;
1454 queue_t links
= &links_data
;
1455 wait_queue_link_t wql
;
1457 mach_port_urefs_t urefs
;
1458 ipc_port_t request
= IP_NULL
;
1459 ipc_port_t nsrequest
= IP_NULL
;
1460 mach_port_mscount_t mscount
= 0;
1462 bits
= entry
->ie_bits
;
1464 assert(is_active(space
));
1466 if (((bits
& MACH_PORT_TYPE_RECEIVE
) == 0) ||
1467 (srdelta
&& ((bits
& MACH_PORT_TYPE_SEND
) == 0))) {
1468 is_write_unlock(space
);
1469 return KERN_INVALID_RIGHT
;
1475 port
= (ipc_port_t
) entry
->ie_object
;
1476 assert(port
!= IP_NULL
);
1479 assert(ip_active(port
));
1480 assert(port
->ip_receiver_name
== name
);
1481 assert(port
->ip_receiver
== space
);
1483 /* Mach Port Guard Checking */
1484 if(port
->ip_guarded
&& (guard
!= port
->ip_context
)) {
1485 uint64_t portguard
= port
->ip_context
;
1487 is_write_unlock(space
);
1488 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
);
1489 return KERN_INVALID_ARGUMENT
;
1493 * First reduce the send rights as requested and
1494 * adjust the entry->ie_bits accordingly. The
1495 * ipc_entry_modified() call is made once the receive
1496 * right is destroyed too.
1501 assert(port
->ip_srights
> 0);
1503 urefs
= IE_BITS_UREFS(bits
);
1505 * Since we made sure that srdelta is negative,
1506 * the check for urefs overflow is not required.
1508 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, srdelta
)) {
1512 if ((urefs
+ srdelta
) == 0) {
1513 if (--port
->ip_srights
== 0) {
1514 nsrequest
= port
->ip_nsrequest
;
1515 if (nsrequest
!= IP_NULL
) {
1516 port
->ip_nsrequest
= IP_NULL
;
1517 mscount
= port
->ip_mscount
;
1520 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_RECEIVE
);
1521 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1522 MACH_PORT_TYPE_SEND
);
1524 entry
->ie_bits
= bits
+ srdelta
;
1529 * Now destroy the receive right. Update space and
1530 * entry accordingly.
1533 bits
= entry
->ie_bits
;
1534 if (bits
& MACH_PORT_TYPE_SEND
) {
1535 assert(IE_BITS_UREFS(bits
) > 0);
1536 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1538 if (port
->ip_pdrequest
!= NULL
) {
1540 * Since another task has requested a
1541 * destroy notification for this port, it
1542 * isn't actually being destroyed - the receive
1543 * right is just being moved to another task.
1544 * Since we still have one or more send rights,
1545 * we need to record the loss of the receive
1546 * right and enter the remaining send right
1547 * into the hash table.
1549 ipc_entry_modified(space
, name
, entry
);
1550 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1551 ipc_hash_insert(space
, (ipc_object_t
) port
,
1556 * The remaining send right turns into a
1557 * dead name. Notice we don't decrement
1558 * ip_srights, generate a no-senders notif,
1559 * or use ipc_right_dncancel, because the
1560 * port is destroyed "first".
1562 bits
&= ~IE_BITS_TYPE_MASK
;
1563 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1564 if (entry
->ie_request
) {
1565 entry
->ie_request
= IE_REQ_NONE
;
1568 entry
->ie_bits
= bits
;
1569 entry
->ie_object
= IO_NULL
;
1570 ipc_entry_modified(space
, name
, entry
);
1573 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1574 assert(IE_BITS_UREFS(bits
) == 0);
1575 request
= ipc_right_request_cancel_macro(space
, port
,
1577 entry
->ie_object
= IO_NULL
;
1578 ipc_entry_dealloc(space
, name
, entry
);
1582 is_write_unlock(space
);
1584 if (nsrequest
!= IP_NULL
)
1585 ipc_notify_no_senders(nsrequest
, mscount
);
1588 ipc_port_clear_receiver(port
, links
);
1589 ipc_port_destroy(port
); /* consumes ref, unlocks */
1591 while(!queue_empty(links
)) {
1592 wql
= (wait_queue_link_t
) dequeue(links
);
1593 wait_queue_link_free(wql
);
1596 if (request
!= IP_NULL
)
1597 ipc_notify_port_deleted(request
, name
);
1599 return KERN_SUCCESS
;
1602 is_write_unlock(space
);
1603 return KERN_INVALID_VALUE
;
1609 * Routine: ipc_right_info
1611 * Retrieves information about the right.
1613 * The space is active and write-locked.
1614 * The space is unlocked upon return.
1616 * KERN_SUCCESS Retrieved info
1622 mach_port_name_t name
,
1624 mach_port_type_t
*typep
,
1625 mach_port_urefs_t
*urefsp
)
1628 ipc_entry_bits_t bits
;
1629 mach_port_type_t type
= 0;
1630 ipc_port_request_index_t request
;
1632 bits
= entry
->ie_bits
;
1633 request
= entry
->ie_request
;
1634 port
= (ipc_port_t
) entry
->ie_object
;
1636 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1637 assert(IP_VALID(port
));
1639 if (request
!= IE_REQ_NONE
) {
1641 assert(ip_active(port
));
1642 type
|= ipc_port_request_type(port
, name
, request
);
1645 is_write_unlock(space
);
1647 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1649 * validate port is still alive - if so, get request
1650 * types while we still have it locked. Otherwise,
1651 * recapture the (now dead) bits.
1653 if (!ipc_right_check(space
, port
, name
, entry
)) {
1654 if (request
!= IE_REQ_NONE
)
1655 type
|= ipc_port_request_type(port
, name
, request
);
1657 is_write_unlock(space
);
1659 bits
= entry
->ie_bits
;
1660 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1661 is_write_unlock(space
);
1665 is_write_unlock(space
);
1668 type
|= IE_BITS_TYPE(bits
);
1671 *urefsp
= IE_BITS_UREFS(bits
);
1672 return KERN_SUCCESS
;
1676 * Routine: ipc_right_copyin_check
1678 * Check if a subsequent ipc_right_copyin would succeed.
1680 * The space is locked (read or write) and active.
1684 ipc_right_copyin_check(
1685 __assert_only ipc_space_t space
,
1686 __unused mach_port_name_t name
,
1688 mach_msg_type_name_t msgt_name
)
1690 ipc_entry_bits_t bits
;
1692 #if CONFIG_MACF_MACH
1693 task_t self
= current_task();
1697 bits
= entry
->ie_bits
;
1698 assert(is_active(space
));
1700 switch (msgt_name
) {
1701 case MACH_MSG_TYPE_MAKE_SEND
:
1702 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1705 #if CONFIG_MACF_MACH
1706 port
= (ipc_port_t
) entry
->ie_object
;
1708 tasklabel_lock(self
);
1709 rc
= mac_port_check_make_send(&self
->maclabel
, &port
->ip_label
); tasklabel_unlock(self
);
1716 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1717 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1720 #if CONFIG_MACF_MACH
1721 port
= (ipc_port_t
) entry
->ie_object
;
1723 tasklabel_lock(self
);
1724 rc
= mac_port_check_make_send_once(&self
->maclabel
, &port
->ip_label
);
1725 tasklabel_unlock(self
);
1732 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1733 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1736 #if CONFIG_MACF_MACH
1737 port
= (ipc_port_t
) entry
->ie_object
;
1739 tasklabel_lock(self
);
1740 rc
= mac_port_check_move_receive(&self
->maclabel
, &port
->ip_label
);
1741 tasklabel_unlock(self
);
1748 case MACH_MSG_TYPE_COPY_SEND
:
1749 case MACH_MSG_TYPE_MOVE_SEND
:
1750 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1753 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1756 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1759 port
= (ipc_port_t
) entry
->ie_object
;
1760 assert(port
!= IP_NULL
);
1763 active
= ip_active(port
);
1764 #if CONFIG_MACF_MACH
1765 tasklabel_lock(self
);
1766 switch (msgt_name
) {
1767 case MACH_MSG_TYPE_COPY_SEND
:
1768 rc
= mac_port_check_copy_send(&self
->maclabel
,
1771 case MACH_MSG_TYPE_MOVE_SEND
:
1772 rc
= mac_port_check_move_send(&self
->maclabel
,
1775 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
1776 rc
= mac_port_check_move_send_once(&self
->maclabel
,
1780 panic("ipc_right_copyin_check: strange rights");
1782 tasklabel_unlock(self
);
1794 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1795 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1798 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1806 panic("ipc_right_copyin_check: strange rights");
1813 * Routine: ipc_right_copyin
1815 * Copyin a capability from a space.
1816 * If successful, the caller gets a ref
1817 * for the resulting object, unless it is IO_DEAD,
1818 * and possibly a send-once right which should
1819 * be used in a port-deleted notification.
1821 * If deadok is not TRUE, the copyin operation
1822 * will fail instead of producing IO_DEAD.
1824 * The entry is never deallocated (except
1825 * when KERN_INVALID_NAME), so the caller
1826 * should deallocate the entry if its type
1827 * is MACH_PORT_TYPE_NONE.
1829 * The space is write-locked and active.
1831 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1832 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1838 mach_port_name_t name
,
1840 mach_msg_type_name_t msgt_name
,
1842 ipc_object_t
*objectp
,
1843 ipc_port_t
*sorightp
,
1844 ipc_port_t
*releasep
,
1845 #if IMPORTANCE_INHERITANCE
1847 #endif /* IMPORTANCE_INHERITANCE */
1850 ipc_entry_bits_t bits
;
1852 #if CONFIG_MACF_MACH
1853 task_t self
= current_task();
1857 *releasep
= IP_NULL
;
1859 #if IMPORTANCE_INHERITANCE
1863 bits
= entry
->ie_bits
;
1865 assert(is_active(space
));
1867 switch (msgt_name
) {
1868 case MACH_MSG_TYPE_MAKE_SEND
: {
1870 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1873 port
= (ipc_port_t
) entry
->ie_object
;
1874 assert(port
!= IP_NULL
);
1877 assert(ip_active(port
));
1878 assert(port
->ip_receiver_name
== name
);
1879 assert(port
->ip_receiver
== space
);
1881 #if CONFIG_MACF_MACH
1882 tasklabel_lock(self
);
1883 rc
= mac_port_check_make_send(&self
->maclabel
, &port
->ip_label
);
1884 tasklabel_unlock(self
);
1887 return KERN_NO_ACCESS
;
1896 *objectp
= (ipc_object_t
) port
;
1897 *sorightp
= IP_NULL
;
1901 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1903 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1906 port
= (ipc_port_t
) entry
->ie_object
;
1907 assert(port
!= IP_NULL
);
1910 assert(ip_active(port
));
1911 assert(port
->ip_receiver_name
== name
);
1912 assert(port
->ip_receiver
== space
);
1914 #if CONFIG_MACF_MACH
1915 tasklabel_lock(self
);
1916 rc
= mac_port_check_make_send_once(&self
->maclabel
, &port
->ip_label
);
1917 tasklabel_unlock(self
);
1920 return KERN_NO_ACCESS
;
1924 port
->ip_sorights
++;
1928 *objectp
= (ipc_object_t
) port
;
1929 *sorightp
= IP_NULL
;
1933 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1934 ipc_port_t request
= IP_NULL
;
1936 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1939 port
= (ipc_port_t
) entry
->ie_object
;
1940 assert(port
!= IP_NULL
);
1943 assert(ip_active(port
));
1944 assert(port
->ip_receiver_name
== name
);
1945 assert(port
->ip_receiver
== space
);
1947 #if CONFIG_MACF_MACH
1948 tasklabel_lock(self
);
1949 rc
= mac_port_check_move_receive(&self
->maclabel
,
1951 tasklabel_unlock(self
);
1954 return KERN_NO_ACCESS
;
1958 if (bits
& MACH_PORT_TYPE_SEND
) {
1959 assert(IE_BITS_TYPE(bits
) ==
1960 MACH_PORT_TYPE_SEND_RECEIVE
);
1961 assert(IE_BITS_UREFS(bits
) > 0);
1962 assert(port
->ip_srights
> 0);
1964 ipc_hash_insert(space
, (ipc_object_t
) port
,
1968 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1969 assert(IE_BITS_UREFS(bits
) == 0);
1971 request
= ipc_right_request_cancel_macro(space
, port
,
1973 entry
->ie_object
= IO_NULL
;
1975 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1976 ipc_entry_modified(space
, name
, entry
);
1978 ipc_port_clear_receiver(port
, links
);
1979 port
->ip_receiver_name
= MACH_PORT_NULL
;
1980 port
->ip_destination
= IP_NULL
;
1982 #if IMPORTANCE_INHERITANCE
1984 * Account for boosts the current task is going to lose when
1985 * copying this right in. Tempowner ports have either not
1986 * been accounting to any task (and therefore are already in
1987 * "limbo" state w.r.t. assertions) or to some other specific
1988 * task. As we have no way to drop the latter task's assertions
1989 * here, We'll deduct those when we enqueue it on its
1990 * destination port (see ipc_port_check_circularity()).
1992 if (port
->ip_tempowner
== 0) {
1993 assert(port
->ip_taskptr
== 0);
1995 /* ports in limbo have to be tempowner */
1996 port
->ip_tempowner
= 1;
1997 *assertcntp
= port
->ip_impcount
;
1999 #endif /* IMPORTANCE_INHERITANCE */
2003 *objectp
= (ipc_object_t
) port
;
2004 *sorightp
= request
;
2008 case MACH_MSG_TYPE_COPY_SEND
: {
2010 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
2013 /* allow for dead send-once rights */
2015 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
2018 assert(IE_BITS_UREFS(bits
) > 0);
2020 port
= (ipc_port_t
) entry
->ie_object
;
2021 assert(port
!= IP_NULL
);
2023 if (ipc_right_check(space
, port
, name
, entry
)) {
2024 bits
= entry
->ie_bits
;
2028 /* port is locked and active */
2030 #if CONFIG_MACF_MACH
2031 tasklabel_lock(self
);
2032 rc
= mac_port_check_copy_send(&self
->maclabel
, &port
->ip_label
);
2033 tasklabel_unlock(self
);
2036 return KERN_NO_ACCESS
;
2040 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2041 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2042 assert(port
->ip_sorights
> 0);
2048 assert(port
->ip_srights
> 0);
2054 *objectp
= (ipc_object_t
) port
;
2055 *sorightp
= IP_NULL
;
2059 case MACH_MSG_TYPE_MOVE_SEND
: {
2060 ipc_port_t request
= IP_NULL
;
2062 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
2065 /* allow for dead send-once rights */
2067 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
2070 assert(IE_BITS_UREFS(bits
) > 0);
2072 port
= (ipc_port_t
) entry
->ie_object
;
2073 assert(port
!= IP_NULL
);
2075 if (ipc_right_check(space
, port
, name
, entry
)) {
2076 bits
= entry
->ie_bits
;
2080 /* port is locked and active */
2082 #if CONFIG_MACF_MACH
2083 tasklabel_lock (self
);
2084 rc
= mac_port_check_copy_send (&self
->maclabel
, &port
->ip_label
);
2085 tasklabel_unlock (self
);
2089 return KERN_NO_ACCESS
;
2093 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
2094 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2095 assert(port
->ip_sorights
> 0);
2101 assert(port
->ip_srights
> 0);
2103 if (IE_BITS_UREFS(bits
) == 1) {
2104 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2105 assert(port
->ip_receiver_name
== name
);
2106 assert(port
->ip_receiver
== space
);
2107 assert(IE_BITS_TYPE(bits
) ==
2108 MACH_PORT_TYPE_SEND_RECEIVE
);
2112 assert(IE_BITS_TYPE(bits
) ==
2113 MACH_PORT_TYPE_SEND
);
2115 request
= ipc_right_request_cancel_macro(space
, port
,
2117 ipc_hash_delete(space
, (ipc_object_t
) port
,
2119 entry
->ie_object
= IO_NULL
;
2121 entry
->ie_bits
= bits
&~
2122 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
2126 entry
->ie_bits
= bits
-1; /* decrement urefs */
2128 ipc_entry_modified(space
, name
, entry
);
2131 *objectp
= (ipc_object_t
) port
;
2132 *sorightp
= request
;
2136 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
2139 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
2142 /* allow for dead send rights */
2144 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
2147 assert(IE_BITS_UREFS(bits
) > 0);
2149 port
= (ipc_port_t
) entry
->ie_object
;
2150 assert(port
!= IP_NULL
);
2152 if (ipc_right_check(space
, port
, name
, entry
)) {
2153 bits
= entry
->ie_bits
;
2156 /* port is locked and active */
2158 #if CONFIG_MACF_MACH
2159 tasklabel_lock (self
);
2160 rc
= mac_port_check_copy_send (&self
->maclabel
, &port
->ip_label
);
2161 tasklabel_unlock (self
);
2165 return KERN_NO_ACCESS
;
2169 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
2170 assert(bits
& MACH_PORT_TYPE_SEND
);
2171 assert(port
->ip_srights
> 0);
2177 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
2178 assert(IE_BITS_UREFS(bits
) == 1);
2179 assert(port
->ip_sorights
> 0);
2181 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
2184 entry
->ie_object
= IO_NULL
;
2185 entry
->ie_bits
= bits
&~
2186 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
2187 ipc_entry_modified(space
, name
, entry
);
2188 *objectp
= (ipc_object_t
) port
;
2189 *sorightp
= request
;
2195 return KERN_INVALID_RIGHT
;
2198 return KERN_SUCCESS
;
2201 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2202 assert(IE_BITS_UREFS(bits
) > 0);
2203 assert(entry
->ie_request
== IE_REQ_NONE
);
2204 assert(entry
->ie_object
== 0);
2210 *sorightp
= IP_NULL
;
2211 return KERN_SUCCESS
;
2214 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2215 assert(IE_BITS_UREFS(bits
) > 0);
2216 assert(entry
->ie_request
== IE_REQ_NONE
);
2217 assert(entry
->ie_object
== 0);
2222 if (IE_BITS_UREFS(bits
) == 1) {
2223 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
2225 entry
->ie_bits
= bits
-1; /* decrement urefs */
2226 ipc_entry_modified(space
, name
, entry
);
2228 *sorightp
= IP_NULL
;
2229 return KERN_SUCCESS
;
2234 * Routine: ipc_right_copyin_undo
2236 * Undoes the effects of an ipc_right_copyin
2237 * of a send/send-once right that is dead.
2238 * (Object is either IO_DEAD or a dead port.)
2240 * The space is write-locked and active.
2244 ipc_right_copyin_undo(
2246 mach_port_name_t name
,
2248 mach_msg_type_name_t msgt_name
,
2249 ipc_object_t object
,
2252 ipc_entry_bits_t bits
;
2254 bits
= entry
->ie_bits
;
2256 assert(is_active(space
));
2258 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2259 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
2260 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2262 if (soright
!= IP_NULL
) {
2263 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2264 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2265 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2266 assert(object
!= IO_DEAD
);
2268 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
2269 MACH_PORT_TYPE_DEAD_NAME
| 2);
2271 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
2272 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2273 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
2275 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
2276 MACH_PORT_TYPE_DEAD_NAME
| 1);
2277 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
2278 assert(object
== IO_DEAD
);
2279 assert(IE_BITS_UREFS(bits
) > 0);
2281 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2282 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
2283 entry
->ie_bits
= bits
+1; /* increment urefs */
2286 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
2287 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
2288 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2289 assert(object
!= IO_DEAD
);
2290 assert(entry
->ie_object
== object
);
2291 assert(IE_BITS_UREFS(bits
) > 0);
2293 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
2294 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
-1);
2295 entry
->ie_bits
= bits
+1; /* increment urefs */
2299 * May as well convert the entry to a dead name.
2300 * (Or if it is a compat entry, destroy it.)
2303 (void) ipc_right_check(space
, (ipc_port_t
) object
,
2305 /* object is dead so it is not locked */
2307 ipc_entry_modified(space
, name
, entry
);
2308 /* release the reference acquired by copyin */
2310 if (object
!= IO_DEAD
)
2315 * Routine: ipc_right_copyin_two
2317 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
2318 * and deadok == FALSE, except that this moves two
2319 * send rights at once.
2321 * The space is write-locked and active.
2322 * The object is returned with two refs/send rights.
2324 * KERN_SUCCESS Acquired an object.
2325 * KERN_INVALID_RIGHT Name doesn't denote correct right.
2329 ipc_right_copyin_two(
2331 mach_port_name_t name
,
2333 ipc_object_t
*objectp
,
2334 ipc_port_t
*sorightp
,
2335 ipc_port_t
*releasep
)
2337 ipc_entry_bits_t bits
;
2338 mach_port_urefs_t urefs
;
2340 ipc_port_t request
= IP_NULL
;
2341 #if CONFIG_MACF_MACH
2342 task_t self
= current_task();
2346 *releasep
= IP_NULL
;
2348 assert(is_active(space
));
2350 bits
= entry
->ie_bits
;
2352 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
2355 urefs
= IE_BITS_UREFS(bits
);
2359 port
= (ipc_port_t
) entry
->ie_object
;
2360 assert(port
!= IP_NULL
);
2362 if (ipc_right_check(space
, port
, name
, entry
)) {
2366 /* port is locked and active */
2368 #if CONFIG_MACF_MACH
2369 tasklabel_lock(self
);
2370 rc
= mac_port_check_copy_send(&self
->maclabel
, &port
->ip_label
);
2371 tasklabel_unlock(self
);
2374 return KERN_NO_ACCESS
;
2378 assert(port
->ip_srights
> 0);
2381 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2382 assert(port
->ip_receiver_name
== name
);
2383 assert(port
->ip_receiver
== space
);
2384 assert(IE_BITS_TYPE(bits
) ==
2385 MACH_PORT_TYPE_SEND_RECEIVE
);
2391 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2393 request
= ipc_right_request_cancel_macro(space
, port
,
2398 ipc_hash_delete(space
, (ipc_object_t
) port
,
2400 entry
->ie_object
= IO_NULL
;
2402 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
2404 port
->ip_srights
+= 2;
2407 entry
->ie_bits
= bits
-2; /* decrement urefs */
2409 ipc_entry_modified(space
, name
, entry
);
2413 *objectp
= (ipc_object_t
) port
;
2414 *sorightp
= request
;
2415 return KERN_SUCCESS
;
2418 return KERN_INVALID_RIGHT
;
2422 * Routine: ipc_right_copyout
2424 * Copyout a capability to a space.
2425 * If successful, consumes a ref for the object.
2427 * Always succeeds when given a newly-allocated entry,
2428 * because user-reference overflow isn't a possibility.
2430 * If copying out the object would cause the user-reference
2431 * count in the entry to overflow, and overflow is TRUE,
2432 * then instead the user-reference count is left pegged
2433 * to its maximum value and the copyout succeeds anyway.
2435 * The space is write-locked and active.
2436 * The object is locked and active.
2437 * The object is unlocked; the space isn't.
2439 * KERN_SUCCESS Copied out capability.
2440 * KERN_UREFS_OVERFLOW User-refs would overflow;
2441 * guaranteed not to happen with a fresh entry
2442 * or if overflow=TRUE was specified.
2448 mach_port_name_t name
,
2450 mach_msg_type_name_t msgt_name
,
2452 ipc_object_t object
)
2454 ipc_entry_bits_t bits
;
2456 #if CONFIG_MACF_MACH
2460 bits
= entry
->ie_bits
;
2462 assert(IO_VALID(object
));
2463 assert(io_otype(object
) == IOT_PORT
);
2464 assert(io_active(object
));
2465 assert(entry
->ie_object
== object
);
2467 port
= (ipc_port_t
) object
;
2469 switch (msgt_name
) {
2470 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
2472 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2473 assert(port
->ip_sorights
> 0);
2475 #if CONFIG_MACF_MACH
2476 if (space
->is_task
) {
2477 tasklabel_lock(space
->is_task
);
2478 rc
= mac_port_check_hold_send_once(&space
->is_task
->maclabel
,
2480 tasklabel_unlock(space
->is_task
);
2484 return KERN_NO_ACCESS
;
2488 /* transfer send-once right and ref to entry */
2491 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1);
2492 ipc_entry_modified(space
, name
, entry
);
2495 case MACH_MSG_TYPE_PORT_SEND
:
2496 assert(port
->ip_srights
> 0);
2498 #if CONFIG_MACF_MACH
2499 if (space
->is_task
) {
2500 tasklabel_lock(space
->is_task
);
2501 rc
= mac_port_check_hold_send(&space
->is_task
->maclabel
,
2503 tasklabel_unlock(space
->is_task
);
2507 return KERN_NO_ACCESS
;
2512 if (bits
& MACH_PORT_TYPE_SEND
) {
2513 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
2515 assert(port
->ip_srights
> 1);
2517 assert(urefs
< MACH_PORT_UREFS_MAX
);
2519 if (urefs
+1 == MACH_PORT_UREFS_MAX
) {
2521 /* leave urefs pegged to maximum */
2526 return KERN_SUCCESS
;
2530 return KERN_UREFS_OVERFLOW
;
2536 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2537 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2538 assert(IE_BITS_UREFS(bits
) == 0);
2540 /* transfer send right to entry */
2545 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2546 assert(IE_BITS_UREFS(bits
) == 0);
2548 /* transfer send right and ref to entry */
2551 /* entry is locked holding ref, so can use port */
2553 ipc_hash_insert(space
, (ipc_object_t
) port
,
2557 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1;
2558 ipc_entry_modified(space
, name
, entry
);
2561 case MACH_MSG_TYPE_PORT_RECEIVE
: {
2564 #if IMPORTANCE_INHERITANCE
2565 natural_t assertcnt
= port
->ip_impcount
;
2566 #endif /* IMPORTANCE_INHERITANCE */
2568 assert(port
->ip_mscount
== 0);
2569 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
2570 dest
= port
->ip_destination
;
2572 #if CONFIG_MACF_MACH
2573 if (space
->is_task
) {
2574 tasklabel_lock(space
->is_task
);
2575 rc
= mac_port_check_hold_receive(&space
->is_task
->maclabel
,
2577 tasklabel_unlock(space
->is_task
);
2581 return KERN_NO_ACCESS
;
2586 port
->ip_receiver_name
= name
;
2587 port
->ip_receiver
= space
;
2589 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
2591 if (bits
& MACH_PORT_TYPE_SEND
) {
2592 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2593 assert(IE_BITS_UREFS(bits
) > 0);
2594 assert(port
->ip_srights
> 0);
2599 /* entry is locked holding ref, so can use port */
2601 ipc_hash_delete(space
, (ipc_object_t
) port
,
2604 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2605 assert(IE_BITS_UREFS(bits
) == 0);
2607 /* transfer ref to entry */
2610 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2611 ipc_entry_modified(space
, name
, entry
);
2613 if (dest
!= IP_NULL
) {
2614 #if IMPORTANCE_INHERITANCE
2616 * Deduct the assertion counts we contributed to
2617 * the old destination port. They've already
2618 * been reflected into the task as a result of
2622 assert(dest
->ip_impcount
>= assertcnt
);
2623 dest
->ip_impcount
-= assertcnt
;
2625 #endif /* IMPORTANCE_INHERITANCE */
2632 panic("ipc_right_copyout: strange rights");
2634 return KERN_SUCCESS
;
2638 * Routine: ipc_right_rename
2640 * Transfer an entry from one name to another.
2641 * The old entry is deallocated.
2643 * The space is write-locked and active.
2644 * The new entry is unused. Upon return,
2645 * the space is unlocked.
2647 * KERN_SUCCESS Moved entry to new name.
2653 mach_port_name_t oname
,
2655 mach_port_name_t nname
,
2658 ipc_port_request_index_t request
= oentry
->ie_request
;
2659 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2660 ipc_object_t object
= oentry
->ie_object
;
2661 ipc_port_t release_port
= IP_NULL
;
2663 assert(is_active(space
));
2664 assert(oname
!= nname
);
2667 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2668 * if the port is dead. (This would foil ipc_port_destroy.)
2669 * Instead we should fail because oentry shouldn't exist.
2670 * Note IE_BITS_COMPAT implies ie_request != 0.
2673 if (request
!= IE_REQ_NONE
) {
2676 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2677 port
= (ipc_port_t
) object
;
2678 assert(port
!= IP_NULL
);
2680 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2681 request
= IE_REQ_NONE
;
2683 bits
= oentry
->ie_bits
;
2684 release_port
= port
;
2685 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2686 assert(oentry
->ie_request
== IE_REQ_NONE
);
2688 /* port is locked and active */
2690 ipc_port_request_rename(port
, request
, oname
, nname
);
2692 oentry
->ie_request
= IE_REQ_NONE
;
2696 /* initialize nentry before letting ipc_hash_insert see it */
2698 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2699 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2700 nentry
->ie_request
= request
;
2701 nentry
->ie_object
= object
;
2703 switch (IE_BITS_TYPE(bits
)) {
2704 case MACH_PORT_TYPE_SEND
: {
2707 port
= (ipc_port_t
) object
;
2708 assert(port
!= IP_NULL
);
2710 /* remember, there are no other share entries possible */
2711 /* or we can't do the rename. Therefore we do not need */
2712 /* to check the other subspaces */
2713 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2714 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2718 case MACH_PORT_TYPE_RECEIVE
:
2719 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2722 port
= (ipc_port_t
) object
;
2723 assert(port
!= IP_NULL
);
2726 assert(ip_active(port
));
2727 assert(port
->ip_receiver_name
== oname
);
2728 assert(port
->ip_receiver
== space
);
2730 port
->ip_receiver_name
= nname
;
2735 case MACH_PORT_TYPE_PORT_SET
: {
2738 pset
= (ipc_pset_t
) object
;
2739 assert(pset
!= IPS_NULL
);
2742 assert(ips_active(pset
));
2743 assert(pset
->ips_local_name
== oname
);
2745 pset
->ips_local_name
= nname
;
2750 case MACH_PORT_TYPE_SEND_ONCE
:
2751 case MACH_PORT_TYPE_DEAD_NAME
:
2755 panic("ipc_right_rename: strange rights");
2758 assert(oentry
->ie_request
== IE_REQ_NONE
);
2759 oentry
->ie_object
= IO_NULL
;
2760 ipc_entry_dealloc(space
, oname
, oentry
);
2761 ipc_entry_modified(space
, nname
, nentry
);
2762 is_write_unlock(space
);
2764 if (release_port
!= IP_NULL
)
2765 ip_release(release_port
);
2767 return KERN_SUCCESS
;