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/debug.h>
87 #include <kern/ipc_kobject.h>
88 #include <kern/kalloc.h>
89 #include <kern/zalloc.h>
90 #include <kern/processor.h>
91 #include <kern/thread.h>
92 #include <kern/sched_prim.h>
94 #include <kern/misc_protos.h>
95 #include <kern/counters.h>
96 #include <kern/cpu_data.h>
98 #include <machine/machlimits.h>
100 #include <vm/vm_map.h>
101 #include <vm/vm_object.h>
102 #include <vm/vm_kern.h>
104 #include <ipc/port.h>
105 #include <ipc/ipc_types.h>
106 #include <ipc/ipc_entry.h>
107 #include <ipc/ipc_kmsg.h>
108 #include <ipc/ipc_notify.h>
109 #include <ipc/ipc_object.h>
110 #include <ipc/ipc_space.h>
111 #include <ipc/ipc_port.h>
112 #include <ipc/ipc_right.h>
113 #include <ipc/ipc_hash.h>
114 #include <ipc/ipc_table.h>
116 #include <security/mac_mach_internal.h>
121 #include <ppc/Firmware.h>
122 #include <ppc/low_trace.h>
126 #define DEBUG_MSGS_K64 1
133 mach_msg_bits_t msgh_bits
;
134 mach_msg_size_t msgh_size
;
135 uint32_t msgh_remote_port
;
136 uint32_t msgh_local_port
;
137 mach_msg_size_t msgh_reserved
;
138 mach_msg_id_t msgh_id
;
139 } mach_msg_legacy_header_t
;
143 mach_msg_legacy_header_t header
;
144 mach_msg_body_t body
;
145 } mach_msg_legacy_base_t
;
149 mach_port_name_t name
;
150 mach_msg_size_t pad1
;
152 mach_msg_type_name_t disposition
: 8;
153 mach_msg_descriptor_type_t type
: 8;
154 } mach_msg_legacy_port_descriptor_t
;
159 mach_msg_legacy_port_descriptor_t port
;
160 mach_msg_ool_descriptor32_t out_of_line32
;
161 mach_msg_ool_ports_descriptor32_t ool_ports32
;
162 mach_msg_type_descriptor_t type
;
163 } mach_msg_legacy_descriptor_t
;
167 #define LEGACY_HEADER_SIZE_DELTA ((mach_msg_size_t)(sizeof(mach_msg_header_t) - sizeof(mach_msg_legacy_header_t)))
172 extern void ipc_pset_print64(
175 extern void ipc_kmsg_print64(
179 extern void ipc_msg_print64(
180 mach_msg_header_t
*msgh
);
182 extern ipc_port_t
ipc_name_to_data64(
184 mach_port_name_t name
);
187 * Forward declarations
189 void ipc_msg_print_untyped64(
190 mach_msg_body_t
*body
);
192 const char * ipc_type_name64(
196 void ipc_print_type_name64(
201 mach_msg_bits_t bit
);
204 mm_copy_options_string64(
205 mach_msg_copy_options_t option
);
207 void db_print_msg_uid64(mach_msg_header_t
*);
210 ipc_msg_body_print64(void *body
, int size
)
212 uint32_t *word
= (uint32_t *) body
;
213 uint32_t *end
= (uint32_t *)(((uintptr_t) body
) + size
214 - sizeof(mach_msg_header_t
));
217 kprintf(" body(%p-%p):\n %p: ", body
, end
, word
);
219 for (i
= 0; i
< 8; i
++, word
++) {
224 kprintf("%08x ", *word
);
226 kprintf("\n %p: ", word
);
237 case MACH_MSG_TYPE_PORT_NAME
:
240 case MACH_MSG_TYPE_MOVE_RECEIVE
:
242 return "port_receive";
244 return "move_receive";
247 case MACH_MSG_TYPE_MOVE_SEND
:
254 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
256 return "port_send_once";
258 return "move_send_once";
261 case MACH_MSG_TYPE_COPY_SEND
:
264 case MACH_MSG_TYPE_MAKE_SEND
:
267 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
268 return "make_send_once";
276 ipc_print_type_name64(
279 const char *name
= ipc_type_name64(type_name
, TRUE
);
283 kprintf("type%d", type_name
);
288 * ipc_kmsg_print64 [ debug ]
295 kprintf("%s kmsg=%p:\n", str
, kmsg
);
296 kprintf(" next=%p, prev=%p, size=%d",
301 ipc_msg_print64(kmsg
->ikm_header
);
309 case MACH_MSGH_BITS_COMPLEX
: return "complex";
310 case MACH_MSGH_BITS_CIRCULAR
: return "circular";
311 default: return (char *) 0;
316 * ipc_msg_print64 [ debug ]
320 mach_msg_header_t
*msgh
)
322 mach_msg_bits_t mbits
;
324 const char *bit_name
;
327 mbits
= msgh
->msgh_bits
;
328 kprintf(" msgh_bits=0x%x: l=0x%x,r=0x%x\n",
330 MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
),
331 MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
333 mbits
= MACH_MSGH_BITS_OTHER(mbits
) & MACH_MSGH_BITS_USED
;
334 kprintf(" decoded bits: ");
336 for (i
= 0, bit
= 1; i
< sizeof(mbits
) * 8; ++i
, bit
<<= 1) {
337 if ((mbits
& bit
) == 0)
339 bit_name
= msgh_bit_decode64((mach_msg_bits_t
)bit
);
341 kprintf("%s%s", needs_comma
? "," : "", bit_name
);
343 kprintf("%sunknown(0x%x),", needs_comma
? "," : "", bit
);
346 if (msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
) {
347 kprintf("%sunused=0x%x,", needs_comma
? "," : "",
348 msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
);
353 if (msgh
->msgh_remote_port
) {
354 kprintf(" remote=%p(", msgh
->msgh_remote_port
);
355 ipc_print_type_name64(MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
358 kprintf(" remote=null");
361 if (msgh
->msgh_local_port
) {
362 kprintf("%slocal=%p(", needs_comma
? "," : "",
363 msgh
->msgh_local_port
);
364 ipc_print_type_name64(MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
));
367 kprintf("local=null\n");
370 kprintf(" msgh_id=%d, size=%d\n",
374 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
375 ipc_msg_print_untyped64((mach_msg_body_t
*) (msgh
+ 1));
378 ipc_msg_body_print64((void *)(msgh
+ 1), msgh
->msgh_size
);
383 mm_copy_options_string64(
384 mach_msg_copy_options_t option
)
389 case MACH_MSG_PHYSICAL_COPY
:
392 case MACH_MSG_VIRTUAL_COPY
:
395 case MACH_MSG_OVERWRITE
:
398 case MACH_MSG_ALLOCATE
:
401 case MACH_MSG_KALLOC_COPY_T
:
402 name
= "KALLOC_COPY_T";
412 ipc_msg_print_untyped64(
413 mach_msg_body_t
*body
)
415 mach_msg_descriptor_t
*saddr
, *send
;
416 mach_msg_descriptor_type_t type
;
418 kprintf(" %d descriptors: \n", body
->msgh_descriptor_count
);
420 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
421 send
= saddr
+ body
->msgh_descriptor_count
;
423 for ( ; saddr
< send
; saddr
++ ) {
425 type
= saddr
->type
.type
;
429 case MACH_MSG_PORT_DESCRIPTOR
: {
430 mach_msg_port_descriptor_t
*dsc
;
433 kprintf(" PORT name = %p disp = ", dsc
->name
);
434 ipc_print_type_name64(dsc
->disposition
);
438 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
439 case MACH_MSG_OOL_DESCRIPTOR
: {
440 mach_msg_ool_descriptor_t
*dsc
;
442 dsc
= (mach_msg_ool_descriptor_t
*) &saddr
->out_of_line
;
443 kprintf(" OOL%s addr = %p size = 0x%x copy = %s %s\n",
444 type
== MACH_MSG_OOL_DESCRIPTOR
? "" : " VOLATILE",
445 dsc
->address
, dsc
->size
,
446 mm_copy_options_string64(dsc
->copy
),
447 dsc
->deallocate
? "DEALLOC" : "");
450 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
451 mach_msg_ool_ports_descriptor_t
*dsc
;
453 dsc
= (mach_msg_ool_ports_descriptor_t
*) &saddr
->ool_ports
;
455 kprintf(" OOL_PORTS addr = %p count = 0x%x ",
456 dsc
->address
, dsc
->count
);
458 ipc_print_type_name64(dsc
->disposition
);
459 kprintf(" copy = %s %s\n",
460 mm_copy_options_string64(dsc
->copy
),
461 dsc
->deallocate
? "DEALLOC" : "");
466 kprintf(" UNKNOWN DESCRIPTOR 0x%x\n", type
);
473 #define DEBUG_IPC_KMSG_PRINT(kmsg,string) \
474 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
475 ipc_kmsg_print64(kmsg, string); \
477 #define DEBUG_IPC_MSG_BODY_PRINT(body,size) \
478 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
479 ipc_msg_body_print64(body,size);\
481 #else /* !DEBUG_MSGS_K64 */
482 #define DEBUG_IPC_KMSG_PRINT(kmsg,string)
483 #define DEBUG_IPC_MSG_BODY_PRINT(body,size)
484 #endif /* !DEBUG_MSGS_K64 */
486 extern vm_map_t ipc_kernel_copy_map
;
487 extern vm_size_t ipc_kmsg_max_vm_space
;
488 extern vm_size_t msg_ool_size_small
;
490 #define MSG_OOL_SIZE_SMALL msg_ool_size_small
492 #if defined(__LP64__)
493 #define MAP_SIZE_DIFFERS(map) (map->max_offset < MACH_VM_MAX_ADDRESS)
494 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor32_t
495 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor32_t
497 #define MAP_SIZE_DIFFERS(map) (map->max_offset > VM_MAX_ADDRESS)
498 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor64_t
499 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor64_t
502 #define DESC_SIZE_ADJUSTMENT ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
503 sizeof(mach_msg_ool_descriptor32_t)))
505 /* scatter list macros */
507 #define SKIP_PORT_DESCRIPTORS(s, c) \
509 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
511 if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
516 (s) = MACH_MSG_DESCRIPTOR_NULL; \
520 #define INCREMENT_SCATTER(s, c, d) \
522 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
523 s = (d) ? (mach_msg_descriptor_t *) \
524 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) : \
530 /* zone for cached ipc_kmsg_t structures */
531 zone_t ipc_kmsg_zone
;
534 * Forward declarations
540 void ipc_kmsg_clean_body(
542 mach_msg_type_number_t number
,
543 mach_msg_descriptor_t
*desc
);
545 void ipc_kmsg_clean_partial(
547 mach_msg_type_number_t number
,
548 mach_msg_descriptor_t
*desc
,
552 mach_msg_return_t
ipc_kmsg_copyin_body(
558 * We keep a per-processor cache of kernel message buffers.
559 * The cache saves the overhead/locking of using kalloc/kfree.
560 * The per-processor cache seems to miss less than a per-thread cache,
561 * and it also uses less memory. Access to the cache doesn't
566 * Routine: ipc_kmsg_alloc
568 * Allocate a kernel message structure. If we can get one from
569 * the cache, that is best. Otherwise, allocate a new one.
575 mach_msg_size_t msg_and_trailer_size
)
577 mach_msg_size_t max_expanded_size
;
582 * Pad the allocation in case we need to expand the
583 * message descrptors for user spaces with pointers larger than
584 * the kernel's own, or vice versa. We don't know how many descriptors
585 * there are yet, so just assume the whole body could be
586 * descriptors (if there could be any at all).
588 * The expansion space is left in front of the header,
589 * because it is easier to pull the header and descriptors
590 * forward as we process them than it is to push all the
593 mach_msg_size_t size
= msg_and_trailer_size
- MAX_TRAILER_SIZE
;
594 if (size
> sizeof(mach_msg_base_t
)) {
595 mach_msg_size_t max_desc
= (mach_msg_size_t
)(((size
- sizeof(mach_msg_base_t
)) /
596 sizeof(mach_msg_ool_descriptor32_t
)) *
597 DESC_SIZE_ADJUSTMENT
);
598 if (msg_and_trailer_size
> MACH_MSG_SIZE_MAX
- max_desc
)
601 max_expanded_size
= msg_and_trailer_size
+ max_desc
;
603 max_expanded_size
= msg_and_trailer_size
;
605 if (max_expanded_size
> ikm_less_overhead(MACH_MSG_SIZE_MAX
))
607 else if (max_expanded_size
< IKM_SAVED_MSG_SIZE
)
608 max_expanded_size
= IKM_SAVED_MSG_SIZE
; /* round up for ikm_cache */
610 if (max_expanded_size
== IKM_SAVED_MSG_SIZE
) {
611 struct ikm_cache
*cache
;
614 disable_preemption();
615 cache
= &PROCESSOR_DATA(current_processor(), ikm_cache
);
616 if ((i
= cache
->avail
) > 0) {
617 assert(i
<= IKM_STASH
);
618 kmsg
= cache
->entries
[--i
];
621 ikm_check_init(kmsg
, max_expanded_size
);
622 ikm_set_header(kmsg
, msg_and_trailer_size
);
626 kmsg
= (ipc_kmsg_t
)zalloc(ipc_kmsg_zone
);
628 kmsg
= (ipc_kmsg_t
)kalloc(ikm_plus_overhead(max_expanded_size
));
631 if (kmsg
!= IKM_NULL
) {
632 ikm_init(kmsg
, max_expanded_size
);
633 ikm_set_header(kmsg
, msg_and_trailer_size
);
640 * Routine: ipc_kmsg_free
642 * Free a kernel message buffer. If the kms is preallocated
643 * to a port, just "put it back (marked unused)." We have to
644 * do this with the port locked. The port may have its hold
645 * on our message released. In that case, we have to just
646 * revert the message to a traditional one and free it normally.
655 mach_msg_size_t size
= kmsg
->ikm_size
;
659 if (kmsg
->ikm_sender
!= NULL
) {
660 task_deallocate(kmsg
->ikm_sender
);
661 kmsg
->ikm_sender
= NULL
;
666 * Check to see if the message is bound to the port. If so,
667 * mark it not in use. If the port isn't already dead, then
668 * leave the message associated with it. Otherwise, free it.
670 port
= ikm_prealloc_inuse_port(kmsg
);
671 if (port
!= IP_NULL
) {
673 ikm_prealloc_clear_inuse(kmsg
, port
);
674 if (ip_active(port
) && (port
->ip_premsg
== kmsg
)) {
675 assert(IP_PREALLOC(port
));
679 ip_check_unlock(port
); /* May be last reference */
683 * Peek and see if it has to go back in the cache.
685 if (kmsg
->ikm_size
== IKM_SAVED_MSG_SIZE
) {
686 struct ikm_cache
*cache
;
689 disable_preemption();
690 cache
= &PROCESSOR_DATA(current_processor(), ikm_cache
);
691 if ((i
= cache
->avail
) < IKM_STASH
) {
692 cache
->entries
[i
] = kmsg
;
693 cache
->avail
= i
+ 1;
698 zfree(ipc_kmsg_zone
, kmsg
);
701 kfree(kmsg
, ikm_plus_overhead(size
));
706 * Routine: ipc_kmsg_enqueue
713 ipc_kmsg_queue_t queue
,
716 ipc_kmsg_enqueue_macro(queue
, kmsg
);
720 * Routine: ipc_kmsg_dequeue
722 * Dequeue and return a kmsg.
727 ipc_kmsg_queue_t queue
)
731 first
= ipc_kmsg_queue_first(queue
);
733 if (first
!= IKM_NULL
)
734 ipc_kmsg_rmqueue_first_macro(queue
, first
);
740 * Routine: ipc_kmsg_rmqueue
742 * Pull a kmsg out of a queue.
747 ipc_kmsg_queue_t queue
,
750 ipc_kmsg_t next
, prev
;
752 assert(queue
->ikmq_base
!= IKM_NULL
);
754 next
= kmsg
->ikm_next
;
755 prev
= kmsg
->ikm_prev
;
758 assert(prev
== kmsg
);
759 assert(queue
->ikmq_base
== kmsg
);
761 queue
->ikmq_base
= IKM_NULL
;
763 if (queue
->ikmq_base
== kmsg
)
764 queue
->ikmq_base
= next
;
766 next
->ikm_prev
= prev
;
767 prev
->ikm_next
= next
;
769 /* XXX Temporary debug logic */
770 assert((kmsg
->ikm_next
= IKM_BOGUS
) == IKM_BOGUS
);
771 assert((kmsg
->ikm_prev
= IKM_BOGUS
) == IKM_BOGUS
);
775 * Routine: ipc_kmsg_queue_next
777 * Return the kmsg following the given kmsg.
778 * (Or IKM_NULL if it is the last one in the queue.)
783 ipc_kmsg_queue_t queue
,
788 assert(queue
->ikmq_base
!= IKM_NULL
);
790 next
= kmsg
->ikm_next
;
791 if (queue
->ikmq_base
== next
)
798 * Routine: ipc_kmsg_destroy
800 * Destroys a kernel message. Releases all rights,
801 * references, and memory held by the message.
811 ipc_kmsg_queue_t queue
;
815 * ipc_kmsg_clean can cause more messages to be destroyed.
816 * Curtail recursion by queueing messages. If a message
817 * is already queued, then this is a recursive call.
820 queue
= &(current_thread()->ith_messages
);
821 empty
= ipc_kmsg_queue_empty(queue
);
822 ipc_kmsg_enqueue(queue
, kmsg
);
825 /* must leave kmsg in queue while cleaning it */
827 while ((kmsg
= ipc_kmsg_queue_first(queue
)) != IKM_NULL
) {
828 ipc_kmsg_clean(kmsg
);
829 ipc_kmsg_rmqueue(queue
, kmsg
);
836 * Routine: ipc_kmsg_destroy_dest
838 * Destroys a kernel message. Releases all rights,
839 * references, and memory held by the message (including
840 * the destination port reference.
846 ipc_kmsg_destroy_dest(
851 port
= kmsg
->ikm_header
->msgh_remote_port
;
853 ipc_port_release(port
);
854 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
855 ipc_kmsg_destroy(kmsg
);
859 * Routine: ipc_kmsg_clean_body
861 * Cleans the body of a kernel message.
862 * Releases all rights, references, and memory.
870 __unused ipc_kmsg_t kmsg
,
871 mach_msg_type_number_t number
,
872 mach_msg_descriptor_t
*saddr
)
874 mach_msg_type_number_t i
;
879 for (i
= 0 ; i
< number
; i
++, saddr
++ ) {
881 switch (saddr
->type
.type
) {
883 case MACH_MSG_PORT_DESCRIPTOR
: {
884 mach_msg_port_descriptor_t
*dsc
;
889 * Destroy port rights carried in the message
891 if (!IO_VALID((ipc_object_t
) dsc
->name
))
893 ipc_object_destroy((ipc_object_t
) dsc
->name
, dsc
->disposition
);
896 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
897 case MACH_MSG_OOL_DESCRIPTOR
: {
898 mach_msg_ool_descriptor_t
*dsc
;
900 dsc
= (mach_msg_ool_descriptor_t
*)&saddr
->out_of_line
;
903 * Destroy memory carried in the message
905 if (dsc
->size
== 0) {
906 assert(dsc
->address
== (void *) 0);
908 vm_map_copy_discard((vm_map_copy_t
) dsc
->address
);
912 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
913 ipc_object_t
*objects
;
914 mach_msg_type_number_t j
;
915 mach_msg_ool_ports_descriptor_t
*dsc
;
917 dsc
= (mach_msg_ool_ports_descriptor_t
*)&saddr
->ool_ports
;
918 objects
= (ipc_object_t
*) dsc
->address
;
920 if (dsc
->count
== 0) {
924 assert(objects
!= (ipc_object_t
*) 0);
926 /* destroy port rights carried in the message */
928 for (j
= 0; j
< dsc
->count
; j
++) {
929 ipc_object_t object
= objects
[j
];
931 if (!IO_VALID(object
))
934 ipc_object_destroy(object
, dsc
->disposition
);
937 /* destroy memory carried in the message */
939 assert(dsc
->count
!= 0);
942 (vm_size_t
) dsc
->count
* sizeof(mach_port_t
));
946 printf("cleanup: don't understand this type of descriptor\n");
953 * Routine: ipc_kmsg_clean_partial
955 * Cleans a partially-acquired kernel message.
956 * number is the index of the type descriptor
957 * in the body of the message that contained the error.
958 * If dolast, the memory and port rights in this last
959 * type spec are also cleaned. In that case, number
960 * specifies the number of port rights to clean.
966 ipc_kmsg_clean_partial(
968 mach_msg_type_number_t number
,
969 mach_msg_descriptor_t
*desc
,
974 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
976 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
977 assert(IO_VALID(object
));
978 ipc_object_destroy(object
, MACH_MSGH_BITS_REMOTE(mbits
));
980 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
981 if (IO_VALID(object
))
982 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
985 (void) vm_deallocate(ipc_kernel_copy_map
, paddr
, length
);
988 ipc_kmsg_clean_body(kmsg
, number
, desc
);
992 * Routine: ipc_kmsg_clean
994 * Cleans a kernel message. Releases all rights,
995 * references, and memory held by the message.
1004 ipc_object_t object
;
1005 mach_msg_bits_t mbits
;
1007 mbits
= kmsg
->ikm_header
->msgh_bits
;
1008 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
1009 if (IO_VALID(object
))
1010 ipc_object_destroy(object
, MACH_MSGH_BITS_REMOTE(mbits
));
1012 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
1013 if (IO_VALID(object
))
1014 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
1016 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
1017 mach_msg_body_t
*body
;
1019 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
1020 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
1021 (mach_msg_descriptor_t
*)(body
+ 1));
1024 #if CONFIG_MACF_MACH
1025 if (kmsg
->ikm_sender
!= NULL
) {
1026 task_deallocate(kmsg
->ikm_sender
);
1027 kmsg
->ikm_sender
= NULL
;
1033 * Routine: ipc_kmsg_set_prealloc
1035 * Assign a kmsg as a preallocated message buffer to a port.
1041 ipc_kmsg_set_prealloc(
1045 assert(kmsg
->ikm_prealloc
== IP_NULL
);
1047 kmsg
->ikm_prealloc
= IP_NULL
;
1048 IP_SET_PREALLOC(port
, kmsg
);
1052 * Routine: ipc_kmsg_clear_prealloc
1054 * Release the Assignment of a preallocated message buffer from a port.
1059 ipc_kmsg_clear_prealloc(
1063 assert(kmsg
->ikm_prealloc
== port
);
1065 kmsg
->ikm_prealloc
= IP_NULL
;
1066 IP_CLEAR_PREALLOC(port
, kmsg
);
1070 * Routine: ipc_kmsg_prealloc
1072 * Wraper to ipc_kmsg_alloc() to account for
1073 * header expansion requirements.
1076 ipc_kmsg_prealloc(mach_msg_size_t size
)
1078 #if defined(__LP64__)
1079 if (size
> MACH_MSG_SIZE_MAX
- LEGACY_HEADER_SIZE_DELTA
)
1082 size
+= LEGACY_HEADER_SIZE_DELTA
;
1084 return ipc_kmsg_alloc(size
);
1089 * Routine: ipc_kmsg_get
1091 * Allocates a kernel message buffer.
1092 * Copies a user message to the message buffer.
1096 * MACH_MSG_SUCCESS Acquired a message buffer.
1097 * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
1098 * MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
1099 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1100 * MACH_SEND_INVALID_DATA Couldn't copy message data.
1105 mach_vm_address_t msg_addr
,
1106 mach_msg_size_t size
,
1109 mach_msg_size_t msg_and_trailer_size
;
1111 mach_msg_max_trailer_t
*trailer
;
1112 mach_msg_legacy_base_t legacy_base
;
1113 mach_msg_size_t len_copied
;
1114 legacy_base
.body
.msgh_descriptor_count
= 0;
1116 if ((size
< sizeof(mach_msg_legacy_header_t
)) || (size
& 3))
1117 return MACH_SEND_MSG_TOO_SMALL
;
1119 if (size
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
)
1120 return MACH_SEND_TOO_LARGE
;
1122 if(size
== sizeof(mach_msg_legacy_header_t
))
1123 len_copied
= sizeof(mach_msg_legacy_header_t
);
1125 len_copied
= sizeof(mach_msg_legacy_base_t
);
1127 if (copyinmsg(msg_addr
, (char *)&legacy_base
, len_copied
))
1128 return MACH_SEND_INVALID_DATA
;
1130 msg_addr
+= sizeof(legacy_base
.header
);
1131 #if defined(__LP64__)
1132 size
+= LEGACY_HEADER_SIZE_DELTA
;
1134 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
1136 for (j
=0; j
<sizeof(legacy_base
.header
); j
++) {
1137 kprintf("%02x\n", ((unsigned char*)&legacy_base
.header
)[j
]);
1141 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
1142 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
1143 if (kmsg
== IKM_NULL
)
1144 return MACH_SEND_NO_BUFFER
;
1146 kmsg
->ikm_header
->msgh_size
= size
;
1147 kmsg
->ikm_header
->msgh_bits
= legacy_base
.header
.msgh_bits
;
1148 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(legacy_base
.header
.msgh_remote_port
);
1149 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(legacy_base
.header
.msgh_local_port
);
1150 kmsg
->ikm_header
->msgh_reserved
= legacy_base
.header
.msgh_reserved
;
1151 kmsg
->ikm_header
->msgh_id
= legacy_base
.header
.msgh_id
;
1153 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
1156 " remote_port: %p\n"
1158 " reserved: 0x%.8x\n"
1160 kmsg
->ikm_header
->msgh_size
,
1161 kmsg
->ikm_header
->msgh_bits
,
1162 kmsg
->ikm_header
->msgh_remote_port
,
1163 kmsg
->ikm_header
->msgh_local_port
,
1164 kmsg
->ikm_header
->msgh_reserved
,
1165 kmsg
->ikm_header
->msgh_id
);
1167 if (copyinmsg(msg_addr
, (char *)(kmsg
->ikm_header
+ 1), size
- (mach_msg_size_t
)sizeof(mach_msg_header_t
))) {
1168 ipc_kmsg_free(kmsg
);
1169 return MACH_SEND_INVALID_DATA
;
1172 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
))
1174 kprintf("body: size: %lu\n", (size
- sizeof(mach_msg_header_t
)));
1176 for(i
=0;i
*4 < (size
- sizeof(mach_msg_header_t
));i
++)
1178 kprintf("%.4x\n",((uint32_t *)(kmsg
->ikm_header
+ 1))[i
]);
1181 DEBUG_IPC_KMSG_PRINT(kmsg
, "ipc_kmsg_get()");
1184 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1185 * However, the internal size field of the trailer (msgh_trailer_size)
1186 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
1187 * the cases where no implicit data is requested.
1189 trailer
= (mach_msg_max_trailer_t
*) ((vm_offset_t
)kmsg
->ikm_header
+ size
);
1190 trailer
->msgh_sender
= current_thread()->task
->sec_token
;
1191 trailer
->msgh_audit
= current_thread()->task
->audit_token
;
1192 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
1193 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
1196 if(trcWork
.traceMask
) dbgTrace(0x1100, (unsigned int)kmsg
->ikm_header
->msgh_id
,
1197 (unsigned int)kmsg
->ikm_header
->msgh_remote_port
,
1198 (unsigned int)kmsg
->ikm_header
->msgh_local_port
, 0);
1201 #if CONFIG_MACF_MACH
1202 /* XXX - why do we zero sender labels here instead of in mach_msg()? */
1203 task_t cur
= current_task();
1205 task_reference(cur
);
1206 kmsg
->ikm_sender
= cur
;
1208 trailer
->msgh_labels
.sender
= 0;
1210 trailer
->msgh_labels
.sender
= 0;
1214 return MACH_MSG_SUCCESS
;
1218 * Routine: ipc_kmsg_get_from_kernel
1220 * First checks for a preallocated message
1221 * reserved for kernel clients. If not found -
1222 * allocates a new kernel message buffer.
1223 * Copies a kernel message to the message buffer.
1224 * Only resource errors are allowed.
1227 * Ports in header are ipc_port_t.
1229 * MACH_MSG_SUCCESS Acquired a message buffer.
1230 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1234 ipc_kmsg_get_from_kernel(
1235 mach_msg_header_t
*msg
,
1236 mach_msg_size_t size
,
1240 mach_msg_size_t msg_and_trailer_size
;
1241 mach_msg_max_trailer_t
*trailer
;
1242 ipc_port_t dest_port
;
1244 assert(size
>= sizeof(mach_msg_header_t
));
1245 // assert((size & 3) == 0);
1247 assert(IP_VALID((ipc_port_t
) msg
->msgh_remote_port
));
1248 dest_port
= (ipc_port_t
)msg
->msgh_remote_port
;
1250 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
1253 * See if the port has a pre-allocated kmsg for kernel
1254 * clients. These are set up for those kernel clients
1255 * which cannot afford to wait.
1257 if (IP_PREALLOC(dest_port
)) {
1258 mach_msg_size_t max_desc
= 0;
1261 if (!ip_active(dest_port
)) {
1262 ip_unlock(dest_port
);
1263 return MACH_SEND_NO_BUFFER
;
1265 assert(IP_PREALLOC(dest_port
));
1266 kmsg
= dest_port
->ip_premsg
;
1267 if (ikm_prealloc_inuse(kmsg
)) {
1268 ip_unlock(dest_port
);
1269 return MACH_SEND_NO_BUFFER
;
1271 #if !defined(__LP64__)
1272 if (msg
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
1273 assert(size
> sizeof(mach_msg_base_t
));
1274 max_desc
= ((mach_msg_base_t
*)msg
)->body
.msgh_descriptor_count
*
1275 DESC_SIZE_ADJUSTMENT
;
1278 if (msg_and_trailer_size
> kmsg
->ikm_size
- max_desc
) {
1279 ip_unlock(dest_port
);
1280 return MACH_SEND_TOO_LARGE
;
1282 ikm_prealloc_set_inuse(kmsg
, dest_port
);
1283 ikm_set_header(kmsg
, msg_and_trailer_size
);
1284 ip_unlock(dest_port
);
1288 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
1289 if (kmsg
== IKM_NULL
)
1290 return MACH_SEND_NO_BUFFER
;
1293 (void) memcpy((void *) kmsg
->ikm_header
, (const void *) msg
, size
);
1295 kmsg
->ikm_header
->msgh_size
= size
;
1298 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1299 * However, the internal size field of the trailer (msgh_trailer_size)
1300 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
1301 * optimize the cases where no implicit data is requested.
1303 trailer
= (mach_msg_max_trailer_t
*)
1304 ((vm_offset_t
)kmsg
->ikm_header
+ size
);
1305 trailer
->msgh_sender
= KERNEL_SECURITY_TOKEN
;
1306 trailer
->msgh_audit
= KERNEL_AUDIT_TOKEN
;
1307 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
1308 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
1310 trailer
->msgh_labels
.sender
= 0;
1312 #if CONFIG_MACF_MACH
1313 kmsg
->ikm_sender
= NULL
;
1316 return MACH_MSG_SUCCESS
;
1320 * Routine: ipc_kmsg_send
1322 * Send a message. The message holds a reference
1323 * for the destination port in the msgh_remote_port field.
1325 * If unsuccessful, the caller still has possession of
1326 * the message and must do something with it. If successful,
1327 * the message is queued, given to a receiver, destroyed,
1328 * or handled directly by the kernel via mach_msg.
1332 * MACH_MSG_SUCCESS The message was accepted.
1333 * MACH_SEND_TIMED_OUT Caller still has message.
1334 * MACH_SEND_INTERRUPTED Caller still has message.
1339 mach_msg_option_t option
,
1340 mach_msg_timeout_t send_timeout
)
1343 mach_msg_return_t error
= MACH_MSG_SUCCESS
;
1346 port
= (ipc_port_t
) kmsg
->ikm_header
->msgh_remote_port
;
1347 assert(IP_VALID(port
));
1349 if ((option
& ~(MACH_SEND_TIMEOUT
|MACH_SEND_ALWAYS
)) != 0)
1350 printf("ipc_kmsg_send: bad option 0x%x\n", option
);
1354 if (port
->ip_receiver
== ipc_space_kernel
) {
1357 * We can check ip_receiver == ipc_space_kernel
1358 * before checking that the port is active because
1359 * ipc_port_dealloc_kernel clears ip_receiver
1360 * before destroying a kernel port.
1362 assert(ip_active(port
));
1363 port
->ip_messages
.imq_seqno
++;
1366 current_task()->messages_sent
++;
1369 * Call the server routine, and get the reply message to send.
1371 kmsg
= ipc_kobject_server(kmsg
);
1372 if (kmsg
== IKM_NULL
)
1373 return MACH_MSG_SUCCESS
;
1375 port
= (ipc_port_t
) kmsg
->ikm_header
->msgh_remote_port
;
1376 assert(IP_VALID(port
));
1378 /* fall thru with reply - same options */
1382 * Can't deliver to a dead port.
1383 * However, we can pretend it got sent
1384 * and was then immediately destroyed.
1386 if (!ip_active(port
)) {
1388 * We can't let ipc_kmsg_destroy deallocate
1389 * the port right, because we might end up
1390 * in an infinite loop trying to deliver
1391 * a send-once notification.
1395 ip_check_unlock(port
);
1396 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
1397 ipc_kmsg_destroy(kmsg
);
1398 return MACH_MSG_SUCCESS
;
1401 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_CIRCULAR
) {
1404 /* don't allow the creation of a circular loop */
1406 ipc_kmsg_destroy(kmsg
);
1407 return MACH_MSG_SUCCESS
;
1411 * We have a valid message and a valid reference on the port.
1412 * we can unlock the port and call mqueue_send() on its message
1413 * queue. Lock message queue while port is locked.
1416 imq_lock(&port
->ip_messages
);
1418 error
= ipc_mqueue_send(&port
->ip_messages
, kmsg
, option
,
1422 * If the port has been destroyed while we wait, treat the message
1423 * as a successful delivery (like we do for an inactive port).
1425 if (error
== MACH_SEND_INVALID_DEST
) {
1426 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
1427 ipc_kmsg_destroy(kmsg
);
1428 return MACH_MSG_SUCCESS
;
1434 * Routine: ipc_kmsg_put
1436 * Copies a message buffer to a user message.
1437 * Copies only the specified number of bytes.
1438 * Frees the message buffer.
1440 * Nothing locked. The message buffer must have clean
1443 * MACH_MSG_SUCCESS Copied data out of message buffer.
1444 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
1449 mach_vm_address_t msg_addr
,
1451 mach_msg_size_t size
)
1453 mach_msg_return_t mr
;
1455 DEBUG_IPC_KMSG_PRINT(kmsg
, "ipc_kmsg_put()");
1458 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
1461 " remote_port: %p\n"
1463 " reserved: 0x%.8x\n"
1465 kmsg
->ikm_header
->msgh_size
,
1466 kmsg
->ikm_header
->msgh_bits
,
1467 kmsg
->ikm_header
->msgh_remote_port
,
1468 kmsg
->ikm_header
->msgh_local_port
,
1469 kmsg
->ikm_header
->msgh_reserved
,
1470 kmsg
->ikm_header
->msgh_id
);
1472 #if defined(__LP64__)
1473 if (current_task() != kernel_task
) { /* don't if receiver expects fully-cooked in-kernel msg; ux_exception */
1474 mach_msg_legacy_header_t
*legacy_header
=
1475 (mach_msg_legacy_header_t
*)((vm_offset_t
)(kmsg
->ikm_header
) + LEGACY_HEADER_SIZE_DELTA
);
1477 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
1478 mach_msg_size_t msg_size
= kmsg
->ikm_header
->msgh_size
;
1479 mach_port_name_t remote_port
= CAST_MACH_PORT_TO_NAME(kmsg
->ikm_header
->msgh_remote_port
);
1480 mach_port_name_t local_port
= CAST_MACH_PORT_TO_NAME(kmsg
->ikm_header
->msgh_local_port
);
1481 mach_msg_size_t reserved
= kmsg
->ikm_header
->msgh_reserved
;
1482 mach_msg_id_t id
= kmsg
->ikm_header
->msgh_id
;
1484 legacy_header
->msgh_id
= id
;
1485 legacy_header
->msgh_reserved
= reserved
;
1486 legacy_header
->msgh_local_port
= local_port
;
1487 legacy_header
->msgh_remote_port
= remote_port
;
1488 legacy_header
->msgh_size
= msg_size
- LEGACY_HEADER_SIZE_DELTA
;
1489 legacy_header
->msgh_bits
= bits
;
1491 size
-= LEGACY_HEADER_SIZE_DELTA
;
1492 kmsg
->ikm_header
= (mach_msg_header_t
*)legacy_header
;
1496 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
1497 kprintf("ipc_kmsg_put header+body: %d\n", (size
));
1499 for(i
=0;i
*4 < size
;i
++)
1501 kprintf("%.4x\n",((uint32_t *)kmsg
->ikm_header
)[i
]);
1503 kprintf("type: %d\n", ((mach_msg_type_descriptor_t
*)(((mach_msg_base_t
*)kmsg
->ikm_header
)+1))->type
);
1505 if (copyoutmsg((const char *) kmsg
->ikm_header
, msg_addr
, size
))
1506 mr
= MACH_RCV_INVALID_DATA
;
1508 mr
= MACH_MSG_SUCCESS
;
1510 ipc_kmsg_free(kmsg
);
1515 * Routine: ipc_kmsg_put_to_kernel
1517 * Copies a message buffer to a kernel message.
1518 * Frees the message buffer.
1519 * No errors allowed.
1525 ipc_kmsg_put_to_kernel(
1526 mach_msg_header_t
*msg
,
1528 mach_msg_size_t size
)
1530 (void) memcpy((void *) msg
, (const void *) kmsg
->ikm_header
, size
);
1532 ipc_kmsg_free(kmsg
);
1536 * Routine: ipc_kmsg_copyin_header
1538 * "Copy-in" port rights in the header of a message.
1539 * Operates atomically; if it doesn't succeed the
1540 * message header and the space are left untouched.
1541 * If it does succeed the remote/local port fields
1542 * contain object pointers instead of port names,
1543 * and the bits field is updated. The destination port
1544 * will be a valid port pointer.
1546 * The notify argument implements the MACH_SEND_CANCEL option.
1547 * If it is not MACH_PORT_NULL, it should name a receive right.
1548 * If the processing of the destination port would generate
1549 * a port-deleted notification (because the right for the
1550 * destination port is destroyed and it had a request for
1551 * a dead-name notification registered), and the port-deleted
1552 * notification would be sent to the named receive right,
1553 * then it isn't sent and the send-once right for the notify
1554 * port is quietly destroyed.
1559 * MACH_MSG_SUCCESS Successful copyin.
1560 * MACH_SEND_INVALID_HEADER
1561 * Illegal value in the message header bits.
1562 * MACH_SEND_INVALID_DEST The space is dead.
1563 * MACH_SEND_INVALID_NOTIFY
1564 * Notify is non-null and doesn't name a receive right.
1565 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1566 * MACH_SEND_INVALID_DEST Can't copyin destination port.
1567 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1568 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
1569 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1573 ipc_kmsg_copyin_header(
1574 mach_msg_header_t
*msg
,
1576 mach_port_name_t notify
)
1578 mach_msg_bits_t mbits
= msg
->msgh_bits
& MACH_MSGH_BITS_USER
;
1579 mach_port_name_t dest_name
= CAST_MACH_PORT_TO_NAME(msg
->msgh_remote_port
);
1580 mach_port_name_t reply_name
= CAST_MACH_PORT_TO_NAME(msg
->msgh_local_port
);
1583 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
1584 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
1585 ipc_object_t dest_port
, reply_port
;
1586 ipc_port_t dest_soright
, reply_soright
;
1587 ipc_port_t notify_port
;
1590 if ((mbits
!= msg
->msgh_bits
) ||
1591 (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type
)) ||
1592 ((reply_type
== 0) ?
1593 (reply_name
!= MACH_PORT_NULL
) :
1594 !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type
)))
1595 return MACH_SEND_INVALID_HEADER
;
1597 reply_soright
= IP_NULL
; /* in case we go to invalid dest early */
1599 is_write_lock(space
);
1600 if (!space
->is_active
)
1603 if (!MACH_PORT_VALID(dest_name
))
1606 #if CONFIG_MACF_MACH
1608 * We do the port send check here instead of in ipc_kmsg_send()
1609 * because copying the header involves copying the port rights too
1610 * and we need to do the send check before anything is actually copied.
1612 entry
= ipc_entry_lookup(space
, dest_name
);
1613 if (entry
!= IE_NULL
) {
1615 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
1616 if (port
== IP_NULL
)
1619 if (ip_active(port
)) {
1620 task_t self
= current_task();
1621 tasklabel_lock(self
);
1622 error
= mac_port_check_send(&self
->maclabel
,
1624 tasklabel_unlock(self
);
1632 if (notify
!= MACH_PORT_NULL
) {
1633 if ((entry
= ipc_entry_lookup(space
, notify
)) == IE_NULL
) {
1634 is_write_unlock(space
);
1635 return MACH_SEND_INVALID_NOTIFY
;
1637 if((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1638 is_write_unlock(space
);
1639 return MACH_SEND_INVALID_NOTIFY
;
1642 notify_port
= (ipc_port_t
) entry
->ie_object
;
1644 notify_port
= IP_NULL
;
1646 if (dest_name
== reply_name
) {
1647 mach_port_name_t name
= dest_name
;
1650 * Destination and reply ports are the same!
1651 * This is a little tedious to make atomic, because
1652 * there are 25 combinations of dest_type/reply_type.
1653 * However, most are easy. If either is move-sonce,
1654 * then there must be an error. If either are
1655 * make-send or make-sonce, then we must be looking
1656 * at a receive right so the port can't die.
1657 * The hard cases are the combinations of
1658 * copy-send and make-send.
1661 entry
= ipc_entry_lookup(space
, name
);
1662 if (entry
== IE_NULL
)
1665 assert(reply_type
!= 0); /* because name not null */
1667 if (!ipc_right_copyin_check(space
, name
, entry
, reply_type
))
1670 if ((dest_type
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) ||
1671 (reply_type
== MACH_MSG_TYPE_MOVE_SEND_ONCE
)) {
1673 * Why must there be an error? To get a valid
1674 * destination, this entry must name a live
1675 * port (not a dead name or dead port). However
1676 * a successful move-sonce will destroy a
1677 * live entry. Therefore the other copyin,
1678 * whatever it is, would fail. We've already
1679 * checked for reply port errors above,
1680 * so report a destination error.
1684 } else if ((dest_type
== MACH_MSG_TYPE_MAKE_SEND
) ||
1685 (dest_type
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) ||
1686 (reply_type
== MACH_MSG_TYPE_MAKE_SEND
) ||
1687 (reply_type
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) {
1688 kr
= ipc_right_copyin(space
, name
, entry
,
1690 &dest_port
, &dest_soright
);
1691 if (kr
!= KERN_SUCCESS
)
1695 * Either dest or reply needs a receive right.
1696 * We know the receive right is there, because
1697 * of the copyin_check and copyin calls. Hence
1698 * the port is not in danger of dying. If dest
1699 * used the receive right, then the right needed
1700 * by reply (and verified by copyin_check) will
1704 assert(IO_VALID(dest_port
));
1705 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
1706 assert(dest_soright
== IP_NULL
);
1708 kr
= ipc_right_copyin(space
, name
, entry
,
1710 &reply_port
, &reply_soright
);
1712 assert(kr
== KERN_SUCCESS
);
1713 assert(reply_port
== dest_port
);
1714 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
1715 assert(reply_soright
== IP_NULL
);
1716 } else if ((dest_type
== MACH_MSG_TYPE_COPY_SEND
) &&
1717 (reply_type
== MACH_MSG_TYPE_COPY_SEND
)) {
1719 * To make this atomic, just do one copy-send,
1720 * and dup the send right we get out.
1723 kr
= ipc_right_copyin(space
, name
, entry
,
1725 &dest_port
, &dest_soright
);
1726 if (kr
!= KERN_SUCCESS
)
1729 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND
);
1730 assert(dest_soright
== IP_NULL
);
1733 * It's OK if the port we got is dead now,
1734 * so reply_port is IP_DEAD, because the msg
1735 * won't go anywhere anyway.
1738 reply_port
= (ipc_object_t
)
1739 ipc_port_copy_send((ipc_port_t
) dest_port
);
1740 reply_soright
= IP_NULL
;
1741 } else if ((dest_type
== MACH_MSG_TYPE_MOVE_SEND
) &&
1742 (reply_type
== MACH_MSG_TYPE_MOVE_SEND
)) {
1744 * This is an easy case. Just use our
1745 * handy-dandy special-purpose copyin call
1746 * to get two send rights for the price of one.
1749 kr
= ipc_right_copyin_two(space
, name
, entry
,
1750 &dest_port
, &dest_soright
);
1751 if (kr
!= KERN_SUCCESS
)
1754 /* the entry might need to be deallocated */
1755 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1756 ipc_entry_dealloc(space
, name
, entry
);
1758 reply_port
= dest_port
;
1759 reply_soright
= IP_NULL
;
1763 assert(((dest_type
== MACH_MSG_TYPE_COPY_SEND
) &&
1764 (reply_type
== MACH_MSG_TYPE_MOVE_SEND
)) ||
1765 ((dest_type
== MACH_MSG_TYPE_MOVE_SEND
) &&
1766 (reply_type
== MACH_MSG_TYPE_COPY_SEND
)));
1769 * To make this atomic, just do a move-send,
1770 * and dup the send right we get out.
1773 kr
= ipc_right_copyin(space
, name
, entry
,
1774 MACH_MSG_TYPE_MOVE_SEND
, FALSE
,
1775 &dest_port
, &soright
);
1776 if (kr
!= KERN_SUCCESS
)
1779 /* the entry might need to be deallocated */
1781 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1782 ipc_entry_dealloc(space
, name
, entry
);
1785 * It's OK if the port we got is dead now,
1786 * so reply_port is IP_DEAD, because the msg
1787 * won't go anywhere anyway.
1790 reply_port
= (ipc_object_t
)
1791 ipc_port_copy_send((ipc_port_t
) dest_port
);
1793 if (dest_type
== MACH_MSG_TYPE_MOVE_SEND
) {
1794 dest_soright
= soright
;
1795 reply_soright
= IP_NULL
;
1797 dest_soright
= IP_NULL
;
1798 reply_soright
= soright
;
1801 } else if (!MACH_PORT_VALID(reply_name
)) {
1803 * No reply port! This is an easy case
1804 * to make atomic. Just copyin the destination.
1807 entry
= ipc_entry_lookup(space
, dest_name
);
1808 if (entry
== IE_NULL
)
1811 kr
= ipc_right_copyin(space
, dest_name
, entry
,
1813 &dest_port
, &dest_soright
);
1814 if (kr
!= KERN_SUCCESS
)
1817 /* the entry might need to be deallocated */
1819 if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1820 ipc_entry_dealloc(space
, dest_name
, entry
);
1822 reply_port
= (ipc_object_t
)CAST_MACH_NAME_TO_PORT(reply_name
);
1823 reply_soright
= IP_NULL
;
1825 ipc_entry_t dest_entry
, reply_entry
;
1828 * This is the tough case to make atomic.
1829 * The difficult problem is serializing with port death.
1830 * At the time we copyin dest_port, it must be alive.
1831 * If reply_port is alive when we copyin it, then
1832 * we are OK, because we serialize before the death
1833 * of both ports. Assume reply_port is dead at copyin.
1834 * Then if dest_port dies/died after reply_port died,
1835 * we are OK, because we serialize between the death
1836 * of the two ports. So the bad case is when dest_port
1837 * dies after its copyin, reply_port dies before its
1838 * copyin, and dest_port dies before reply_port. Then
1839 * the copyins operated as if dest_port was alive
1840 * and reply_port was dead, which shouldn't have happened
1841 * because they died in the other order.
1843 * Note that it is easy for a user task to tell if
1844 * a copyin happened before or after a port died.
1845 * For example, suppose both dest and reply are
1846 * send-once rights (types are both move-sonce) and
1847 * both rights have dead-name requests registered.
1848 * If a port dies before copyin, a dead-name notification
1849 * is generated and the dead name's urefs are incremented,
1850 * and if the copyin happens first, a port-deleted
1851 * notification is generated.
1853 * Note that although the entries are different,
1854 * dest_port and reply_port might still be the same.
1856 * JMM - The code to handle this was too expensive and, anyway,
1857 * we intend to separate the dest lookup from the reply copyin
1858 * by a wide margin, so the user will have to learn to deal!
1859 * I will be making the change soon!
1862 dest_entry
= ipc_entry_lookup(space
, dest_name
);
1863 if (dest_entry
== IE_NULL
)
1866 reply_entry
= ipc_entry_lookup(space
, reply_name
);
1867 if (reply_entry
== IE_NULL
)
1870 assert(dest_entry
!= reply_entry
); /* names are not equal */
1871 assert(reply_type
!= 0); /* because reply_name not null */
1873 if (!ipc_right_copyin_check(space
, reply_name
, reply_entry
,
1877 kr
= ipc_right_copyin(space
, dest_name
, dest_entry
,
1879 &dest_port
, &dest_soright
);
1880 if (kr
!= KERN_SUCCESS
)
1883 assert(IO_VALID(dest_port
));
1885 kr
= ipc_right_copyin(space
, reply_name
, reply_entry
,
1887 &reply_port
, &reply_soright
);
1889 assert(kr
== KERN_SUCCESS
);
1891 /* the entries might need to be deallocated */
1893 if (IE_BITS_TYPE(reply_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1894 ipc_entry_dealloc(space
, reply_name
, reply_entry
);
1896 if (IE_BITS_TYPE(dest_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
1897 ipc_entry_dealloc(space
, dest_name
, dest_entry
);
1901 * At this point, dest_port, reply_port,
1902 * dest_soright, reply_soright are all initialized.
1903 * Any defunct entries have been deallocated.
1904 * The space is still write-locked, and we need to
1905 * make the MACH_SEND_CANCEL check. The notify_port pointer
1906 * is still usable, because the copyin code above won't ever
1907 * deallocate a receive right, so its entry still exists
1908 * and holds a ref. Note notify_port might even equal
1909 * dest_port or reply_port.
1912 if ((notify
!= MACH_PORT_NULL
) &&
1913 (dest_soright
== notify_port
)) {
1914 ipc_port_release_sonce(dest_soright
);
1915 dest_soright
= IP_NULL
;
1918 is_write_unlock(space
);
1920 if (dest_soright
!= IP_NULL
)
1921 ipc_notify_port_deleted(dest_soright
, dest_name
);
1923 if (reply_soright
!= IP_NULL
)
1924 ipc_notify_port_deleted(reply_soright
, reply_name
);
1926 dest_type
= ipc_object_copyin_type(dest_type
);
1927 reply_type
= ipc_object_copyin_type(reply_type
);
1929 msg
->msgh_bits
= (MACH_MSGH_BITS_OTHER(mbits
) |
1930 MACH_MSGH_BITS(dest_type
, reply_type
));
1931 msg
->msgh_remote_port
= (ipc_port_t
)dest_port
;
1932 msg
->msgh_local_port
= (ipc_port_t
)reply_port
;
1934 return MACH_MSG_SUCCESS
;
1937 is_write_unlock(space
);
1938 return MACH_SEND_INVALID_REPLY
;
1941 is_write_unlock(space
);
1942 if (reply_soright
!= IP_NULL
)
1943 ipc_notify_port_deleted(reply_soright
, reply_name
);
1944 return MACH_SEND_INVALID_DEST
;
1947 mach_msg_descriptor_t
*ipc_kmsg_copyin_port_descriptor(
1948 volatile mach_msg_port_descriptor_t
*dsc
,
1949 mach_msg_legacy_port_descriptor_t
*user_dsc
,
1953 mach_msg_return_t
*mr
);
1955 void ipc_print_type_name(
1957 mach_msg_descriptor_t
*
1958 ipc_kmsg_copyin_port_descriptor(
1959 volatile mach_msg_port_descriptor_t
*dsc
,
1960 mach_msg_legacy_port_descriptor_t
*user_dsc_in
,
1964 mach_msg_return_t
*mr
)
1966 volatile mach_msg_legacy_port_descriptor_t
*user_dsc
= user_dsc_in
;
1967 mach_msg_type_name_t user_disp
;
1968 mach_msg_type_name_t result_disp
;
1969 mach_port_name_t name
;
1970 ipc_object_t object
;
1972 user_disp
= user_dsc
->disposition
;
1973 result_disp
= ipc_object_copyin_type(user_disp
);
1975 name
= (mach_port_name_t
)user_dsc
->name
;
1976 if (MACH_PORT_VALID(name
)) {
1978 kern_return_t kr
= ipc_object_copyin(space
, name
, user_disp
, &object
);
1979 if (kr
!= KERN_SUCCESS
) {
1980 *mr
= MACH_SEND_INVALID_RIGHT
;
1984 if ((result_disp
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
1985 ipc_port_check_circularity((ipc_port_t
) object
,
1986 (ipc_port_t
) dest
)) {
1987 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
1989 dsc
->name
= (ipc_port_t
) object
;
1991 dsc
->name
= CAST_MACH_NAME_TO_PORT(name
);
1993 dsc
->disposition
= result_disp
;
1994 dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
1996 dsc
->pad_end
= 0; // debug, unnecessary
1998 return (mach_msg_descriptor_t
*)(user_dsc_in
+1);
2001 mach_msg_descriptor_t
* ipc_kmsg_copyin_ool_descriptor(
2002 mach_msg_ool_descriptor_t
*dsc
,
2003 mach_msg_descriptor_t
*user_dsc
,
2006 vm_map_copy_t
*copy
,
2007 vm_size_t
*space_needed
,
2009 mach_msg_return_t
*mr
);
2010 mach_msg_descriptor_t
*
2011 ipc_kmsg_copyin_ool_descriptor(
2012 mach_msg_ool_descriptor_t
*dsc
,
2013 mach_msg_descriptor_t
*user_dsc
,
2016 vm_map_copy_t
*copy
,
2017 vm_size_t
*space_needed
,
2019 mach_msg_return_t
*mr
)
2023 mach_msg_copy_options_t copy_options
;
2024 mach_vm_offset_t addr
;
2025 mach_msg_descriptor_type_t dsc_type
;
2028 mach_msg_ool_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2030 addr
= (mach_vm_offset_t
) user_ool_dsc
->address
;
2031 length
= user_ool_dsc
->size
;
2032 dealloc
= user_ool_dsc
->deallocate
;
2033 copy_options
= user_ool_dsc
->copy
;
2034 dsc_type
= user_ool_dsc
->type
;
2036 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2038 mach_msg_ool_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2040 addr
= CAST_USER_ADDR_T(user_ool_dsc
->address
);
2041 dealloc
= user_ool_dsc
->deallocate
;
2042 copy_options
= user_ool_dsc
->copy
;
2043 dsc_type
= user_ool_dsc
->type
;
2044 length
= user_ool_dsc
->size
;
2046 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2049 dsc
->size
= (mach_msg_size_t
)length
;
2050 dsc
->deallocate
= dealloc
;
2051 dsc
->copy
= copy_options
;
2052 dsc
->type
= dsc_type
;
2055 dsc
->address
= NULL
;
2056 } else if ((length
>= MSG_OOL_SIZE_SMALL
) &&
2057 (copy_options
== MACH_MSG_PHYSICAL_COPY
) && !dealloc
) {
2060 * If the request is a physical copy and the source
2061 * is not being deallocated, then allocate space
2062 * in the kernel's pageable ipc copy map and copy
2063 * the data in. The semantics guarantee that the
2064 * data will have been physically copied before
2065 * the send operation terminates. Thus if the data
2066 * is not being deallocated, we must be prepared
2067 * to page if the region is sufficiently large.
2069 if (copyin(addr
, (char *)*paddr
, length
)) {
2070 *mr
= MACH_SEND_INVALID_MEMORY
;
2075 * The kernel ipc copy map is marked no_zero_fill.
2076 * If the transfer is not a page multiple, we need
2077 * to zero fill the balance.
2079 if (!page_aligned(length
)) {
2080 (void) memset((void *) (*paddr
+ length
), 0,
2081 round_page(length
) - length
);
2083 if (vm_map_copyin(ipc_kernel_copy_map
, (vm_map_address_t
)*paddr
,
2084 (vm_map_size_t
)length
, TRUE
, copy
) != KERN_SUCCESS
) {
2085 *mr
= MACH_MSG_VM_KERNEL
;
2088 dsc
->address
= (void *)*copy
;
2089 *paddr
+= round_page(length
);
2090 *space_needed
-= round_page(length
);
2094 * Make a vm_map_copy_t of the of the data. If the
2095 * data is small, this will do an optimized physical
2096 * copy. Otherwise, it will do a virtual copy.
2098 * NOTE: A virtual copy is OK if the original is being
2099 * deallocted, even if a physical copy was requested.
2101 kern_return_t kr
= vm_map_copyin(map
, addr
,
2102 (vm_map_size_t
)length
, dealloc
, copy
);
2103 if (kr
!= KERN_SUCCESS
) {
2104 *mr
= (kr
== KERN_RESOURCE_SHORTAGE
) ?
2105 MACH_MSG_VM_KERNEL
:
2106 MACH_SEND_INVALID_MEMORY
;
2109 dsc
->address
= (void *)*copy
;
2114 mach_msg_descriptor_t
* ipc_kmsg_copyin_ool_ports_descriptor(
2115 mach_msg_ool_ports_descriptor_t
*dsc
,
2116 mach_msg_descriptor_t
*user_dsc
,
2122 mach_msg_return_t
*mr
);
2123 mach_msg_descriptor_t
*
2124 ipc_kmsg_copyin_ool_ports_descriptor(
2125 mach_msg_ool_ports_descriptor_t
*dsc
,
2126 mach_msg_descriptor_t
*user_dsc
,
2132 mach_msg_return_t
*mr
)
2135 ipc_object_t
*objects
;
2137 mach_vm_offset_t addr
;
2138 mach_msg_type_name_t user_disp
;
2139 mach_msg_type_name_t result_disp
;
2140 mach_msg_type_number_t count
;
2141 mach_msg_copy_options_t copy_option
;
2142 boolean_t deallocate
;
2143 mach_msg_descriptor_type_t type
;
2144 vm_size_t ports_length
, names_length
;
2147 mach_msg_ool_ports_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2149 addr
= (mach_vm_offset_t
)user_ool_dsc
->address
;
2150 count
= user_ool_dsc
->count
;
2151 deallocate
= user_ool_dsc
->deallocate
;
2152 copy_option
= user_ool_dsc
->copy
;
2153 user_disp
= user_ool_dsc
->disposition
;
2154 type
= user_ool_dsc
->type
;
2156 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2158 mach_msg_ool_ports_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2160 addr
= CAST_USER_ADDR_T(user_ool_dsc
->address
);
2161 count
= user_ool_dsc
->count
;
2162 deallocate
= user_ool_dsc
->deallocate
;
2163 copy_option
= user_ool_dsc
->copy
;
2164 user_disp
= user_ool_dsc
->disposition
;
2165 type
= user_ool_dsc
->type
;
2167 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2170 dsc
->deallocate
= deallocate
;
2171 dsc
->copy
= copy_option
;
2174 dsc
->address
= NULL
; /* for now */
2176 result_disp
= ipc_object_copyin_type(user_disp
);
2177 dsc
->disposition
= result_disp
;
2179 if (count
> (INT_MAX
/ sizeof(mach_port_t
))) {
2180 *mr
= MACH_SEND_TOO_LARGE
;
2184 /* calculate length of data in bytes, rounding up */
2185 ports_length
= count
* sizeof(mach_port_t
);
2186 names_length
= count
* sizeof(mach_port_name_t
);
2188 if (ports_length
== 0) {
2192 data
= kalloc(ports_length
);
2195 *mr
= MACH_SEND_NO_BUFFER
;
2200 mach_port_name_t
*names
= &((mach_port_name_t
*)data
)[count
];
2202 mach_port_name_t
*names
= ((mach_port_name_t
*)data
);
2205 if (copyinmap(map
, addr
, names
, names_length
) != KERN_SUCCESS
) {
2206 kfree(data
, ports_length
);
2207 *mr
= MACH_SEND_INVALID_MEMORY
;
2212 (void) mach_vm_deallocate(map
, addr
, (mach_vm_size_t
)ports_length
);
2215 objects
= (ipc_object_t
*) data
;
2216 dsc
->address
= data
;
2218 for ( i
= 0; i
< count
; i
++) {
2219 mach_port_name_t name
= names
[i
];
2220 ipc_object_t object
;
2222 if (!MACH_PORT_VALID(name
)) {
2223 objects
[i
] = (ipc_object_t
)CAST_MACH_NAME_TO_PORT(name
);
2227 kern_return_t kr
= ipc_object_copyin(space
, name
, user_disp
, &object
);
2229 if (kr
!= KERN_SUCCESS
) {
2232 for(j
= 0; j
< i
; j
++) {
2233 object
= objects
[j
];
2234 if (IPC_OBJECT_VALID(object
))
2235 ipc_object_destroy(object
, result_disp
);
2237 kfree(data
, ports_length
);
2238 dsc
->address
= NULL
;
2239 *mr
= MACH_SEND_INVALID_RIGHT
;
2243 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2244 ipc_port_check_circularity(
2245 (ipc_port_t
) object
,
2247 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
2249 objects
[i
] = object
;
2256 * Routine: ipc_kmsg_copyin_body
2258 * "Copy-in" port rights and out-of-line memory
2259 * in the message body.
2261 * In all failure cases, the message is left holding
2262 * no rights or memory. However, the message buffer
2263 * is not deallocated. If successful, the message
2264 * contains a valid destination port.
2268 * MACH_MSG_SUCCESS Successful copyin.
2269 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2270 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2271 * MACH_SEND_INVALID_TYPE Bad type specification.
2272 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2273 * MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
2274 * MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
2278 ipc_kmsg_copyin_body(
2284 mach_msg_body_t
*body
;
2285 mach_msg_descriptor_t
*daddr
, *naddr
;
2286 mach_msg_descriptor_t
*user_addr
, *kern_addr
;
2287 mach_msg_type_number_t dsc_count
;
2288 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
2289 boolean_t
complex = FALSE
;
2290 vm_size_t space_needed
= 0;
2291 vm_offset_t paddr
= 0;
2292 vm_map_copy_t copy
= VM_MAP_COPY_NULL
;
2293 mach_msg_type_number_t i
;
2294 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
2296 vm_size_t descriptor_size
= 0;
2299 * Determine if the target is a kernel port.
2301 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
2302 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
2303 naddr
= (mach_msg_descriptor_t
*) (body
+ 1);
2305 dsc_count
= body
->msgh_descriptor_count
;
2307 return MACH_MSG_SUCCESS
;
2310 * Make an initial pass to determine kernal VM space requirements for
2311 * physical copies and possible contraction of the descriptors from
2312 * processes with pointers larger than the kernel's.
2315 for (i
= 0; i
< dsc_count
; i
++) {
2318 /* make sure the descriptor fits in the message */
2319 if (is_task_64bit
) {
2320 switch (daddr
->type
.type
) {
2321 case MACH_MSG_OOL_DESCRIPTOR
:
2322 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2323 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2324 descriptor_size
+= 16;
2325 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 16);
2328 descriptor_size
+= 12;
2329 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 12);
2333 descriptor_size
+= 12;
2334 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 12);
2337 if (naddr
> (mach_msg_descriptor_t
*)
2338 ((vm_offset_t
)kmsg
->ikm_header
+ kmsg
->ikm_header
->msgh_size
)) {
2339 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
2340 mr
= MACH_SEND_MSG_TOO_SMALL
;
2344 switch (daddr
->type
.type
) {
2345 mach_msg_size_t size
;
2347 case MACH_MSG_OOL_DESCRIPTOR
:
2348 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2349 size
= (is_task_64bit
) ?
2350 ((mach_msg_ool_descriptor64_t
*)daddr
)->size
:
2351 daddr
->out_of_line
.size
;
2353 if (daddr
->out_of_line
.copy
!= MACH_MSG_PHYSICAL_COPY
&&
2354 daddr
->out_of_line
.copy
!= MACH_MSG_VIRTUAL_COPY
) {
2356 * Invalid copy option
2358 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
2359 mr
= MACH_SEND_INVALID_TYPE
;
2363 if ((size
>= MSG_OOL_SIZE_SMALL
) &&
2364 (daddr
->out_of_line
.copy
== MACH_MSG_PHYSICAL_COPY
) &&
2365 !(daddr
->out_of_line
.deallocate
)) {
2368 * Out-of-line memory descriptor, accumulate kernel
2369 * memory requirements
2371 space_needed
+= round_page(size
);
2372 if (space_needed
> ipc_kmsg_max_vm_space
) {
2375 * Per message kernel memory limit exceeded
2377 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
2378 mr
= MACH_MSG_VM_KERNEL
;
2386 * Allocate space in the pageable kernel ipc copy map for all the
2387 * ool data that is to be physically copied. Map is marked wait for
2391 if (vm_allocate(ipc_kernel_copy_map
, &paddr
, space_needed
,
2392 VM_FLAGS_ANYWHERE
) != KERN_SUCCESS
) {
2393 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
2394 mr
= MACH_MSG_VM_KERNEL
;
2399 /* user_addr = just after base as it was copied in */
2400 user_addr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
2401 /* Shift the mach_msg_base_t down to make for dsc_count*16bytes of descriptors */
2402 if(descriptor_size
!= 16*dsc_count
) {
2403 vm_offset_t dsc_adjust
= 16*dsc_count
- descriptor_size
;
2404 memmove((char *)(((vm_offset_t
)kmsg
->ikm_header
) - dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
2405 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
- dsc_adjust
);
2406 /* Update the message size for the larger in-kernel representation */
2407 kmsg
->ikm_header
->msgh_size
+= (mach_msg_size_t
)dsc_adjust
;
2411 /* kern_addr = just after base after it has been (conditionally) moved */
2412 kern_addr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
2414 /* handle the OOL regions and port descriptors. */
2415 for(i
=0;i
<dsc_count
;i
++) {
2416 switch (user_addr
->type
.type
) {
2417 case MACH_MSG_PORT_DESCRIPTOR
:
2418 user_addr
= ipc_kmsg_copyin_port_descriptor((mach_msg_port_descriptor_t
*)kern_addr
,
2419 (mach_msg_legacy_port_descriptor_t
*)user_addr
, space
, dest
, kmsg
, &mr
);
2423 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2424 case MACH_MSG_OOL_DESCRIPTOR
:
2425 user_addr
= ipc_kmsg_copyin_ool_descriptor((mach_msg_ool_descriptor_t
*)kern_addr
,
2426 user_addr
, is_task_64bit
, &paddr
, ©
, &space_needed
, map
, &mr
);
2430 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2431 user_addr
= ipc_kmsg_copyin_ool_ports_descriptor((mach_msg_ool_ports_descriptor_t
*)kern_addr
,
2432 user_addr
, is_task_64bit
, map
, space
, dest
, kmsg
, &mr
);
2437 /* Invalid descriptor */
2438 mr
= MACH_SEND_INVALID_TYPE
;
2442 if (MACH_MSG_SUCCESS
!= mr
) {
2443 /* clean from start of message descriptors to i */
2444 ipc_kmsg_clean_partial(kmsg
, i
,
2445 (mach_msg_descriptor_t
*)((mach_msg_base_t
*)kmsg
->ikm_header
+ 1),
2446 paddr
, space_needed
);
2452 kmsg
->ikm_header
->msgh_bits
&= ~MACH_MSGH_BITS_COMPLEX
;
2460 * Routine: ipc_kmsg_copyin
2462 * "Copy-in" port rights and out-of-line memory
2465 * In all failure cases, the message is left holding
2466 * no rights or memory. However, the message buffer
2467 * is not deallocated. If successful, the message
2468 * contains a valid destination port.
2472 * MACH_MSG_SUCCESS Successful copyin.
2473 * MACH_SEND_INVALID_HEADER
2474 * Illegal value in the message header bits.
2475 * MACH_SEND_INVALID_NOTIFY Bad notify port.
2476 * MACH_SEND_INVALID_DEST Can't copyin destination port.
2477 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
2478 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2479 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2480 * MACH_SEND_INVALID_TYPE Bad type specification.
2481 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2489 mach_port_name_t notify
)
2491 mach_msg_return_t mr
;
2493 mr
= ipc_kmsg_copyin_header(kmsg
->ikm_header
, space
, notify
);
2494 if (mr
!= MACH_MSG_SUCCESS
)
2497 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_copyin header:\n%.8x\n%.8x\n%p\n%p\n%.8x\n%.8x\n",
2498 kmsg
->ikm_header
->msgh_size
,
2499 kmsg
->ikm_header
->msgh_bits
,
2500 kmsg
->ikm_header
->msgh_remote_port
,
2501 kmsg
->ikm_header
->msgh_local_port
,
2502 kmsg
->ikm_header
->msgh_reserved
,
2503 kmsg
->ikm_header
->msgh_id
);
2505 if ((kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
2506 return MACH_MSG_SUCCESS
;
2508 mr
= ipc_kmsg_copyin_body( kmsg
, space
, map
);
2510 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
))
2514 for(i
=0;i
*4 < (kmsg
->ikm_header
->msgh_size
- sizeof(mach_msg_header_t
));i
++)
2516 kprintf("%.4x\n",((uint32_t *)(kmsg
->ikm_header
+ 1))[i
]);
2523 * Routine: ipc_kmsg_copyin_from_kernel
2525 * "Copy-in" port rights and out-of-line memory
2526 * in a message sent from the kernel.
2528 * Because the message comes from the kernel,
2529 * the implementation assumes there are no errors
2530 * or peculiarities in the message.
2532 * Returns TRUE if queueing the message
2533 * would result in a circularity.
2539 ipc_kmsg_copyin_from_kernel(
2542 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
2543 mach_msg_type_name_t rname
= MACH_MSGH_BITS_REMOTE(bits
);
2544 mach_msg_type_name_t lname
= MACH_MSGH_BITS_LOCAL(bits
);
2545 ipc_object_t remote
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
2546 ipc_object_t local
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
2548 /* translate the destination and reply ports */
2550 ipc_object_copyin_from_kernel(remote
, rname
);
2551 if (IO_VALID(local
))
2552 ipc_object_copyin_from_kernel(local
, lname
);
2555 * The common case is a complex message with no reply port,
2556 * because that is what the memory_object interface uses.
2559 if (bits
== (MACH_MSGH_BITS_COMPLEX
|
2560 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0))) {
2561 bits
= (MACH_MSGH_BITS_COMPLEX
|
2562 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND
, 0));
2564 kmsg
->ikm_header
->msgh_bits
= bits
;
2566 bits
= (MACH_MSGH_BITS_OTHER(bits
) |
2567 MACH_MSGH_BITS(ipc_object_copyin_type(rname
),
2568 ipc_object_copyin_type(lname
)));
2570 kmsg
->ikm_header
->msgh_bits
= bits
;
2571 if ((bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
2575 mach_msg_descriptor_t
*saddr
;
2576 mach_msg_body_t
*body
;
2577 mach_msg_type_number_t i
, count
;
2579 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
2580 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
2581 count
= body
->msgh_descriptor_count
;
2583 for (i
= 0; i
< count
; i
++, saddr
++) {
2585 switch (saddr
->type
.type
) {
2587 case MACH_MSG_PORT_DESCRIPTOR
: {
2588 mach_msg_type_name_t name
;
2589 ipc_object_t object
;
2590 mach_msg_port_descriptor_t
*dsc
;
2594 /* this is really the type SEND, SEND_ONCE, etc. */
2595 name
= dsc
->disposition
;
2596 object
= (ipc_object_t
) dsc
->name
;
2597 dsc
->disposition
= ipc_object_copyin_type(name
);
2599 if (!IO_VALID(object
)) {
2603 ipc_object_copyin_from_kernel(object
, name
);
2605 /* CDY avoid circularity when the destination is also */
2606 /* the kernel. This check should be changed into an */
2607 /* assert when the new kobject model is in place since*/
2608 /* ports will not be used in kernel to kernel chats */
2610 if (((ipc_port_t
)remote
)->ip_receiver
!= ipc_space_kernel
) {
2611 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2612 ipc_port_check_circularity((ipc_port_t
) object
,
2613 (ipc_port_t
) remote
)) {
2614 kmsg
->ikm_header
->msgh_bits
|=
2615 MACH_MSGH_BITS_CIRCULAR
;
2620 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2621 case MACH_MSG_OOL_DESCRIPTOR
: {
2623 * The sender should supply ready-made memory, i.e.
2624 * a vm_map_copy_t, so we don't need to do anything.
2628 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
2629 ipc_object_t
*objects
;
2631 mach_msg_type_name_t name
;
2632 mach_msg_ool_ports_descriptor_t
*dsc
;
2634 dsc
= (mach_msg_ool_ports_descriptor_t
*)&saddr
->ool_ports
;
2636 /* this is really the type SEND, SEND_ONCE, etc. */
2637 name
= dsc
->disposition
;
2638 dsc
->disposition
= ipc_object_copyin_type(name
);
2640 objects
= (ipc_object_t
*) dsc
->address
;
2642 for ( j
= 0; j
< dsc
->count
; j
++) {
2643 ipc_object_t object
= objects
[j
];
2645 if (!IO_VALID(object
))
2648 ipc_object_copyin_from_kernel(object
, name
);
2650 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2651 ipc_port_check_circularity(
2652 (ipc_port_t
) object
,
2653 (ipc_port_t
) remote
))
2654 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
2660 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
2661 #endif /* MACH_ASSERT */
2668 #if IKM_SUPPORT_LEGACY
2670 ipc_kmsg_copyin_from_kernel_legacy(
2673 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
2674 mach_msg_type_name_t rname
= MACH_MSGH_BITS_REMOTE(bits
);
2675 mach_msg_type_name_t lname
= MACH_MSGH_BITS_LOCAL(bits
);
2676 ipc_object_t remote
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
2677 ipc_object_t local
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
2679 /* translate the destination and reply ports */
2681 ipc_object_copyin_from_kernel(remote
, rname
);
2682 if (IO_VALID(local
))
2683 ipc_object_copyin_from_kernel(local
, lname
);
2686 * The common case is a complex message with no reply port,
2687 * because that is what the memory_object interface uses.
2690 if (bits
== (MACH_MSGH_BITS_COMPLEX
|
2691 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0))) {
2692 bits
= (MACH_MSGH_BITS_COMPLEX
|
2693 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND
, 0));
2695 kmsg
->ikm_header
->msgh_bits
= bits
;
2697 bits
= (MACH_MSGH_BITS_OTHER(bits
) |
2698 MACH_MSGH_BITS(ipc_object_copyin_type(rname
),
2699 ipc_object_copyin_type(lname
)));
2701 kmsg
->ikm_header
->msgh_bits
= bits
;
2702 if ((bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
2706 mach_msg_legacy_descriptor_t
*saddr
;
2707 mach_msg_descriptor_t
*daddr
;
2708 mach_msg_body_t
*body
;
2709 mach_msg_type_number_t i
, count
;
2711 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
2712 saddr
= (typeof(saddr
)) (body
+ 1);
2713 count
= body
->msgh_descriptor_count
;
2716 vm_offset_t dsc_adjust
= 4*count
;
2717 memmove((char *)(((vm_offset_t
)kmsg
->ikm_header
) - dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
2718 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
- dsc_adjust
);
2719 /* Update the message size for the larger in-kernel representation */
2720 kmsg
->ikm_header
->msgh_size
+= dsc_adjust
;
2722 daddr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
2724 for (i
= 0; i
< count
; i
++, saddr
++, daddr
++) {
2725 switch (saddr
->type
.type
) {
2727 case MACH_MSG_PORT_DESCRIPTOR
: {
2728 mach_msg_type_name_t name
;
2729 ipc_object_t object
;
2730 mach_msg_legacy_port_descriptor_t
*dsc
;
2731 mach_msg_port_descriptor_t
*dest_dsc
;
2733 dsc
= (typeof(dsc
))&saddr
->port
;
2734 dest_dsc
= &daddr
->port
;
2736 /* this is really the type SEND, SEND_ONCE, etc. */
2737 name
= dsc
->disposition
;
2738 object
= (ipc_object_t
) CAST_MACH_NAME_TO_PORT(dsc
->name
);
2739 dest_dsc
->disposition
= ipc_object_copyin_type(name
);
2740 dest_dsc
->name
= (mach_port_t
)object
;
2741 dest_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
2743 if (!IO_VALID(object
)) {
2747 ipc_object_copyin_from_kernel(object
, name
);
2749 /* CDY avoid circularity when the destination is also */
2750 /* the kernel. This check should be changed into an */
2751 /* assert when the new kobject model is in place since*/
2752 /* ports will not be used in kernel to kernel chats */
2754 if (((ipc_port_t
)remote
)->ip_receiver
!= ipc_space_kernel
) {
2755 if ((dest_dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2756 ipc_port_check_circularity((ipc_port_t
) object
,
2757 (ipc_port_t
) remote
)) {
2758 kmsg
->ikm_header
->msgh_bits
|=
2759 MACH_MSGH_BITS_CIRCULAR
;
2764 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
2765 case MACH_MSG_OOL_DESCRIPTOR
: {
2766 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
2767 * so we don't need to do anything special. */
2769 mach_msg_ool_descriptor32_t
*source_dsc
= &saddr
->out_of_line32
;
2770 mach_msg_ool_descriptor_t
*dest_dsc
= (typeof(dest_dsc
))&daddr
->out_of_line
;
2772 vm_offset_t address
= source_dsc
->address
;
2773 vm_size_t size
= source_dsc
->size
;
2774 boolean_t deallocate
= source_dsc
->deallocate
;
2775 mach_msg_copy_options_t copy
= source_dsc
->copy
;
2776 mach_msg_descriptor_type_t type
= source_dsc
->type
;
2778 dest_dsc
->address
= (void *)address
;
2779 dest_dsc
->size
= size
;
2780 dest_dsc
->deallocate
= deallocate
;
2781 dest_dsc
->copy
= copy
;
2782 dest_dsc
->type
= type
;
2785 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
2786 ipc_object_t
*objects
;
2788 mach_msg_type_name_t name
;
2789 mach_msg_ool_ports_descriptor_t
*dest_dsc
;
2791 mach_msg_ool_ports_descriptor32_t
*source_dsc
= &saddr
->ool_ports32
;
2792 dest_dsc
= (typeof(dest_dsc
))&daddr
->ool_ports
;
2794 boolean_t deallocate
= source_dsc
->deallocate
;
2795 mach_msg_copy_options_t copy
= source_dsc
->copy
;
2796 mach_msg_size_t port_count
= source_dsc
->count
;
2797 mach_msg_type_name_t disposition
= source_dsc
->disposition
;
2799 /* this is really the type SEND, SEND_ONCE, etc. */
2801 disposition
= ipc_object_copyin_type(name
);
2803 objects
= (ipc_object_t
*) (uintptr_t)source_dsc
->address
;
2805 for ( j
= 0; j
< port_count
; j
++) {
2806 ipc_object_t object
= objects
[j
];
2808 if (!IO_VALID(object
))
2811 ipc_object_copyin_from_kernel(object
, name
);
2813 if ((disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2814 ipc_port_check_circularity(
2815 (ipc_port_t
) object
,
2816 (ipc_port_t
) remote
))
2817 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
2820 dest_dsc
->address
= objects
;
2821 dest_dsc
->deallocate
= deallocate
;
2822 dest_dsc
->copy
= copy
;
2823 dest_dsc
->disposition
= disposition
;
2824 dest_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
2825 dest_dsc
->count
= port_count
;
2830 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
2831 #endif /* MACH_ASSERT */
2837 #endif /* IKM_SUPPORT_LEGACY */
2840 * Routine: ipc_kmsg_copyout_header
2842 * "Copy-out" port rights in the header of a message.
2843 * Operates atomically; if it doesn't succeed the
2844 * message header and the space are left untouched.
2845 * If it does succeed the remote/local port fields
2846 * contain port names instead of object pointers,
2847 * and the bits field is updated.
2849 * The notify argument implements the MACH_RCV_NOTIFY option.
2850 * If it is not MACH_PORT_NULL, it should name a receive right.
2851 * If the process of receiving the reply port creates a
2852 * new right in the receiving task, then the new right is
2853 * automatically registered for a dead-name notification,
2854 * with the notify port supplying the send-once right.
2858 * MACH_MSG_SUCCESS Copied out port rights.
2859 * MACH_RCV_INVALID_NOTIFY
2860 * Notify is non-null and doesn't name a receive right.
2861 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2862 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
2863 * The space is dead.
2864 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
2865 * No room in space for another name.
2866 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
2867 * Couldn't allocate memory for the reply port.
2868 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
2869 * Couldn't allocate memory for the dead-name request.
2873 ipc_kmsg_copyout_header(
2874 mach_msg_header_t
*msg
,
2876 mach_port_name_t notify
)
2878 mach_msg_bits_t mbits
= msg
->msgh_bits
;
2879 ipc_port_t dest
= (ipc_port_t
) msg
->msgh_remote_port
;
2881 assert(IP_VALID(dest
));
2884 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
2885 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
2886 ipc_port_t reply
= (ipc_port_t
) msg
->msgh_local_port
;
2887 mach_port_name_t dest_name
, reply_name
;
2889 if (IP_VALID(reply
)) {
2890 ipc_port_t notify_port
;
2895 * Handling notify (for MACH_RCV_NOTIFY) is tricky.
2896 * The problem is atomically making a send-once right
2897 * from the notify port and installing it for a
2898 * dead-name request in the new entry, because this
2899 * requires two port locks (on the notify port and
2900 * the reply port). However, we can safely make
2901 * and consume send-once rights for the notify port
2902 * as long as we hold the space locked. This isn't
2903 * an atomicity problem, because the only way
2904 * to detect that a send-once right has been created
2905 * and then consumed if it wasn't needed is by getting
2906 * at the receive right to look at ip_sorights, and
2907 * because the space is write-locked status calls can't
2908 * lookup the notify port receive right. When we make
2909 * the send-once right, we lock the notify port,
2910 * so any status calls in progress will be done.
2913 is_write_lock(space
);
2916 ipc_port_request_index_t request
;
2918 if (!space
->is_active
) {
2919 is_write_unlock(space
);
2920 return (MACH_RCV_HEADER_ERROR
|
2921 MACH_MSG_IPC_SPACE
);
2924 if (notify
!= MACH_PORT_NULL
) {
2925 notify_port
= ipc_port_lookup_notify(space
,
2927 if (notify_port
== IP_NULL
) {
2928 printf("ipc_kmsg_copyout_header: no notify port\n");
2929 is_write_unlock(space
);
2930 return MACH_RCV_INVALID_NOTIFY
;
2933 notify_port
= IP_NULL
;
2935 if ((reply_type
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
2936 ipc_right_reverse(space
, (ipc_object_t
) reply
,
2937 &reply_name
, &entry
)) {
2938 /* reply port is locked and active */
2941 * We don't need the notify_port
2942 * send-once right, but we can't release
2943 * it here because reply port is locked.
2944 * Wait until after the copyout to
2945 * release the notify port right.
2948 assert(entry
->ie_bits
&
2949 MACH_PORT_TYPE_SEND_RECEIVE
);
2954 if (!ip_active(reply
)) {
2956 ip_check_unlock(reply
);
2958 if (notify_port
!= IP_NULL
)
2959 ipc_port_release_sonce(notify_port
);
2962 is_write_unlock(space
);
2965 reply_name
= MACH_PORT_DEAD
;
2969 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
2970 kr
= ipc_entry_get(space
, &reply_name
, &entry
);
2971 if (kr
!= KERN_SUCCESS
) {
2974 if (notify_port
!= IP_NULL
)
2975 ipc_port_release_sonce(notify_port
);
2977 /* space is locked */
2978 kr
= ipc_entry_grow_table(space
,
2980 if (kr
!= KERN_SUCCESS
) {
2981 /* space is unlocked */
2983 if (kr
== KERN_RESOURCE_SHORTAGE
) {
2984 printf("ipc_kmsg_copyout_header: can't grow kernel ipc space\n");
2985 return (MACH_RCV_HEADER_ERROR
|
2986 MACH_MSG_IPC_KERNEL
);
2988 printf("ipc_kmsg_copyout_header: can't grow user ipc space\n");
2989 return (MACH_RCV_HEADER_ERROR
|
2990 MACH_MSG_IPC_SPACE
);
2993 /* space is locked again; start over */
2997 assert(IE_BITS_TYPE(entry
->ie_bits
) ==
2998 MACH_PORT_TYPE_NONE
);
2999 assert(entry
->ie_object
== IO_NULL
);
3001 if (notify_port
== IP_NULL
) {
3002 /* not making a dead-name request */
3004 entry
->ie_object
= (ipc_object_t
) reply
;
3008 kr
= ipc_port_dnrequest(reply
, reply_name
,
3009 notify_port
, &request
);
3010 if (kr
!= KERN_SUCCESS
) {
3013 ipc_port_release_sonce(notify_port
);
3015 ipc_entry_dealloc(space
, reply_name
, entry
);
3016 is_write_unlock(space
);
3019 if (!ip_active(reply
)) {
3020 /* will fail next time around loop */
3023 is_write_lock(space
);
3027 kr
= ipc_port_dngrow(reply
, ITS_SIZE_NONE
);
3028 /* port is unlocked */
3029 if (kr
!= KERN_SUCCESS
) {
3030 printf("ipc_kmsg_copyout_header: can't grow kernel ipc space2\n");
3031 return (MACH_RCV_HEADER_ERROR
|
3032 MACH_MSG_IPC_KERNEL
);
3035 is_write_lock(space
);
3039 notify_port
= IP_NULL
; /* don't release right below */
3041 entry
->ie_object
= (ipc_object_t
) reply
;
3042 entry
->ie_request
= request
;
3046 /* space and reply port are locked and active */
3048 ip_reference(reply
); /* hold onto the reply port */
3050 kr
= ipc_right_copyout(space
, reply_name
, entry
,
3051 reply_type
, TRUE
, (ipc_object_t
) reply
);
3052 /* reply port is unlocked */
3053 assert(kr
== KERN_SUCCESS
);
3055 if (notify_port
!= IP_NULL
)
3056 ipc_port_release_sonce(notify_port
);
3059 is_write_unlock(space
);
3062 * No reply port! This is an easy case.
3063 * We only need to have the space locked
3064 * when checking notify and when locking
3065 * the destination (to ensure atomicity).
3068 is_read_lock(space
);
3069 if (!space
->is_active
) {
3070 is_read_unlock(space
);
3071 return MACH_RCV_HEADER_ERROR
|MACH_MSG_IPC_SPACE
;
3074 if (notify
!= MACH_PORT_NULL
) {
3077 /* must check notify even though it won't be used */
3079 if ((entry
= ipc_entry_lookup(space
, notify
)) == IE_NULL
) {
3080 printf("ipc_kmsg_copyout_header: ipc_entry_lookup failed\n");
3081 is_read_unlock(space
);
3082 return MACH_RCV_INVALID_NOTIFY
;
3085 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
3086 printf("ipc_kmsg_copyout_header: MACH_PORT_TYPE_RECEIVE not set!\n");
3087 is_read_unlock(space
);
3088 return MACH_RCV_INVALID_NOTIFY
;
3093 is_read_unlock(space
);
3095 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
3099 * At this point, the space is unlocked and the destination
3100 * port is locked. (Lock taken while space was locked.)
3101 * reply_name is taken care of; we still need dest_name.
3102 * We still hold a ref for reply (if it is valid).
3104 * If the space holds receive rights for the destination,
3105 * we return its name for the right. Otherwise the task
3106 * managed to destroy or give away the receive right between
3107 * receiving the message and this copyout. If the destination
3108 * is dead, return MACH_PORT_DEAD, and if the receive right
3109 * exists somewhere else (another space, in transit)
3110 * return MACH_PORT_NULL.
3112 * Making this copyout operation atomic with the previous
3113 * copyout of the reply port is a bit tricky. If there was
3114 * no real reply port (it wasn't IP_VALID) then this isn't
3115 * an issue. If the reply port was dead at copyout time,
3116 * then we are OK, because if dest is dead we serialize
3117 * after the death of both ports and if dest is alive
3118 * we serialize after reply died but before dest's (later) death.
3119 * So assume reply was alive when we copied it out. If dest
3120 * is alive, then we are OK because we serialize before
3121 * the ports' deaths. So assume dest is dead when we look at it.
3122 * If reply dies/died after dest, then we are OK because
3123 * we serialize after dest died but before reply dies.
3124 * So the hard case is when reply is alive at copyout,
3125 * dest is dead at copyout, and reply died before dest died.
3126 * In this case pretend that dest is still alive, so
3127 * we serialize while both ports are alive.
3129 * Because the space lock is held across the copyout of reply
3130 * and locking dest, the receive right for dest can't move
3131 * in or out of the space while the copyouts happen, so
3132 * that isn't an atomicity problem. In the last hard case
3133 * above, this implies that when dest is dead that the
3134 * space couldn't have had receive rights for dest at
3135 * the time reply was copied-out, so when we pretend
3136 * that dest is still alive, we can return MACH_PORT_NULL.
3138 * If dest == reply, then we have to make it look like
3139 * either both copyouts happened before the port died,
3140 * or both happened after the port died. This special
3141 * case works naturally if the timestamp comparison
3142 * is done correctly.
3147 if (ip_active(dest
)) {
3148 ipc_object_copyout_dest(space
, (ipc_object_t
) dest
,
3149 dest_type
, &dest_name
);
3150 /* dest is unlocked */
3152 ipc_port_timestamp_t timestamp
;
3154 timestamp
= dest
->ip_timestamp
;
3156 ip_check_unlock(dest
);
3158 if (IP_VALID(reply
)) {
3160 if (ip_active(reply
) ||
3161 IP_TIMESTAMP_ORDER(timestamp
,
3162 reply
->ip_timestamp
))
3163 dest_name
= MACH_PORT_DEAD
;
3165 dest_name
= MACH_PORT_NULL
;
3168 dest_name
= MACH_PORT_DEAD
;
3171 if (IP_VALID(reply
))
3172 ipc_port_release(reply
);
3174 msg
->msgh_bits
= (MACH_MSGH_BITS_OTHER(mbits
) |
3175 MACH_MSGH_BITS(reply_type
, dest_type
));
3176 msg
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
3177 msg
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
3180 return MACH_MSG_SUCCESS
;
3184 * Routine: ipc_kmsg_copyout_object
3186 * Copy-out a port right. Always returns a name,
3187 * even for unsuccessful return codes. Always
3188 * consumes the supplied object.
3192 * MACH_MSG_SUCCESS The space acquired the right
3193 * (name is valid) or the object is dead (MACH_PORT_DEAD).
3194 * MACH_MSG_IPC_SPACE No room in space for the right,
3195 * or the space is dead. (Name is MACH_PORT_NULL.)
3196 * MACH_MSG_IPC_KERNEL Kernel resource shortage.
3197 * (Name is MACH_PORT_NULL.)
3201 ipc_kmsg_copyout_object(
3203 ipc_object_t object
,
3204 mach_msg_type_name_t msgt_name
,
3205 mach_port_name_t
*namep
)
3209 if (!IO_VALID(object
)) {
3210 *namep
= CAST_MACH_PORT_TO_NAME(object
);
3211 return MACH_MSG_SUCCESS
;
3214 kr
= ipc_object_copyout(space
, object
, msgt_name
, TRUE
, namep
);
3215 if (kr
!= KERN_SUCCESS
) {
3216 ipc_object_destroy(object
, msgt_name
);
3218 if (kr
== KERN_INVALID_CAPABILITY
)
3219 *namep
= MACH_PORT_DEAD
;
3221 *namep
= MACH_PORT_NULL
;
3223 if (kr
== KERN_RESOURCE_SHORTAGE
)
3224 return MACH_MSG_IPC_KERNEL
;
3226 return MACH_MSG_IPC_SPACE
;
3230 return MACH_MSG_SUCCESS
;
3233 mach_msg_descriptor_t
*
3234 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t
*dsc
,
3235 mach_msg_descriptor_t
*user_dsc
,
3238 mach_msg_descriptor_t
*
3239 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t
*dsc
,
3240 mach_msg_descriptor_t
*dest_dsc
,
3245 mach_port_name_t name
;
3246 mach_msg_type_name_t disp
;
3249 /* Copyout port right carried in the message */
3250 port
= dsc
->port
.name
;
3251 disp
= dsc
->port
.disposition
;
3252 *mr
|= ipc_kmsg_copyout_object(space
,
3257 if(current_task() == kernel_task
)
3259 mach_msg_port_descriptor_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
3260 user_dsc
--; // point to the start of this port descriptor
3261 user_dsc
->name
= CAST_MACH_NAME_TO_PORT(name
);
3262 user_dsc
->disposition
= disp
;
3263 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
3264 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
3266 mach_msg_legacy_port_descriptor_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
3267 user_dsc
--; // point to the start of this port descriptor
3268 user_dsc
->name
= CAST_MACH_PORT_TO_NAME(name
);
3269 user_dsc
->disposition
= disp
;
3270 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
3271 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
3274 return (mach_msg_descriptor_t
*)dest_dsc
;
3277 mach_msg_descriptor_t
*
3278 ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t
*dsc
, mach_msg_descriptor_t
*user_dsc
, int is_64bit
, vm_map_t map
, mach_msg_return_t
*mr
);
3279 mach_msg_descriptor_t
*
3280 ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t
*dsc
, mach_msg_descriptor_t
*user_dsc
, int is_64bit
, vm_map_t map
, mach_msg_return_t
*mr
)
3283 mach_vm_offset_t rcv_addr
;
3284 mach_msg_copy_options_t copy_options
;
3285 mach_msg_size_t size
;
3286 mach_msg_descriptor_type_t dsc_type
;
3288 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
3290 copy
= (vm_map_copy_t
) dsc
->address
;
3292 copy_options
= dsc
->copy
;
3293 assert(copy_options
!= MACH_MSG_KALLOC_COPY_T
);
3294 dsc_type
= dsc
->type
;
3297 if (copy
!= VM_MAP_COPY_NULL
) {
3299 * Check to see if there is an overwrite descriptor
3300 * specified in the scatter list for this ool data.
3301 * The descriptor has already been verified.
3304 if (saddr
!= MACH_MSG_DESCRIPTOR_NULL
) {
3306 OTHER_OOL_DESCRIPTOR
*scatter_dsc
;
3308 scatter_dsc
= (OTHER_OOL_DESCRIPTOR
*)saddr
;
3309 if (scatter_dsc
->copy
== MACH_MSG_OVERWRITE
) {
3310 rcv_addr
= (mach_vm_offset_t
) scatter_dsc
->address
;
3311 copy_options
= MACH_MSG_OVERWRITE
;
3313 copy_options
= MACH_MSG_VIRTUAL_COPY
;
3316 mach_msg_ool_descriptor_t
*scatter_dsc
;
3318 scatter_dsc
= &saddr
->out_of_line
;
3319 if (scatter_dsc
->copy
== MACH_MSG_OVERWRITE
) {
3320 rcv_addr
= CAST_USER_ADDR_T(scatter_dsc
->address
);
3321 copy_options
= MACH_MSG_OVERWRITE
;
3323 copy_options
= MACH_MSG_VIRTUAL_COPY
;
3326 INCREMENT_SCATTER(saddr
, sdsc_count
, differs
);
3332 * Whether the data was virtually or physically
3333 * copied we have a vm_map_copy_t for it.
3334 * If there's an overwrite region specified
3335 * overwrite it, otherwise do a virtual copy out.
3338 if (copy_options
== MACH_MSG_OVERWRITE
&& rcv_addr
!= 0) {
3339 kr
= vm_map_copy_overwrite(map
, rcv_addr
,
3342 kr
= vm_map_copyout(map
, &rcv_addr
, copy
);
3344 if (kr
!= KERN_SUCCESS
) {
3345 if (kr
== KERN_RESOURCE_SHORTAGE
)
3346 *mr
|= MACH_MSG_VM_KERNEL
;
3348 *mr
|= MACH_MSG_VM_SPACE
;
3349 vm_map_copy_discard(copy
);
3359 * Now update the descriptor as the user would see it.
3360 * This may require expanding the descriptor to the user
3361 * visible size. There is already space allocated for
3362 * this in what naddr points to.
3364 if(current_task() == kernel_task
)
3366 mach_msg_ool_descriptor_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3369 user_ool_dsc
->address
= (void *)(uintptr_t)rcv_addr
;
3370 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
3372 user_ool_dsc
->copy
= copy_options
;
3373 user_ool_dsc
->type
= dsc_type
;
3374 user_ool_dsc
->size
= size
;
3376 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
3377 } else if (is_64bit
) {
3378 mach_msg_ool_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3381 user_ool_dsc
->address
= rcv_addr
;
3382 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
3384 user_ool_dsc
->copy
= copy_options
;
3385 user_ool_dsc
->type
= dsc_type
;
3386 user_ool_dsc
->size
= size
;
3388 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
3390 mach_msg_ool_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3393 user_ool_dsc
->address
= CAST_DOWN_EXPLICIT(uint32_t, rcv_addr
);
3394 user_ool_dsc
->size
= size
;
3395 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
3397 user_ool_dsc
->copy
= copy_options
;
3398 user_ool_dsc
->type
= dsc_type
;
3400 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
3405 mach_msg_descriptor_t
*
3406 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t
*dsc
,
3407 mach_msg_descriptor_t
*user_dsc
,
3412 mach_msg_return_t
*mr
);
3413 mach_msg_descriptor_t
*
3414 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t
*dsc
,
3415 mach_msg_descriptor_t
*user_dsc
,
3420 mach_msg_return_t
*mr
)
3422 mach_vm_offset_t rcv_addr
;
3423 mach_msg_type_name_t disp
;
3424 mach_msg_type_number_t count
, i
;
3425 vm_size_t ports_length
, names_length
;
3427 mach_msg_copy_options_t copy_options
= MACH_MSG_VIRTUAL_COPY
;
3429 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
3432 disp
= dsc
->disposition
;
3433 ports_length
= count
* sizeof(mach_port_t
);
3434 names_length
= count
* sizeof(mach_port_name_t
);
3436 if (ports_length
!= 0 && dsc
->address
!= 0) {
3439 * Check to see if there is an overwrite descriptor
3440 * specified in the scatter list for this ool data.
3441 * The descriptor has already been verified.
3444 if (saddr
!= MACH_MSG_DESCRIPTOR_NULL
) {
3446 OTHER_OOL_DESCRIPTOR
*scatter_dsc
;
3448 scatter_dsc
= (OTHER_OOL_DESCRIPTOR
*)saddr
;
3449 rcv_addr
= (mach_vm_offset_t
) scatter_dsc
->address
;
3450 copy_options
= scatter_dsc
->copy
;
3452 mach_msg_ool_descriptor_t
*scatter_dsc
;
3454 scatter_dsc
= &saddr
->out_of_line
;
3455 rcv_addr
= CAST_USER_ADDR_T(scatter_dsc
->address
);
3456 copy_options
= scatter_dsc
->copy
;
3458 INCREMENT_SCATTER(saddr
, sdsc_count
, differs
);
3462 if (copy_options
== MACH_MSG_VIRTUAL_COPY
) {
3464 * Dynamically allocate the region
3466 int anywhere
= VM_MAKE_TAG(VM_MEMORY_MACH_MSG
)|
3470 if ((kr
= mach_vm_allocate(map
, &rcv_addr
,
3471 (mach_vm_size_t
)names_length
,
3472 anywhere
)) != KERN_SUCCESS
) {
3473 ipc_kmsg_clean_body(kmsg
, 1, (mach_msg_descriptor_t
*)dsc
);
3476 if (kr
== KERN_RESOURCE_SHORTAGE
){
3477 *mr
|= MACH_MSG_VM_KERNEL
;
3479 *mr
|= MACH_MSG_VM_SPACE
;
3485 * Handle the port rights and copy out the names
3486 * for those rights out to user-space.
3488 if (rcv_addr
!= 0) {
3489 mach_port_t
*objects
= (mach_port_t
*) dsc
->address
;
3490 mach_port_name_t
*names
= (mach_port_name_t
*) dsc
->address
;
3492 /* copyout port rights carried in the message */
3494 for ( i
= 0; i
< count
; i
++) {
3495 ipc_object_t object
= (ipc_object_t
)objects
[i
];
3497 *mr
|= ipc_kmsg_copyout_object(space
, object
,
3501 /* copyout to memory allocated above */
3502 void *data
= dsc
->address
;
3503 if (copyoutmap(map
, data
, rcv_addr
, names_length
) != KERN_SUCCESS
)
3504 *mr
|= MACH_MSG_VM_SPACE
;
3505 kfree(data
, ports_length
);
3512 * Now update the descriptor based on the information
3515 if(current_task() == kernel_task
) {
3516 mach_msg_ool_ports_descriptor_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3519 user_ool_dsc
->address
= (void *)(uintptr_t)rcv_addr
;
3520 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
3522 user_ool_dsc
->copy
= copy_options
;
3523 user_ool_dsc
->disposition
= disp
;
3524 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
3525 user_ool_dsc
->count
= count
;
3527 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
3529 mach_msg_ool_ports_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3532 user_ool_dsc
->address
= rcv_addr
;
3533 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
3535 user_ool_dsc
->copy
= copy_options
;
3536 user_ool_dsc
->disposition
= disp
;
3537 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
3538 user_ool_dsc
->count
= count
;
3540 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
3542 mach_msg_ool_ports_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3545 user_ool_dsc
->address
= CAST_DOWN_EXPLICIT(uint32_t, rcv_addr
);
3546 user_ool_dsc
->count
= count
;
3547 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
3549 user_ool_dsc
->copy
= copy_options
;
3550 user_ool_dsc
->disposition
= disp
;
3551 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
3553 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
3559 * Routine: ipc_kmsg_copyout_body
3561 * "Copy-out" port rights and out-of-line memory
3562 * in the body of a message.
3564 * The error codes are a combination of special bits.
3565 * The copyout proceeds despite errors.
3569 * MACH_MSG_SUCCESS Successful copyout.
3570 * MACH_MSG_IPC_SPACE No room for port right in name space.
3571 * MACH_MSG_VM_SPACE No room for memory in address space.
3572 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
3573 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
3574 * MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
3578 ipc_kmsg_copyout_body(
3582 mach_msg_body_t
*slist
)
3584 mach_msg_body_t
*body
;
3585 mach_msg_descriptor_t
*kern_dsc
, *user_dsc
;
3586 mach_msg_descriptor_t
*saddr
;
3587 mach_msg_type_number_t dsc_count
, sdsc_count
;
3589 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
3590 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
3592 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3593 dsc_count
= body
->msgh_descriptor_count
;
3594 kern_dsc
= (mach_msg_descriptor_t
*) (body
+ 1);
3595 /* Point user_dsc just after the end of all the descriptors */
3596 user_dsc
= &kern_dsc
[dsc_count
];
3598 /* Do scatter list setup */
3599 if (slist
!= MACH_MSG_BODY_NULL
) {
3600 panic("Scatter lists disabled");
3601 saddr
= (mach_msg_descriptor_t
*) (slist
+ 1);
3602 sdsc_count
= slist
->msgh_descriptor_count
;
3605 saddr
= MACH_MSG_DESCRIPTOR_NULL
;
3609 /* Now process the descriptors */
3610 for (i
= dsc_count
-1; i
>= 0; i
--) {
3611 switch (kern_dsc
[i
].type
.type
) {
3613 case MACH_MSG_PORT_DESCRIPTOR
:
3614 user_dsc
= ipc_kmsg_copyout_port_descriptor(&kern_dsc
[i
], user_dsc
, space
, &mr
);
3616 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3617 case MACH_MSG_OOL_DESCRIPTOR
:
3618 user_dsc
= ipc_kmsg_copyout_ool_descriptor(
3619 (mach_msg_ool_descriptor_t
*)&kern_dsc
[i
], user_dsc
, is_task_64bit
, map
, &mr
);
3621 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3622 user_dsc
= ipc_kmsg_copyout_ool_ports_descriptor(
3623 (mach_msg_ool_ports_descriptor_t
*)&kern_dsc
[i
], user_dsc
, is_task_64bit
, map
, space
, kmsg
, &mr
);
3626 panic("untyped IPC copyout body: invalid message descriptor");
3631 if(user_dsc
!= kern_dsc
) {
3632 vm_offset_t dsc_adjust
= (vm_offset_t
)user_dsc
- (vm_offset_t
)kern_dsc
;
3633 memmove((char *)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
3634 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
);
3635 /* Update the message size for the smaller user representation */
3636 kmsg
->ikm_header
->msgh_size
-= (mach_msg_size_t
)dsc_adjust
;
3643 * Routine: ipc_kmsg_copyout_size
3645 * Compute the size of the message as copied out to the given
3646 * map. If the destination map's pointers are a different size
3647 * than the kernel's, we have to allow for expansion/
3648 * contraction of the descriptors as appropriate.
3652 * size of the message as it would be received.
3656 ipc_kmsg_copyout_size(
3660 mach_msg_size_t send_size
;
3662 send_size
= kmsg
->ikm_header
->msgh_size
;
3664 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
3666 #if defined(__LP64__)
3667 send_size
-= LEGACY_HEADER_SIZE_DELTA
;
3670 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
3672 mach_msg_body_t
*body
;
3673 mach_msg_descriptor_t
*saddr
, *eaddr
;
3675 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3676 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
3677 eaddr
= saddr
+ body
->msgh_descriptor_count
;
3679 for ( ; saddr
< eaddr
; saddr
++ ) {
3680 switch (saddr
->type
.type
) {
3681 case MACH_MSG_OOL_DESCRIPTOR
:
3682 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3683 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3685 send_size
-= DESC_SIZE_ADJUSTMENT
;
3687 case MACH_MSG_PORT_DESCRIPTOR
:
3688 send_size
-= DESC_SIZE_ADJUSTMENT
;
3699 * Routine: ipc_kmsg_copyout
3701 * "Copy-out" port rights and out-of-line memory
3706 * MACH_MSG_SUCCESS Copied out all rights and memory.
3707 * MACH_RCV_INVALID_NOTIFY Bad notify port.
3708 * Rights and memory in the message are intact.
3709 * MACH_RCV_HEADER_ERROR + special bits
3710 * Rights and memory in the message are intact.
3711 * MACH_RCV_BODY_ERROR + special bits
3712 * The message header was successfully copied out.
3713 * As much of the body was handled as possible.
3721 mach_port_name_t notify
,
3722 mach_msg_body_t
*slist
)
3724 mach_msg_return_t mr
;
3726 mr
= ipc_kmsg_copyout_header(kmsg
->ikm_header
, space
, notify
);
3727 if (mr
!= MACH_MSG_SUCCESS
) {
3731 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
3732 mr
= ipc_kmsg_copyout_body(kmsg
, space
, map
, slist
);
3734 if (mr
!= MACH_MSG_SUCCESS
)
3735 mr
|= MACH_RCV_BODY_ERROR
;
3742 * Routine: ipc_kmsg_copyout_pseudo
3744 * Does a pseudo-copyout of the message.
3745 * This is like a regular copyout, except
3746 * that the ports in the header are handled
3747 * as if they are in the body. They aren't reversed.
3749 * The error codes are a combination of special bits.
3750 * The copyout proceeds despite errors.
3754 * MACH_MSG_SUCCESS Successful copyout.
3755 * MACH_MSG_IPC_SPACE No room for port right in name space.
3756 * MACH_MSG_VM_SPACE No room for memory in address space.
3757 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
3758 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
3762 ipc_kmsg_copyout_pseudo(
3766 mach_msg_body_t
*slist
)
3768 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
3769 ipc_object_t dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
3770 ipc_object_t reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
3771 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
3772 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
3773 mach_port_name_t dest_name
, reply_name
;
3774 mach_msg_return_t mr
;
3776 assert(IO_VALID(dest
));
3778 mr
= (ipc_kmsg_copyout_object(space
, dest
, dest_type
, &dest_name
) |
3779 ipc_kmsg_copyout_object(space
, reply
, reply_type
, &reply_name
));
3781 kmsg
->ikm_header
->msgh_bits
= mbits
&~ MACH_MSGH_BITS_CIRCULAR
;
3782 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
3783 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
3785 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
3786 mr
|= ipc_kmsg_copyout_body(kmsg
, space
, map
, slist
);
3793 * Routine: ipc_kmsg_copyout_dest
3795 * Copies out the destination port in the message.
3796 * Destroys all other rights and memory in the message.
3802 ipc_kmsg_copyout_dest(
3806 mach_msg_bits_t mbits
;
3809 mach_msg_type_name_t dest_type
;
3810 mach_msg_type_name_t reply_type
;
3811 mach_port_name_t dest_name
, reply_name
;
3813 mbits
= kmsg
->ikm_header
->msgh_bits
;
3814 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
3815 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
3816 dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
3817 reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
3819 assert(IO_VALID(dest
));
3822 if (io_active(dest
)) {
3823 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
3824 /* dest is unlocked */
3827 io_check_unlock(dest
);
3828 dest_name
= MACH_PORT_DEAD
;
3831 if (IO_VALID(reply
)) {
3832 ipc_object_destroy(reply
, reply_type
);
3833 reply_name
= MACH_PORT_NULL
;
3835 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
3837 kmsg
->ikm_header
->msgh_bits
= (MACH_MSGH_BITS_OTHER(mbits
) |
3838 MACH_MSGH_BITS(reply_type
, dest_type
));
3839 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
3840 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
3842 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
3843 mach_msg_body_t
*body
;
3845 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3846 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
3847 (mach_msg_descriptor_t
*)(body
+ 1));
3852 * Routine: ipc_kmsg_copyin_scatter
3854 * allocate and copyin a scatter list
3856 * The gather (kmsg) is valid since it has been copied in.
3857 * Gather list descriptors are sequentially paired with scatter
3858 * list descriptors, with port descriptors in either list ignored.
3859 * Descriptors are consistent if the type fileds match and size
3860 * of the scatter descriptor is less than or equal to the
3861 * size of the gather descriptor. A MACH_MSG_ALLOCATE copy
3862 * strategy in a scatter descriptor matches any size in the
3863 * corresponding gather descriptor assuming they are the same type.
3864 * Either list may be larger than the other. During the
3865 * subsequent copy out, excess scatter descriptors are ignored
3866 * and excess gather descriptors default to dynamic allocation.
3868 * In the case of a size error, the scatter list is released.
3872 * the allocated message body containing the scatter list.
3876 ipc_kmsg_get_scatter(
3877 mach_vm_address_t msg_addr
,
3878 mach_msg_size_t slist_size
,
3881 mach_msg_body_t
*slist
;
3882 mach_msg_body_t
*body
;
3883 mach_msg_descriptor_t
*gstart
, *gend
;
3884 mach_msg_descriptor_t
*sstart
, *send
;
3886 #if defined(__LP64__)
3887 panic("ipc_kmsg_get_scatter called!");
3890 if (slist_size
< sizeof(mach_msg_base_t
))
3891 return MACH_MSG_BODY_NULL
;
3893 slist_size
-= (mach_msg_size_t
)sizeof(mach_msg_header_t
);
3894 slist
= (mach_msg_body_t
*)kalloc(slist_size
);
3895 if (slist
== MACH_MSG_BODY_NULL
)
3898 if (copyin(msg_addr
+ sizeof(mach_msg_header_t
), (char *)slist
, slist_size
)) {
3899 kfree(slist
, slist_size
);
3900 return MACH_MSG_BODY_NULL
;
3903 if ((slist
->msgh_descriptor_count
* sizeof(mach_msg_descriptor_t
)
3904 + sizeof(mach_msg_size_t
)) > slist_size
) {
3905 kfree(slist
, slist_size
);
3906 return MACH_MSG_BODY_NULL
;
3909 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3910 gstart
= (mach_msg_descriptor_t
*) (body
+ 1);
3911 gend
= gstart
+ body
->msgh_descriptor_count
;
3913 sstart
= (mach_msg_descriptor_t
*) (slist
+ 1);
3914 send
= sstart
+ slist
->msgh_descriptor_count
;
3916 while (gstart
< gend
) {
3917 mach_msg_descriptor_type_t g_type
;
3920 * Skip port descriptors in gather list.
3922 g_type
= gstart
->type
.type
;
3924 if (g_type
!= MACH_MSG_PORT_DESCRIPTOR
) {
3927 * A scatter list with a 0 descriptor count is treated as an
3928 * automatic size mismatch.
3930 if (slist
->msgh_descriptor_count
== 0) {
3931 kfree(slist
, slist_size
);
3932 return MACH_MSG_BODY_NULL
;
3936 * Skip port descriptors in scatter list.
3938 while (sstart
< send
) {
3939 if (sstart
->type
.type
!= MACH_MSG_PORT_DESCRIPTOR
)
3945 * No more scatter descriptors, we're done
3947 if (sstart
>= send
) {
3952 * Check type, copy and size fields
3954 if (g_type
== MACH_MSG_OOL_DESCRIPTOR
||
3955 g_type
== MACH_MSG_OOL_VOLATILE_DESCRIPTOR
) {
3956 if (sstart
->type
.type
!= MACH_MSG_OOL_DESCRIPTOR
&&
3957 sstart
->type
.type
!= MACH_MSG_OOL_VOLATILE_DESCRIPTOR
) {
3958 kfree(slist
, slist_size
);
3959 return MACH_MSG_BODY_NULL
;
3961 if (sstart
->out_of_line
.copy
== MACH_MSG_OVERWRITE
&&
3962 gstart
->out_of_line
.size
> sstart
->out_of_line
.size
) {
3963 kfree(slist
, slist_size
);
3964 return MACH_MSG_BODY_NULL
;
3968 if (sstart
->type
.type
!= MACH_MSG_OOL_PORTS_DESCRIPTOR
) {
3969 kfree(slist
, slist_size
);
3970 return MACH_MSG_BODY_NULL
;
3972 if (sstart
->ool_ports
.copy
== MACH_MSG_OVERWRITE
&&
3973 gstart
->ool_ports
.count
> sstart
->ool_ports
.count
) {
3974 kfree(slist
, slist_size
);
3975 return MACH_MSG_BODY_NULL
;
3987 * Routine: ipc_kmsg_free_scatter
3989 * Deallocate a scatter list. Since we actually allocated
3990 * a body without a header, and since the header was originally
3991 * accounted for in slist_size, we have to ajust it down
3992 * before freeing the scatter list.
3995 ipc_kmsg_free_scatter(
3996 mach_msg_body_t
*slist
,
3997 mach_msg_size_t slist_size
)
3999 #if defined(__LP64__)
4000 panic("%s called; halting!", __func__
);
4003 slist_size
-= (mach_msg_size_t
)sizeof(mach_msg_header_t
);
4004 kfree(slist
, slist_size
);
4009 * Routine: ipc_kmsg_copyout_to_kernel
4011 * Copies out the destination and reply ports in the message.
4012 * Leaves all other rights and memory in the message alone.
4016 * Derived from ipc_kmsg_copyout_dest.
4017 * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
4018 * We really do want to save rights and memory.
4022 ipc_kmsg_copyout_to_kernel(
4028 mach_msg_type_name_t dest_type
;
4029 mach_msg_type_name_t reply_type
;
4030 mach_port_name_t dest_name
, reply_name
;
4032 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
4033 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
4034 dest_type
= MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
);
4035 reply_type
= MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
);
4037 assert(IO_VALID(dest
));
4040 if (io_active(dest
)) {
4041 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
4042 /* dest is unlocked */
4045 io_check_unlock(dest
);
4046 dest_name
= MACH_PORT_DEAD
;
4049 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
4051 kmsg
->ikm_header
->msgh_bits
=
4052 (MACH_MSGH_BITS_OTHER(kmsg
->ikm_header
->msgh_bits
) |
4053 MACH_MSGH_BITS(reply_type
, dest_type
));
4054 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
4055 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
4058 #if IKM_SUPPORT_LEGACY
4060 ipc_kmsg_copyout_to_kernel_legacy(
4066 mach_msg_type_name_t dest_type
;
4067 mach_msg_type_name_t reply_type
;
4068 mach_port_name_t dest_name
, reply_name
;
4070 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
4071 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
4072 dest_type
= MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
);
4073 reply_type
= MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
);
4075 assert(IO_VALID(dest
));
4078 if (io_active(dest
)) {
4079 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
4080 /* dest is unlocked */
4083 io_check_unlock(dest
);
4084 dest_name
= MACH_PORT_DEAD
;
4087 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
4089 kmsg
->ikm_header
->msgh_bits
=
4090 (MACH_MSGH_BITS_OTHER(kmsg
->ikm_header
->msgh_bits
) |
4091 MACH_MSGH_BITS(reply_type
, dest_type
));
4092 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
4093 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
4095 mach_msg_descriptor_t
*saddr
;
4096 mach_msg_legacy_descriptor_t
*daddr
;
4097 mach_msg_type_number_t i
, count
= ((mach_msg_base_t
*)kmsg
->ikm_header
)->body
.msgh_descriptor_count
;
4098 saddr
= (mach_msg_descriptor_t
*) (((mach_msg_base_t
*)kmsg
->ikm_header
) + 1);
4099 saddr
= &saddr
[count
-1];
4100 daddr
= (mach_msg_legacy_descriptor_t
*)&saddr
[count
];
4103 vm_offset_t dsc_adjust
= 0;
4105 for (i
= 0; i
< count
; i
++, saddr
--, daddr
--) {
4106 switch (saddr
->type
.type
) {
4107 case MACH_MSG_PORT_DESCRIPTOR
: {
4108 mach_msg_port_descriptor_t
*dsc
= &saddr
->port
;
4109 mach_msg_legacy_port_descriptor_t
*dest_dsc
= &daddr
->port
;
4111 mach_port_t name
= dsc
->name
;
4112 mach_msg_type_name_t disposition
= dsc
->disposition
;
4114 dest_dsc
->name
= CAST_MACH_PORT_TO_NAME(name
);
4115 dest_dsc
->disposition
= disposition
;
4116 dest_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
4119 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4120 case MACH_MSG_OOL_DESCRIPTOR
: {
4121 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
4122 * so we don't need to do anything special. */
4124 mach_msg_ool_descriptor_t
*source_dsc
= (typeof(source_dsc
))&saddr
->out_of_line
;
4126 mach_msg_ool_descriptor32_t
*dest_dsc
= &daddr
->out_of_line32
;
4128 vm_offset_t address
= (vm_offset_t
)source_dsc
->address
;
4129 vm_size_t size
= source_dsc
->size
;
4130 boolean_t deallocate
= source_dsc
->deallocate
;
4131 mach_msg_copy_options_t copy
= source_dsc
->copy
;
4132 mach_msg_descriptor_type_t type
= source_dsc
->type
;
4134 dest_dsc
->address
= address
;
4135 dest_dsc
->size
= size
;
4136 dest_dsc
->deallocate
= deallocate
;
4137 dest_dsc
->copy
= copy
;
4138 dest_dsc
->type
= type
;
4141 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
4142 mach_msg_ool_ports_descriptor_t
*source_dsc
= (typeof(source_dsc
))&saddr
->ool_ports
;
4144 mach_msg_ool_ports_descriptor32_t
*dest_dsc
= &daddr
->ool_ports32
;
4146 vm_offset_t address
= (vm_offset_t
)source_dsc
->address
;
4147 vm_size_t port_count
= source_dsc
->count
;
4148 boolean_t deallocate
= source_dsc
->deallocate
;
4149 mach_msg_copy_options_t copy
= source_dsc
->copy
;
4150 mach_msg_descriptor_type_t type
= source_dsc
->type
;
4152 dest_dsc
->address
= address
;
4153 dest_dsc
->count
= port_count
;
4154 dest_dsc
->deallocate
= deallocate
;
4155 dest_dsc
->copy
= copy
;
4156 dest_dsc
->type
= type
;
4161 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
4162 #endif /* MACH_ASSERT */
4168 dsc_adjust
= 4*count
;
4169 memmove((char *)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
4170 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
);
4171 /* Update the message size for the smaller user representation */
4172 kmsg
->ikm_header
->msgh_size
-= dsc_adjust
;
4175 #endif /* IKM_SUPPORT_LEGACY */
4178 #include <mach_kdb.h>
4181 #include <ddb/db_output.h>
4182 #include <ipc/ipc_print.h>
4184 * Forward declarations
4186 void ipc_msg_print_untyped(
4187 mach_msg_body_t
*body
);
4189 const char * ipc_type_name(
4191 boolean_t received
);
4195 mach_msg_bits_t bit
);
4198 mm_copy_options_string(
4199 mach_msg_copy_options_t option
);
4201 void db_print_msg_uid(mach_msg_header_t
*);
4209 switch (type_name
) {
4210 case MACH_MSG_TYPE_PORT_NAME
:
4213 case MACH_MSG_TYPE_MOVE_RECEIVE
:
4215 return "port_receive";
4217 return "move_receive";
4220 case MACH_MSG_TYPE_MOVE_SEND
:
4227 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
4229 return "port_send_once";
4231 return "move_send_once";
4234 case MACH_MSG_TYPE_COPY_SEND
:
4237 case MACH_MSG_TYPE_MAKE_SEND
:
4240 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
4241 return "make_send_once";
4249 ipc_print_type_name(
4252 const char *name
= ipc_type_name(type_name
, TRUE
);
4256 printf("type%d", type_name
);
4261 * ipc_kmsg_print [ debug ]
4267 iprintf("kmsg=0x%x\n", kmsg
);
4268 iprintf("ikm_next=0x%x, prev=0x%x, size=%d",
4273 ipc_msg_print(kmsg
->ikm_header
);
4278 mach_msg_bits_t bit
)
4281 case MACH_MSGH_BITS_COMPLEX
: return "complex";
4282 case MACH_MSGH_BITS_CIRCULAR
: return "circular";
4283 default: return (char *) 0;
4288 * ipc_msg_print [ debug ]
4292 mach_msg_header_t
*msgh
)
4294 mach_msg_bits_t mbits
;
4295 unsigned int bit
, i
;
4296 const char *bit_name
;
4299 mbits
= msgh
->msgh_bits
;
4300 iprintf("msgh_bits=0x%x: l=0x%x,r=0x%x\n",
4302 MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
),
4303 MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
4305 mbits
= MACH_MSGH_BITS_OTHER(mbits
) & MACH_MSGH_BITS_USED
;
4308 iprintf("decoded bits: ");
4310 for (i
= 0, bit
= 1; i
< sizeof(mbits
) * 8; ++i
, bit
<<= 1) {
4311 if ((mbits
& bit
) == 0)
4313 bit_name
= msgh_bit_decode((mach_msg_bits_t
)bit
);
4315 printf("%s%s", needs_comma
? "," : "", bit_name
);
4317 printf("%sunknown(0x%x),", needs_comma
? "," : "", bit
);
4320 if (msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
) {
4321 printf("%sunused=0x%x,", needs_comma
? "," : "",
4322 msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
);
4328 if (msgh
->msgh_remote_port
) {
4329 iprintf("remote=0x%x(", msgh
->msgh_remote_port
);
4330 ipc_print_type_name(MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
4333 iprintf("remote=null");
4336 if (msgh
->msgh_local_port
) {
4337 printf("%slocal=%p(", needs_comma
? "," : "",
4338 msgh
->msgh_local_port
);
4339 ipc_print_type_name(MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
));
4342 printf("local=null\n");
4345 iprintf("msgh_id=%d, size=%d\n",
4349 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
4350 ipc_msg_print_untyped((mach_msg_body_t
*) (msgh
+ 1));
4356 mm_copy_options_string(
4357 mach_msg_copy_options_t option
)
4362 case MACH_MSG_PHYSICAL_COPY
:
4365 case MACH_MSG_VIRTUAL_COPY
:
4368 case MACH_MSG_OVERWRITE
:
4371 case MACH_MSG_ALLOCATE
:
4374 case MACH_MSG_KALLOC_COPY_T
:
4375 name
= "KALLOC_COPY_T";
4385 ipc_msg_print_untyped(
4386 mach_msg_body_t
*body
)
4388 mach_msg_descriptor_t
*saddr
, *send
;
4389 mach_msg_descriptor_type_t type
;
4391 iprintf("%d descriptors %d: \n", body
->msgh_descriptor_count
);
4393 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
4394 send
= saddr
+ body
->msgh_descriptor_count
;
4396 for ( ; saddr
< send
; saddr
++ ) {
4398 type
= saddr
->type
.type
;
4402 case MACH_MSG_PORT_DESCRIPTOR
: {
4403 mach_msg_port_descriptor_t
*dsc
;
4406 iprintf("-- PORT name = 0x%x disp = ", dsc
->name
);
4407 ipc_print_type_name(dsc
->disposition
);
4411 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4412 case MACH_MSG_OOL_DESCRIPTOR
: {
4413 mach_msg_ool_descriptor_t
*dsc
;
4415 dsc
= &saddr
->out_of_line
;
4416 iprintf("-- OOL%s addr = 0x%x size = 0x%x copy = %s %s\n",
4417 type
== MACH_MSG_OOL_DESCRIPTOR
? "" : " VOLATILE",
4418 dsc
->address
, dsc
->size
,
4419 mm_copy_options_string(dsc
->copy
),
4420 dsc
->deallocate
? "DEALLOC" : "");
4423 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
4424 mach_msg_ool_ports_descriptor_t
*dsc
;
4426 dsc
= &saddr
->ool_ports
;
4428 iprintf("-- OOL_PORTS addr = 0x%x count = 0x%x ",
4429 dsc
->address
, dsc
->count
);
4431 ipc_print_type_name(dsc
->disposition
);
4432 printf(" copy = %s %s\n",
4433 mm_copy_options_string(dsc
->copy
),
4434 dsc
->deallocate
? "DEALLOC" : "");
4439 iprintf("-- UNKNOWN DESCRIPTOR 0x%x\n", type
);
4445 #endif /* MACH_KDB */