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>
92 * Routine: ipc_right_lookup_write
94 * Finds an entry in a space, given the name.
96 * Nothing locked. If successful, the space is write-locked.
98 * KERN_SUCCESS Found an entry.
99 * KERN_INVALID_TASK The space is dead.
100 * KERN_INVALID_NAME Name doesn't exist in space.
104 ipc_right_lookup_write(
106 mach_port_name_t name
,
111 assert(space
!= IS_NULL
);
113 is_write_lock(space
);
115 if (!space
->is_active
) {
116 is_write_unlock(space
);
117 return KERN_INVALID_TASK
;
120 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
121 is_write_unlock(space
);
122 return KERN_INVALID_NAME
;
130 * Routine: ipc_right_lookup_two_write
132 * Like ipc_right_lookup except that it returns two
133 * entries for two different names that were looked
134 * up under the same space lock.
136 * Nothing locked. If successful, the space is write-locked.
138 * KERN_INVALID_TASK The space is dead.
139 * KERN_INVALID_NAME Name doesn't exist in space.
143 ipc_right_lookup_two_write(
145 mach_port_name_t name1
,
146 ipc_entry_t
*entryp1
,
147 mach_port_name_t name2
,
148 ipc_entry_t
*entryp2
)
153 assert(space
!= IS_NULL
);
155 is_write_lock(space
);
157 if (!space
->is_active
) {
158 is_write_unlock(space
);
159 return KERN_INVALID_TASK
;
162 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
163 is_write_unlock(space
);
164 return KERN_INVALID_NAME
;
166 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
167 is_write_unlock(space
);
168 return KERN_INVALID_NAME
;
176 * Routine: ipc_right_reverse
178 * Translate (space, object) -> (name, entry).
179 * Only finds send/receive rights.
180 * Returns TRUE if an entry is found; if so,
181 * the object is locked and active.
183 * The space must be locked (read or write) and active.
184 * Nothing else locked.
191 mach_port_name_t
*namep
,
195 mach_port_name_t name
;
198 /* would switch on io_otype to handle multiple types of object */
200 assert(space
->is_active
);
201 assert(io_otype(object
) == IOT_PORT
);
203 port
= (ipc_port_t
) object
;
206 if (!ip_active(port
)) {
212 if (port
->ip_receiver
== space
) {
213 name
= port
->ip_receiver_name
;
214 assert(name
!= MACH_PORT_NULL
);
216 entry
= ipc_entry_lookup(space
, name
);
218 assert(entry
!= IE_NULL
);
219 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
220 assert(port
== (ipc_port_t
) entry
->ie_object
);
227 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
228 assert((entry
= *entryp
) != IE_NULL
);
229 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
230 assert(port
== (ipc_port_t
) entry
->ie_object
);
240 * Routine: ipc_right_dnrequest
242 * Make a dead-name request, returning the previously
243 * registered send-once right. If notify is IP_NULL,
244 * just cancels the previously registered request.
247 * Nothing locked. May allocate memory.
248 * Only consumes/returns refs if successful.
250 * KERN_SUCCESS Made/canceled dead-name request.
251 * KERN_INVALID_TASK The space is dead.
252 * KERN_INVALID_NAME Name doesn't exist in space.
253 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
254 * KERN_INVALID_ARGUMENT Name denotes dead name, but
255 * immediate is FALSE or notify is IP_NULL.
256 * KERN_UREFS_OVERFLOW Name denotes dead name, but
257 * generating immediate notif. would overflow urefs.
258 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
262 ipc_right_request_alloc(
264 mach_port_name_t name
,
266 boolean_t send_possible
,
268 ipc_port_t
*previousp
)
270 ipc_port_request_index_t prev_request
;
271 ipc_port_t previous
= IP_NULL
;
276 kr
= ipc_right_lookup_write(space
, name
, &entry
);
277 if (kr
!= KERN_SUCCESS
)
280 /* space is write-locked and active */
282 prev_request
= entry
->ie_request
;
284 /* if nothing to do or undo, we're done */
285 if (notify
== IP_NULL
&& prev_request
== IE_REQ_NONE
) {
286 is_write_unlock(space
);
287 *previousp
= IP_NULL
;
291 /* see if the entry is of proper type for requests */
292 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
293 ipc_port_request_index_t new_request
;
296 port
= (ipc_port_t
) entry
->ie_object
;
297 assert(port
!= IP_NULL
);
299 if (!ipc_right_check(space
, port
, name
, entry
)) {
300 /* port is locked and active */
302 /* if no new request, just cancel previous */
303 if (notify
== IP_NULL
) {
304 if (prev_request
!= IE_REQ_NONE
)
305 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
307 entry
->ie_request
= IE_REQ_NONE
;
308 is_write_unlock(space
);
313 * send-once rights, kernel objects, and non-full other queues
314 * fire immediately (if immediate specified).
316 if (send_possible
&& immediate
&&
317 ((entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
) ||
318 port
->ip_receiver
== ipc_space_kernel
|| !ip_full(port
))) {
319 if (prev_request
!= IE_REQ_NONE
)
320 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
322 entry
->ie_request
= IE_REQ_NONE
;
323 is_write_unlock(space
);
325 ipc_notify_send_possible(notify
, name
);
330 * If there is a previous request, free it. Any subsequent
331 * allocation cannot fail, thus assuring an atomic swap.
333 if (prev_request
!= IE_REQ_NONE
)
334 previous
= ipc_port_request_cancel(port
, name
, prev_request
);
336 kr
= ipc_port_request_alloc(port
, name
, notify
,
337 send_possible
, immediate
,
339 if (kr
!= KERN_SUCCESS
) {
340 assert(previous
== IP_NULL
);
341 is_write_unlock(space
);
343 kr
= ipc_port_request_grow(port
, ITS_SIZE_NONE
);
344 /* port is unlocked */
346 if (kr
!= KERN_SUCCESS
)
352 assert(new_request
!= IE_REQ_NONE
);
354 entry
->ie_request
= new_request
;
355 is_write_unlock(space
);
358 /* entry may have changed to dead-name by ipc_right_check() */
362 /* treat send_possible requests as immediate w.r.t. dead-name */
363 if ((send_possible
|| immediate
) && notify
!= IP_NULL
&&
364 (entry
->ie_bits
& MACH_PORT_TYPE_DEAD_NAME
)) {
365 mach_port_urefs_t urefs
= IE_BITS_UREFS(entry
->ie_bits
);
369 if (MACH_PORT_UREFS_OVERFLOW(urefs
, 1)) {
370 is_write_unlock(space
);
371 return KERN_UREFS_OVERFLOW
;
374 (entry
->ie_bits
)++; /* increment urefs */
375 is_write_unlock(space
);
377 ipc_notify_dead_name(notify
, name
);
382 is_write_unlock(space
);
383 if (entry
->ie_bits
& MACH_PORT_TYPE_PORT_OR_DEAD
)
384 return KERN_INVALID_ARGUMENT
;
386 return KERN_INVALID_RIGHT
;
389 *previousp
= previous
;
394 * Routine: ipc_right_request_cancel
396 * Cancel a notification request and return the send-once right.
397 * Afterwards, entry->ie_request == 0.
399 * The space must be write-locked; the port must be locked.
400 * The port must be active; the space doesn't have to be.
404 ipc_right_request_cancel(
405 __unused ipc_space_t space
,
407 mach_port_name_t name
,
412 assert(ip_active(port
));
413 assert(port
== (ipc_port_t
) entry
->ie_object
);
415 if (entry
->ie_request
== IE_REQ_NONE
)
418 previous
= ipc_port_request_cancel(port
, name
, entry
->ie_request
);
419 entry
->ie_request
= IE_REQ_NONE
;
424 * Routine: ipc_right_inuse
426 * Check if an entry is being used.
427 * Returns TRUE if it is.
429 * The space is write-locked and active.
430 * It is unlocked if the entry is inuse.
436 __unused mach_port_name_t name
,
439 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
440 is_write_unlock(space
);
447 * Routine: ipc_right_check
449 * Check if the port has died. If it has,
450 * clean up the entry and return TRUE.
452 * The space is write-locked; the port is not locked.
453 * If returns FALSE, the port is also locked and active.
454 * Otherwise, entry is converted to a dead name, freeing
455 * a reference to port.
462 mach_port_name_t name
,
465 ipc_entry_bits_t bits
;
467 assert(space
->is_active
);
468 assert(port
== (ipc_port_t
) entry
->ie_object
);
475 /* this was either a pure send right or a send-once right */
477 bits
= entry
->ie_bits
;
478 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
479 assert(IE_BITS_UREFS(bits
) > 0);
481 if (bits
& MACH_PORT_TYPE_SEND
) {
482 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
484 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
485 assert(IE_BITS_UREFS(bits
) == 1);
489 /* convert entry to dead name */
491 if ((bits
& MACH_PORT_TYPE_SEND
) && !(bits
& MACH_PORT_TYPE_RECEIVE
))
492 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
494 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
497 * If there was a notification request outstanding on this
498 * name, and the port went dead, that notification
499 * must already be on its way up from the port layer.
501 * Add the reference that the notification carries. It
502 * is done here, and not in the notification delivery,
503 * because the latter doesn't have a space reference and
504 * trying to actually move a send-right reference would
505 * get short-circuited into a MACH_PORT_DEAD by IPC. Since
506 * all calls that deal with the right eventually come
507 * through here, it has the same result.
509 * Once done, clear the request index so we only account
512 if (entry
->ie_request
!= IE_REQ_NONE
) {
513 if (ipc_port_request_type(port
, name
, entry
->ie_request
) != 0) {
514 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
517 entry
->ie_request
= IE_REQ_NONE
;
519 entry
->ie_bits
= bits
;
520 entry
->ie_object
= IO_NULL
;
522 ipc_port_release(port
);
528 * Routine: ipc_right_clean
530 * Cleans up an entry in a dead space.
531 * The entry isn't deallocated or removed
532 * from reverse hash tables.
534 * The space is dead and unlocked.
540 mach_port_name_t name
,
543 ipc_entry_bits_t bits
;
544 mach_port_type_t type
;
546 bits
= entry
->ie_bits
;
547 type
= IE_BITS_TYPE(bits
);
549 assert(!space
->is_active
);
552 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
553 * problem, because we check that the port is active. If
554 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
555 * would still work, but dead space refs would accumulate
556 * in ip_dnrequests. They would use up slots in
557 * ip_dnrequests and keep the spaces from being freed.
561 case MACH_PORT_TYPE_DEAD_NAME
:
562 assert(entry
->ie_request
== IE_REQ_NONE
);
563 assert(entry
->ie_object
== IO_NULL
);
566 case MACH_PORT_TYPE_PORT_SET
: {
567 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
569 assert(entry
->ie_request
== IE_REQ_NONE
);
570 assert(pset
!= IPS_NULL
);
573 assert(ips_active(pset
));
575 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
579 case MACH_PORT_TYPE_SEND
:
580 case MACH_PORT_TYPE_RECEIVE
:
581 case MACH_PORT_TYPE_SEND_RECEIVE
:
582 case MACH_PORT_TYPE_SEND_ONCE
: {
583 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
585 ipc_port_t nsrequest
= IP_NULL
;
586 mach_port_mscount_t mscount
= 0;
588 assert(port
!= IP_NULL
);
591 if (!ip_active(port
)) {
593 ip_check_unlock(port
);
597 request
= ipc_right_request_cancel_macro(space
, port
,
600 if (type
& MACH_PORT_TYPE_SEND
) {
601 assert(port
->ip_srights
> 0);
602 if (--port
->ip_srights
== 0
604 nsrequest
= port
->ip_nsrequest
;
605 if (nsrequest
!= IP_NULL
) {
606 port
->ip_nsrequest
= IP_NULL
;
607 mscount
= port
->ip_mscount
;
612 if (type
& MACH_PORT_TYPE_RECEIVE
) {
613 assert(port
->ip_receiver_name
== name
);
614 assert(port
->ip_receiver
== space
);
616 ipc_port_clear_receiver(port
);
617 ipc_port_destroy(port
); /* consumes our ref, unlocks */
618 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
619 assert(port
->ip_sorights
> 0);
622 ipc_notify_send_once(port
); /* consumes our ref */
624 assert(port
->ip_receiver
!= space
);
627 ip_unlock(port
); /* port is active */
630 if (nsrequest
!= IP_NULL
)
631 ipc_notify_no_senders(nsrequest
, mscount
);
633 if (request
!= IP_NULL
)
634 ipc_notify_port_deleted(request
, name
);
639 panic("ipc_right_clean: strange type - 0x%x", type
);
644 * Routine: ipc_right_destroy
646 * Destroys an entry in a space.
648 * The space is write-locked.
649 * The space must be active.
651 * KERN_SUCCESS The entry was destroyed.
657 mach_port_name_t name
,
660 ipc_entry_bits_t bits
;
661 mach_port_type_t type
;
663 bits
= entry
->ie_bits
;
664 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
665 type
= IE_BITS_TYPE(bits
);
667 assert(space
->is_active
);
670 case MACH_PORT_TYPE_DEAD_NAME
:
671 assert(entry
->ie_request
== IE_REQ_NONE
);
672 assert(entry
->ie_object
== IO_NULL
);
674 ipc_entry_dealloc(space
, name
, entry
);
677 case MACH_PORT_TYPE_PORT_SET
: {
678 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
680 assert(entry
->ie_request
== IE_REQ_NONE
);
681 assert(pset
!= IPS_NULL
);
683 entry
->ie_object
= IO_NULL
;
684 ipc_entry_dealloc(space
, name
, entry
);
687 assert(ips_active(pset
));
689 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
693 case MACH_PORT_TYPE_SEND
:
694 case MACH_PORT_TYPE_RECEIVE
:
695 case MACH_PORT_TYPE_SEND_RECEIVE
:
696 case MACH_PORT_TYPE_SEND_ONCE
: {
697 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
698 ipc_port_t nsrequest
= IP_NULL
;
699 mach_port_mscount_t mscount
= 0;
702 assert(port
!= IP_NULL
);
704 if (type
== MACH_PORT_TYPE_SEND
)
705 ipc_hash_delete(space
, (ipc_object_t
) port
,
710 if (!ip_active(port
)) {
711 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
713 ip_check_unlock(port
);
715 entry
->ie_request
= IE_REQ_NONE
;
716 entry
->ie_object
= IO_NULL
;
717 ipc_entry_dealloc(space
, name
, entry
);
722 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
724 entry
->ie_object
= IO_NULL
;
725 ipc_entry_dealloc(space
, name
, entry
);
727 if (type
& MACH_PORT_TYPE_SEND
) {
728 assert(port
->ip_srights
> 0);
729 if (--port
->ip_srights
== 0) {
730 nsrequest
= port
->ip_nsrequest
;
731 if (nsrequest
!= IP_NULL
) {
732 port
->ip_nsrequest
= IP_NULL
;
733 mscount
= port
->ip_mscount
;
738 if (type
& MACH_PORT_TYPE_RECEIVE
) {
739 assert(ip_active(port
));
740 assert(port
->ip_receiver
== space
);
742 ipc_port_clear_receiver(port
);
743 ipc_port_destroy(port
); /* consumes our ref, unlocks */
744 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
745 assert(port
->ip_sorights
> 0);
748 ipc_notify_send_once(port
); /* consumes our ref */
750 assert(port
->ip_receiver
!= space
);
756 if (nsrequest
!= IP_NULL
)
757 ipc_notify_no_senders(nsrequest
, mscount
);
759 if (request
!= IP_NULL
)
760 ipc_notify_port_deleted(request
, name
);
765 panic("ipc_right_destroy: strange type");
772 * Routine: ipc_right_dealloc
774 * Releases a send/send-once/dead-name user ref.
775 * Like ipc_right_delta with a delta of -1,
776 * but looks at the entry to determine the right.
778 * The space is write-locked, and is unlocked upon return.
779 * The space must be active.
781 * KERN_SUCCESS A user ref was released.
782 * KERN_INVALID_RIGHT Entry has wrong type.
788 mach_port_name_t name
,
792 ipc_entry_bits_t bits
;
793 mach_port_type_t type
;
795 bits
= entry
->ie_bits
;
796 type
= IE_BITS_TYPE(bits
);
799 assert(space
->is_active
);
802 case MACH_PORT_TYPE_DEAD_NAME
: {
805 assert(IE_BITS_UREFS(bits
) > 0);
806 assert(entry
->ie_request
== IE_REQ_NONE
);
807 assert(entry
->ie_object
== IO_NULL
);
809 if (IE_BITS_UREFS(bits
) == 1) {
810 ipc_entry_dealloc(space
, name
, entry
);
813 entry
->ie_bits
= bits
-1; /* decrement urefs */
815 is_write_unlock(space
);
819 case MACH_PORT_TYPE_SEND_ONCE
: {
820 ipc_port_t port
, request
;
822 assert(IE_BITS_UREFS(bits
) == 1);
824 port
= (ipc_port_t
) entry
->ie_object
;
825 assert(port
!= IP_NULL
);
827 if (ipc_right_check(space
, port
, name
, entry
)) {
829 bits
= entry
->ie_bits
;
830 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
833 /* port is locked and active */
835 assert(port
->ip_sorights
> 0);
837 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
840 entry
->ie_object
= IO_NULL
;
841 ipc_entry_dealloc(space
, name
, entry
);
843 is_write_unlock(space
);
845 ipc_notify_send_once(port
);
847 if (request
!= IP_NULL
)
848 ipc_notify_port_deleted(request
, name
);
852 case MACH_PORT_TYPE_SEND
: {
854 ipc_port_t request
= IP_NULL
;
855 ipc_port_t nsrequest
= IP_NULL
;
856 mach_port_mscount_t mscount
= 0;
859 assert(IE_BITS_UREFS(bits
) > 0);
861 port
= (ipc_port_t
) entry
->ie_object
;
862 assert(port
!= IP_NULL
);
864 if (ipc_right_check(space
, port
, name
, entry
)) {
865 bits
= entry
->ie_bits
;
866 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
869 /* port is locked and active */
871 assert(port
->ip_srights
> 0);
873 if (IE_BITS_UREFS(bits
) == 1) {
874 if (--port
->ip_srights
== 0) {
875 nsrequest
= port
->ip_nsrequest
;
876 if (nsrequest
!= IP_NULL
) {
877 port
->ip_nsrequest
= IP_NULL
;
878 mscount
= port
->ip_mscount
;
882 request
= ipc_right_request_cancel_macro(space
, port
,
884 ipc_hash_delete(space
, (ipc_object_t
) port
,
888 entry
->ie_object
= IO_NULL
;
889 ipc_entry_dealloc(space
, name
, entry
);
892 entry
->ie_bits
= bits
-1; /* decrement urefs */
894 /* even if dropped a ref, port is active */
896 is_write_unlock(space
);
898 if (nsrequest
!= IP_NULL
)
899 ipc_notify_no_senders(nsrequest
, mscount
);
901 if (request
!= IP_NULL
)
902 ipc_notify_port_deleted(request
, name
);
906 case MACH_PORT_TYPE_SEND_RECEIVE
: {
908 ipc_port_t nsrequest
= IP_NULL
;
909 mach_port_mscount_t mscount
= 0;
911 assert(IE_BITS_UREFS(bits
) > 0);
913 port
= (ipc_port_t
) entry
->ie_object
;
914 assert(port
!= IP_NULL
);
917 assert(ip_active(port
));
918 assert(port
->ip_receiver_name
== name
);
919 assert(port
->ip_receiver
== space
);
920 assert(port
->ip_srights
> 0);
922 if (IE_BITS_UREFS(bits
) == 1) {
923 if (--port
->ip_srights
== 0) {
924 nsrequest
= port
->ip_nsrequest
;
925 if (nsrequest
!= IP_NULL
) {
926 port
->ip_nsrequest
= IP_NULL
;
927 mscount
= port
->ip_mscount
;
931 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
932 MACH_PORT_TYPE_SEND
);
934 entry
->ie_bits
= bits
-1; /* decrement urefs */
937 is_write_unlock(space
);
939 if (nsrequest
!= IP_NULL
)
940 ipc_notify_no_senders(nsrequest
, mscount
);
945 is_write_unlock(space
);
946 return KERN_INVALID_RIGHT
;
953 * Routine: ipc_right_delta
955 * Modifies the user-reference count for a right.
956 * May deallocate the right, if the count goes to zero.
958 * The space is write-locked, and is unlocked upon return.
959 * The space must be active.
961 * KERN_SUCCESS Count was modified.
962 * KERN_INVALID_RIGHT Entry has wrong type.
963 * KERN_INVALID_VALUE Bad delta for the right.
964 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
970 mach_port_name_t name
,
972 mach_port_right_t right
,
973 mach_port_delta_t delta
)
975 ipc_entry_bits_t bits
;
977 bits
= entry
->ie_bits
;
981 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
982 * switch below. It is used to keep track of those cases (in DIPC)
983 * where we have postponed the dropping of a port reference. Since
984 * the dropping of the reference could cause the port to disappear
985 * we postpone doing so when we are holding the space lock.
988 assert(space
->is_active
);
989 assert(right
< MACH_PORT_RIGHT_NUMBER
);
991 /* Rights-specific restrictions and operations. */
994 case MACH_PORT_RIGHT_PORT_SET
: {
997 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0)
1000 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
1001 assert(IE_BITS_UREFS(bits
) == 0);
1002 assert(entry
->ie_request
== IE_REQ_NONE
);
1010 pset
= (ipc_pset_t
) entry
->ie_object
;
1011 assert(pset
!= IPS_NULL
);
1015 entry
->ie_object
= IO_NULL
;
1016 ipc_entry_dealloc(space
, name
, entry
);
1020 assert(ips_active(pset
));
1021 is_write_unlock(space
);
1023 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
1027 case MACH_PORT_RIGHT_RECEIVE
: {
1029 ipc_port_t request
= IP_NULL
;
1031 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1040 port
= (ipc_port_t
) entry
->ie_object
;
1041 assert(port
!= IP_NULL
);
1044 * The port lock is needed for ipc_right_dncancel;
1045 * otherwise, we wouldn't have to take the lock
1046 * until just before dropping the space lock.
1050 assert(ip_active(port
));
1051 assert(port
->ip_receiver_name
== name
);
1052 assert(port
->ip_receiver
== space
);
1054 if (bits
& MACH_PORT_TYPE_SEND
) {
1055 assert(IE_BITS_TYPE(bits
) ==
1056 MACH_PORT_TYPE_SEND_RECEIVE
);
1057 assert(IE_BITS_UREFS(bits
) > 0);
1058 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1059 assert(port
->ip_srights
> 0);
1061 if (port
->ip_pdrequest
!= NULL
) {
1063 * Since another task has requested a
1064 * destroy notification for this port, it
1065 * isn't actually being destroyed - the receive
1066 * right is just being moved to another task.
1067 * Since we still have one or more send rights,
1068 * we need to record the loss of the receive
1069 * right and enter the remaining send right
1070 * into the hash table.
1072 entry
->ie_bits
&= ~MACH_PORT_TYPE_RECEIVE
;
1073 ipc_hash_insert(space
, (ipc_object_t
) port
,
1078 * The remaining send right turns into a
1079 * dead name. Notice we don't decrement
1080 * ip_srights, generate a no-senders notif,
1081 * or use ipc_right_dncancel, because the
1082 * port is destroyed "first".
1084 bits
&= ~IE_BITS_TYPE_MASK
;
1085 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1086 if (entry
->ie_request
) {
1087 entry
->ie_request
= IE_REQ_NONE
;
1090 entry
->ie_bits
= bits
;
1091 entry
->ie_object
= IO_NULL
;
1094 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1095 assert(IE_BITS_UREFS(bits
) == 0);
1097 request
= ipc_right_request_cancel_macro(space
, port
,
1099 entry
->ie_object
= IO_NULL
;
1100 ipc_entry_dealloc(space
, name
, entry
);
1102 is_write_unlock(space
);
1104 ipc_port_clear_receiver(port
);
1105 ipc_port_destroy(port
); /* consumes ref, unlocks */
1107 if (request
!= IP_NULL
)
1108 ipc_notify_port_deleted(request
, name
);
1112 case MACH_PORT_RIGHT_SEND_ONCE
: {
1113 ipc_port_t port
, request
;
1115 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1118 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1119 assert(IE_BITS_UREFS(bits
) == 1);
1121 port
= (ipc_port_t
) entry
->ie_object
;
1122 assert(port
!= IP_NULL
);
1124 if (ipc_right_check(space
, port
, name
, entry
)) {
1125 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1128 /* port is locked and active */
1130 assert(port
->ip_sorights
> 0);
1132 if ((delta
> 0) || (delta
< -1)) {
1142 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1145 entry
->ie_object
= IO_NULL
;
1146 ipc_entry_dealloc(space
, name
, entry
);
1148 is_write_unlock(space
);
1150 ipc_notify_send_once(port
);
1152 if (request
!= IP_NULL
)
1153 ipc_notify_port_deleted(request
, name
);
1157 case MACH_PORT_RIGHT_DEAD_NAME
: {
1158 mach_port_urefs_t urefs
;
1160 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1163 port
= (ipc_port_t
) entry
->ie_object
;
1164 assert(port
!= IP_NULL
);
1166 if (!ipc_right_check(space
, port
, name
, entry
)) {
1167 /* port is locked and active */
1171 bits
= entry
->ie_bits
;
1172 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0)
1175 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1176 assert(IE_BITS_UREFS(bits
) > 0);
1177 assert(entry
->ie_object
== IO_NULL
);
1178 assert(entry
->ie_request
== IE_REQ_NONE
);
1180 urefs
= IE_BITS_UREFS(bits
);
1181 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1183 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
))
1184 goto urefs_overflow
;
1186 if ((urefs
+ delta
) == 0) {
1187 ipc_entry_dealloc(space
, name
, entry
);
1190 entry
->ie_bits
= bits
+ delta
;
1192 is_write_unlock(space
);
1197 case MACH_PORT_RIGHT_SEND
: {
1198 mach_port_urefs_t urefs
;
1200 ipc_port_t request
= IP_NULL
;
1201 ipc_port_t nsrequest
= IP_NULL
;
1202 mach_port_mscount_t mscount
= 0;
1204 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1207 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1209 port
= (ipc_port_t
) entry
->ie_object
;
1210 assert(port
!= IP_NULL
);
1212 if (ipc_right_check(space
, port
, name
, entry
)) {
1213 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1216 /* port is locked and active */
1218 assert(port
->ip_srights
> 0);
1220 urefs
= IE_BITS_UREFS(bits
);
1221 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1225 if (MACH_PORT_UREFS_OVERFLOW(urefs
+1, delta
)) {
1227 goto urefs_overflow
;
1230 if ((urefs
+ delta
) == 0) {
1231 if (--port
->ip_srights
== 0) {
1232 nsrequest
= port
->ip_nsrequest
;
1233 if (nsrequest
!= IP_NULL
) {
1234 port
->ip_nsrequest
= IP_NULL
;
1235 mscount
= port
->ip_mscount
;
1239 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1240 assert(port
->ip_receiver_name
== name
);
1241 assert(port
->ip_receiver
== space
);
1242 assert(IE_BITS_TYPE(bits
) ==
1243 MACH_PORT_TYPE_SEND_RECEIVE
);
1245 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1246 MACH_PORT_TYPE_SEND
);
1248 assert(IE_BITS_TYPE(bits
) ==
1249 MACH_PORT_TYPE_SEND
);
1251 request
= ipc_right_request_cancel_macro(space
, port
,
1253 ipc_hash_delete(space
, (ipc_object_t
) port
,
1258 entry
->ie_object
= IO_NULL
;
1259 ipc_entry_dealloc(space
, name
, entry
);
1262 entry
->ie_bits
= bits
+ delta
;
1264 /* even if dropped a ref, port is active */
1266 is_write_unlock(space
);
1268 if (nsrequest
!= IP_NULL
)
1269 ipc_notify_no_senders(nsrequest
, mscount
);
1271 if (request
!= IP_NULL
)
1272 ipc_notify_port_deleted(request
, name
);
1277 panic("ipc_right_delta: strange right");
1280 return KERN_SUCCESS
;
1283 is_write_unlock(space
);
1284 return KERN_SUCCESS
;
1287 is_write_unlock(space
);
1288 return KERN_INVALID_RIGHT
;
1291 is_write_unlock(space
);
1292 return KERN_INVALID_VALUE
;
1295 is_write_unlock(space
);
1296 return KERN_UREFS_OVERFLOW
;
1300 * Routine: ipc_right_info
1302 * Retrieves information about the right.
1304 * The space is write-locked, and is unlocked upon return
1305 * if the call is unsuccessful. The space must be active.
1307 * KERN_SUCCESS Retrieved info; space still locked.
1313 mach_port_name_t name
,
1315 mach_port_type_t
*typep
,
1316 mach_port_urefs_t
*urefsp
)
1319 ipc_entry_bits_t bits
;
1320 mach_port_type_t type
= 0;
1321 ipc_port_request_index_t request
;
1323 bits
= entry
->ie_bits
;
1324 request
= entry
->ie_request
;
1325 port
= (ipc_port_t
) entry
->ie_object
;
1327 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1328 assert(IP_VALID(port
));
1330 if (request
!= IE_REQ_NONE
) {
1332 assert(ip_active(port
));
1333 type
|= ipc_port_request_type(port
, name
, request
);
1337 } else if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1339 * validate port is still alive - if so, get request
1340 * types while we still have it locked. Otherwise,
1341 * recapture the (now dead) bits.
1343 if (!ipc_right_check(space
, port
, name
, entry
)) {
1344 if (request
!= IE_REQ_NONE
)
1345 type
|= ipc_port_request_type(port
, name
, request
);
1348 bits
= entry
->ie_bits
;
1349 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1353 type
|= IE_BITS_TYPE(bits
);
1356 *urefsp
= IE_BITS_UREFS(bits
);
1357 return KERN_SUCCESS
;
1361 * Routine: ipc_right_copyin_check
1363 * Check if a subsequent ipc_right_copyin would succeed.
1365 * The space is locked (read or write) and active.
1369 ipc_right_copyin_check(
1370 __assert_only ipc_space_t space
,
1371 __unused mach_port_name_t name
,
1373 mach_msg_type_name_t msgt_name
)
1375 ipc_entry_bits_t bits
;
1377 #if CONFIG_MACF_MACH
1378 task_t self
= current_task();
1382 bits
= entry
->ie_bits
;
1383 assert(space
->is_active
);
1385 switch (msgt_name
) {
1386 case MACH_MSG_TYPE_MAKE_SEND
:
1387 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1390 #if CONFIG_MACF_MACH
1391 port
= (ipc_port_t
) entry
->ie_object
;
1393 tasklabel_lock(self
);
1394 rc
= mac_port_check_make_send(&self
->maclabel
, &port
->ip_label
); tasklabel_unlock(self
);
1401 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1402 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1405 #if CONFIG_MACF_MACH
1406 port
= (ipc_port_t
) entry
->ie_object
;
1408 tasklabel_lock(self
);
1409 rc
= mac_port_check_make_send_once(&self
->maclabel
, &port
->ip_label
);
1410 tasklabel_unlock(self
);
1417 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1418 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1421 #if CONFIG_MACF_MACH
1422 port
= (ipc_port_t
) entry
->ie_object
;
1424 tasklabel_lock(self
);
1425 rc
= mac_port_check_move_receive(&self
->maclabel
, &port
->ip_label
);
1426 tasklabel_unlock(self
);
1433 case MACH_MSG_TYPE_COPY_SEND
:
1434 case MACH_MSG_TYPE_MOVE_SEND
:
1435 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1438 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1441 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1444 port
= (ipc_port_t
) entry
->ie_object
;
1445 assert(port
!= IP_NULL
);
1448 active
= ip_active(port
);
1449 #if CONFIG_MACF_MACH
1450 tasklabel_lock(self
);
1451 switch (msgt_name
) {
1452 case MACH_MSG_TYPE_COPY_SEND
:
1453 rc
= mac_port_check_copy_send(&self
->maclabel
,
1456 case MACH_MSG_TYPE_MOVE_SEND
:
1457 rc
= mac_port_check_move_send(&self
->maclabel
,
1460 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
1461 rc
= mac_port_check_move_send_once(&self
->maclabel
,
1465 panic("ipc_right_copyin_check: strange rights");
1467 tasklabel_unlock(self
);
1479 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1480 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1483 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1491 panic("ipc_right_copyin_check: strange rights");
1498 * Routine: ipc_right_copyin
1500 * Copyin a capability from a space.
1501 * If successful, the caller gets a ref
1502 * for the resulting object, unless it is IO_DEAD,
1503 * and possibly a send-once right which should
1504 * be used in a port-deleted notification.
1506 * If deadok is not TRUE, the copyin operation
1507 * will fail instead of producing IO_DEAD.
1509 * The entry is never deallocated (except
1510 * when KERN_INVALID_NAME), so the caller
1511 * should deallocate the entry if its type
1512 * is MACH_PORT_TYPE_NONE.
1514 * The space is write-locked and active.
1516 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1517 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1523 mach_port_name_t name
,
1525 mach_msg_type_name_t msgt_name
,
1527 ipc_object_t
*objectp
,
1528 ipc_port_t
*sorightp
)
1530 ipc_entry_bits_t bits
;
1531 #if CONFIG_MACF_MACH
1532 task_t self
= current_task();
1536 bits
= entry
->ie_bits
;
1538 assert(space
->is_active
);
1540 switch (msgt_name
) {
1541 case MACH_MSG_TYPE_MAKE_SEND
: {
1544 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1547 port
= (ipc_port_t
) entry
->ie_object
;
1548 assert(port
!= IP_NULL
);
1551 assert(ip_active(port
));
1552 assert(port
->ip_receiver_name
== name
);
1553 assert(port
->ip_receiver
== space
);
1555 #if CONFIG_MACF_MACH
1556 tasklabel_lock(self
);
1557 rc
= mac_port_check_make_send(&self
->maclabel
, &port
->ip_label
);
1558 tasklabel_unlock(self
);
1561 return KERN_NO_ACCESS
;
1570 *objectp
= (ipc_object_t
) port
;
1571 *sorightp
= IP_NULL
;
1575 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1578 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1581 port
= (ipc_port_t
) entry
->ie_object
;
1582 assert(port
!= IP_NULL
);
1585 assert(ip_active(port
));
1586 assert(port
->ip_receiver_name
== name
);
1587 assert(port
->ip_receiver
== space
);
1589 #if CONFIG_MACF_MACH
1590 tasklabel_lock(self
);
1591 rc
= mac_port_check_make_send_once(&self
->maclabel
, &port
->ip_label
);
1592 tasklabel_unlock(self
);
1595 return KERN_NO_ACCESS
;
1599 port
->ip_sorights
++;
1603 *objectp
= (ipc_object_t
) port
;
1604 *sorightp
= IP_NULL
;
1608 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1610 ipc_port_t request
= IP_NULL
;
1612 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1615 port
= (ipc_port_t
) entry
->ie_object
;
1616 assert(port
!= IP_NULL
);
1619 assert(ip_active(port
));
1620 assert(port
->ip_receiver_name
== name
);
1621 assert(port
->ip_receiver
== space
);
1623 #if CONFIG_MACF_MACH
1624 tasklabel_lock(self
);
1625 rc
= mac_port_check_move_receive(&self
->maclabel
,
1627 tasklabel_unlock(self
);
1630 return KERN_NO_ACCESS
;
1634 if (bits
& MACH_PORT_TYPE_SEND
) {
1635 assert(IE_BITS_TYPE(bits
) ==
1636 MACH_PORT_TYPE_SEND_RECEIVE
);
1637 assert(IE_BITS_UREFS(bits
) > 0);
1638 assert(port
->ip_srights
> 0);
1640 ipc_hash_insert(space
, (ipc_object_t
) port
,
1644 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1645 assert(IE_BITS_UREFS(bits
) == 0);
1647 request
= ipc_right_request_cancel_macro(space
, port
,
1649 entry
->ie_object
= IO_NULL
;
1651 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1653 ipc_port_clear_receiver(port
);
1655 port
->ip_receiver_name
= MACH_PORT_NULL
;
1656 port
->ip_destination
= IP_NULL
;
1659 *objectp
= (ipc_object_t
) port
;
1660 *sorightp
= request
;
1664 case MACH_MSG_TYPE_COPY_SEND
: {
1667 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1670 /* allow for dead send-once rights */
1672 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1675 assert(IE_BITS_UREFS(bits
) > 0);
1677 port
= (ipc_port_t
) entry
->ie_object
;
1678 assert(port
!= IP_NULL
);
1680 if (ipc_right_check(space
, port
, name
, entry
)) {
1681 bits
= entry
->ie_bits
;
1684 /* port is locked and active */
1686 #if CONFIG_MACF_MACH
1687 tasklabel_lock(self
);
1688 rc
= mac_port_check_copy_send(&self
->maclabel
, &port
->ip_label
);
1689 tasklabel_unlock(self
);
1692 return KERN_NO_ACCESS
;
1696 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1697 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1698 assert(port
->ip_sorights
> 0);
1704 assert(port
->ip_srights
> 0);
1710 *objectp
= (ipc_object_t
) port
;
1711 *sorightp
= IP_NULL
;
1715 case MACH_MSG_TYPE_MOVE_SEND
: {
1717 ipc_port_t request
= IP_NULL
;
1719 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1722 /* allow for dead send-once rights */
1724 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1727 assert(IE_BITS_UREFS(bits
) > 0);
1729 port
= (ipc_port_t
) entry
->ie_object
;
1730 assert(port
!= IP_NULL
);
1732 if (ipc_right_check(space
, port
, name
, entry
)) {
1733 bits
= entry
->ie_bits
;
1736 /* port is locked and active */
1738 #if CONFIG_MACF_MACH
1739 tasklabel_lock (self
);
1740 rc
= mac_port_check_copy_send (&self
->maclabel
, &port
->ip_label
);
1741 tasklabel_unlock (self
);
1745 return KERN_NO_ACCESS
;
1749 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1750 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1751 assert(port
->ip_sorights
> 0);
1757 assert(port
->ip_srights
> 0);
1759 if (IE_BITS_UREFS(bits
) == 1) {
1760 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1761 assert(port
->ip_receiver_name
== name
);
1762 assert(port
->ip_receiver
== space
);
1763 assert(IE_BITS_TYPE(bits
) ==
1764 MACH_PORT_TYPE_SEND_RECEIVE
);
1768 assert(IE_BITS_TYPE(bits
) ==
1769 MACH_PORT_TYPE_SEND
);
1771 request
= ipc_right_request_cancel_macro(space
, port
,
1773 ipc_hash_delete(space
, (ipc_object_t
) port
,
1775 entry
->ie_object
= IO_NULL
;
1777 entry
->ie_bits
= bits
&~
1778 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1782 entry
->ie_bits
= bits
-1; /* decrement urefs */
1787 *objectp
= (ipc_object_t
) port
;
1788 *sorightp
= request
;
1792 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1796 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1799 /* allow for dead send rights */
1801 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1804 assert(IE_BITS_UREFS(bits
) > 0);
1806 port
= (ipc_port_t
) entry
->ie_object
;
1807 assert(port
!= IP_NULL
);
1809 if (ipc_right_check(space
, port
, name
, entry
)) {
1810 bits
= entry
->ie_bits
;
1813 /* port is locked and active */
1815 #if CONFIG_MACF_MACH
1816 tasklabel_lock (self
);
1817 rc
= mac_port_check_copy_send (&self
->maclabel
, &port
->ip_label
);
1818 tasklabel_unlock (self
);
1822 return KERN_NO_ACCESS
;
1826 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1827 assert(bits
& MACH_PORT_TYPE_SEND
);
1828 assert(port
->ip_srights
> 0);
1834 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1835 assert(IE_BITS_UREFS(bits
) == 1);
1836 assert(port
->ip_sorights
> 0);
1838 request
= ipc_right_request_cancel_macro(space
, port
, name
, entry
);
1841 entry
->ie_object
= IO_NULL
;
1842 entry
->ie_bits
= bits
&~
1843 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
1845 *objectp
= (ipc_object_t
) port
;
1846 *sorightp
= request
;
1852 return KERN_INVALID_RIGHT
;
1855 return KERN_SUCCESS
;
1858 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1859 assert(IE_BITS_UREFS(bits
) > 0);
1860 assert(entry
->ie_request
== IE_REQ_NONE
);
1861 assert(entry
->ie_object
== 0);
1867 *sorightp
= IP_NULL
;
1868 return KERN_SUCCESS
;
1871 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1872 assert(IE_BITS_UREFS(bits
) > 0);
1873 assert(entry
->ie_request
== IE_REQ_NONE
);
1874 assert(entry
->ie_object
== 0);
1879 if (IE_BITS_UREFS(bits
) == 1) {
1880 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
1882 entry
->ie_bits
= bits
-1; /* decrement urefs */
1885 *sorightp
= IP_NULL
;
1886 return KERN_SUCCESS
;
1891 * Routine: ipc_right_copyin_undo
1893 * Undoes the effects of an ipc_right_copyin
1894 * of a send/send-once right that is dead.
1895 * (Object is either IO_DEAD or a dead port.)
1897 * The space is write-locked and active.
1901 ipc_right_copyin_undo(
1903 mach_port_name_t name
,
1905 mach_msg_type_name_t msgt_name
,
1906 ipc_object_t object
,
1909 ipc_entry_bits_t bits
;
1911 bits
= entry
->ie_bits
;
1913 assert(space
->is_active
);
1915 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1916 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
1917 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1919 if (soright
!= IP_NULL
) {
1920 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1921 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1922 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1923 assert(object
!= IO_DEAD
);
1925 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1926 MACH_PORT_TYPE_DEAD_NAME
| 2);
1928 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
1929 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1930 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1932 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1933 MACH_PORT_TYPE_DEAD_NAME
| 1);
1934 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
1935 assert(object
== IO_DEAD
);
1936 assert(IE_BITS_UREFS(bits
) > 0);
1938 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1939 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1940 entry
->ie_bits
= bits
+1; /* increment urefs */
1943 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1944 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
1945 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1946 assert(object
!= IO_DEAD
);
1947 assert(entry
->ie_object
== object
);
1948 assert(IE_BITS_UREFS(bits
) > 0);
1950 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1951 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
-1);
1952 entry
->ie_bits
= bits
+1; /* increment urefs */
1956 * May as well convert the entry to a dead name.
1957 * (Or if it is a compat entry, destroy it.)
1960 (void) ipc_right_check(space
, (ipc_port_t
) object
,
1962 /* object is dead so it is not locked */
1965 /* release the reference acquired by copyin */
1967 if (object
!= IO_DEAD
)
1968 ipc_object_release(object
);
1972 * Routine: ipc_right_copyin_two
1974 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
1975 * and deadok == FALSE, except that this moves two
1976 * send rights at once.
1978 * The space is write-locked and active.
1979 * The object is returned with two refs/send rights.
1981 * KERN_SUCCESS Acquired an object.
1982 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1986 ipc_right_copyin_two(
1988 mach_port_name_t name
,
1990 ipc_object_t
*objectp
,
1991 ipc_port_t
*sorightp
)
1993 ipc_entry_bits_t bits
;
1994 mach_port_urefs_t urefs
;
1996 ipc_port_t request
= IP_NULL
;
1997 #if CONFIG_MACF_MACH
1998 task_t self
= current_task();
2002 assert(space
->is_active
);
2004 bits
= entry
->ie_bits
;
2006 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
2009 urefs
= IE_BITS_UREFS(bits
);
2013 port
= (ipc_port_t
) entry
->ie_object
;
2014 assert(port
!= IP_NULL
);
2016 if (ipc_right_check(space
, port
, name
, entry
)) {
2019 /* port is locked and active */
2021 #if CONFIG_MACF_MACH
2022 tasklabel_lock(self
);
2023 rc
= mac_port_check_copy_send(&self
->maclabel
, &port
->ip_label
);
2024 tasklabel_unlock(self
);
2027 return KERN_NO_ACCESS
;
2031 assert(port
->ip_srights
> 0);
2034 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2035 assert(port
->ip_receiver_name
== name
);
2036 assert(port
->ip_receiver
== space
);
2037 assert(IE_BITS_TYPE(bits
) ==
2038 MACH_PORT_TYPE_SEND_RECEIVE
);
2044 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2046 request
= ipc_right_request_cancel_macro(space
, port
,
2051 ipc_hash_delete(space
, (ipc_object_t
) port
,
2053 entry
->ie_object
= IO_NULL
;
2055 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
2057 port
->ip_srights
+= 2;
2060 entry
->ie_bits
= bits
-2; /* decrement urefs */
2064 *objectp
= (ipc_object_t
) port
;
2065 *sorightp
= request
;
2066 return KERN_SUCCESS
;
2069 return KERN_INVALID_RIGHT
;
2073 * Routine: ipc_right_copyout
2075 * Copyout a capability to a space.
2076 * If successful, consumes a ref for the object.
2078 * Always succeeds when given a newly-allocated entry,
2079 * because user-reference overflow isn't a possibility.
2081 * If copying out the object would cause the user-reference
2082 * count in the entry to overflow, and overflow is TRUE,
2083 * then instead the user-reference count is left pegged
2084 * to its maximum value and the copyout succeeds anyway.
2086 * The space is write-locked and active.
2087 * The object is locked and active.
2088 * The object is unlocked; the space isn't.
2090 * KERN_SUCCESS Copied out capability.
2091 * KERN_UREFS_OVERFLOW User-refs would overflow;
2092 * guaranteed not to happen with a fresh entry
2093 * or if overflow=TRUE was specified.
2099 mach_port_name_t name
,
2101 mach_msg_type_name_t msgt_name
,
2103 ipc_object_t object
)
2105 ipc_entry_bits_t bits
;
2107 #if CONFIG_MACF_MACH
2111 bits
= entry
->ie_bits
;
2113 assert(IO_VALID(object
));
2114 assert(io_otype(object
) == IOT_PORT
);
2115 assert(io_active(object
));
2116 assert(entry
->ie_object
== object
);
2118 port
= (ipc_port_t
) object
;
2120 switch (msgt_name
) {
2121 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
2123 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2124 assert(port
->ip_sorights
> 0);
2126 #if CONFIG_MACF_MACH
2127 if (space
->is_task
) {
2128 tasklabel_lock(space
->is_task
);
2129 rc
= mac_port_check_hold_send_once(&space
->is_task
->maclabel
,
2131 tasklabel_unlock(space
->is_task
);
2135 return KERN_NO_ACCESS
;
2139 /* transfer send-once right and ref to entry */
2142 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1);
2145 case MACH_MSG_TYPE_PORT_SEND
:
2146 assert(port
->ip_srights
> 0);
2148 #if CONFIG_MACF_MACH
2149 if (space
->is_task
) {
2150 tasklabel_lock(space
->is_task
);
2151 rc
= mac_port_check_hold_send(&space
->is_task
->maclabel
,
2153 tasklabel_unlock(space
->is_task
);
2157 return KERN_NO_ACCESS
;
2162 if (bits
& MACH_PORT_TYPE_SEND
) {
2163 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
2165 assert(port
->ip_srights
> 1);
2167 assert(urefs
< MACH_PORT_UREFS_MAX
);
2169 if (urefs
+1 == MACH_PORT_UREFS_MAX
) {
2171 /* leave urefs pegged to maximum */
2176 return KERN_SUCCESS
;
2180 return KERN_UREFS_OVERFLOW
;
2186 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
2187 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
2188 assert(IE_BITS_UREFS(bits
) == 0);
2190 /* transfer send right to entry */
2194 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2195 assert(IE_BITS_UREFS(bits
) == 0);
2197 /* transfer send right and ref to entry */
2200 /* entry is locked holding ref, so can use port */
2202 ipc_hash_insert(space
, (ipc_object_t
) port
,
2206 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1;
2209 case MACH_MSG_TYPE_PORT_RECEIVE
: {
2212 assert(port
->ip_mscount
== 0);
2213 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
2214 dest
= port
->ip_destination
;
2216 #if CONFIG_MACF_MACH
2217 if (space
->is_task
) {
2218 tasklabel_lock(space
->is_task
);
2219 rc
= mac_port_check_hold_receive(&space
->is_task
->maclabel
,
2221 tasklabel_unlock(space
->is_task
);
2225 return KERN_NO_ACCESS
;
2230 port
->ip_receiver_name
= name
;
2231 port
->ip_receiver
= space
;
2233 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
2235 if (bits
& MACH_PORT_TYPE_SEND
) {
2236 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
2237 assert(IE_BITS_UREFS(bits
) > 0);
2238 assert(port
->ip_srights
> 0);
2243 /* entry is locked holding ref, so can use port */
2245 ipc_hash_delete(space
, (ipc_object_t
) port
,
2248 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2249 assert(IE_BITS_UREFS(bits
) == 0);
2251 /* transfer ref to entry */
2254 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2256 if (dest
!= IP_NULL
)
2257 ipc_port_release(dest
);
2262 panic("ipc_right_copyout: strange rights");
2265 return KERN_SUCCESS
;
2269 * Routine: ipc_right_rename
2271 * Transfer an entry from one name to another.
2272 * The old entry is deallocated.
2274 * The space is write-locked and active.
2275 * The new entry is unused. Upon return,
2276 * the space is unlocked.
2278 * KERN_SUCCESS Moved entry to new name.
2284 mach_port_name_t oname
,
2286 mach_port_name_t nname
,
2289 ipc_port_request_index_t request
= oentry
->ie_request
;
2290 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2291 ipc_object_t object
= oentry
->ie_object
;
2293 assert(space
->is_active
);
2294 assert(oname
!= nname
);
2297 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2298 * if the port is dead. (This would foil ipc_port_destroy.)
2299 * Instead we should fail because oentry shouldn't exist.
2300 * Note IE_BITS_COMPAT implies ie_request != 0.
2303 if (request
!= IE_REQ_NONE
) {
2306 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2307 port
= (ipc_port_t
) object
;
2308 assert(port
!= IP_NULL
);
2310 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2311 request
= IE_REQ_NONE
;
2313 bits
= oentry
->ie_bits
;
2314 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2315 assert(oentry
->ie_request
== IE_REQ_NONE
);
2317 /* port is locked and active */
2319 ipc_port_request_rename(port
, request
, oname
, nname
);
2321 oentry
->ie_request
= IE_REQ_NONE
;
2325 /* initialize nentry before letting ipc_hash_insert see it */
2327 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2328 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2329 nentry
->ie_request
= request
;
2330 nentry
->ie_object
= object
;
2332 switch (IE_BITS_TYPE(bits
)) {
2333 case MACH_PORT_TYPE_SEND
: {
2336 port
= (ipc_port_t
) object
;
2337 assert(port
!= IP_NULL
);
2339 /* remember, there are no other share entries possible */
2340 /* or we can't do the rename. Therefore we do not need */
2341 /* to check the other subspaces */
2342 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2343 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2347 case MACH_PORT_TYPE_RECEIVE
:
2348 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2351 port
= (ipc_port_t
) object
;
2352 assert(port
!= IP_NULL
);
2355 assert(ip_active(port
));
2356 assert(port
->ip_receiver_name
== oname
);
2357 assert(port
->ip_receiver
== space
);
2359 port
->ip_receiver_name
= nname
;
2364 case MACH_PORT_TYPE_PORT_SET
: {
2367 pset
= (ipc_pset_t
) object
;
2368 assert(pset
!= IPS_NULL
);
2371 assert(ips_active(pset
));
2372 assert(pset
->ips_local_name
== oname
);
2374 pset
->ips_local_name
= nname
;
2379 case MACH_PORT_TYPE_SEND_ONCE
:
2380 case MACH_PORT_TYPE_DEAD_NAME
:
2384 panic("ipc_right_rename: strange rights");
2387 assert(oentry
->ie_request
== IE_REQ_NONE
);
2388 oentry
->ie_object
= IO_NULL
;
2389 ipc_entry_dealloc(space
, oname
, oentry
);
2390 is_write_unlock(space
);
2392 return KERN_SUCCESS
;