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,
65 * File: ipc/ipc_port.c
69 * Functions to manipulate IPC ports.
73 #include <zone_debug.h>
74 #include <mach_assert.h>
76 #include <mach/port.h>
77 #include <mach/kern_return.h>
78 #include <kern/lock.h>
79 #include <kern/ipc_kobject.h>
80 #include <kern/thread.h>
81 #include <kern/misc_protos.h>
82 #include <kern/wait_queue.h>
83 #include <ipc/ipc_entry.h>
84 #include <ipc/ipc_space.h>
85 #include <ipc/ipc_object.h>
86 #include <ipc/ipc_port.h>
87 #include <ipc/ipc_pset.h>
88 #include <ipc/ipc_kmsg.h>
89 #include <ipc/ipc_mqueue.h>
90 #include <ipc/ipc_notify.h>
91 #include <ipc/ipc_table.h>
93 #include <security/mac_mach_internal.h>
97 decl_lck_mtx_data(, ipc_port_multiple_lock_data
)
98 lck_mtx_ext_t ipc_port_multiple_lock_data_ext
;
99 ipc_port_timestamp_t ipc_port_timestamp_data
;
103 void ipc_port_init_debug(
105 natural_t
*callstack
,
106 unsigned int callstack_max
);
108 void ipc_port_callstack_init_debug(
109 natural_t
*callstack
,
110 unsigned int callstack_max
);
112 #endif /* MACH_ASSERT */
115 ipc_port_release(ipc_port_t port
)
121 ipc_port_reference(ipc_port_t port
)
127 * Routine: ipc_port_timestamp
129 * Retrieve a timestamp value.
133 ipc_port_timestamp(void)
135 return OSIncrementAtomic(&ipc_port_timestamp_data
);
139 * Routine: ipc_port_request_alloc
141 * Try to allocate a request slot.
142 * If successful, returns the request index.
143 * Otherwise returns zero.
145 * The port is locked and active.
147 * KERN_SUCCESS A request index was found.
148 * KERN_NO_SPACE No index allocated.
152 ipc_port_request_alloc(
154 mach_port_name_t name
,
156 boolean_t send_possible
,
158 ipc_port_request_index_t
*indexp
)
160 ipc_port_request_t ipr
, table
;
161 ipc_port_request_index_t index
;
164 assert(ip_active(port
));
165 assert(name
!= MACH_PORT_NULL
);
166 assert(soright
!= IP_NULL
);
168 table
= port
->ip_requests
;
170 if (table
== IPR_NULL
)
171 return KERN_NO_SPACE
;
173 index
= table
->ipr_next
;
175 return KERN_NO_SPACE
;
178 assert(ipr
->ipr_name
== MACH_PORT_NULL
);
180 table
->ipr_next
= ipr
->ipr_next
;
181 ipr
->ipr_name
= name
;
184 mask
|= IPR_SOR_SPREQ_MASK
;
186 mask
|= IPR_SOR_SPARM_MASK
;
187 port
->ip_sprequests
= TRUE
;
190 ipr
->ipr_soright
= IPR_SOR_MAKE(soright
, mask
);
198 * Routine: ipc_port_request_grow
200 * Grow a port's table of requests.
202 * The port must be locked and active.
203 * Nothing else locked; will allocate memory.
204 * Upon return the port is unlocked.
206 * KERN_SUCCESS Grew the table.
207 * KERN_SUCCESS Somebody else grew the table.
208 * KERN_SUCCESS The port died.
209 * KERN_RESOURCE_SHORTAGE Couldn't allocate new table.
210 * KERN_NO_SPACE Couldn't grow to desired size
214 ipc_port_request_grow(
216 ipc_table_elems_t target_size
)
218 ipc_table_size_t its
;
219 ipc_port_request_t otable
, ntable
;
221 assert(ip_active(port
));
223 otable
= port
->ip_requests
;
224 if (otable
== IPR_NULL
)
225 its
= &ipc_table_requests
[0];
227 its
= otable
->ipr_size
+ 1;
229 if (target_size
!= ITS_SIZE_NONE
) {
230 if ((otable
!= IPR_NULL
) &&
231 (target_size
<= otable
->ipr_size
->its_size
)) {
235 while ((its
->its_size
) && (its
->its_size
< target_size
)) {
238 if (its
->its_size
== 0) {
240 return KERN_NO_SPACE
;
247 if ((its
->its_size
== 0) ||
248 ((ntable
= it_requests_alloc(its
)) == IPR_NULL
)) {
250 return KERN_RESOURCE_SHORTAGE
;
256 * Check that port is still active and that nobody else
257 * has slipped in and grown the table on us. Note that
258 * just checking if the current table pointer == otable
259 * isn't sufficient; must check ipr_size.
262 if (ip_active(port
) && (port
->ip_requests
== otable
) &&
263 ((otable
== IPR_NULL
) || (otable
->ipr_size
+1 == its
))) {
264 ipc_table_size_t oits
;
265 ipc_table_elems_t osize
, nsize
;
266 ipc_port_request_index_t free
, i
;
268 /* copy old table to new table */
270 if (otable
!= IPR_NULL
) {
271 oits
= otable
->ipr_size
;
272 osize
= oits
->its_size
;
273 free
= otable
->ipr_next
;
275 (void) memcpy((void *)(ntable
+ 1),
276 (const void *)(otable
+ 1),
277 (osize
- 1) * sizeof(struct ipc_port_request
));
284 nsize
= its
->its_size
;
285 assert(nsize
> osize
);
287 /* add new elements to the new table's free list */
289 for (i
= osize
; i
< nsize
; i
++) {
290 ipc_port_request_t ipr
= &ntable
[i
];
292 ipr
->ipr_name
= MACH_PORT_NULL
;
293 ipr
->ipr_next
= free
;
297 ntable
->ipr_next
= free
;
298 ntable
->ipr_size
= its
;
299 port
->ip_requests
= ntable
;
303 if (otable
!= IPR_NULL
) {
304 it_requests_free(oits
, otable
);
309 it_requests_free(its
, ntable
);
316 * Routine: ipc_port_request_sparm
318 * Arm delayed send-possible request.
320 * The port must be locked and active.
324 ipc_port_request_sparm(
326 __assert_only mach_port_name_t name
,
327 ipc_port_request_index_t index
)
329 if (index
!= IE_REQ_NONE
) {
330 ipc_port_request_t ipr
, table
;
332 assert(ip_active(port
));
334 table
= port
->ip_requests
;
335 assert(table
!= IPR_NULL
);
338 assert(ipr
->ipr_name
== name
);
340 if (IPR_SOR_SPREQ(ipr
->ipr_soright
)) {
341 ipr
->ipr_soright
= IPR_SOR_MAKE(ipr
->ipr_soright
, IPR_SOR_SPARM_MASK
);
342 port
->ip_sprequests
= TRUE
;
348 * Routine: ipc_port_request_type
350 * Determine the type(s) of port requests enabled for a name.
352 * The port must be locked or inactive (to avoid table growth).
353 * The index must not be IE_REQ_NONE and for the name in question.
356 ipc_port_request_type(
358 __assert_only mach_port_name_t name
,
359 ipc_port_request_index_t index
)
361 ipc_port_request_t ipr
, table
;
362 mach_port_type_t type
= 0;
364 table
= port
->ip_requests
;
365 assert (table
!= IPR_NULL
);
367 assert(index
!= IE_REQ_NONE
);
369 assert(ipr
->ipr_name
== name
);
371 if (IP_VALID(IPR_SOR_PORT(ipr
->ipr_soright
))) {
372 type
|= MACH_PORT_TYPE_DNREQUEST
;
374 if (IPR_SOR_SPREQ(ipr
->ipr_soright
)) {
375 type
|= MACH_PORT_TYPE_SPREQUEST
;
377 if (!IPR_SOR_SPARMED(ipr
->ipr_soright
)) {
378 type
|= MACH_PORT_TYPE_SPREQUEST_DELAYED
;
386 * Routine: ipc_port_request_cancel
388 * Cancel a dead-name/send-possible request and return the send-once right.
390 * The port must be locked and active.
391 * The index must not be IPR_REQ_NONE and must correspond with name.
395 ipc_port_request_cancel(
397 __assert_only mach_port_name_t name
,
398 ipc_port_request_index_t index
)
400 ipc_port_request_t ipr
, table
;
401 ipc_port_t request
= IP_NULL
;
403 assert(ip_active(port
));
404 table
= port
->ip_requests
;
405 assert(table
!= IPR_NULL
);
407 assert (index
!= IE_REQ_NONE
);
409 assert(ipr
->ipr_name
== name
);
410 request
= IPR_SOR_PORT(ipr
->ipr_soright
);
412 /* return ipr to the free list inside the table */
413 ipr
->ipr_name
= MACH_PORT_NULL
;
414 ipr
->ipr_next
= table
->ipr_next
;
415 table
->ipr_next
= index
;
421 * Routine: ipc_port_pdrequest
423 * Make a port-deleted request, returning the
424 * previously registered send-once right.
425 * Just cancels the previous request if notify is IP_NULL.
427 * The port is locked and active. It is unlocked.
428 * Consumes a ref for notify (if non-null), and
429 * returns previous with a ref (if non-null).
436 ipc_port_t
*previousp
)
440 assert(ip_active(port
));
442 previous
= port
->ip_pdrequest
;
443 port
->ip_pdrequest
= notify
;
446 *previousp
= previous
;
450 * Routine: ipc_port_nsrequest
452 * Make a no-senders request, returning the
453 * previously registered send-once right.
454 * Just cancels the previous request if notify is IP_NULL.
456 * The port is locked and active. It is unlocked.
457 * Consumes a ref for notify (if non-null), and
458 * returns previous with a ref (if non-null).
464 mach_port_mscount_t sync
,
466 ipc_port_t
*previousp
)
469 mach_port_mscount_t mscount
;
471 assert(ip_active(port
));
473 previous
= port
->ip_nsrequest
;
474 mscount
= port
->ip_mscount
;
476 if ((port
->ip_srights
== 0) && (sync
<= mscount
) &&
477 (notify
!= IP_NULL
)) {
478 port
->ip_nsrequest
= IP_NULL
;
480 ipc_notify_no_senders(notify
, mscount
);
482 port
->ip_nsrequest
= notify
;
486 *previousp
= previous
;
491 * Routine: ipc_port_clear_receiver
493 * Prepares a receive right for transmission/destruction.
495 * The port is locked and active.
499 ipc_port_clear_receiver(
505 assert(ip_active(port
));
508 * pull ourselves from any sets.
510 if (port
->ip_pset_count
!= 0) {
511 ipc_pset_remove_from_all(port
, links
);
512 assert(port
->ip_pset_count
== 0);
516 * Send anyone waiting on the port's queue directly away.
517 * Also clear the mscount and seqno.
520 imq_lock(&port
->ip_messages
);
521 ipc_mqueue_changed(&port
->ip_messages
);
522 ipc_port_set_mscount(port
, 0);
523 port
->ip_messages
.imq_seqno
= 0;
524 imq_unlock(&port
->ip_messages
);
529 * Routine: ipc_port_init
531 * Initializes a newly-allocated port.
532 * Doesn't touch the ip_object fields.
539 mach_port_name_t name
)
541 /* port->ip_kobject doesn't have to be initialized */
543 port
->ip_receiver
= space
;
544 port
->ip_receiver_name
= name
;
546 port
->ip_mscount
= 0;
547 port
->ip_srights
= 0;
548 port
->ip_sorights
= 0;
550 port
->ip_nsrequest
= IP_NULL
;
551 port
->ip_pdrequest
= IP_NULL
;
552 port
->ip_requests
= IPR_NULL
;
554 port
->ip_pset_count
= 0;
555 port
->ip_premsg
= IKM_NULL
;
556 port
->ip_context
= 0;
558 ipc_mqueue_init(&port
->ip_messages
, FALSE
/* set */);
562 * Routine: ipc_port_alloc
566 * Nothing locked. If successful, the port is returned
567 * locked. (The caller doesn't have a reference.)
569 * KERN_SUCCESS The port is allocated.
570 * KERN_INVALID_TASK The space is dead.
571 * KERN_NO_SPACE No room for an entry in the space.
572 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
578 mach_port_name_t
*namep
,
582 mach_port_name_t name
;
586 natural_t buf
[IP_CALLSTACK_MAX
];
587 ipc_port_callstack_init_debug(&buf
[0], IP_CALLSTACK_MAX
);
588 #endif /* MACH_ASSERT */
590 kr
= ipc_object_alloc(space
, IOT_PORT
,
591 MACH_PORT_TYPE_RECEIVE
, 0,
592 &name
, (ipc_object_t
*) &port
);
593 if (kr
!= KERN_SUCCESS
)
598 ipc_port_init(port
, space
, name
);
601 ipc_port_init_debug(port
, &buf
[0], IP_CALLSTACK_MAX
);
602 #endif /* MACH_ASSERT */
605 task_t issuer
= current_task();
606 tasklabel_lock2 (issuer
, space
->is_task
);
607 mac_port_label_associate(&issuer
->maclabel
, &space
->is_task
->maclabel
,
609 tasklabel_unlock2 (issuer
, space
->is_task
);
619 * Routine: ipc_port_alloc_name
621 * Allocate a port, with a specific name.
623 * Nothing locked. If successful, the port is returned
624 * locked. (The caller doesn't have a reference.)
626 * KERN_SUCCESS The port is allocated.
627 * KERN_INVALID_TASK The space is dead.
628 * KERN_NAME_EXISTS The name already denotes a right.
629 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
635 mach_port_name_t name
,
642 natural_t buf
[IP_CALLSTACK_MAX
];
643 ipc_port_callstack_init_debug(&buf
[0], IP_CALLSTACK_MAX
);
644 #endif /* MACH_ASSERT */
646 kr
= ipc_object_alloc_name(space
, IOT_PORT
,
647 MACH_PORT_TYPE_RECEIVE
, 0,
648 name
, (ipc_object_t
*) &port
);
649 if (kr
!= KERN_SUCCESS
)
654 ipc_port_init(port
, space
, name
);
657 ipc_port_init_debug(port
, &buf
[0], IP_CALLSTACK_MAX
);
658 #endif /* MACH_ASSERT */
661 task_t issuer
= current_task();
662 tasklabel_lock2 (issuer
, space
->is_task
);
663 mac_port_label_associate(&issuer
->maclabel
, &space
->is_task
->maclabel
,
665 tasklabel_unlock2 (issuer
, space
->is_task
);
674 * Routine: ipc_port_spnotify
676 * Generate send-possible port notifications.
678 * Nothing locked, reference held on port.
684 ipc_port_request_index_t index
= 0;
685 ipc_table_elems_t size
= 0;
688 * If the port has no send-possible request
689 * armed, don't bother to lock the port.
691 if (!port
->ip_sprequests
)
695 if (!port
->ip_sprequests
) {
699 port
->ip_sprequests
= FALSE
;
702 if (ip_active(port
)) {
703 ipc_port_request_t requests
;
705 /* table may change each time port unlocked (reload) */
706 requests
= port
->ip_requests
;
707 assert(requests
!= IPR_NULL
);
710 * no need to go beyond table size when first
711 * we entered - those are future notifications.
714 size
= requests
->ipr_size
->its_size
;
716 /* no need to backtrack either */
717 while (++index
< size
) {
718 ipc_port_request_t ipr
= &requests
[index
];
719 mach_port_name_t name
= ipr
->ipr_name
;
720 ipc_port_t soright
= IPR_SOR_PORT(ipr
->ipr_soright
);
721 boolean_t armed
= IPR_SOR_SPARMED(ipr
->ipr_soright
);
723 if (MACH_PORT_VALID(name
) && armed
&& IP_VALID(soright
)) {
724 /* claim send-once right - slot still inuse */
725 ipr
->ipr_soright
= IP_NULL
;
728 ipc_notify_send_possible(soright
, name
);
739 * Routine: ipc_port_dnnotify
741 * Generate dead name notifications for
742 * all outstanding dead-name and send-
746 * Port must be inactive.
747 * Reference held on port.
753 ipc_port_request_t requests
= port
->ip_requests
;
755 assert(!ip_active(port
));
756 if (requests
!= IPR_NULL
) {
757 ipc_table_size_t its
= requests
->ipr_size
;
758 ipc_table_elems_t size
= its
->its_size
;
759 ipc_port_request_index_t index
;
760 for (index
= 1; index
< size
; index
++) {
761 ipc_port_request_t ipr
= &requests
[index
];
762 mach_port_name_t name
= ipr
->ipr_name
;
763 ipc_port_t soright
= IPR_SOR_PORT(ipr
->ipr_soright
);
765 if (MACH_PORT_VALID(name
) && IP_VALID(soright
)) {
766 ipc_notify_dead_name(soright
, name
);
774 * Routine: ipc_port_destroy
776 * Destroys a port. Cleans up queued messages.
778 * If the port has a backup, it doesn't get destroyed,
779 * but is sent in a port-destroyed notification to the backup.
781 * The port is locked and alive; nothing else locked.
782 * The caller has a reference, which is consumed.
783 * Afterwards, the port is unlocked and dead.
790 ipc_port_t pdrequest
, nsrequest
;
794 assert(ip_active(port
));
795 /* port->ip_receiver_name is garbage */
796 /* port->ip_receiver/port->ip_destination is garbage */
797 assert(port
->ip_pset_count
== 0);
798 assert(port
->ip_mscount
== 0);
800 /* first check for a backup port */
802 pdrequest
= port
->ip_pdrequest
;
803 if (pdrequest
!= IP_NULL
) {
804 /* we assume the ref for pdrequest */
805 port
->ip_pdrequest
= IP_NULL
;
807 /* make port be in limbo */
808 port
->ip_receiver_name
= MACH_PORT_NULL
;
809 port
->ip_destination
= IP_NULL
;
812 /* consumes our refs for port and pdrequest */
813 ipc_notify_port_destroyed(pdrequest
, port
);
817 /* once port is dead, we don't need to keep it locked */
819 port
->ip_object
.io_bits
&= ~IO_BITS_ACTIVE
;
820 port
->ip_timestamp
= ipc_port_timestamp();
823 * If the port has a preallocated message buffer and that buffer
824 * is not inuse, free it. If it has an inuse one, then the kmsg
825 * free will detect that we freed the association and it can free it
826 * like a normal buffer.
828 if (IP_PREALLOC(port
)) {
829 ipc_port_t inuse_port
;
831 kmsg
= port
->ip_premsg
;
832 assert(kmsg
!= IKM_NULL
);
833 inuse_port
= ikm_prealloc_inuse_port(kmsg
);
834 IP_CLEAR_PREALLOC(port
, kmsg
);
836 if (inuse_port
!= IP_NULL
) {
837 assert(inuse_port
== port
);
845 /* throw away no-senders request */
846 nsrequest
= port
->ip_nsrequest
;
847 if (nsrequest
!= IP_NULL
)
848 ipc_notify_send_once(nsrequest
); /* consumes ref */
850 /* destroy any queued messages */
851 mqueue
= &port
->ip_messages
;
852 ipc_mqueue_destroy(mqueue
);
854 /* generate dead-name notifications */
855 ipc_port_dnnotify(port
);
857 ipc_kobject_destroy(port
);
859 ip_release(port
); /* consume caller's ref */
863 * Routine: ipc_port_check_circularity
865 * Check if queueing "port" in a message for "dest"
866 * would create a circular group of ports and messages.
868 * If no circularity (FALSE returned), then "port"
869 * is changed from "in limbo" to "in transit".
871 * That is, we want to set port->ip_destination == dest,
872 * but guaranteeing that this doesn't create a circle
873 * port->ip_destination->ip_destination->... == port
875 * No ports locked. References held for "port" and "dest".
879 ipc_port_check_circularity(
885 assert(port
!= IP_NULL
);
886 assert(dest
!= IP_NULL
);
893 * First try a quick check that can run in parallel.
894 * No circularity if dest is not in transit.
898 if (ip_lock_try(dest
)) {
899 if (!ip_active(dest
) ||
900 (dest
->ip_receiver_name
!= MACH_PORT_NULL
) ||
901 (dest
->ip_destination
== IP_NULL
))
904 /* dest is in transit; further checking necessary */
910 ipc_port_multiple_lock(); /* massive serialization */
913 * Search for the end of the chain (a port not in transit),
914 * acquiring locks along the way.
920 if (!ip_active(base
) ||
921 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
922 (base
->ip_destination
== IP_NULL
))
925 base
= base
->ip_destination
;
928 /* all ports in chain from dest to base, inclusive, are locked */
931 /* circularity detected! */
933 ipc_port_multiple_unlock();
935 /* port (== base) is in limbo */
937 assert(ip_active(port
));
938 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
939 assert(port
->ip_destination
== IP_NULL
);
941 while (dest
!= IP_NULL
) {
944 /* dest is in transit or in limbo */
946 assert(ip_active(dest
));
947 assert(dest
->ip_receiver_name
== MACH_PORT_NULL
);
949 next
= dest
->ip_destination
;
958 * The guarantee: lock port while the entire chain is locked.
959 * Once port is locked, we can take a reference to dest,
960 * add port to the chain, and unlock everything.
964 ipc_port_multiple_unlock();
968 /* port is in limbo */
970 assert(ip_active(port
));
971 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
972 assert(port
->ip_destination
== IP_NULL
);
975 port
->ip_destination
= dest
;
977 /* now unlock chain */
979 while (port
!= base
) {
982 /* port is in transit */
984 assert(ip_active(port
));
985 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
986 assert(port
->ip_destination
!= IP_NULL
);
988 next
= port
->ip_destination
;
993 /* base is not in transit */
995 assert(!ip_active(base
) ||
996 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
997 (base
->ip_destination
== IP_NULL
));
1004 * Routine: ipc_port_lookup_notify
1006 * Make a send-once notify port from a receive right.
1007 * Returns IP_NULL if name doesn't denote a receive right.
1009 * The space must be locked (read or write) and active.
1010 * Being the active space, we can rely on thread server_id
1011 * context to give us the proper server level sub-order
1016 ipc_port_lookup_notify(
1018 mach_port_name_t name
)
1023 assert(is_active(space
));
1025 entry
= ipc_entry_lookup(space
, name
);
1026 if (entry
== IE_NULL
)
1028 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1031 port
= (ipc_port_t
) entry
->ie_object
;
1032 assert(port
!= IP_NULL
);
1035 assert(ip_active(port
));
1036 assert(port
->ip_receiver_name
== name
);
1037 assert(port
->ip_receiver
== space
);
1040 port
->ip_sorights
++;
1047 * Routine: ipc_port_make_send_locked
1049 * Make a naked send right from a receive right.
1052 * port locked and active.
1055 ipc_port_make_send_locked(
1058 assert(ip_active(port
));
1067 * Routine: ipc_port_make_send
1069 * Make a naked send right from a receive right.
1077 if (!IP_VALID(port
))
1081 if (ip_active(port
)) {
1093 * Routine: ipc_port_copy_send
1095 * Make a naked send right from another naked send right.
1096 * IP_NULL -> IP_NULL
1097 * IP_DEAD -> IP_DEAD
1098 * dead port -> IP_DEAD
1099 * live port -> port + ref
1101 * Nothing locked except possibly a space.
1110 if (!IP_VALID(port
))
1114 if (ip_active(port
)) {
1115 assert(port
->ip_srights
> 0);
1128 * Routine: ipc_port_copyout_send
1130 * Copyout a naked send right (possibly null/dead),
1131 * or if that fails, destroy the right.
1137 ipc_port_copyout_send(
1141 mach_port_name_t name
;
1143 if (IP_VALID(sright
)) {
1146 kr
= ipc_object_copyout(space
, (ipc_object_t
) sright
,
1147 MACH_MSG_TYPE_PORT_SEND
, TRUE
, &name
);
1148 if (kr
!= KERN_SUCCESS
) {
1149 ipc_port_release_send(sright
);
1151 if (kr
== KERN_INVALID_CAPABILITY
)
1152 name
= MACH_PORT_DEAD
;
1154 name
= MACH_PORT_NULL
;
1157 name
= CAST_MACH_PORT_TO_NAME(sright
);
1163 * Routine: ipc_port_release_send
1165 * Release a naked send right.
1166 * Consumes a ref for the port.
1172 ipc_port_release_send(
1175 ipc_port_t nsrequest
= IP_NULL
;
1176 mach_port_mscount_t mscount
;
1178 if (!IP_VALID(port
))
1183 if (!ip_active(port
)) {
1189 assert(port
->ip_srights
> 0);
1191 if (--port
->ip_srights
== 0 &&
1192 port
->ip_nsrequest
!= IP_NULL
) {
1193 nsrequest
= port
->ip_nsrequest
;
1194 port
->ip_nsrequest
= IP_NULL
;
1195 mscount
= port
->ip_mscount
;
1198 ipc_notify_no_senders(nsrequest
, mscount
);
1206 * Routine: ipc_port_make_sonce_locked
1208 * Make a naked send-once right from a receive right.
1210 * The port is locked and active.
1214 ipc_port_make_sonce_locked(
1217 assert(ip_active(port
));
1218 port
->ip_sorights
++;
1224 * Routine: ipc_port_make_sonce
1226 * Make a naked send-once right from a receive right.
1228 * The port is not locked.
1232 ipc_port_make_sonce(
1235 if (!IP_VALID(port
))
1239 if (ip_active(port
)) {
1240 port
->ip_sorights
++;
1250 * Routine: ipc_port_release_sonce
1252 * Release a naked send-once right.
1253 * Consumes a ref for the port.
1255 * In normal situations, this is never used.
1256 * Send-once rights are only consumed when
1257 * a message (possibly a send-once notification)
1260 * Nothing locked except possibly a space.
1264 ipc_port_release_sonce(
1267 if (!IP_VALID(port
))
1272 assert(port
->ip_sorights
> 0);
1274 port
->ip_sorights
--;
1281 * Routine: ipc_port_release_receive
1283 * Release a naked (in limbo or in transit) receive right.
1284 * Consumes a ref for the port; destroys the port.
1290 ipc_port_release_receive(
1295 if (!IP_VALID(port
))
1299 assert(ip_active(port
));
1300 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1301 dest
= port
->ip_destination
;
1303 ipc_port_destroy(port
); /* consumes ref, unlocks */
1305 if (dest
!= IP_NULL
)
1310 * Routine: ipc_port_alloc_special
1312 * Allocate a port in a special space.
1313 * The new port is returned with one ref.
1314 * If unsuccessful, IP_NULL is returned.
1320 ipc_port_alloc_special(
1325 port
= (ipc_port_t
) io_alloc(IOT_PORT
);
1326 if (port
== IP_NULL
)
1330 natural_t buf
[IP_CALLSTACK_MAX
];
1331 ipc_port_callstack_init_debug(&buf
[0], IP_CALLSTACK_MAX
);
1332 #endif /* MACH_ASSERT */
1334 bzero((char *)port
, sizeof(*port
));
1335 io_lock_init(&port
->ip_object
);
1336 port
->ip_references
= 1;
1337 port
->ip_object
.io_bits
= io_makebits(TRUE
, IOT_PORT
, 0);
1339 ipc_port_init(port
, space
, 1);
1342 ipc_port_init_debug(port
, &buf
[0], IP_CALLSTACK_MAX
);
1343 #endif /* MACH_ASSERT */
1345 #if CONFIG_MACF_MACH
1346 /* Currently, ipc_port_alloc_special is used for two things:
1347 * - Reply ports for messages from the kernel
1348 * - Ports for communication with the kernel (e.g. task ports)
1349 * Since both of these would typically be labelled as kernel objects,
1350 * we will use a new entry point for this purpose, as current_task()
1351 * is often wrong (i.e. not kernel_task) or null.
1353 mac_port_label_init(&port
->ip_label
);
1354 mac_port_label_associate_kernel(&port
->ip_label
, space
== ipc_space_reply
);
1361 * Routine: ipc_port_dealloc_special
1363 * Deallocate a port in a special space.
1364 * Consumes one ref for the port.
1370 ipc_port_dealloc_special(
1372 __assert_only ipc_space_t space
)
1375 assert(ip_active(port
));
1376 // assert(port->ip_receiver_name != MACH_PORT_NULL);
1377 assert(port
->ip_receiver
== space
);
1380 * We clear ip_receiver_name and ip_receiver to simplify
1381 * the ipc_space_kernel check in ipc_mqueue_send.
1384 port
->ip_receiver_name
= MACH_PORT_NULL
;
1385 port
->ip_receiver
= IS_NULL
;
1387 /* relevant part of ipc_port_clear_receiver */
1388 ipc_port_set_mscount(port
, 0);
1389 port
->ip_messages
.imq_seqno
= 0;
1391 ipc_port_destroy(port
);
1395 * Routine: ipc_port_finalize
1397 * Called on last reference deallocate to
1398 * free any remaining data associated with the
1407 ipc_port_request_t requests
= port
->ip_requests
;
1409 assert(!ip_active(port
));
1410 if (requests
!= IPR_NULL
) {
1411 ipc_table_size_t its
= requests
->ipr_size
;
1412 it_requests_free(its
, requests
);
1413 port
->ip_requests
= IPR_NULL
;
1417 ipc_port_track_dealloc(port
);
1418 #endif /* MACH_ASSERT */
1420 #if CONFIG_MACF_MACH
1421 /* Port label should have been initialized after creation. */
1422 mac_port_label_destroy(&port
->ip_label
);
1427 #include <kern/machine.h>
1430 * Keep a list of all allocated ports.
1431 * Allocation is intercepted via ipc_port_init;
1432 * deallocation is intercepted via io_free.
1434 queue_head_t port_alloc_queue
;
1435 lck_spin_t port_alloc_queue_lock
;
1437 unsigned long port_count
= 0;
1438 unsigned long port_count_warning
= 20000;
1439 unsigned long port_timestamp
= 0;
1441 void db_port_stack_trace(
1446 unsigned int verbose
,
1447 unsigned int display
,
1448 unsigned int ref_search
,
1449 unsigned int ref_target
);
1452 * Initialize global state needed for run-time
1456 ipc_port_debug_init(void)
1458 queue_init(&port_alloc_queue
);
1460 lck_spin_init(&port_alloc_queue_lock
, &ipc_lck_grp
, &ipc_lck_attr
);
1462 if (!PE_parse_boot_argn("ipc_portbt", &ipc_portbt
, sizeof (ipc_portbt
)))
1467 extern int proc_pid(struct proc
*);
1468 #endif /* MACH_BSD */
1471 * Initialize all of the debugging state in a port.
1472 * Insert the port into a global list of all allocated ports.
1475 ipc_port_init_debug(
1477 natural_t
*callstack
,
1478 unsigned int callstack_max
)
1482 port
->ip_thread
= current_thread();
1483 port
->ip_timetrack
= port_timestamp
++;
1484 for (i
= 0; i
< callstack_max
; ++i
)
1485 port
->ip_callstack
[i
] = callstack
[i
];
1486 for (i
= 0; i
< IP_NSPARES
; ++i
)
1487 port
->ip_spares
[i
] = 0;
1490 task_t task
= current_task();
1491 if (task
!= TASK_NULL
) {
1492 struct proc
* proc
= (struct proc
*) get_bsdtask_info(task
);
1494 port
->ip_spares
[0] = proc_pid(proc
);
1496 #endif /* MACH_BSD */
1499 lck_spin_lock(&port_alloc_queue_lock
);
1501 if (port_count_warning
> 0 && port_count
>= port_count_warning
)
1502 assert(port_count
< port_count_warning
);
1503 queue_enter(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1504 lck_spin_unlock(&port_alloc_queue_lock
);
1509 * Routine: ipc_port_callstack_init_debug
1511 * Calls the machine-dependent routine to
1512 * fill in an array with up to IP_CALLSTACK_MAX
1513 * levels of return pc information
1515 * May block (via copyin)
1518 ipc_port_callstack_init_debug(
1519 natural_t
*callstack
,
1520 unsigned int callstack_max
)
1524 /* guarantee the callstack is initialized */
1525 for (i
=0; i
< callstack_max
; i
++)
1529 machine_callstack(callstack
, callstack_max
);
1533 * Remove a port from the queue of allocated ports.
1534 * This routine should be invoked JUST prior to
1535 * deallocating the actual memory occupied by the port.
1539 ipc_port_track_dealloc(
1540 __unused ipc_port_t port
)
1545 ipc_port_track_dealloc(
1548 lck_spin_lock(&port_alloc_queue_lock
);
1549 assert(port_count
> 0);
1551 queue_remove(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1552 lck_spin_unlock(&port_alloc_queue_lock
);
1557 #endif /* MACH_ASSERT */