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@
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 SPARTA, Inc.
66 * File: ipc/ipc_kmsg.c
70 * Operations on kernel messages.
75 #include <mach/mach_types.h>
76 #include <mach/boolean.h>
77 #include <mach/kern_return.h>
78 #include <mach/message.h>
79 #include <mach/port.h>
80 #include <mach/vm_map.h>
81 #include <mach/mach_vm.h>
82 #include <mach/vm_statistics.h>
84 #include <kern/kern_types.h>
85 #include <kern/assert.h>
86 #include <kern/ipc_kobject.h>
87 #include <kern/kalloc.h>
88 #include <kern/zalloc.h>
89 #include <kern/processor.h>
90 #include <kern/thread.h>
91 #include <kern/sched_prim.h>
93 #include <kern/misc_protos.h>
94 #include <kern/counters.h>
95 #include <kern/cpu_data.h>
97 #include <vm/vm_map.h>
98 #include <vm/vm_object.h>
99 #include <vm/vm_kern.h>
101 #include <ipc/port.h>
102 #include <ipc/ipc_types.h>
103 #include <ipc/ipc_entry.h>
104 #include <ipc/ipc_kmsg.h>
105 #include <ipc/ipc_notify.h>
106 #include <ipc/ipc_object.h>
107 #include <ipc/ipc_space.h>
108 #include <ipc/ipc_port.h>
109 #include <ipc/ipc_right.h>
110 #include <ipc/ipc_hash.h>
111 #include <ipc/ipc_table.h>
113 #include <security/mac_mach_internal.h>
118 #include <ppc/Firmware.h>
119 #include <ppc/low_trace.h>
123 extern vm_map_t ipc_kernel_copy_map
;
124 extern vm_size_t ipc_kmsg_max_vm_space
;
125 extern vm_size_t msg_ool_size_small
;
127 #define MSG_OOL_SIZE_SMALL msg_ool_size_small
129 #if defined(__LP64__)
130 #define MAP_SIZE_DIFFERS(map) (map->max_offset < MACH_VM_MAX_ADDRESS)
131 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor32_t
132 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor32_t
134 #define MAP_SIZE_DIFFERS(map) (map->max_offset > VM_MAX_ADDRESS)
135 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor64_t
136 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor64_t
139 #define DESC_SIZE_ADJUSTMENT (sizeof(OTHER_OOL_DESCRIPTOR) - \
140 sizeof(mach_msg_ool_descriptor_t))
142 /* scatter list macros */
144 #define SKIP_PORT_DESCRIPTORS(s, c) \
146 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
148 if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
153 (s) = MACH_MSG_DESCRIPTOR_NULL; \
157 #define INCREMENT_SCATTER(s, c, d) \
159 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
160 s = (d) ? (mach_msg_descriptor_t *) \
161 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) : \
167 /* zone for cached ipc_kmsg_t structures */
168 zone_t ipc_kmsg_zone
;
171 * Forward declarations
177 void ipc_kmsg_clean_body(
179 mach_msg_type_number_t number
,
180 mach_msg_descriptor_t
*desc
);
182 void ipc_kmsg_clean_partial(
184 mach_msg_type_number_t number
,
185 mach_msg_descriptor_t
*desc
,
189 mach_msg_return_t
ipc_kmsg_copyin_body(
195 * We keep a per-processor cache of kernel message buffers.
196 * The cache saves the overhead/locking of using kalloc/kfree.
197 * The per-processor cache seems to miss less than a per-thread cache,
198 * and it also uses less memory. Access to the cache doesn't
203 * Routine: ipc_kmsg_alloc
205 * Allocate a kernel message structure. If we can get one from
206 * the cache, that is best. Otherwise, allocate a new one.
212 mach_msg_size_t msg_and_trailer_size
)
214 mach_msg_size_t max_expanded_size
;
217 #if !defined(__LP64__)
220 * Pad the allocation in case we need to expand the
221 * message descrptors for user spaces with pointers larger than
222 * the kernel's own. We don't know how many descriptors
223 * there are yet, so just assume the whole body could be
224 * descriptors (if there could be any at all).
226 * The expansion space is left in front of the header,
227 * because it is easier to pull the header and descriptors
228 * forward as we process them than it is to push all the
232 mach_msg_size_t size
= msg_and_trailer_size
- MAX_TRAILER_SIZE
;
233 if (size
> sizeof(mach_msg_base_t
)) {
234 mach_msg_size_t max_desc
= ((size
- sizeof(mach_msg_base_t
)) /
235 sizeof(mach_msg_ool_descriptor_t
)) *
236 DESC_SIZE_ADJUSTMENT
;
237 if (msg_and_trailer_size
>= MACH_MSG_SIZE_MAX
- max_desc
)
239 max_expanded_size
= msg_and_trailer_size
+ max_desc
;
242 max_expanded_size
= msg_and_trailer_size
;
244 if (max_expanded_size
> ikm_less_overhead(MACH_MSG_SIZE_MAX
))
246 else if (max_expanded_size
< IKM_SAVED_MSG_SIZE
)
247 max_expanded_size
= IKM_SAVED_MSG_SIZE
; /* round up for ikm_cache */
249 if (max_expanded_size
== IKM_SAVED_MSG_SIZE
) {
250 struct ikm_cache
*cache
;
253 disable_preemption();
254 cache
= &PROCESSOR_DATA(current_processor(), ikm_cache
);
255 if ((i
= cache
->avail
) > 0) {
256 assert(i
<= IKM_STASH
);
257 kmsg
= cache
->entries
[--i
];
259 ikm_check_init(kmsg
, max_expanded_size
);
261 kmsg
->ikm_header
= (mach_msg_header_t
*)
262 ((vm_offset_t
)(kmsg
+ 1) +
264 msg_and_trailer_size
);
268 kmsg
= (ipc_kmsg_t
)zalloc(ipc_kmsg_zone
);
270 kmsg
= (ipc_kmsg_t
)kalloc(ikm_plus_overhead(max_expanded_size
));
273 if (kmsg
!= IKM_NULL
) {
274 ikm_init(kmsg
, max_expanded_size
);
275 kmsg
->ikm_header
= (mach_msg_header_t
*)
276 ((vm_offset_t
)(kmsg
+ 1) +
278 msg_and_trailer_size
);
285 * Routine: ipc_kmsg_free
287 * Free a kernel message buffer. If the kms is preallocated
288 * to a port, just "put it back (marked unused)." We have to
289 * do this with the port locked. The port may have its hold
290 * on our message released. In that case, we have to just
291 * revert the message to a traditional one and free it normally.
300 mach_msg_size_t size
= kmsg
->ikm_size
;
304 if (kmsg
->ikm_sender
!= NULL
) {
305 task_deallocate(kmsg
->ikm_sender
);
306 kmsg
->ikm_sender
= NULL
;
311 * Check to see if the message is bound to the port. If so,
312 * mark it not in use. If the port isn't already dead, then
313 * leave the message associated with it. Otherwise, free it.
315 port
= ikm_prealloc_inuse_port(kmsg
);
316 if (port
!= IP_NULL
) {
318 ikm_prealloc_clear_inuse(kmsg
, port
);
319 if (ip_active(port
) && (port
->ip_premsg
== kmsg
)) {
320 assert(IP_PREALLOC(port
));
324 ip_check_unlock(port
); /* May be last reference */
328 * Peek and see if it has to go back in the cache.
330 if (kmsg
->ikm_size
== IKM_SAVED_MSG_SIZE
) {
331 struct ikm_cache
*cache
;
334 disable_preemption();
335 cache
= &PROCESSOR_DATA(current_processor(), ikm_cache
);
336 if ((i
= cache
->avail
) < IKM_STASH
) {
337 cache
->entries
[i
] = kmsg
;
338 cache
->avail
= i
+ 1;
343 zfree(ipc_kmsg_zone
, kmsg
);
346 kfree(kmsg
, ikm_plus_overhead(size
));
351 * Routine: ipc_kmsg_enqueue
358 ipc_kmsg_queue_t queue
,
361 ipc_kmsg_enqueue_macro(queue
, kmsg
);
365 * Routine: ipc_kmsg_dequeue
367 * Dequeue and return a kmsg.
372 ipc_kmsg_queue_t queue
)
376 first
= ipc_kmsg_queue_first(queue
);
378 if (first
!= IKM_NULL
)
379 ipc_kmsg_rmqueue_first_macro(queue
, first
);
385 * Routine: ipc_kmsg_rmqueue
387 * Pull a kmsg out of a queue.
392 ipc_kmsg_queue_t queue
,
395 ipc_kmsg_t next
, prev
;
397 assert(queue
->ikmq_base
!= IKM_NULL
);
399 next
= kmsg
->ikm_next
;
400 prev
= kmsg
->ikm_prev
;
403 assert(prev
== kmsg
);
404 assert(queue
->ikmq_base
== kmsg
);
406 queue
->ikmq_base
= IKM_NULL
;
408 if (queue
->ikmq_base
== kmsg
)
409 queue
->ikmq_base
= next
;
411 next
->ikm_prev
= prev
;
412 prev
->ikm_next
= next
;
414 /* XXX Temporary debug logic */
415 assert((kmsg
->ikm_next
= IKM_BOGUS
) == IKM_BOGUS
);
416 assert((kmsg
->ikm_prev
= IKM_BOGUS
) == IKM_BOGUS
);
420 * Routine: ipc_kmsg_queue_next
422 * Return the kmsg following the given kmsg.
423 * (Or IKM_NULL if it is the last one in the queue.)
428 ipc_kmsg_queue_t queue
,
433 assert(queue
->ikmq_base
!= IKM_NULL
);
435 next
= kmsg
->ikm_next
;
436 if (queue
->ikmq_base
== next
)
443 * Routine: ipc_kmsg_destroy
445 * Destroys a kernel message. Releases all rights,
446 * references, and memory held by the message.
456 ipc_kmsg_queue_t queue
;
460 * ipc_kmsg_clean can cause more messages to be destroyed.
461 * Curtail recursion by queueing messages. If a message
462 * is already queued, then this is a recursive call.
465 queue
= &(current_thread()->ith_messages
);
466 empty
= ipc_kmsg_queue_empty(queue
);
467 ipc_kmsg_enqueue(queue
, kmsg
);
470 /* must leave kmsg in queue while cleaning it */
472 while ((kmsg
= ipc_kmsg_queue_first(queue
)) != IKM_NULL
) {
473 ipc_kmsg_clean(kmsg
);
474 ipc_kmsg_rmqueue(queue
, kmsg
);
481 * Routine: ipc_kmsg_destroy_dest
483 * Destroys a kernel message. Releases all rights,
484 * references, and memory held by the message (including
485 * the destination port reference.
491 ipc_kmsg_destroy_dest(
496 port
= kmsg
->ikm_header
->msgh_remote_port
;
498 ipc_port_release(port
);
499 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
500 ipc_kmsg_destroy(kmsg
);
504 * Routine: ipc_kmsg_clean_body
506 * Cleans the body of a kernel message.
507 * Releases all rights, references, and memory.
515 __unused ipc_kmsg_t kmsg
,
516 mach_msg_type_number_t number
,
517 mach_msg_descriptor_t
*saddr
)
519 mach_msg_descriptor_t
*eaddr
;
524 eaddr
= saddr
+ number
;
526 for ( ; saddr
< eaddr
; saddr
++ ) {
528 switch (saddr
->type
.type
) {
530 case MACH_MSG_PORT_DESCRIPTOR
: {
531 mach_msg_port_descriptor_t
*dsc
;
536 * Destroy port rights carried in the message
538 if (!IO_VALID((ipc_object_t
) dsc
->name
))
540 ipc_object_destroy((ipc_object_t
) dsc
->name
, dsc
->disposition
);
543 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
544 case MACH_MSG_OOL_DESCRIPTOR
: {
545 mach_msg_ool_descriptor_t
*dsc
;
547 dsc
= &saddr
->out_of_line
;
550 * Destroy memory carried in the message
552 if (dsc
->size
== 0) {
553 assert(dsc
->address
== (void *) 0);
555 vm_map_copy_discard((vm_map_copy_t
) dsc
->address
);
559 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
560 ipc_object_t
*objects
;
561 mach_msg_type_number_t j
;
562 mach_msg_ool_ports_descriptor_t
*dsc
;
564 dsc
= &saddr
->ool_ports
;
565 objects
= (ipc_object_t
*) dsc
->address
;
567 if (dsc
->count
== 0) {
571 assert(objects
!= (ipc_object_t
*) 0);
573 /* destroy port rights carried in the message */
575 for (j
= 0; j
< dsc
->count
; j
++) {
576 ipc_object_t object
= objects
[j
];
578 if (!IO_VALID(object
))
581 ipc_object_destroy(object
, dsc
->disposition
);
584 /* destroy memory carried in the message */
586 assert(dsc
->count
!= 0);
589 (vm_size_t
) dsc
->count
* sizeof(mach_port_name_t
));
593 printf("cleanup: don't understand this type of descriptor\n");
600 * Routine: ipc_kmsg_clean_partial
602 * Cleans a partially-acquired kernel message.
603 * number is the index of the type descriptor
604 * in the body of the message that contained the error.
605 * If dolast, the memory and port rights in this last
606 * type spec are also cleaned. In that case, number
607 * specifies the number of port rights to clean.
613 ipc_kmsg_clean_partial(
615 mach_msg_type_number_t number
,
616 mach_msg_descriptor_t
*desc
,
621 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
623 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
624 assert(IO_VALID(object
));
625 ipc_object_destroy(object
, MACH_MSGH_BITS_REMOTE(mbits
));
627 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
628 if (IO_VALID(object
))
629 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
632 (void) vm_deallocate(ipc_kernel_copy_map
, paddr
, length
);
635 ipc_kmsg_clean_body(kmsg
, number
, desc
);
639 * Routine: ipc_kmsg_clean
641 * Cleans a kernel message. Releases all rights,
642 * references, and memory held by the message.
652 mach_msg_bits_t mbits
;
654 mbits
= kmsg
->ikm_header
->msgh_bits
;
655 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
656 if (IO_VALID(object
))
657 ipc_object_destroy(object
, MACH_MSGH_BITS_REMOTE(mbits
));
659 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
660 if (IO_VALID(object
))
661 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
663 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
664 mach_msg_body_t
*body
;
666 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
667 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
668 (mach_msg_descriptor_t
*)(body
+ 1));
672 if (kmsg
->ikm_sender
!= NULL
) {
673 task_deallocate(kmsg
->ikm_sender
);
674 kmsg
->ikm_sender
= NULL
;
680 * Routine: ipc_kmsg_set_prealloc
682 * Assign a kmsg as a preallocated message buffer to a port.
688 ipc_kmsg_set_prealloc(
692 assert(kmsg
->ikm_prealloc
== IP_NULL
);
694 kmsg
->ikm_prealloc
= IP_NULL
;
695 IP_SET_PREALLOC(port
, kmsg
);
699 * Routine: ipc_kmsg_clear_prealloc
701 * Release the Assignment of a preallocated message buffer from a port.
706 ipc_kmsg_clear_prealloc(
710 assert(kmsg
->ikm_prealloc
== port
);
712 kmsg
->ikm_prealloc
= IP_NULL
;
713 IP_CLEAR_PREALLOC(port
, kmsg
);
719 * Routine: ipc_kmsg_get
721 * Allocates a kernel message buffer.
722 * Copies a user message to the message buffer.
726 * MACH_MSG_SUCCESS Acquired a message buffer.
727 * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
728 * MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
729 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
730 * MACH_SEND_INVALID_DATA Couldn't copy message data.
735 mach_vm_address_t msg_addr
,
736 mach_msg_size_t size
,
739 mach_msg_size_t msg_and_trailer_size
;
741 mach_msg_max_trailer_t
*trailer
;
743 if ((size
< sizeof(mach_msg_header_t
)) || (size
& 3))
744 return MACH_SEND_MSG_TOO_SMALL
;
746 if (size
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
)
747 return MACH_SEND_TOO_LARGE
;
749 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
751 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
753 if (kmsg
== IKM_NULL
)
754 return MACH_SEND_NO_BUFFER
;
756 if (copyinmsg(msg_addr
, (char *) kmsg
->ikm_header
, size
)) {
758 return MACH_SEND_INVALID_DATA
;
761 kmsg
->ikm_header
->msgh_size
= size
;
764 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
765 * However, the internal size field of the trailer (msgh_trailer_size)
766 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
767 * the cases where no implicit data is requested.
769 trailer
= (mach_msg_max_trailer_t
*) ((vm_offset_t
)kmsg
->ikm_header
+ size
);
770 trailer
->msgh_sender
= current_thread()->task
->sec_token
;
771 trailer
->msgh_audit
= current_thread()->task
->audit_token
;
772 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
773 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
776 if(trcWork
.traceMask
) dbgTrace(0x1100, (unsigned int)kmsg
->ikm_header
->msgh_id
,
777 (unsigned int)kmsg
->ikm_header
->msgh_remote_port
,
778 (unsigned int)kmsg
->ikm_header
->msgh_local_port
, 0);
782 /* XXX - why do we zero sender labels here instead of in mach_msg()? */
783 task_t cur
= current_task();
786 kmsg
->ikm_sender
= cur
;
788 trailer
->msgh_labels
.sender
= 0;
790 trailer
->msgh_labels
.sender
= 0;
794 return MACH_MSG_SUCCESS
;
798 * Routine: ipc_kmsg_get_from_kernel
800 * First checks for a preallocated message
801 * reserved for kernel clients. If not found -
802 * allocates a new kernel message buffer.
803 * Copies a kernel message to the message buffer.
804 * Only resource errors are allowed.
807 * Ports in header are ipc_port_t.
809 * MACH_MSG_SUCCESS Acquired a message buffer.
810 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
814 ipc_kmsg_get_from_kernel(
815 mach_msg_header_t
*msg
,
816 mach_msg_size_t size
,
820 mach_msg_size_t msg_and_trailer_size
;
821 mach_msg_max_trailer_t
*trailer
;
822 ipc_port_t dest_port
;
824 assert(size
>= sizeof(mach_msg_header_t
));
825 // assert((size & 3) == 0);
827 assert(IP_VALID((ipc_port_t
) msg
->msgh_remote_port
));
828 dest_port
= (ipc_port_t
)msg
->msgh_remote_port
;
830 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
833 * See if the port has a pre-allocated kmsg for kernel
834 * clients. These are set up for those kernel clients
835 * which cannot afford to wait.
837 if (IP_PREALLOC(dest_port
)) {
839 if (!ip_active(dest_port
)) {
840 ip_unlock(dest_port
);
841 return MACH_SEND_NO_BUFFER
;
843 assert(IP_PREALLOC(dest_port
));
844 kmsg
= dest_port
->ip_premsg
;
845 if (msg_and_trailer_size
> kmsg
->ikm_size
) {
846 ip_unlock(dest_port
);
847 return MACH_SEND_TOO_LARGE
;
849 if (ikm_prealloc_inuse(kmsg
)) {
850 ip_unlock(dest_port
);
851 return MACH_SEND_NO_BUFFER
;
853 ikm_prealloc_set_inuse(kmsg
, dest_port
);
854 ip_unlock(dest_port
);
856 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
857 if (kmsg
== IKM_NULL
)
858 return MACH_SEND_NO_BUFFER
;
861 (void) memcpy((void *) kmsg
->ikm_header
, (const void *) msg
, size
);
863 kmsg
->ikm_header
->msgh_size
= size
;
866 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
867 * However, the internal size field of the trailer (msgh_trailer_size)
868 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
869 * optimize the cases where no implicit data is requested.
871 trailer
= (mach_msg_max_trailer_t
*)
872 ((vm_offset_t
)kmsg
->ikm_header
+ size
);
873 trailer
->msgh_sender
= KERNEL_SECURITY_TOKEN
;
874 trailer
->msgh_audit
= KERNEL_AUDIT_TOKEN
;
875 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
876 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
878 trailer
->msgh_labels
.sender
= 0;
881 kmsg
->ikm_sender
= NULL
;
884 return MACH_MSG_SUCCESS
;
888 * Routine: ipc_kmsg_send
890 * Send a message. The message holds a reference
891 * for the destination port in the msgh_remote_port field.
893 * If unsuccessful, the caller still has possession of
894 * the message and must do something with it. If successful,
895 * the message is queued, given to a receiver, destroyed,
896 * or handled directly by the kernel via mach_msg.
900 * MACH_MSG_SUCCESS The message was accepted.
901 * MACH_SEND_TIMED_OUT Caller still has message.
902 * MACH_SEND_INTERRUPTED Caller still has message.
907 mach_msg_option_t option
,
908 mach_msg_timeout_t send_timeout
)
912 port
= (ipc_port_t
) kmsg
->ikm_header
->msgh_remote_port
;
913 assert(IP_VALID(port
));
915 if ((option
& ~(MACH_SEND_TIMEOUT
|MACH_SEND_ALWAYS
)) != 0)
916 printf("ipc_kmsg_send: bad option 0x%x\n", option
);
920 if (port
->ip_receiver
== ipc_space_kernel
) {
923 * We can check ip_receiver == ipc_space_kernel
924 * before checking that the port is active because
925 * ipc_port_dealloc_kernel clears ip_receiver
926 * before destroying a kernel port.
928 assert(ip_active(port
));
929 port
->ip_messages
.imq_seqno
++;
932 current_task()->messages_sent
++;
935 * Call the server routine, and get the reply message to send.
937 kmsg
= ipc_kobject_server(kmsg
);
938 if (kmsg
== IKM_NULL
)
939 return MACH_MSG_SUCCESS
;
941 port
= (ipc_port_t
) kmsg
->ikm_header
->msgh_remote_port
;
942 assert(IP_VALID(port
));
944 /* fall thru with reply - same options */
948 * Can't deliver to a dead port.
949 * However, we can pretend it got sent
950 * and was then immediately destroyed.
952 if (!ip_active(port
)) {
954 * We can't let ipc_kmsg_destroy deallocate
955 * the port right, because we might end up
956 * in an infinite loop trying to deliver
957 * a send-once notification.
961 ip_check_unlock(port
);
962 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
963 ipc_kmsg_destroy(kmsg
);
964 return MACH_MSG_SUCCESS
;
967 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_CIRCULAR
) {
970 /* don't allow the creation of a circular loop */
972 ipc_kmsg_destroy(kmsg
);
973 return MACH_MSG_SUCCESS
;
977 * We have a valid message and a valid reference on the port.
978 * we can unlock the port and call mqueue_send() on it's message
982 return (ipc_mqueue_send(&port
->ip_messages
, kmsg
, option
, send_timeout
));
986 * Routine: ipc_kmsg_put
988 * Copies a message buffer to a user message.
989 * Copies only the specified number of bytes.
990 * Frees the message buffer.
992 * Nothing locked. The message buffer must have clean
995 * MACH_MSG_SUCCESS Copied data out of message buffer.
996 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
1001 mach_vm_address_t msg_addr
,
1003 mach_msg_size_t size
)
1005 mach_msg_return_t mr
;
1007 if (copyoutmsg((const char *) kmsg
->ikm_header
, msg_addr
, size
))
1008 mr
= MACH_RCV_INVALID_DATA
;
1010 mr
= MACH_MSG_SUCCESS
;
1012 ipc_kmsg_free(kmsg
);
1017 * Routine: ipc_kmsg_put_to_kernel
1019 * Copies a message buffer to a kernel message.
1020 * Frees the message buffer.
1021 * No errors allowed.
1027 ipc_kmsg_put_to_kernel(
1028 mach_msg_header_t
*msg
,
1030 mach_msg_size_t size
)
1032 (void) memcpy((void *) msg
, (const void *) kmsg
->ikm_header
, size
);
1034 ipc_kmsg_free(kmsg
);
1038 * Routine: ipc_kmsg_copyin_header
1040 * "Copy-in" port rights in the header of a message.
1041 * Operates atomically; if it doesn't succeed the
1042 * message header and the space are left untouched.
1043 * If it does succeed the remote/local port fields
1044 * contain object pointers instead of port names,
1045 * and the bits field is updated. The destination port
1046 * will be a valid port pointer.
1048 * The notify argument implements the MACH_SEND_CANCEL option.
1049 * If it is not MACH_PORT_NULL, it should name a receive right.
1050 * If the processing of the destination port would generate
1051 * a port-deleted notification (because the right for the
1052 * destination port is destroyed and it had a request for
1053 * a dead-name notification registered), and the port-deleted
1054 * notification would be sent to the named receive right,
1055 * then it isn't sent and the send-once right for the notify
1056 * port is quietly destroyed.
1061 * MACH_MSG_SUCCESS Successful copyin.
1062 * MACH_SEND_INVALID_HEADER
1063 * Illegal value in the message header bits.
1064 * MACH_SEND_INVALID_DEST The space is dead.
1065 * MACH_SEND_INVALID_NOTIFY
1066 * Notify is non-null and doesn't name a receive right.
1067 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1068 * MACH_SEND_INVALID_DEST Can't copyin destination port.
1069 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1070 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
1071 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1075 ipc_kmsg_copyin_header(
1076 mach_msg_header_t
*msg
,
1078 mach_port_name_t notify
)
1080 mach_msg_bits_t mbits
= msg
->msgh_bits
& MACH_MSGH_BITS_USER
;
1081 mach_port_name_t dest_name
= (mach_port_name_t
)msg
->msgh_remote_port
;
1082 mach_port_name_t reply_name
= (mach_port_name_t
)msg
->msgh_local_port
;
1085 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
1086 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
1087 ipc_object_t dest_port
, reply_port
;
1088 ipc_port_t dest_soright
, reply_soright
;
1089 ipc_port_t notify_port
;
1092 if ((mbits
!= msg
->msgh_bits
) ||
1093 (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type
)) ||
1094 ((reply_type
== 0) ?
1095 (reply_name
!= MACH_PORT_NULL
) :
1096 !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type
)))
1097 return MACH_SEND_INVALID_HEADER
;
1099 reply_soright
= IP_NULL
; /* in case we go to invalid dest early */
1101 is_write_lock(space
);
1102 if (!space
->is_active
)
1105 if (!MACH_PORT_VALID(dest_name
))
1108 #if CONFIG_MACF_MACH
1110 * We do the port send check here instead of in ipc_kmsg_send()
1111 * because copying the header involves copying the port rights too
1112 * and we need to do the send check before anything is actually copied.
1114 entry
= ipc_entry_lookup(space
, dest_name
);
1115 if (entry
!= IE_NULL
) {
1117 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
1118 if (port
== IP_NULL
)
1121 if (ip_active(port
)) {
1122 task_t self
= current_task();
1123 tasklabel_lock(self
);
1124 error
= mac_port_check_send(&self
->maclabel
,
1126 tasklabel_unlock(self
);
1134 if (notify
!= MACH_PORT_NULL
) {
1135 if ((entry
= ipc_entry_lookup(space
, notify
)) == IE_NULL
) {
1136 is_write_unlock(space
);
1137 return MACH_SEND_INVALID_NOTIFY
;
1139 if((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1140 is_write_unlock(space
);
1141 return MACH_SEND_INVALID_NOTIFY
;
1144 notify_port
= (ipc_port_t
) entry
->ie_object
;
1146 notify_port
= IP_NULL
;
1148 if (dest_name
== reply_name
) {
1149 mach_port_name_t name
= dest_name
;
1152 * Destination and reply ports are the same!
1153 * This is a little tedious to make atomic, because
1154 * there are 25 combinations of dest_type/reply_type.
1155 * However, most are easy. If either is move-sonce,
1156 * then there must be an error. If either are
1157 * make-send or make-sonce, then we must be looking
1158 * at a receive right so the port can't die.
1159 * The hard cases are the combinations of
1160 * copy-send and make-send.
1163 entry
= ipc_entry_lookup(space
, name
);
1164 if (entry
== IE_NULL
)
1167 assert(reply_type
!= 0); /* because name not null */
1169 if (!ipc_right_copyin_check(space
, name
, entry
, reply_type
))
1172 if ((dest_type
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) ||
1173 (reply_type
== MACH_MSG_TYPE_MOVE_SEND_ONCE
)) {
1175 * Why must there be an error? To get a valid
1176 * destination, this entry must name a live
1177 * port (not a dead name or dead port). However
1178 * a successful move-sonce will destroy a
1179 * live entry. Therefore the other copyin,
1180 * whatever it is, would fail. We've already
1181 * checked for reply port errors above,
1182 * so report a destination error.
1186 } else if ((dest_type
== MACH_MSG_TYPE_MAKE_SEND
) ||
1187 (dest_type
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) ||
1188 (reply_type
== MACH_MSG_TYPE_MAKE_SEND
) ||
1189 (reply_type
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) {
1190 kr
= ipc_right_copyin(space
, name
, entry
,
1192 &dest_port
, &dest_soright
);
1193 if (kr
!= KERN_SUCCESS
)
1197 * Either dest or reply needs a receive right.
1198 * We know the receive right is there, because
1199 * of the copyin_check and copyin calls. Hence
1200 * the port is not in danger of dying. If dest
1201 * used the receive right, then the right needed
1202 * by reply (and verified by copyin_check) will
1206 assert(IO_VALID(dest_port
));
1207 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
1208 assert(dest_soright
== IP_NULL
);
1210 kr
= ipc_right_copyin(space
, name
, entry
,
1212 &reply_port
, &reply_soright
);
1214 assert(kr
== KERN_SUCCESS
);
1215 assert(reply_port
== dest_port
);
1216 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
1217 assert(reply_soright
== IP_NULL
);
1218 } else if ((dest_type
== MACH_MSG_TYPE_COPY_SEND
) &&
1219 (reply_type
== MACH_MSG_TYPE_COPY_SEND
)) {
1221 * To make this atomic, just do one copy-send,
1222 * and dup the send right we get out.
1225 kr
= ipc_right_copyin(space
, name
, entry
,
1227 &dest_port
, &dest_soright
);
1228 if (kr
!= KERN_SUCCESS
)
1231 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND
);
1232 assert(dest_soright
== IP_NULL
);
1235 * It's OK if the port we got is dead now,
1236 * so reply_port is IP_DEAD, because the msg
1237 * won't go anywhere anyway.
1240 reply_port
= (ipc_object_t
)
1241 ipc_port_copy_send((ipc_port_t
) dest_port
);
1242 reply_soright
= IP_NULL
;
1243 } else if ((dest_type
== MACH_MSG_TYPE_MOVE_SEND
) &&
1244 (reply_type
== MACH_MSG_TYPE_MOVE_SEND
)) {
1246 * This is an easy case. Just use our
1247 * handy-dandy special-purpose copyin call
1248 * to get two send rights for the price of one.
1251 kr
= ipc_right_copyin_two(space
, name
, entry
,
1252 &dest_port
, &dest_soright
);
1253 if (kr
!= KERN_SUCCESS
)
1256 /* the entry might need to be deallocated */
1257 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1258 ipc_entry_dealloc(space
, name
, entry
);
1260 reply_port
= dest_port
;
1261 reply_soright
= IP_NULL
;
1265 assert(((dest_type
== MACH_MSG_TYPE_COPY_SEND
) &&
1266 (reply_type
== MACH_MSG_TYPE_MOVE_SEND
)) ||
1267 ((dest_type
== MACH_MSG_TYPE_MOVE_SEND
) &&
1268 (reply_type
== MACH_MSG_TYPE_COPY_SEND
)));
1271 * To make this atomic, just do a move-send,
1272 * and dup the send right we get out.
1275 kr
= ipc_right_copyin(space
, name
, entry
,
1276 MACH_MSG_TYPE_MOVE_SEND
, FALSE
,
1277 &dest_port
, &soright
);
1278 if (kr
!= KERN_SUCCESS
)
1281 /* the entry might need to be deallocated */
1283 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1284 ipc_entry_dealloc(space
, name
, entry
);
1287 * It's OK if the port we got is dead now,
1288 * so reply_port is IP_DEAD, because the msg
1289 * won't go anywhere anyway.
1292 reply_port
= (ipc_object_t
)
1293 ipc_port_copy_send((ipc_port_t
) dest_port
);
1295 if (dest_type
== MACH_MSG_TYPE_MOVE_SEND
) {
1296 dest_soright
= soright
;
1297 reply_soright
= IP_NULL
;
1299 dest_soright
= IP_NULL
;
1300 reply_soright
= soright
;
1303 } else if (!MACH_PORT_VALID(reply_name
)) {
1305 * No reply port! This is an easy case
1306 * to make atomic. Just copyin the destination.
1309 entry
= ipc_entry_lookup(space
, dest_name
);
1310 if (entry
== IE_NULL
)
1313 kr
= ipc_right_copyin(space
, dest_name
, entry
,
1315 &dest_port
, &dest_soright
);
1316 if (kr
!= KERN_SUCCESS
)
1319 /* the entry might need to be deallocated */
1321 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1322 ipc_entry_dealloc(space
, dest_name
, entry
);
1324 reply_port
= (ipc_object_t
) reply_name
;
1325 reply_soright
= IP_NULL
;
1327 ipc_entry_t dest_entry
, reply_entry
;
1330 * This is the tough case to make atomic.
1331 * The difficult problem is serializing with port death.
1332 * At the time we copyin dest_port, it must be alive.
1333 * If reply_port is alive when we copyin it, then
1334 * we are OK, because we serialize before the death
1335 * of both ports. Assume reply_port is dead at copyin.
1336 * Then if dest_port dies/died after reply_port died,
1337 * we are OK, because we serialize between the death
1338 * of the two ports. So the bad case is when dest_port
1339 * dies after its copyin, reply_port dies before its
1340 * copyin, and dest_port dies before reply_port. Then
1341 * the copyins operated as if dest_port was alive
1342 * and reply_port was dead, which shouldn't have happened
1343 * because they died in the other order.
1345 * Note that it is easy for a user task to tell if
1346 * a copyin happened before or after a port died.
1347 * For example, suppose both dest and reply are
1348 * send-once rights (types are both move-sonce) and
1349 * both rights have dead-name requests registered.
1350 * If a port dies before copyin, a dead-name notification
1351 * is generated and the dead name's urefs are incremented,
1352 * and if the copyin happens first, a port-deleted
1353 * notification is generated.
1355 * Note that although the entries are different,
1356 * dest_port and reply_port might still be the same.
1358 * JMM - The code to handle this was too expensive and, anyway,
1359 * we intend to separate the dest lookup from the reply copyin
1360 * by a wide margin, so the user will have to learn to deal!
1361 * I will be making the change soon!
1364 dest_entry
= ipc_entry_lookup(space
, dest_name
);
1365 if (dest_entry
== IE_NULL
)
1368 reply_entry
= ipc_entry_lookup(space
, reply_name
);
1369 if (reply_entry
== IE_NULL
)
1372 assert(dest_entry
!= reply_entry
); /* names are not equal */
1373 assert(reply_type
!= 0); /* because reply_name not null */
1375 if (!ipc_right_copyin_check(space
, reply_name
, reply_entry
,
1379 kr
= ipc_right_copyin(space
, dest_name
, dest_entry
,
1381 &dest_port
, &dest_soright
);
1382 if (kr
!= KERN_SUCCESS
)
1385 assert(IO_VALID(dest_port
));
1387 kr
= ipc_right_copyin(space
, reply_name
, reply_entry
,
1389 &reply_port
, &reply_soright
);
1391 assert(kr
== KERN_SUCCESS
);
1393 /* the entries might need to be deallocated */
1395 if (IE_BITS_TYPE(reply_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1396 ipc_entry_dealloc(space
, reply_name
, reply_entry
);
1398 if (IE_BITS_TYPE(dest_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1399 ipc_entry_dealloc(space
, dest_name
, dest_entry
);
1403 * At this point, dest_port, reply_port,
1404 * dest_soright, reply_soright are all initialized.
1405 * Any defunct entries have been deallocated.
1406 * The space is still write-locked, and we need to
1407 * make the MACH_SEND_CANCEL check. The notify_port pointer
1408 * is still usable, because the copyin code above won't ever
1409 * deallocate a receive right, so its entry still exists
1410 * and holds a ref. Note notify_port might even equal
1411 * dest_port or reply_port.
1414 if ((notify
!= MACH_PORT_NULL
) &&
1415 (dest_soright
== notify_port
)) {
1416 ipc_port_release_sonce(dest_soright
);
1417 dest_soright
= IP_NULL
;
1420 is_write_unlock(space
);
1422 if (dest_soright
!= IP_NULL
)
1423 ipc_notify_port_deleted(dest_soright
, dest_name
);
1425 if (reply_soright
!= IP_NULL
)
1426 ipc_notify_port_deleted(reply_soright
, reply_name
);
1428 dest_type
= ipc_object_copyin_type(dest_type
);
1429 reply_type
= ipc_object_copyin_type(reply_type
);
1431 msg
->msgh_bits
= (MACH_MSGH_BITS_OTHER(mbits
) |
1432 MACH_MSGH_BITS(dest_type
, reply_type
));
1433 msg
->msgh_remote_port
= (ipc_port_t
)dest_port
;
1434 msg
->msgh_local_port
= (ipc_port_t
)reply_port
;
1436 return MACH_MSG_SUCCESS
;
1439 is_write_unlock(space
);
1440 return MACH_SEND_INVALID_REPLY
;
1443 is_write_unlock(space
);
1444 if (reply_soright
!= IP_NULL
)
1445 ipc_notify_port_deleted(reply_soright
, reply_name
);
1446 return MACH_SEND_INVALID_DEST
;
1450 * Routine: ipc_kmsg_copyin_body
1452 * "Copy-in" port rights and out-of-line memory
1453 * in the message body.
1455 * In all failure cases, the message is left holding
1456 * no rights or memory. However, the message buffer
1457 * is not deallocated. If successful, the message
1458 * contains a valid destination port.
1462 * MACH_MSG_SUCCESS Successful copyin.
1463 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
1464 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
1465 * MACH_SEND_INVALID_TYPE Bad type specification.
1466 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
1467 * MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
1468 * MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
1471 #define DESC_COUNT_SMALL 64
1474 ipc_kmsg_copyin_body(
1480 mach_msg_body_t
*body
;
1481 mach_msg_descriptor_t
*daddr
, *naddr
;
1482 mach_msg_type_number_t dsc_count
;
1483 boolean_t differs
= MAP_SIZE_DIFFERS(map
);
1484 boolean_t
complex = FALSE
;
1485 vm_size_t space_needed
= 0;
1486 vm_size_t desc_size_space
[DESC_COUNT_SMALL
];
1487 vm_size_t
*user_desc_sizes
= NULL
;
1488 vm_offset_t paddr
= 0;
1489 vm_map_copy_t copy
= VM_MAP_COPY_NULL
;
1491 mach_msg_type_number_t i
;
1492 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
1495 * Determine if the target is a kernel port.
1497 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
1498 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
1499 naddr
= (mach_msg_descriptor_t
*) (body
+ 1);
1501 dsc_count
= body
->msgh_descriptor_count
;
1503 return MACH_MSG_SUCCESS
;
1506 user_desc_sizes
= (dsc_count
<= DESC_COUNT_SMALL
) ?
1507 &desc_size_space
: kalloc(dsc_count
* sizeof(vm_size_t
));
1508 if (user_desc_sizes
== NULL
) {
1509 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
1510 return KERN_RESOURCE_SHORTAGE
;
1515 * Make an initial pass to determine kernal VM space requirements for
1516 * physical copies and possible contraction of the descriptors from
1517 * processes with pointers larger than the kernel's.
1520 for (i
= 0; i
< dsc_count
; i
++) {
1523 /* make sure the descriptor fits in the message */
1525 switch (daddr
->type
.type
) {
1526 case MACH_MSG_OOL_DESCRIPTOR
:
1527 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
1528 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
1529 user_desc_sizes
[i
] = sizeof(OTHER_OOL_DESCRIPTOR
);
1532 user_desc_sizes
[i
] = sizeof(*daddr
);
1535 naddr
= (mach_msg_descriptor_t
*)
1536 ((vm_offset_t
)daddr
+ user_desc_sizes
[i
]);
1541 if (naddr
> (mach_msg_descriptor_t
*)
1542 ((vm_offset_t
)kmsg
->ikm_header
+ kmsg
->ikm_header
->msgh_size
)) {
1543 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
1544 mr
= MACH_SEND_MSG_TOO_SMALL
;
1548 switch (daddr
->type
.type
) {
1549 mach_msg_size_t size
;
1551 case MACH_MSG_OOL_DESCRIPTOR
:
1552 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
1554 ((OTHER_OOL_DESCRIPTOR
*)daddr
)->size
:
1555 daddr
->out_of_line
.size
;
1557 if (daddr
->out_of_line
.copy
!= MACH_MSG_PHYSICAL_COPY
&&
1558 daddr
->out_of_line
.copy
!= MACH_MSG_VIRTUAL_COPY
) {
1560 * Invalid copy option
1562 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
1563 mr
= MACH_SEND_INVALID_TYPE
;
1567 if ((size
>= MSG_OOL_SIZE_SMALL
) &&
1568 (daddr
->out_of_line
.copy
== MACH_MSG_PHYSICAL_COPY
) &&
1569 !(daddr
->out_of_line
.deallocate
)) {
1572 * Out-of-line memory descriptor, accumulate kernel
1573 * memory requirements
1575 space_needed
+= round_page(size
);
1576 if (space_needed
> ipc_kmsg_max_vm_space
) {
1579 * Per message kernel memory limit exceeded
1581 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
1582 mr
= MACH_MSG_VM_KERNEL
;
1590 * Allocate space in the pageable kernel ipc copy map for all the
1591 * ool data that is to be physically copied. Map is marked wait for
1595 if (vm_allocate(ipc_kernel_copy_map
, &paddr
, space_needed
, VM_FLAGS_ANYWHERE
) !=
1597 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
1598 mr
= MACH_MSG_VM_KERNEL
;
1604 * handle the OOL regions and port descriptors.
1605 * We process them in reverse order starting with the last one
1606 * scanned above. That way, we can compact them up against
1607 * the message body (if the user-descriptor size is larger than
1608 * the kernel representation).
1613 switch (daddr
->type
.type
) {
1615 /* port descriptors are the same size everywhere, how nice */
1616 case MACH_MSG_PORT_DESCRIPTOR
: {
1617 mach_msg_type_name_t user_disp
;
1618 mach_msg_type_name_t result_disp
;
1619 mach_port_name_t name
;
1620 ipc_object_t object
;
1621 volatile mach_msg_port_descriptor_t
*dsc
;
1622 volatile mach_msg_port_descriptor_t
*user_dsc
;
1624 user_dsc
= &daddr
->port
;
1627 user_disp
= user_dsc
->disposition
;
1628 result_disp
= ipc_object_copyin_type(user_disp
);
1630 name
= (mach_port_name_t
)user_dsc
->name
;
1631 if (MACH_PORT_VALID(name
)) {
1633 kr
= ipc_object_copyin(space
, name
, user_disp
, &object
);
1634 if (kr
!= KERN_SUCCESS
) {
1635 mr
= MACH_SEND_INVALID_RIGHT
;
1639 if ((result_disp
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
1640 ipc_port_check_circularity((ipc_port_t
) object
,
1641 (ipc_port_t
) dest
)) {
1642 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
1644 dsc
->name
= (ipc_port_t
) object
;
1646 dsc
->name
= (mach_port_t
)name
;
1648 dsc
->disposition
= result_disp
;
1649 dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
1654 /* out of line descriptors differ in size between 32 and 64 bit processes */
1655 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
1656 case MACH_MSG_OOL_DESCRIPTOR
: {
1659 mach_msg_copy_options_t copy_options
;
1660 mach_vm_offset_t addr
;
1661 mach_msg_descriptor_type_t dsc_type
;
1663 volatile mach_msg_ool_descriptor_t
*dsc
;
1666 volatile OTHER_OOL_DESCRIPTOR
*user_dsc
;
1668 user_dsc
= (OTHER_OOL_DESCRIPTOR
*)&daddr
->out_of_line
;
1669 addr
= (mach_vm_offset_t
) user_dsc
->address
;
1670 length
= user_dsc
->size
;
1671 dealloc
= user_dsc
->deallocate
;
1672 copy_options
= user_dsc
->copy
;
1673 dsc_type
= user_dsc
->type
;
1675 volatile mach_msg_ool_descriptor_t
*user_dsc
;
1677 user_dsc
= &daddr
->out_of_line
;
1678 addr
= CAST_USER_ADDR_T(user_dsc
->address
);
1679 dealloc
= user_dsc
->deallocate
;
1680 copy_options
= user_dsc
->copy
;
1681 dsc_type
= user_dsc
->type
;
1682 length
= user_dsc
->size
;
1685 dsc
= &naddr
->out_of_line
;
1687 dsc
->deallocate
= dealloc
;
1688 dsc
->copy
= copy_options
;
1689 dsc
->type
= dsc_type
;
1692 dsc
->address
= NULL
;
1693 } else if ((length
>= MSG_OOL_SIZE_SMALL
) &&
1694 (copy_options
== MACH_MSG_PHYSICAL_COPY
) && !dealloc
) {
1697 * If the request is a physical copy and the source
1698 * is not being deallocated, then allocate space
1699 * in the kernel's pageable ipc copy map and copy
1700 * the data in. The semantics guarantee that the
1701 * data will have been physically copied before
1702 * the send operation terminates. Thus if the data
1703 * is not being deallocated, we must be prepared
1704 * to page if the region is sufficiently large.
1706 if (copyin(addr
, (char *) paddr
, length
)) {
1707 mr
= MACH_SEND_INVALID_MEMORY
;
1712 * The kernel ipc copy map is marked no_zero_fill.
1713 * If the transfer is not a page multiple, we need
1714 * to zero fill the balance.
1716 if (!page_aligned(length
)) {
1717 (void) memset((void *) (paddr
+ length
), 0,
1718 round_page(length
) - length
);
1720 if (vm_map_copyin(ipc_kernel_copy_map
, (vm_map_address_t
)paddr
,
1721 (vm_map_size_t
)length
, TRUE
, ©
) != KERN_SUCCESS
) {
1722 mr
= MACH_MSG_VM_KERNEL
;
1725 dsc
->address
= (void *) copy
;
1726 paddr
+= round_page(length
);
1727 space_needed
-= round_page(length
);
1731 * Make a vm_map_copy_t of the of the data. If the
1732 * data is small, this will do an optimized physical
1733 * copy. Otherwise, it will do a virtual copy.
1735 * NOTE: A virtual copy is OK if the original is being
1736 * deallocted, even if a physical copy was requested.
1738 kr
= vm_map_copyin(map
, addr
,
1739 (vm_map_size_t
)length
, dealloc
, ©
);
1740 if (kr
!= KERN_SUCCESS
) {
1741 mr
= (kr
== KERN_RESOURCE_SHORTAGE
) ?
1742 MACH_MSG_VM_KERNEL
:
1743 MACH_SEND_INVALID_MEMORY
;
1746 dsc
->address
= (void *) copy
;
1751 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
1754 ipc_object_t
*objects
;
1756 mach_vm_offset_t addr
;
1757 mach_msg_type_name_t user_disp
;
1758 mach_msg_type_name_t result_disp
;
1759 mach_msg_type_number_t count
;
1760 mach_msg_copy_options_t copy_option
;
1761 boolean_t deallocate
;
1763 volatile mach_msg_ool_ports_descriptor_t
*dsc
;
1766 volatile OTHER_OOL_PORTS_DESCRIPTOR
*user_dsc
;
1768 user_dsc
= (OTHER_OOL_PORTS_DESCRIPTOR
*)&daddr
->ool_ports
;
1769 addr
= (mach_vm_offset_t
)user_dsc
->address
;
1770 count
= user_dsc
->count
;
1771 deallocate
= user_dsc
->deallocate
;
1772 copy_option
= user_dsc
->copy
;
1773 user_disp
= user_dsc
->disposition
;
1775 volatile mach_msg_ool_ports_descriptor_t
*user_dsc
;
1777 user_dsc
= &daddr
->ool_ports
;
1778 addr
= CAST_USER_ADDR_T(user_dsc
->address
);
1779 count
= user_dsc
->count
;
1780 deallocate
= user_dsc
->deallocate
;
1781 copy_option
= user_dsc
->copy
;
1782 user_disp
= user_dsc
->disposition
;
1785 dsc
= &naddr
->ool_ports
;
1786 dsc
->deallocate
= deallocate
;
1787 dsc
->copy
= copy_option
;
1788 dsc
->type
= daddr
->type
.type
;
1790 dsc
->address
= NULL
; /* for now */
1792 result_disp
= ipc_object_copyin_type(user_disp
);
1793 dsc
->disposition
= result_disp
;
1795 /* calculate length of data in bytes, rounding up */
1796 length
= count
* sizeof(mach_port_name_t
);
1803 data
= kalloc(length
);
1806 mr
= MACH_SEND_NO_BUFFER
;
1810 if (copyinmap(map
, addr
, data
, length
) != KERN_SUCCESS
) {
1811 kfree(data
, length
);
1812 mr
= MACH_SEND_INVALID_MEMORY
;
1817 (void) mach_vm_deallocate(map
, addr
, (mach_vm_size_t
)length
);
1820 objects
= (ipc_object_t
*) data
;
1821 dsc
->address
= data
;
1823 for ( j
= 0; j
< count
; j
++) {
1824 mach_port_name_t port
= (mach_port_name_t
) objects
[j
];
1825 ipc_object_t object
;
1827 if (!MACH_PORT_VALID(port
))
1830 kr
= ipc_object_copyin(space
, port
, user_disp
, &object
);
1832 if (kr
!= KERN_SUCCESS
) {
1835 for(k
= 0; k
< j
; k
++) {
1836 object
= objects
[k
];
1837 if (IPC_OBJECT_VALID(object
))
1838 ipc_object_destroy(object
, result_disp
);
1840 kfree(data
, length
);
1841 dsc
->address
= NULL
;
1842 mr
= MACH_SEND_INVALID_RIGHT
;
1846 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
1847 ipc_port_check_circularity(
1848 (ipc_port_t
) object
,
1850 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
1852 objects
[j
] = object
;
1860 * Invalid descriptor
1862 mr
= MACH_SEND_INVALID_TYPE
;
1867 if (MACH_MSG_SUCCESS
!= mr
) {
1868 ipc_kmsg_clean_partial(kmsg
, dsc_count
- i
,
1869 naddr
+ 1, paddr
, space_needed
);
1875 (daddr
= (differs
) ? (mach_msg_descriptor_t
*)((vm_offset_t
)(daddr
) -
1876 user_desc_sizes
[i
- 1]) : daddr
- 1)
1881 kmsg
->ikm_header
->msgh_bits
&= ~MACH_MSGH_BITS_COMPLEX
;
1884 if (differs
&& naddr
!= daddr
) {
1885 mach_msg_base_t
*old_base
= (mach_msg_base_t
*)kmsg
->ikm_header
;
1886 mach_msg_base_t
*new_base
= (mach_msg_base_t
*)naddr
- 1;
1888 memmove(new_base
, old_base
, sizeof(mach_msg_base_t
));
1889 new_base
->header
.msgh_size
-= (vm_offset_t
)naddr
- (vm_offset_t
)daddr
;
1890 kmsg
->ikm_header
= &new_base
->header
;
1894 if (differs
&& dsc_count
> DESC_COUNT_SMALL
)
1895 kfree(user_desc_sizes
, body
->msgh_descriptor_count
* sizeof(vm_size_t
));
1902 * Routine: ipc_kmsg_copyin
1904 * "Copy-in" port rights and out-of-line memory
1907 * In all failure cases, the message is left holding
1908 * no rights or memory. However, the message buffer
1909 * is not deallocated. If successful, the message
1910 * contains a valid destination port.
1914 * MACH_MSG_SUCCESS Successful copyin.
1915 * MACH_SEND_INVALID_HEADER
1916 * Illegal value in the message header bits.
1917 * MACH_SEND_INVALID_NOTIFY Bad notify port.
1918 * MACH_SEND_INVALID_DEST Can't copyin destination port.
1919 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
1920 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
1921 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
1922 * MACH_SEND_INVALID_TYPE Bad type specification.
1923 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
1931 mach_port_name_t notify
)
1933 mach_msg_return_t mr
;
1935 mr
= ipc_kmsg_copyin_header(kmsg
->ikm_header
, space
, notify
);
1936 if (mr
!= MACH_MSG_SUCCESS
)
1939 if ((kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
1940 return MACH_MSG_SUCCESS
;
1942 return( ipc_kmsg_copyin_body( kmsg
, space
, map
) );
1946 * Routine: ipc_kmsg_copyin_from_kernel
1948 * "Copy-in" port rights and out-of-line memory
1949 * in a message sent from the kernel.
1951 * Because the message comes from the kernel,
1952 * the implementation assumes there are no errors
1953 * or peculiarities in the message.
1955 * Returns TRUE if queueing the message
1956 * would result in a circularity.
1962 ipc_kmsg_copyin_from_kernel(
1965 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
1966 mach_msg_type_name_t rname
= MACH_MSGH_BITS_REMOTE(bits
);
1967 mach_msg_type_name_t lname
= MACH_MSGH_BITS_LOCAL(bits
);
1968 ipc_object_t remote
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
1969 ipc_object_t local
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
1971 /* translate the destination and reply ports */
1973 ipc_object_copyin_from_kernel(remote
, rname
);
1974 if (IO_VALID(local
))
1975 ipc_object_copyin_from_kernel(local
, lname
);
1978 * The common case is a complex message with no reply port,
1979 * because that is what the memory_object interface uses.
1982 if (bits
== (MACH_MSGH_BITS_COMPLEX
|
1983 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0))) {
1984 bits
= (MACH_MSGH_BITS_COMPLEX
|
1985 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND
, 0));
1987 kmsg
->ikm_header
->msgh_bits
= bits
;
1989 bits
= (MACH_MSGH_BITS_OTHER(bits
) |
1990 MACH_MSGH_BITS(ipc_object_copyin_type(rname
),
1991 ipc_object_copyin_type(lname
)));
1993 kmsg
->ikm_header
->msgh_bits
= bits
;
1994 if ((bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
1998 mach_msg_descriptor_t
*saddr
, *eaddr
;
1999 mach_msg_body_t
*body
;
2001 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
2002 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
2003 eaddr
= (mach_msg_descriptor_t
*) saddr
+ body
->msgh_descriptor_count
;
2005 for ( ; saddr
< eaddr
; saddr
++) {
2007 switch (saddr
->type
.type
) {
2009 case MACH_MSG_PORT_DESCRIPTOR
: {
2010 mach_msg_type_name_t name
;
2011 ipc_object_t object
;
2012 mach_msg_port_descriptor_t
*dsc
;
2016 /* this is really the type SEND, SEND_ONCE, etc. */
2017 name
= dsc
->disposition
;
2018 object
= (ipc_object_t
) dsc
->name
;
2019 dsc
->disposition
= ipc_object_copyin_type(name
);
2021 if (!IO_VALID(object
)) {
2025 ipc_object_copyin_from_kernel(object
, name
);
2027 /* CDY avoid circularity when the destination is also */
2028 /* the kernel. This check should be changed into an */
2029 /* assert when the new kobject model is in place since*/
2030 /* ports will not be used in kernel to kernel chats */
2032 if (((ipc_port_t
)remote
)->ip_receiver
!= ipc_space_kernel
) {
2033 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2034 ipc_port_check_circularity((ipc_port_t
) object
,
2035 (ipc_port_t
) remote
)) {
2036 kmsg
->ikm_header
->msgh_bits
|=
2037 MACH_MSGH_BITS_CIRCULAR
;
2042 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2043 case MACH_MSG_OOL_DESCRIPTOR
: {
2045 * The sender should supply ready-made memory, i.e.
2046 * a vm_map_copy_t, so we don't need to do anything.
2050 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
2051 ipc_object_t
*objects
;
2053 mach_msg_type_name_t name
;
2054 mach_msg_ool_ports_descriptor_t
*dsc
;
2056 dsc
= &saddr
->ool_ports
;
2058 /* this is really the type SEND, SEND_ONCE, etc. */
2059 name
= dsc
->disposition
;
2060 dsc
->disposition
= ipc_object_copyin_type(name
);
2062 objects
= (ipc_object_t
*) dsc
->address
;
2064 for ( j
= 0; j
< dsc
->count
; j
++) {
2065 ipc_object_t object
= objects
[j
];
2067 if (!IO_VALID(object
))
2070 ipc_object_copyin_from_kernel(object
, name
);
2072 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2073 ipc_port_check_circularity(
2074 (ipc_port_t
) object
,
2075 (ipc_port_t
) remote
))
2076 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
2082 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
2083 #endif /* MACH_ASSERT */
2091 * Routine: ipc_kmsg_copyout_header
2093 * "Copy-out" port rights in the header of a message.
2094 * Operates atomically; if it doesn't succeed the
2095 * message header and the space are left untouched.
2096 * If it does succeed the remote/local port fields
2097 * contain port names instead of object pointers,
2098 * and the bits field is updated.
2100 * The notify argument implements the MACH_RCV_NOTIFY option.
2101 * If it is not MACH_PORT_NULL, it should name a receive right.
2102 * If the process of receiving the reply port creates a
2103 * new right in the receiving task, then the new right is
2104 * automatically registered for a dead-name notification,
2105 * with the notify port supplying the send-once right.
2109 * MACH_MSG_SUCCESS Copied out port rights.
2110 * MACH_RCV_INVALID_NOTIFY
2111 * Notify is non-null and doesn't name a receive right.
2112 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2113 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
2114 * The space is dead.
2115 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
2116 * No room in space for another name.
2117 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
2118 * Couldn't allocate memory for the reply port.
2119 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
2120 * Couldn't allocate memory for the dead-name request.
2124 ipc_kmsg_copyout_header(
2125 mach_msg_header_t
*msg
,
2127 mach_port_name_t notify
)
2129 mach_msg_bits_t mbits
= msg
->msgh_bits
;
2130 ipc_port_t dest
= (ipc_port_t
) msg
->msgh_remote_port
;
2132 assert(IP_VALID(dest
));
2135 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
2136 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
2137 ipc_port_t reply
= (ipc_port_t
) msg
->msgh_local_port
;
2138 mach_port_name_t dest_name
, reply_name
;
2140 if (IP_VALID(reply
)) {
2141 ipc_port_t notify_port
;
2146 * Handling notify (for MACH_RCV_NOTIFY) is tricky.
2147 * The problem is atomically making a send-once right
2148 * from the notify port and installing it for a
2149 * dead-name request in the new entry, because this
2150 * requires two port locks (on the notify port and
2151 * the reply port). However, we can safely make
2152 * and consume send-once rights for the notify port
2153 * as long as we hold the space locked. This isn't
2154 * an atomicity problem, because the only way
2155 * to detect that a send-once right has been created
2156 * and then consumed if it wasn't needed is by getting
2157 * at the receive right to look at ip_sorights, and
2158 * because the space is write-locked status calls can't
2159 * lookup the notify port receive right. When we make
2160 * the send-once right, we lock the notify port,
2161 * so any status calls in progress will be done.
2164 is_write_lock(space
);
2167 ipc_port_request_index_t request
;
2169 if (!space
->is_active
) {
2170 printf("ipc_kmsg_copyout_header: dead space\n");
2171 is_write_unlock(space
);
2172 return (MACH_RCV_HEADER_ERROR
|
2173 MACH_MSG_IPC_SPACE
);
2176 if (notify
!= MACH_PORT_NULL
) {
2177 notify_port
= ipc_port_lookup_notify(space
,
2179 if (notify_port
== IP_NULL
) {
2180 printf("ipc_kmsg_copyout_header: no notify port\n");
2181 is_write_unlock(space
);
2182 return MACH_RCV_INVALID_NOTIFY
;
2185 notify_port
= IP_NULL
;
2187 if ((reply_type
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
2188 ipc_right_reverse(space
, (ipc_object_t
) reply
,
2189 &reply_name
, &entry
)) {
2190 /* reply port is locked and active */
2193 * We don't need the notify_port
2194 * send-once right, but we can't release
2195 * it here because reply port is locked.
2196 * Wait until after the copyout to
2197 * release the notify port right.
2200 assert(entry
->ie_bits
&
2201 MACH_PORT_TYPE_SEND_RECEIVE
);
2206 if (!ip_active(reply
)) {
2208 ip_check_unlock(reply
);
2210 if (notify_port
!= IP_NULL
)
2211 ipc_port_release_sonce(notify_port
);
2214 is_write_unlock(space
);
2217 reply_name
= MACH_PORT_DEAD
;
2221 reply_name
= (mach_port_name_t
)reply
;
2222 kr
= ipc_entry_get(space
, &reply_name
, &entry
);
2223 if (kr
!= KERN_SUCCESS
) {
2226 if (notify_port
!= IP_NULL
)
2227 ipc_port_release_sonce(notify_port
);
2229 /* space is locked */
2230 kr
= ipc_entry_grow_table(space
,
2232 if (kr
!= KERN_SUCCESS
) {
2233 /* space is unlocked */
2235 if (kr
== KERN_RESOURCE_SHORTAGE
) {
2236 printf("ipc_kmsg_copyout_header: can't grow kernel ipc space\n");
2237 return (MACH_RCV_HEADER_ERROR
|
2238 MACH_MSG_IPC_KERNEL
);
2240 printf("ipc_kmsg_copyout_header: can't grow user ipc space\n");
2241 return (MACH_RCV_HEADER_ERROR
|
2242 MACH_MSG_IPC_SPACE
);
2245 /* space is locked again; start over */
2249 assert(IE_BITS_TYPE(entry
->ie_bits
) ==
2250 MACH_PORT_TYPE_NONE
);
2251 assert(entry
->ie_object
== IO_NULL
);
2253 if (notify_port
== IP_NULL
) {
2254 /* not making a dead-name request */
2256 entry
->ie_object
= (ipc_object_t
) reply
;
2260 kr
= ipc_port_dnrequest(reply
, reply_name
,
2261 notify_port
, &request
);
2262 if (kr
!= KERN_SUCCESS
) {
2265 ipc_port_release_sonce(notify_port
);
2267 ipc_entry_dealloc(space
, reply_name
, entry
);
2268 is_write_unlock(space
);
2271 if (!ip_active(reply
)) {
2272 /* will fail next time around loop */
2275 is_write_lock(space
);
2279 kr
= ipc_port_dngrow(reply
, ITS_SIZE_NONE
);
2280 /* port is unlocked */
2281 if (kr
!= KERN_SUCCESS
) {
2282 printf("ipc_kmsg_copyout_header: can't grow kernel ipc space2\n");
2283 return (MACH_RCV_HEADER_ERROR
|
2284 MACH_MSG_IPC_KERNEL
);
2287 is_write_lock(space
);
2291 notify_port
= IP_NULL
; /* don't release right below */
2293 entry
->ie_object
= (ipc_object_t
) reply
;
2294 entry
->ie_request
= request
;
2298 /* space and reply port are locked and active */
2300 ip_reference(reply
); /* hold onto the reply port */
2302 kr
= ipc_right_copyout(space
, reply_name
, entry
,
2303 reply_type
, TRUE
, (ipc_object_t
) reply
);
2304 /* reply port is unlocked */
2305 assert(kr
== KERN_SUCCESS
);
2307 if (notify_port
!= IP_NULL
)
2308 ipc_port_release_sonce(notify_port
);
2311 is_write_unlock(space
);
2314 * No reply port! This is an easy case.
2315 * We only need to have the space locked
2316 * when checking notify and when locking
2317 * the destination (to ensure atomicity).
2320 is_read_lock(space
);
2321 if (!space
->is_active
) {
2322 printf("ipc_kmsg_copyout_header: dead space2\n");
2323 is_read_unlock(space
);
2324 return MACH_RCV_HEADER_ERROR
|MACH_MSG_IPC_SPACE
;
2327 if (notify
!= MACH_PORT_NULL
) {
2330 /* must check notify even though it won't be used */
2332 if ((entry
= ipc_entry_lookup(space
, notify
)) == IE_NULL
) {
2333 printf("ipc_kmsg_copyout_header: ipc_entry_lookup failed\n");
2334 is_read_unlock(space
);
2335 return MACH_RCV_INVALID_NOTIFY
;
2338 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
2339 printf("ipc_kmsg_copyout_header: MACH_PORT_TYPE_RECEIVE not set!\n");
2340 is_read_unlock(space
);
2341 return MACH_RCV_INVALID_NOTIFY
;
2346 is_read_unlock(space
);
2348 reply_name
= (mach_port_name_t
) reply
;
2352 * At this point, the space is unlocked and the destination
2353 * port is locked. (Lock taken while space was locked.)
2354 * reply_name is taken care of; we still need dest_name.
2355 * We still hold a ref for reply (if it is valid).
2357 * If the space holds receive rights for the destination,
2358 * we return its name for the right. Otherwise the task
2359 * managed to destroy or give away the receive right between
2360 * receiving the message and this copyout. If the destination
2361 * is dead, return MACH_PORT_DEAD, and if the receive right
2362 * exists somewhere else (another space, in transit)
2363 * return MACH_PORT_NULL.
2365 * Making this copyout operation atomic with the previous
2366 * copyout of the reply port is a bit tricky. If there was
2367 * no real reply port (it wasn't IP_VALID) then this isn't
2368 * an issue. If the reply port was dead at copyout time,
2369 * then we are OK, because if dest is dead we serialize
2370 * after the death of both ports and if dest is alive
2371 * we serialize after reply died but before dest's (later) death.
2372 * So assume reply was alive when we copied it out. If dest
2373 * is alive, then we are OK because we serialize before
2374 * the ports' deaths. So assume dest is dead when we look at it.
2375 * If reply dies/died after dest, then we are OK because
2376 * we serialize after dest died but before reply dies.
2377 * So the hard case is when reply is alive at copyout,
2378 * dest is dead at copyout, and reply died before dest died.
2379 * In this case pretend that dest is still alive, so
2380 * we serialize while both ports are alive.
2382 * Because the space lock is held across the copyout of reply
2383 * and locking dest, the receive right for dest can't move
2384 * in or out of the space while the copyouts happen, so
2385 * that isn't an atomicity problem. In the last hard case
2386 * above, this implies that when dest is dead that the
2387 * space couldn't have had receive rights for dest at
2388 * the time reply was copied-out, so when we pretend
2389 * that dest is still alive, we can return MACH_PORT_NULL.
2391 * If dest == reply, then we have to make it look like
2392 * either both copyouts happened before the port died,
2393 * or both happened after the port died. This special
2394 * case works naturally if the timestamp comparison
2395 * is done correctly.
2400 if (ip_active(dest
)) {
2401 ipc_object_copyout_dest(space
, (ipc_object_t
) dest
,
2402 dest_type
, &dest_name
);
2403 /* dest is unlocked */
2405 ipc_port_timestamp_t timestamp
;
2407 timestamp
= dest
->ip_timestamp
;
2409 ip_check_unlock(dest
);
2411 if (IP_VALID(reply
)) {
2413 if (ip_active(reply
) ||
2414 IP_TIMESTAMP_ORDER(timestamp
,
2415 reply
->ip_timestamp
))
2416 dest_name
= MACH_PORT_DEAD
;
2418 dest_name
= MACH_PORT_NULL
;
2421 dest_name
= MACH_PORT_DEAD
;
2424 if (IP_VALID(reply
))
2425 ipc_port_release(reply
);
2427 msg
->msgh_bits
= (MACH_MSGH_BITS_OTHER(mbits
) |
2428 MACH_MSGH_BITS(reply_type
, dest_type
));
2429 msg
->msgh_local_port
= (ipc_port_t
)dest_name
;
2430 msg
->msgh_remote_port
= (ipc_port_t
)reply_name
;
2433 return MACH_MSG_SUCCESS
;
2437 * Routine: ipc_kmsg_copyout_object
2439 * Copy-out a port right. Always returns a name,
2440 * even for unsuccessful return codes. Always
2441 * consumes the supplied object.
2445 * MACH_MSG_SUCCESS The space acquired the right
2446 * (name is valid) or the object is dead (MACH_PORT_DEAD).
2447 * MACH_MSG_IPC_SPACE No room in space for the right,
2448 * or the space is dead. (Name is MACH_PORT_NULL.)
2449 * MACH_MSG_IPC_KERNEL Kernel resource shortage.
2450 * (Name is MACH_PORT_NULL.)
2454 ipc_kmsg_copyout_object(
2456 ipc_object_t object
,
2457 mach_msg_type_name_t msgt_name
,
2458 mach_port_name_t
*namep
)
2462 if (!IO_VALID(object
)) {
2463 *namep
= (mach_port_name_t
) object
;
2464 return MACH_MSG_SUCCESS
;
2467 kr
= ipc_object_copyout(space
, object
, msgt_name
, TRUE
, namep
);
2468 if (kr
!= KERN_SUCCESS
) {
2469 ipc_object_destroy(object
, msgt_name
);
2471 if (kr
== KERN_INVALID_CAPABILITY
)
2472 *namep
= MACH_PORT_DEAD
;
2474 *namep
= MACH_PORT_NULL
;
2476 if (kr
== KERN_RESOURCE_SHORTAGE
)
2477 return MACH_MSG_IPC_KERNEL
;
2479 return MACH_MSG_IPC_SPACE
;
2483 return MACH_MSG_SUCCESS
;
2487 * Routine: ipc_kmsg_copyout_body
2489 * "Copy-out" port rights and out-of-line memory
2490 * in the body of a message.
2492 * The error codes are a combination of special bits.
2493 * The copyout proceeds despite errors.
2497 * MACH_MSG_SUCCESS Successful copyout.
2498 * MACH_MSG_IPC_SPACE No room for port right in name space.
2499 * MACH_MSG_VM_SPACE No room for memory in address space.
2500 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
2501 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
2502 * MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
2506 ipc_kmsg_copyout_body(
2510 mach_msg_body_t
*slist
)
2512 mach_msg_body_t
*body
;
2513 mach_msg_descriptor_t
*daddr
, *naddr
;
2514 mach_msg_descriptor_t
*saddr
;
2515 mach_msg_type_number_t i
, dsc_count
, sdsc_count
;
2516 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
2519 boolean_t differs
= MAP_SIZE_DIFFERS(map
);
2521 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
2522 dsc_count
= body
->msgh_descriptor_count
;
2523 daddr
= (mach_msg_descriptor_t
*) (body
+ 1);
2526 * Do scatter list setup
2528 if (slist
!= MACH_MSG_BODY_NULL
) {
2529 saddr
= (mach_msg_descriptor_t
*) (slist
+ 1);
2530 sdsc_count
= slist
->msgh_descriptor_count
;
2533 saddr
= MACH_MSG_DESCRIPTOR_NULL
;
2538 * Compute the true size of the resulting descriptors
2539 * after potential expansion and adjust the header
2540 * and body location accordingly.
2543 mach_msg_size_t dsc_adjust
;
2547 for (i
= 0; i
< dsc_count
; i
++, naddr
++)
2548 switch (naddr
->type
.type
) {
2549 case MACH_MSG_OOL_DESCRIPTOR
:
2550 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2551 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2552 dsc_adjust
+= DESC_SIZE_ADJUSTMENT
;
2558 mach_msg_base_t
*old_base
= (mach_msg_base_t
*)kmsg
->ikm_header
;
2559 mach_msg_base_t
*new_base
;
2561 new_base
= (mach_msg_base_t
*)((vm_offset_t
)old_base
- dsc_adjust
);
2562 memmove(new_base
, old_base
, sizeof(mach_msg_base_t
));
2563 kmsg
->ikm_header
= &new_base
->header
;
2564 kmsg
->ikm_header
->msgh_size
+= dsc_adjust
;
2565 naddr
= (mach_msg_descriptor_t
*)(new_base
+ 1);
2574 * Now process the descriptors
2576 for ( i
= 0; i
< dsc_count
; i
++, daddr
++ ) {
2577 switch (daddr
->type
.type
) {
2579 case MACH_MSG_PORT_DESCRIPTOR
: {
2580 volatile mach_msg_port_descriptor_t
*dsc
;
2581 volatile mach_msg_port_descriptor_t
*user_dsc
;
2583 mach_port_name_t name
;
2584 mach_msg_type_name_t disp
;
2587 * Copyout port right carried in the message
2590 user_dsc
= &naddr
->port
;
2592 disp
= dsc
->disposition
;
2593 mr
|= ipc_kmsg_copyout_object(space
,
2597 user_dsc
->name
= (mach_port_t
)name
;
2598 user_dsc
->disposition
= disp
;
2599 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
2604 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2605 case MACH_MSG_OOL_DESCRIPTOR
: {
2607 mach_vm_offset_t rcv_addr
;
2608 mach_msg_ool_descriptor_t
*dsc
;
2609 mach_msg_copy_options_t copy_options
;
2610 mach_msg_size_t size
;
2611 mach_msg_descriptor_type_t dsc_type
;
2613 SKIP_PORT_DESCRIPTORS(saddr
, sdsc_count
);
2615 dsc
= &daddr
->out_of_line
;
2616 copy
= (vm_map_copy_t
) dsc
->address
;
2618 copy_options
= dsc
->copy
;
2619 assert(copy_options
!= MACH_MSG_KALLOC_COPY_T
);
2620 dsc_type
= dsc
->type
;
2622 if (copy
!= VM_MAP_COPY_NULL
) {
2624 * Check to see if there is an overwrite descriptor
2625 * specified in the scatter list for this ool data.
2626 * The descriptor has already been verified.
2628 if (saddr
!= MACH_MSG_DESCRIPTOR_NULL
) {
2630 OTHER_OOL_DESCRIPTOR
*scatter_dsc
;
2632 scatter_dsc
= (OTHER_OOL_DESCRIPTOR
*)saddr
;
2633 if (scatter_dsc
->copy
== MACH_MSG_OVERWRITE
) {
2634 rcv_addr
= (mach_vm_offset_t
) scatter_dsc
->address
;
2635 copy_options
= MACH_MSG_OVERWRITE
;
2638 copy_options
= MACH_MSG_VIRTUAL_COPY
;
2641 mach_msg_ool_descriptor_t
*scatter_dsc
;
2643 scatter_dsc
= &saddr
->out_of_line
;
2644 if (scatter_dsc
->copy
== MACH_MSG_OVERWRITE
) {
2645 rcv_addr
= CAST_USER_ADDR_T(scatter_dsc
->address
);
2646 copy_options
= MACH_MSG_OVERWRITE
;
2649 copy_options
= MACH_MSG_VIRTUAL_COPY
;
2652 INCREMENT_SCATTER(saddr
, sdsc_count
, differs
);
2657 * Whether the data was virtually or physically
2658 * copied we have a vm_map_copy_t for it.
2659 * If there's an overwrite region specified
2660 * overwrite it, otherwise do a virtual copy out.
2662 if (copy_options
== MACH_MSG_OVERWRITE
) {
2663 kr
= vm_map_copy_overwrite(map
, rcv_addr
,
2666 kr
= vm_map_copyout(map
, &rcv_addr
, copy
);
2668 if (kr
!= KERN_SUCCESS
) {
2669 if (kr
== KERN_RESOURCE_SHORTAGE
)
2670 mr
|= MACH_MSG_VM_KERNEL
;
2672 mr
|= MACH_MSG_VM_SPACE
;
2673 vm_map_copy_discard(copy
);
2683 * Now update the descriptor as the user would see it.
2684 * This may require expanding the descriptor to the user
2685 * visible size. There is already space allocated for
2686 * this in what naddr points to.
2689 volatile OTHER_OOL_DESCRIPTOR
*user_dsc
;
2691 user_dsc
= (OTHER_OOL_DESCRIPTOR
*)naddr
;
2692 user_dsc
->address
= rcv_addr
;
2693 user_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
2695 user_dsc
->copy
= copy_options
;
2696 user_dsc
->type
= dsc_type
;
2697 user_dsc
->size
= size
;
2698 naddr
= (mach_msg_descriptor_t
*)((OTHER_OOL_DESCRIPTOR
*)naddr
+ 1);
2700 volatile mach_msg_ool_descriptor_t
*user_dsc
;
2702 user_dsc
= &naddr
->out_of_line
;
2703 user_dsc
->address
= CAST_DOWN(void *, rcv_addr
);
2704 user_dsc
->size
= size
;
2705 user_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
2707 user_dsc
->copy
= copy_options
;
2708 user_dsc
->type
= dsc_type
;
2714 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
2715 mach_vm_offset_t rcv_addr
;
2716 mach_port_name_t
*objects
;
2717 mach_msg_type_name_t disp
;
2718 mach_msg_type_number_t count
, j
;
2721 volatile mach_msg_ool_ports_descriptor_t
*dsc
;
2722 mach_msg_copy_options_t copy_options
= MACH_MSG_VIRTUAL_COPY
;
2724 SKIP_PORT_DESCRIPTORS(saddr
, sdsc_count
);
2726 dsc
= &daddr
->ool_ports
;
2728 disp
= dsc
->disposition
;
2729 length
= count
* sizeof(mach_port_name_t
);
2731 if (length
!= 0 && dsc
->address
!= 0) {
2734 * Check to see if there is an overwrite descriptor
2735 * specified in the scatter list for this ool data.
2736 * The descriptor has already been verified.
2738 if (saddr
!= MACH_MSG_DESCRIPTOR_NULL
) {
2740 OTHER_OOL_DESCRIPTOR
*scatter_dsc
;
2742 scatter_dsc
= (OTHER_OOL_DESCRIPTOR
*)saddr
;
2743 rcv_addr
= (mach_vm_offset_t
) scatter_dsc
->address
;
2744 copy_options
= scatter_dsc
->copy
;
2746 mach_msg_ool_descriptor_t
*scatter_dsc
;
2748 scatter_dsc
= &saddr
->out_of_line
;
2749 rcv_addr
= CAST_USER_ADDR_T(scatter_dsc
->address
);
2750 copy_options
= scatter_dsc
->copy
;
2752 INCREMENT_SCATTER(saddr
, sdsc_count
, differs
);
2755 if (copy_options
== MACH_MSG_VIRTUAL_COPY
) {
2757 * Dynamically allocate the region
2759 int anywhere
= VM_MAKE_TAG(VM_MEMORY_MACH_MSG
)|
2762 if ((kr
= mach_vm_allocate(map
, &rcv_addr
,
2763 (mach_vm_size_t
)length
,
2764 anywhere
)) != KERN_SUCCESS
) {
2765 ipc_kmsg_clean_body(kmsg
, 1, daddr
);
2768 if (kr
== KERN_RESOURCE_SHORTAGE
){
2769 mr
|= MACH_MSG_VM_KERNEL
;
2771 mr
|= MACH_MSG_VM_SPACE
;
2778 * Handle the port rights and copy out the names
2779 * for those rights out to user-space.
2781 if (rcv_addr
!= 0) {
2782 objects
= (mach_port_name_t
*) dsc
->address
;
2784 /* copyout port rights carried in the message */
2786 for ( j
= 0; j
< count
; j
++) {
2787 ipc_object_t object
=
2788 (ipc_object_t
) objects
[j
];
2790 mr
|= ipc_kmsg_copyout_object(space
, object
,
2794 /* copyout to memory allocated above */
2795 data
= dsc
->address
;
2796 if (copyoutmap(map
, data
, rcv_addr
, length
) != KERN_SUCCESS
)
2797 mr
|= MACH_MSG_VM_SPACE
;
2798 kfree(data
, length
);
2805 * Now update the descriptor based on the information
2809 volatile OTHER_OOL_PORTS_DESCRIPTOR
*user_dsc
;
2811 user_dsc
= (OTHER_OOL_PORTS_DESCRIPTOR
*)naddr
;
2812 user_dsc
->address
= rcv_addr
;
2813 user_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
2815 user_dsc
->copy
= copy_options
;
2816 user_dsc
->disposition
= disp
;
2817 user_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
2818 user_dsc
->count
= count
;
2819 naddr
= (mach_msg_descriptor_t
*)((OTHER_OOL_PORTS_DESCRIPTOR
*)naddr
+ 1);
2821 volatile mach_msg_ool_ports_descriptor_t
*user_dsc
;
2823 user_dsc
= &naddr
->ool_ports
;
2824 user_dsc
->address
= CAST_DOWN(void *, rcv_addr
);
2825 user_dsc
->count
= count
;
2826 user_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
2828 user_dsc
->copy
= copy_options
;
2829 user_dsc
->disposition
= disp
;
2830 user_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
2836 panic("untyped IPC copyout body: invalid message descriptor");
2844 * Routine: ipc_kmsg_copyout_size
2846 * Compute the size of the message as copied out to the given
2847 * map. If the destination map's pointers are a different size
2848 * than the kernel's, we have to allow for expansion/
2849 * contraction of the descriptors as appropriate.
2853 * size of the message as it would be received.
2857 ipc_kmsg_copyout_size(
2861 mach_msg_size_t send_size
;
2863 send_size
= kmsg
->ikm_header
->msgh_size
;
2865 if ((kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) &&
2866 MAP_SIZE_DIFFERS(map
)) {
2868 mach_msg_body_t
*body
;
2869 mach_msg_descriptor_t
*saddr
, *eaddr
;
2871 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
2872 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
2873 eaddr
= saddr
+ body
->msgh_descriptor_count
;
2875 for ( ; saddr
< eaddr
; saddr
++ ) {
2876 switch (saddr
->type
.type
) {
2878 case MACH_MSG_OOL_DESCRIPTOR
:
2879 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2880 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2881 send_size
+= DESC_SIZE_ADJUSTMENT
;
2893 * Routine: ipc_kmsg_copyout
2895 * "Copy-out" port rights and out-of-line memory
2900 * MACH_MSG_SUCCESS Copied out all rights and memory.
2901 * MACH_RCV_INVALID_NOTIFY Bad notify port.
2902 * Rights and memory in the message are intact.
2903 * MACH_RCV_HEADER_ERROR + special bits
2904 * Rights and memory in the message are intact.
2905 * MACH_RCV_BODY_ERROR + special bits
2906 * The message header was successfully copied out.
2907 * As much of the body was handled as possible.
2915 mach_port_name_t notify
,
2916 mach_msg_body_t
*slist
)
2918 mach_msg_return_t mr
;
2920 mr
= ipc_kmsg_copyout_header(kmsg
->ikm_header
, space
, notify
);
2921 if (mr
!= MACH_MSG_SUCCESS
) {
2922 printf("ipc_kmsg_copyout: ipc_kmsg_copyout_header failed: %d\n", mr
);
2926 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
2927 mr
= ipc_kmsg_copyout_body(kmsg
, space
, map
, slist
);
2929 if (mr
!= MACH_MSG_SUCCESS
)
2930 mr
|= MACH_RCV_BODY_ERROR
;
2937 * Routine: ipc_kmsg_copyout_pseudo
2939 * Does a pseudo-copyout of the message.
2940 * This is like a regular copyout, except
2941 * that the ports in the header are handled
2942 * as if they are in the body. They aren't reversed.
2944 * The error codes are a combination of special bits.
2945 * The copyout proceeds despite errors.
2949 * MACH_MSG_SUCCESS Successful copyout.
2950 * MACH_MSG_IPC_SPACE No room for port right in name space.
2951 * MACH_MSG_VM_SPACE No room for memory in address space.
2952 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
2953 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
2957 ipc_kmsg_copyout_pseudo(
2961 mach_msg_body_t
*slist
)
2963 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
2964 ipc_object_t dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
2965 ipc_object_t reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
2966 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
2967 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
2968 mach_port_name_t dest_name
, reply_name
;
2969 mach_msg_return_t mr
;
2971 assert(IO_VALID(dest
));
2973 mr
= (ipc_kmsg_copyout_object(space
, dest
, dest_type
, &dest_name
) |
2974 ipc_kmsg_copyout_object(space
, reply
, reply_type
, &reply_name
));
2976 kmsg
->ikm_header
->msgh_bits
= mbits
&~ MACH_MSGH_BITS_CIRCULAR
;
2977 kmsg
->ikm_header
->msgh_remote_port
= (ipc_port_t
)dest_name
;
2978 kmsg
->ikm_header
->msgh_local_port
= (ipc_port_t
)reply_name
;
2980 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
2981 mr
|= ipc_kmsg_copyout_body(kmsg
, space
, map
, slist
);
2988 * Routine: ipc_kmsg_copyout_dest
2990 * Copies out the destination port in the message.
2991 * Destroys all other rights and memory in the message.
2997 ipc_kmsg_copyout_dest(
3001 mach_msg_bits_t mbits
;
3004 mach_msg_type_name_t dest_type
;
3005 mach_msg_type_name_t reply_type
;
3006 mach_port_name_t dest_name
, reply_name
;
3008 mbits
= kmsg
->ikm_header
->msgh_bits
;
3009 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
3010 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
3011 dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
3012 reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
3014 assert(IO_VALID(dest
));
3017 if (io_active(dest
)) {
3018 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
3019 /* dest is unlocked */
3022 io_check_unlock(dest
);
3023 dest_name
= MACH_PORT_DEAD
;
3026 if (IO_VALID(reply
)) {
3027 ipc_object_destroy(reply
, reply_type
);
3028 reply_name
= MACH_PORT_NULL
;
3030 reply_name
= (mach_port_name_t
) reply
;
3032 kmsg
->ikm_header
->msgh_bits
= (MACH_MSGH_BITS_OTHER(mbits
) |
3033 MACH_MSGH_BITS(reply_type
, dest_type
));
3034 kmsg
->ikm_header
->msgh_local_port
= (ipc_port_t
)dest_name
;
3035 kmsg
->ikm_header
->msgh_remote_port
= (ipc_port_t
)reply_name
;
3037 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
3038 mach_msg_body_t
*body
;
3040 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3041 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
3042 (mach_msg_descriptor_t
*)(body
+ 1));
3047 * Routine: ipc_kmsg_copyin_scatter
3049 * allocate and copyin a scatter list
3051 * The gather (kmsg) is valid since it has been copied in.
3052 * Gather list descriptors are sequentially paired with scatter
3053 * list descriptors, with port descriptors in either list ignored.
3054 * Descriptors are consistent if the type fileds match and size
3055 * of the scatter descriptor is less than or equal to the
3056 * size of the gather descriptor. A MACH_MSG_ALLOCATE copy
3057 * strategy in a scatter descriptor matches any size in the
3058 * corresponding gather descriptor assuming they are the same type.
3059 * Either list may be larger than the other. During the
3060 * subsequent copy out, excess scatter descriptors are ignored
3061 * and excess gather descriptors default to dynamic allocation.
3063 * In the case of a size error, the scatter list is released.
3067 * the allocated message body containing the scatter list.
3071 ipc_kmsg_get_scatter(
3072 mach_vm_address_t msg_addr
,
3073 mach_msg_size_t slist_size
,
3076 mach_msg_body_t
*slist
;
3077 mach_msg_body_t
*body
;
3078 mach_msg_descriptor_t
*gstart
, *gend
;
3079 mach_msg_descriptor_t
*sstart
, *send
;
3082 if (slist_size
< sizeof(mach_msg_base_t
))
3083 return MACH_MSG_BODY_NULL
;
3085 slist_size
-= sizeof(mach_msg_header_t
);
3086 slist
= (mach_msg_body_t
*)kalloc(slist_size
);
3087 if (slist
== MACH_MSG_BODY_NULL
)
3090 if (copyin(msg_addr
+ sizeof(mach_msg_header_t
), (char *)slist
, slist_size
)) {
3091 kfree(slist
, slist_size
);
3092 return MACH_MSG_BODY_NULL
;
3095 if ((slist
->msgh_descriptor_count
* sizeof(mach_msg_descriptor_t
)
3096 + sizeof(mach_msg_size_t
)) > slist_size
) {
3097 kfree(slist
, slist_size
);
3098 return MACH_MSG_BODY_NULL
;
3101 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3102 gstart
= (mach_msg_descriptor_t
*) (body
+ 1);
3103 gend
= gstart
+ body
->msgh_descriptor_count
;
3105 sstart
= (mach_msg_descriptor_t
*) (slist
+ 1);
3106 send
= sstart
+ slist
->msgh_descriptor_count
;
3108 while (gstart
< gend
) {
3109 mach_msg_descriptor_type_t g_type
;
3112 * Skip port descriptors in gather list.
3114 g_type
= gstart
->type
.type
;
3116 if (g_type
!= MACH_MSG_PORT_DESCRIPTOR
) {
3119 * A scatter list with a 0 descriptor count is treated as an
3120 * automatic size mismatch.
3122 if (slist
->msgh_descriptor_count
== 0) {
3123 kfree(slist
, slist_size
);
3124 return MACH_MSG_BODY_NULL
;
3128 * Skip port descriptors in scatter list.
3130 while (sstart
< send
) {
3131 if (sstart
->type
.type
!= MACH_MSG_PORT_DESCRIPTOR
)
3137 * No more scatter descriptors, we're done
3139 if (sstart
>= send
) {
3144 * Check type, copy and size fields
3146 if (g_type
== MACH_MSG_OOL_DESCRIPTOR
||
3147 g_type
== MACH_MSG_OOL_VOLATILE_DESCRIPTOR
) {
3148 if (sstart
->type
.type
!= MACH_MSG_OOL_DESCRIPTOR
&&
3149 sstart
->type
.type
!= MACH_MSG_OOL_VOLATILE_DESCRIPTOR
) {
3150 kfree(slist
, slist_size
);
3151 return MACH_MSG_BODY_NULL
;
3153 if (sstart
->out_of_line
.copy
== MACH_MSG_OVERWRITE
&&
3154 gstart
->out_of_line
.size
> sstart
->out_of_line
.size
) {
3155 kfree(slist
, slist_size
);
3156 return MACH_MSG_BODY_NULL
;
3160 if (sstart
->type
.type
!= MACH_MSG_OOL_PORTS_DESCRIPTOR
) {
3161 kfree(slist
, slist_size
);
3162 return MACH_MSG_BODY_NULL
;
3164 if (sstart
->ool_ports
.copy
== MACH_MSG_OVERWRITE
&&
3165 gstart
->ool_ports
.count
> sstart
->ool_ports
.count
) {
3166 kfree(slist
, slist_size
);
3167 return MACH_MSG_BODY_NULL
;
3179 * Routine: ipc_kmsg_free_scatter
3181 * Deallocate a scatter list. Since we actually allocated
3182 * a body without a header, and since the header was originally
3183 * accounted for in slist_size, we have to ajust it down
3184 * before freeing the scatter list.
3187 ipc_kmsg_free_scatter(
3188 mach_msg_body_t
*slist
,
3189 mach_msg_size_t slist_size
)
3191 slist_size
-= sizeof(mach_msg_header_t
);
3192 kfree(slist
, slist_size
);
3197 * Routine: ipc_kmsg_copyout_to_kernel
3199 * Copies out the destination and reply ports in the message.
3200 * Leaves all other rights and memory in the message alone.
3204 * Derived from ipc_kmsg_copyout_dest.
3205 * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
3206 * We really do want to save rights and memory.
3210 ipc_kmsg_copyout_to_kernel(
3216 mach_msg_type_name_t dest_type
;
3217 mach_msg_type_name_t reply_type
;
3218 mach_port_name_t dest_name
, reply_name
;
3220 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
3221 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
3222 dest_type
= MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
);
3223 reply_type
= MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
);
3225 assert(IO_VALID(dest
));
3228 if (io_active(dest
)) {
3229 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
3230 /* dest is unlocked */
3233 io_check_unlock(dest
);
3234 dest_name
= MACH_PORT_DEAD
;
3237 reply_name
= (mach_port_name_t
) reply
;
3239 kmsg
->ikm_header
->msgh_bits
=
3240 (MACH_MSGH_BITS_OTHER(kmsg
->ikm_header
->msgh_bits
) |
3241 MACH_MSGH_BITS(reply_type
, dest_type
));
3242 kmsg
->ikm_header
->msgh_local_port
= (ipc_port_t
)dest_name
;
3243 kmsg
->ikm_header
->msgh_remote_port
= (ipc_port_t
)reply_name
;
3246 #include <mach_kdb.h>
3249 #include <ddb/db_output.h>
3250 #include <ipc/ipc_print.h>
3252 * Forward declarations
3254 void ipc_msg_print_untyped(
3255 mach_msg_body_t
*body
);
3257 const char * ipc_type_name(
3259 boolean_t received
);
3261 void ipc_print_type_name(
3266 mach_msg_bits_t bit
);
3269 mm_copy_options_string(
3270 mach_msg_copy_options_t option
);
3272 void db_print_msg_uid(mach_msg_header_t
*);
3280 switch (type_name
) {
3281 case MACH_MSG_TYPE_PORT_NAME
:
3284 case MACH_MSG_TYPE_MOVE_RECEIVE
:
3286 return "port_receive";
3288 return "move_receive";
3291 case MACH_MSG_TYPE_MOVE_SEND
:
3298 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
3300 return "port_send_once";
3302 return "move_send_once";
3305 case MACH_MSG_TYPE_COPY_SEND
:
3308 case MACH_MSG_TYPE_MAKE_SEND
:
3311 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
3312 return "make_send_once";
3320 ipc_print_type_name(
3323 const char *name
= ipc_type_name(type_name
, TRUE
);
3327 printf("type%d", type_name
);
3332 * ipc_kmsg_print [ debug ]
3338 iprintf("kmsg=0x%x\n", kmsg
);
3339 iprintf("ikm_next=0x%x, prev=0x%x, size=%d",
3344 ipc_msg_print(kmsg
->ikm_header
);
3349 mach_msg_bits_t bit
)
3352 case MACH_MSGH_BITS_COMPLEX
: return "complex";
3353 case MACH_MSGH_BITS_CIRCULAR
: return "circular";
3354 default: return (char *) 0;
3359 * ipc_msg_print [ debug ]
3363 mach_msg_header_t
*msgh
)
3365 mach_msg_bits_t mbits
;
3366 unsigned int bit
, i
;
3367 const char *bit_name
;
3370 mbits
= msgh
->msgh_bits
;
3371 iprintf("msgh_bits=0x%x: l=0x%x,r=0x%x\n",
3373 MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
),
3374 MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
3376 mbits
= MACH_MSGH_BITS_OTHER(mbits
) & MACH_MSGH_BITS_USED
;
3379 iprintf("decoded bits: ");
3381 for (i
= 0, bit
= 1; i
< sizeof(mbits
) * 8; ++i
, bit
<<= 1) {
3382 if ((mbits
& bit
) == 0)
3384 bit_name
= msgh_bit_decode((mach_msg_bits_t
)bit
);
3386 printf("%s%s", needs_comma
? "," : "", bit_name
);
3388 printf("%sunknown(0x%x),", needs_comma
? "," : "", bit
);
3391 if (msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
) {
3392 printf("%sunused=0x%x,", needs_comma
? "," : "",
3393 msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
);
3399 if (msgh
->msgh_remote_port
) {
3400 iprintf("remote=0x%x(", msgh
->msgh_remote_port
);
3401 ipc_print_type_name(MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
3404 iprintf("remote=null");
3407 if (msgh
->msgh_local_port
) {
3408 printf("%slocal=%p(", needs_comma
? "," : "",
3409 msgh
->msgh_local_port
);
3410 ipc_print_type_name(MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
));
3413 printf("local=null\n");
3416 iprintf("msgh_id=%d, size=%d\n",
3420 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
3421 ipc_msg_print_untyped((mach_msg_body_t
*) (msgh
+ 1));
3427 mm_copy_options_string(
3428 mach_msg_copy_options_t option
)
3433 case MACH_MSG_PHYSICAL_COPY
:
3436 case MACH_MSG_VIRTUAL_COPY
:
3439 case MACH_MSG_OVERWRITE
:
3442 case MACH_MSG_ALLOCATE
:
3445 case MACH_MSG_KALLOC_COPY_T
:
3446 name
= "KALLOC_COPY_T";
3456 ipc_msg_print_untyped(
3457 mach_msg_body_t
*body
)
3459 mach_msg_descriptor_t
*saddr
, *send
;
3460 mach_msg_descriptor_type_t type
;
3462 iprintf("%d descriptors %d: \n", body
->msgh_descriptor_count
);
3464 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
3465 send
= saddr
+ body
->msgh_descriptor_count
;
3467 for ( ; saddr
< send
; saddr
++ ) {
3469 type
= saddr
->type
.type
;
3473 case MACH_MSG_PORT_DESCRIPTOR
: {
3474 mach_msg_port_descriptor_t
*dsc
;
3477 iprintf("-- PORT name = 0x%x disp = ", dsc
->name
);
3478 ipc_print_type_name(dsc
->disposition
);
3482 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3483 case MACH_MSG_OOL_DESCRIPTOR
: {
3484 mach_msg_ool_descriptor_t
*dsc
;
3486 dsc
= &saddr
->out_of_line
;
3487 iprintf("-- OOL%s addr = 0x%x size = 0x%x copy = %s %s\n",
3488 type
== MACH_MSG_OOL_DESCRIPTOR
? "" : " VOLATILE",
3489 dsc
->address
, dsc
->size
,
3490 mm_copy_options_string(dsc
->copy
),
3491 dsc
->deallocate
? "DEALLOC" : "");
3494 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
3495 mach_msg_ool_ports_descriptor_t
*dsc
;
3497 dsc
= &saddr
->ool_ports
;
3499 iprintf("-- OOL_PORTS addr = 0x%x count = 0x%x ",
3500 dsc
->address
, dsc
->count
);
3502 ipc_print_type_name(dsc
->disposition
);
3503 printf(" copy = %s %s\n",
3504 mm_copy_options_string(dsc
->copy
),
3505 dsc
->deallocate
? "DEALLOC" : "");
3510 iprintf("-- UNKNOWN DESCRIPTOR 0x%x\n", type
);
3516 #endif /* MACH_KDB */