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.
74 #include <mach/mach_types.h>
75 #include <mach/boolean.h>
76 #include <mach/kern_return.h>
77 #include <mach/message.h>
78 #include <mach/port.h>
79 #include <mach/vm_map.h>
80 #include <mach/mach_vm.h>
81 #include <mach/vm_statistics.h>
83 #include <kern/kern_types.h>
84 #include <kern/assert.h>
85 #include <kern/debug.h>
86 #include <kern/ipc_kobject.h>
87 #include <kern/kalloc.h>
88 #include <kern/zalloc.h>
89 #include <kern/processor.h>
90 #include <kern/thread.h>
91 #include <kern/sched_prim.h>
92 #include <kern/misc_protos.h>
93 #include <kern/counters.h>
94 #include <kern/cpu_data.h>
95 #include <kern/policy_internal.h>
97 #include <pthread/priority_private.h>
99 #include <machine/limits.h>
101 #include <vm/vm_map.h>
102 #include <vm/vm_object.h>
103 #include <vm/vm_kern.h>
105 #include <ipc/port.h>
106 #include <ipc/ipc_types.h>
107 #include <ipc/ipc_entry.h>
108 #include <ipc/ipc_kmsg.h>
109 #include <ipc/ipc_notify.h>
110 #include <ipc/ipc_object.h>
111 #include <ipc/ipc_space.h>
112 #include <ipc/ipc_port.h>
113 #include <ipc/ipc_right.h>
114 #include <ipc/ipc_hash.h>
115 #include <ipc/ipc_table.h>
116 #include <ipc/ipc_importance.h>
118 #include <kern/mach_node.h>
119 #include <ipc/flipc.h>
122 #include <os/overflow.h>
124 #include <security/mac_mach_internal.h>
126 #include <device/device_server.h>
131 #include <ppc/Firmware.h>
132 #include <ppc/low_trace.h>
136 #define DEBUG_MSGS_K64 1
139 #include <sys/kdebug.h>
140 #include <libkern/OSAtomic.h>
145 mach_msg_bits_t msgh_bits
;
146 mach_msg_size_t msgh_size
;
147 mach_port_name_t msgh_remote_port
;
148 mach_port_name_t msgh_local_port
;
149 mach_port_name_t msgh_voucher_port
;
150 mach_msg_id_t msgh_id
;
151 } mach_msg_legacy_header_t
;
154 mach_msg_legacy_header_t header
;
155 mach_msg_body_t body
;
156 } mach_msg_legacy_base_t
;
159 mach_port_name_t name
;
160 mach_msg_size_t pad1
;
162 mach_msg_type_name_t disposition
: 8;
163 mach_msg_descriptor_type_t type
: 8;
164 } mach_msg_legacy_port_descriptor_t
;
168 mach_msg_legacy_port_descriptor_t port
;
169 mach_msg_ool_descriptor32_t out_of_line32
;
170 mach_msg_ool_ports_descriptor32_t ool_ports32
;
171 mach_msg_guarded_port_descriptor32_t guarded_port32
;
172 mach_msg_type_descriptor_t type
;
173 } mach_msg_legacy_descriptor_t
;
177 #define LEGACY_HEADER_SIZE_DELTA ((mach_msg_size_t)(sizeof(mach_msg_header_t) - sizeof(mach_msg_legacy_header_t)))
183 extern void ipc_pset_print64(
186 extern void ipc_kmsg_print64(
190 extern void ipc_msg_print64(
191 mach_msg_header_t
*msgh
);
193 extern ipc_port_t
ipc_name_to_data64(
195 mach_port_name_t name
);
198 * Forward declarations
200 void ipc_msg_print_untyped64(
201 mach_msg_body_t
*body
);
203 const char * ipc_type_name64(
207 void ipc_print_type_name64(
212 mach_msg_bits_t bit
);
215 mm_copy_options_string64(
216 mach_msg_copy_options_t option
);
218 void db_print_msg_uid64(mach_msg_header_t
*);
221 ipc_msg_body_print64(void *body
, int size
)
223 uint32_t *word
= (uint32_t *) body
;
224 uint32_t *end
= (uint32_t *)(((uintptr_t) body
) + size
225 - sizeof(mach_msg_header_t
));
228 kprintf(" body(%p-%p):\n %p: ", body
, end
, word
);
230 for (i
= 0; i
< 8; i
++, word
++) {
235 kprintf("%08x ", *word
);
237 kprintf("\n %p: ", word
);
248 case MACH_MSG_TYPE_PORT_NAME
:
251 case MACH_MSG_TYPE_MOVE_RECEIVE
:
253 return "port_receive";
255 return "move_receive";
258 case MACH_MSG_TYPE_MOVE_SEND
:
265 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
267 return "port_send_once";
269 return "move_send_once";
272 case MACH_MSG_TYPE_COPY_SEND
:
275 case MACH_MSG_TYPE_MAKE_SEND
:
278 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
279 return "make_send_once";
287 ipc_print_type_name64(
290 const char *name
= ipc_type_name64(type_name
, TRUE
);
294 kprintf("type%d", type_name
);
299 * ipc_kmsg_print64 [ debug ]
306 kprintf("%s kmsg=%p:\n", str
, kmsg
);
307 kprintf(" next=%p, prev=%p, size=%d",
312 ipc_msg_print64(kmsg
->ikm_header
);
320 case MACH_MSGH_BITS_COMPLEX
: return "complex";
321 case MACH_MSGH_BITS_CIRCULAR
: return "circular";
322 default: return (char *) 0;
327 * ipc_msg_print64 [ debug ]
331 mach_msg_header_t
*msgh
)
333 mach_msg_bits_t mbits
;
335 const char *bit_name
;
338 mbits
= msgh
->msgh_bits
;
339 kprintf(" msgh_bits=0x%x: l=0x%x,r=0x%x\n",
341 MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
),
342 MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
344 mbits
= MACH_MSGH_BITS_OTHER(mbits
) & MACH_MSGH_BITS_USED
;
345 kprintf(" decoded bits: ");
347 for (i
= 0, bit
= 1; i
< sizeof(mbits
) * 8; ++i
, bit
<<= 1) {
348 if ((mbits
& bit
) == 0) {
351 bit_name
= msgh_bit_decode64((mach_msg_bits_t
)bit
);
353 kprintf("%s%s", needs_comma
? "," : "", bit_name
);
355 kprintf("%sunknown(0x%x),", needs_comma
? "," : "", bit
);
359 if (msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
) {
360 kprintf("%sunused=0x%x,", needs_comma
? "," : "",
361 msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
);
366 if (msgh
->msgh_remote_port
) {
367 kprintf(" remote=%p(", msgh
->msgh_remote_port
);
368 ipc_print_type_name64(MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
371 kprintf(" remote=null");
374 if (msgh
->msgh_local_port
) {
375 kprintf("%slocal=%p(", needs_comma
? "," : "",
376 msgh
->msgh_local_port
);
377 ipc_print_type_name64(MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
));
380 kprintf("local=null\n");
383 kprintf(" msgh_id=%d, size=%d\n",
387 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
388 ipc_msg_print_untyped64((mach_msg_body_t
*) (msgh
+ 1));
391 ipc_msg_body_print64((void *)(msgh
+ 1), msgh
->msgh_size
);
396 mm_copy_options_string64(
397 mach_msg_copy_options_t option
)
402 case MACH_MSG_PHYSICAL_COPY
:
405 case MACH_MSG_VIRTUAL_COPY
:
408 case MACH_MSG_OVERWRITE
:
409 name
= "OVERWRITE(DEPRECATED)";
411 case MACH_MSG_ALLOCATE
:
414 case MACH_MSG_KALLOC_COPY_T
:
415 name
= "KALLOC_COPY_T";
425 ipc_msg_print_untyped64(
426 mach_msg_body_t
*body
)
428 mach_msg_descriptor_t
*saddr
, *send
;
429 mach_msg_descriptor_type_t type
;
431 kprintf(" %d descriptors: \n", body
->msgh_descriptor_count
);
433 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
434 send
= saddr
+ body
->msgh_descriptor_count
;
436 for (; saddr
< send
; saddr
++) {
437 type
= saddr
->type
.type
;
440 case MACH_MSG_PORT_DESCRIPTOR
: {
441 mach_msg_port_descriptor_t
*dsc
;
444 kprintf(" PORT name = %p disp = ", dsc
->name
);
445 ipc_print_type_name64(dsc
->disposition
);
449 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
450 case MACH_MSG_OOL_DESCRIPTOR
: {
451 mach_msg_ool_descriptor_t
*dsc
;
453 dsc
= (mach_msg_ool_descriptor_t
*) &saddr
->out_of_line
;
454 kprintf(" OOL%s addr = %p size = 0x%x copy = %s %s\n",
455 type
== MACH_MSG_OOL_DESCRIPTOR
? "" : " VOLATILE",
456 dsc
->address
, dsc
->size
,
457 mm_copy_options_string64(dsc
->copy
),
458 dsc
->deallocate
? "DEALLOC" : "");
461 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
462 mach_msg_ool_ports_descriptor_t
*dsc
;
464 dsc
= (mach_msg_ool_ports_descriptor_t
*) &saddr
->ool_ports
;
466 kprintf(" OOL_PORTS addr = %p count = 0x%x ",
467 dsc
->address
, dsc
->count
);
469 ipc_print_type_name64(dsc
->disposition
);
470 kprintf(" copy = %s %s\n",
471 mm_copy_options_string64(dsc
->copy
),
472 dsc
->deallocate
? "DEALLOC" : "");
475 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
: {
476 mach_msg_guarded_port_descriptor_t
*dsc
;
478 dsc
= (mach_msg_guarded_port_descriptor_t
*)&saddr
->guarded_port
;
479 kprintf(" GUARDED_PORT name = %p flags = 0x%x disp = ", dsc
->name
, dsc
->flags
);
480 ipc_print_type_name64(dsc
->disposition
);
485 kprintf(" UNKNOWN DESCRIPTOR 0x%x\n", type
);
492 #define DEBUG_IPC_KMSG_PRINT(kmsg, string) \
493 __unreachable_ok_push \
494 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
495 ipc_kmsg_print64(kmsg, string); \
499 #define DEBUG_IPC_MSG_BODY_PRINT(body, size) \
500 __unreachable_ok_push \
501 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
502 ipc_msg_body_print64(body,size);\
505 #else /* !DEBUG_MSGS_K64 */
506 #define DEBUG_IPC_KMSG_PRINT(kmsg, string)
507 #define DEBUG_IPC_MSG_BODY_PRINT(body, size)
508 #endif /* !DEBUG_MSGS_K64 */
510 extern vm_map_t ipc_kernel_copy_map
;
511 extern vm_size_t ipc_kmsg_max_space
;
512 extern vm_size_t ipc_kmsg_max_vm_space
;
513 extern vm_size_t ipc_kmsg_max_body_space
;
514 extern vm_size_t msg_ool_size_small
;
516 #define MSG_OOL_SIZE_SMALL msg_ool_size_small
518 #if defined(__LP64__)
519 #define MAP_SIZE_DIFFERS(map) (map->max_offset < MACH_VM_MAX_ADDRESS)
520 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor32_t
521 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor32_t
523 #define MAP_SIZE_DIFFERS(map) (map->max_offset > VM_MAX_ADDRESS)
524 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor64_t
525 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor64_t
528 #define DESC_SIZE_ADJUSTMENT ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
529 sizeof(mach_msg_ool_descriptor32_t)))
531 /* scatter list macros */
533 #define SKIP_PORT_DESCRIPTORS(s, c) \
535 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
537 if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
542 (s) = MACH_MSG_DESCRIPTOR_NULL; \
546 #define INCREMENT_SCATTER(s, c, d) \
548 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
549 s = (d) ? (mach_msg_descriptor_t *) \
550 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) : \
556 #define KMSG_TRACE_FLAG_TRACED 0x000001
557 #define KMSG_TRACE_FLAG_COMPLEX 0x000002
558 #define KMSG_TRACE_FLAG_OOLMEM 0x000004
559 #define KMSG_TRACE_FLAG_VCPY 0x000008
560 #define KMSG_TRACE_FLAG_PCPY 0x000010
561 #define KMSG_TRACE_FLAG_SND64 0x000020
562 #define KMSG_TRACE_FLAG_RAISEIMP 0x000040
563 #define KMSG_TRACE_FLAG_APP_SRC 0x000080
564 #define KMSG_TRACE_FLAG_APP_DST 0x000100
565 #define KMSG_TRACE_FLAG_DAEMON_SRC 0x000200
566 #define KMSG_TRACE_FLAG_DAEMON_DST 0x000400
567 #define KMSG_TRACE_FLAG_DST_NDFLTQ 0x000800
568 #define KMSG_TRACE_FLAG_SRC_NDFLTQ 0x001000
569 #define KMSG_TRACE_FLAG_DST_SONCE 0x002000
570 #define KMSG_TRACE_FLAG_SRC_SONCE 0x004000
571 #define KMSG_TRACE_FLAG_CHECKIN 0x008000
572 #define KMSG_TRACE_FLAG_ONEWAY 0x010000
573 #define KMSG_TRACE_FLAG_IOKIT 0x020000
574 #define KMSG_TRACE_FLAG_SNDRCV 0x040000
575 #define KMSG_TRACE_FLAG_DSTQFULL 0x080000
576 #define KMSG_TRACE_FLAG_VOUCHER 0x100000
577 #define KMSG_TRACE_FLAG_TIMER 0x200000
578 #define KMSG_TRACE_FLAG_SEMA 0x400000
579 #define KMSG_TRACE_FLAG_DTMPOWNER 0x800000
580 #define KMSG_TRACE_FLAG_GUARDED_DESC 0x1000000
582 #define KMSG_TRACE_FLAGS_MASK 0x1ffffff
583 #define KMSG_TRACE_FLAGS_SHIFT 8
585 #define KMSG_TRACE_PORTS_MASK 0xff
586 #define KMSG_TRACE_PORTS_SHIFT 0
588 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
592 ipc_kmsg_trace_send(ipc_kmsg_t kmsg
,
593 mach_msg_option_t option
)
595 task_t send_task
= TASK_NULL
;
596 ipc_port_t dst_port
, src_port
;
597 boolean_t is_task_64bit
;
598 mach_msg_header_t
*msg
;
599 mach_msg_trailer_t
*trailer
;
602 uint32_t msg_size
= 0;
603 uint64_t msg_flags
= KMSG_TRACE_FLAG_TRACED
;
604 uint32_t num_ports
= 0;
605 uint32_t send_pid
, dst_pid
;
608 * check to see not only if ktracing is enabled, but if we will
609 * _actually_ emit the KMSG_INFO tracepoint. This saves us a
610 * significant amount of processing (and a port lock hold) in
611 * the non-tracing case.
613 if (__probable((kdebug_enable
& KDEBUG_TRACE
) == 0)) {
616 if (!kdebug_debugid_enabled(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_INFO
))) {
620 msg
= kmsg
->ikm_header
;
622 dst_port
= msg
->msgh_remote_port
;
623 if (!IPC_PORT_VALID(dst_port
)) {
628 * Message properties / options
630 if ((option
& (MACH_SEND_MSG
| MACH_RCV_MSG
)) == (MACH_SEND_MSG
| MACH_RCV_MSG
)) {
631 msg_flags
|= KMSG_TRACE_FLAG_SNDRCV
;
634 if (msg
->msgh_id
>= is_iokit_subsystem
.start
&&
635 msg
->msgh_id
< is_iokit_subsystem
.end
+ 100) {
636 msg_flags
|= KMSG_TRACE_FLAG_IOKIT
;
638 /* magic XPC checkin message id (XPC_MESSAGE_ID_CHECKIN) from libxpc */
639 else if (msg
->msgh_id
== 0x77303074u
/* w00t */) {
640 msg_flags
|= KMSG_TRACE_FLAG_CHECKIN
;
643 if (msg
->msgh_bits
& MACH_MSGH_BITS_RAISEIMP
) {
644 msg_flags
|= KMSG_TRACE_FLAG_RAISEIMP
;
647 if (unsafe_convert_port_to_voucher(kmsg
->ikm_voucher
)) {
648 msg_flags
|= KMSG_TRACE_FLAG_VOUCHER
;
652 * Sending task / port
654 send_task
= current_task();
655 send_pid
= task_pid(send_task
);
658 if (task_is_daemon(send_task
)) {
659 msg_flags
|= KMSG_TRACE_FLAG_DAEMON_SRC
;
660 } else if (task_is_app(send_task
)) {
661 msg_flags
|= KMSG_TRACE_FLAG_APP_SRC
;
665 is_task_64bit
= (send_task
->map
->max_offset
> VM_MAX_ADDRESS
);
667 msg_flags
|= KMSG_TRACE_FLAG_SND64
;
670 src_port
= msg
->msgh_local_port
;
672 if (src_port
->ip_messages
.imq_qlimit
!= MACH_PORT_QLIMIT_DEFAULT
) {
673 msg_flags
|= KMSG_TRACE_FLAG_SRC_NDFLTQ
;
675 switch (MACH_MSGH_BITS_LOCAL(msg
->msgh_bits
)) {
676 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
677 msg_flags
|= KMSG_TRACE_FLAG_SRC_SONCE
;
683 msg_flags
|= KMSG_TRACE_FLAG_ONEWAY
;
688 * Destination task / port
691 if (!ip_active(dst_port
)) {
692 /* dst port is being torn down */
693 dst_pid
= (uint32_t)0xfffffff0;
694 } else if (dst_port
->ip_tempowner
) {
695 msg_flags
|= KMSG_TRACE_FLAG_DTMPOWNER
;
696 if (IIT_NULL
!= dst_port
->ip_imp_task
) {
697 dst_pid
= task_pid(dst_port
->ip_imp_task
->iit_task
);
699 dst_pid
= (uint32_t)0xfffffff1;
701 } else if (dst_port
->ip_receiver_name
== MACH_PORT_NULL
) {
702 /* dst_port is otherwise in-transit */
703 dst_pid
= (uint32_t)0xfffffff2;
705 if (dst_port
->ip_receiver
== ipc_space_kernel
) {
708 ipc_space_t dst_space
;
709 dst_space
= dst_port
->ip_receiver
;
710 if (dst_space
&& is_active(dst_space
)) {
711 dst_pid
= task_pid(dst_space
->is_task
);
712 if (task_is_daemon(dst_space
->is_task
)) {
713 msg_flags
|= KMSG_TRACE_FLAG_DAEMON_DST
;
714 } else if (task_is_app(dst_space
->is_task
)) {
715 msg_flags
|= KMSG_TRACE_FLAG_APP_DST
;
718 /* receiving task is being torn down */
719 dst_pid
= (uint32_t)0xfffffff3;
724 if (dst_port
->ip_messages
.imq_qlimit
!= MACH_PORT_QLIMIT_DEFAULT
) {
725 msg_flags
|= KMSG_TRACE_FLAG_DST_NDFLTQ
;
727 if (imq_full(&dst_port
->ip_messages
)) {
728 msg_flags
|= KMSG_TRACE_FLAG_DSTQFULL
;
731 kotype
= ip_kotype(dst_port
);
737 msg_flags
|= KMSG_TRACE_FLAG_SEMA
;
741 msg_flags
|= KMSG_TRACE_FLAG_TIMER
;
743 case IKOT_MASTER_DEVICE
:
744 case IKOT_IOKIT_CONNECT
:
745 case IKOT_IOKIT_OBJECT
:
746 case IKOT_IOKIT_IDENT
:
747 case IKOT_UEXT_OBJECT
:
748 msg_flags
|= KMSG_TRACE_FLAG_IOKIT
;
754 switch (MACH_MSGH_BITS_REMOTE(msg
->msgh_bits
)) {
755 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
756 msg_flags
|= KMSG_TRACE_FLAG_DST_SONCE
;
764 * Message size / content
766 msg_size
= msg
->msgh_size
- sizeof(mach_msg_header_t
);
768 if (msg
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
769 mach_msg_body_t
*msg_body
;
770 mach_msg_descriptor_t
*kern_dsc
;
773 msg_flags
|= KMSG_TRACE_FLAG_COMPLEX
;
775 msg_body
= (mach_msg_body_t
*)(kmsg
->ikm_header
+ 1);
776 dsc_count
= (int)msg_body
->msgh_descriptor_count
;
777 kern_dsc
= (mach_msg_descriptor_t
*)(msg_body
+ 1);
779 /* this is gross: see ipc_kmsg_copyin_body()... */
780 if (!is_task_64bit
) {
781 msg_size
-= (dsc_count
* 12);
784 for (int i
= 0; i
< dsc_count
; i
++) {
785 switch (kern_dsc
[i
].type
.type
) {
786 case MACH_MSG_PORT_DESCRIPTOR
:
792 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
793 case MACH_MSG_OOL_DESCRIPTOR
: {
794 mach_msg_ool_descriptor_t
*dsc
;
795 dsc
= (mach_msg_ool_descriptor_t
*)&kern_dsc
[i
];
796 msg_flags
|= KMSG_TRACE_FLAG_OOLMEM
;
797 msg_size
+= dsc
->size
;
798 if ((dsc
->size
>= MSG_OOL_SIZE_SMALL
) &&
799 (dsc
->copy
== MACH_MSG_PHYSICAL_COPY
) &&
801 msg_flags
|= KMSG_TRACE_FLAG_PCPY
;
802 } else if (dsc
->size
<= MSG_OOL_SIZE_SMALL
) {
803 msg_flags
|= KMSG_TRACE_FLAG_PCPY
;
805 msg_flags
|= KMSG_TRACE_FLAG_VCPY
;
811 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
812 mach_msg_ool_ports_descriptor_t
*dsc
;
813 dsc
= (mach_msg_ool_ports_descriptor_t
*)&kern_dsc
[i
];
814 num_ports
+= dsc
->count
;
819 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
821 msg_flags
|= KMSG_TRACE_FLAG_GUARDED_DESC
;
834 trailer
= (mach_msg_trailer_t
*)((vm_offset_t
)msg
+
835 round_msg((vm_offset_t
)msg
->msgh_size
));
836 if (trailer
->msgh_trailer_size
<= sizeof(mach_msg_security_trailer_t
)) {
837 extern const security_token_t KERNEL_SECURITY_TOKEN
;
838 mach_msg_security_trailer_t
*strailer
;
839 strailer
= (mach_msg_security_trailer_t
*)trailer
;
841 * verify the sender PID: replies from the kernel often look
842 * like self-talk because the sending port is not reset.
844 if (memcmp(&strailer
->msgh_sender
,
845 &KERNEL_SECURITY_TOKEN
,
846 sizeof(KERNEL_SECURITY_TOKEN
)) == 0) {
848 msg_flags
&= ~(KMSG_TRACE_FLAG_APP_SRC
| KMSG_TRACE_FLAG_DAEMON_SRC
);
852 KDBG(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
,
857 ((msg_flags
& KMSG_TRACE_FLAGS_MASK
) << KMSG_TRACE_FLAGS_SHIFT
) |
858 ((num_ports
& KMSG_TRACE_PORTS_MASK
) << KMSG_TRACE_PORTS_SHIFT
)
864 /* zone for cached ipc_kmsg_t structures */
865 zone_t ipc_kmsg_zone
;
868 * Forward declarations
874 void ipc_kmsg_clean_body(
876 mach_msg_type_number_t number
,
877 mach_msg_descriptor_t
*desc
);
879 void ipc_kmsg_clean_partial(
881 mach_msg_type_number_t number
,
882 mach_msg_descriptor_t
*desc
,
886 mach_msg_return_t
ipc_kmsg_copyin_body(
890 mach_msg_option_t
*optionp
);
893 extern int enforce_strict_reply
;
896 ipc_kmsg_link_reply_context_locked(
897 ipc_port_t reply_port
,
898 ipc_port_t voucher_port
);
901 ipc_kmsg_validate_reply_port_locked(
902 ipc_port_t reply_port
,
903 mach_msg_option_t options
);
905 static mach_msg_return_t
906 ipc_kmsg_validate_reply_context_locked(
907 mach_msg_option_t option
,
908 ipc_port_t dest_port
,
909 ipc_voucher_t voucher
,
910 mach_port_name_t voucher_name
);
912 /* we can't include the BSD <sys/persona.h> header here... */
913 #ifndef PERSONA_ID_NONE
914 #define PERSONA_ID_NONE ((uint32_t)-1)
918 * We keep a per-processor cache of kernel message buffers.
919 * The cache saves the overhead/locking of using kalloc/kfree.
920 * The per-processor cache seems to miss less than a per-thread cache,
921 * and it also uses less memory. Access to the cache doesn't
926 * Routine: ipc_kmsg_alloc
928 * Allocate a kernel message structure. If we can get one from
929 * the cache, that is best. Otherwise, allocate a new one.
935 mach_msg_size_t msg_and_trailer_size
)
937 mach_msg_size_t max_expanded_size
;
942 * Pad the allocation in case we need to expand the
943 * message descriptors for user spaces with pointers larger than
944 * the kernel's own, or vice versa. We don't know how many descriptors
945 * there are yet, so just assume the whole body could be
946 * descriptors (if there could be any at all).
948 * The expansion space is left in front of the header,
949 * because it is easier to pull the header and descriptors
950 * forward as we process them than it is to push all the
953 mach_msg_size_t size
= msg_and_trailer_size
- MAX_TRAILER_SIZE
;
955 /* compare against implementation upper limit for the body */
956 if (size
> ipc_kmsg_max_body_space
) {
960 if (size
> sizeof(mach_msg_base_t
)) {
961 mach_msg_size_t max_desc
= (mach_msg_size_t
)(((size
- sizeof(mach_msg_base_t
)) /
962 sizeof(mach_msg_ool_descriptor32_t
)) *
963 DESC_SIZE_ADJUSTMENT
);
965 /* make sure expansion won't cause wrap */
966 if (msg_and_trailer_size
> MACH_MSG_SIZE_MAX
- max_desc
) {
970 max_expanded_size
= msg_and_trailer_size
+ max_desc
;
972 max_expanded_size
= msg_and_trailer_size
;
975 if (max_expanded_size
< IKM_SAVED_MSG_SIZE
) {
976 max_expanded_size
= IKM_SAVED_MSG_SIZE
; /* round up for ikm_cache */
978 if (max_expanded_size
== IKM_SAVED_MSG_SIZE
) {
979 kmsg
= (ipc_kmsg_t
)zalloc(ipc_kmsg_zone
);
981 kmsg
= (ipc_kmsg_t
)kalloc(ikm_plus_overhead(max_expanded_size
));
984 if (kmsg
!= IKM_NULL
) {
985 ikm_init(kmsg
, max_expanded_size
);
986 ikm_set_header(kmsg
, msg_and_trailer_size
);
993 * Routine: ipc_kmsg_free
995 * Free a kernel message buffer. If the kms is preallocated
996 * to a port, just "put it back (marked unused)." We have to
997 * do this with the port locked. The port may have its hold
998 * on our message released. In that case, we have to just
999 * revert the message to a traditional one and free it normally.
1008 mach_msg_size_t size
= kmsg
->ikm_size
;
1011 assert(!IP_VALID(kmsg
->ikm_voucher
));
1013 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_FREE
) | DBG_FUNC_NONE
,
1014 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
1018 * Check to see if the message is bound to the port. If so,
1019 * mark it not in use. If the port isn't already dead, then
1020 * leave the message associated with it. Otherwise, free it.
1022 port
= ikm_prealloc_inuse_port(kmsg
);
1023 if (port
!= IP_NULL
) {
1025 ikm_prealloc_clear_inuse(kmsg
, port
);
1026 if (ip_active(port
) && (port
->ip_premsg
== kmsg
)) {
1027 assert(IP_PREALLOC(port
));
1033 ip_release(port
); /* May be last reference */
1036 if (kmsg
->ikm_size
== IKM_SAVED_MSG_SIZE
) {
1037 zfree(ipc_kmsg_zone
, kmsg
);
1040 kfree(kmsg
, ikm_plus_overhead(size
));
1045 * Routine: ipc_kmsg_enqueue
1052 ipc_kmsg_queue_t queue
,
1055 ipc_kmsg_t first
= queue
->ikmq_base
;
1058 if (first
== IKM_NULL
) {
1059 queue
->ikmq_base
= kmsg
;
1060 kmsg
->ikm_next
= kmsg
;
1061 kmsg
->ikm_prev
= kmsg
;
1063 last
= first
->ikm_prev
;
1064 kmsg
->ikm_next
= first
;
1065 kmsg
->ikm_prev
= last
;
1066 first
->ikm_prev
= kmsg
;
1067 last
->ikm_next
= kmsg
;
1072 * Routine: ipc_kmsg_enqueue_qos
1074 * Enqueue a kmsg, propagating qos
1075 * overrides towards the head of the queue.
1078 * whether the head of the queue had
1079 * it's override-qos adjusted because
1080 * of this insertion.
1084 ipc_kmsg_enqueue_qos(
1085 ipc_kmsg_queue_t queue
,
1088 ipc_kmsg_t first
= queue
->ikmq_base
;
1090 mach_msg_priority_t override
;
1092 if (first
== IKM_NULL
) {
1093 /* insert a first message */
1094 queue
->ikmq_base
= kmsg
;
1095 kmsg
->ikm_next
= kmsg
;
1096 kmsg
->ikm_prev
= kmsg
;
1100 /* insert at the tail */
1101 prev
= first
->ikm_prev
;
1102 kmsg
->ikm_next
= first
;
1103 kmsg
->ikm_prev
= prev
;
1104 first
->ikm_prev
= kmsg
;
1105 prev
->ikm_next
= kmsg
;
1107 /* apply QoS overrides towards the head */
1108 override
= kmsg
->ikm_qos_override
;
1109 while (prev
!= kmsg
&&
1110 override
> prev
->ikm_qos_override
) {
1111 prev
->ikm_qos_override
= override
;
1112 prev
= prev
->ikm_prev
;
1115 /* did we adjust everything? */
1116 return prev
== kmsg
;
1120 * Routine: ipc_kmsg_override_qos
1122 * Update the override for a given kmsg already
1123 * enqueued, propagating qos override adjustments
1124 * towards the head of the queue.
1127 * whether the head of the queue had
1128 * it's override-qos adjusted because
1129 * of this insertion.
1133 ipc_kmsg_override_qos(
1134 ipc_kmsg_queue_t queue
,
1136 mach_msg_priority_t override
)
1138 ipc_kmsg_t first
= queue
->ikmq_base
;
1139 ipc_kmsg_t cur
= kmsg
;
1141 /* apply QoS overrides towards the head */
1142 while (override
> cur
->ikm_qos_override
) {
1143 cur
->ikm_qos_override
= override
;
1147 cur
= cur
->ikm_prev
;
1153 * Routine: ipc_kmsg_dequeue
1155 * Dequeue and return a kmsg.
1160 ipc_kmsg_queue_t queue
)
1164 first
= ipc_kmsg_queue_first(queue
);
1166 if (first
!= IKM_NULL
) {
1167 ipc_kmsg_rmqueue(queue
, first
);
1174 * Routine: ipc_kmsg_rmqueue
1176 * Pull a kmsg out of a queue.
1181 ipc_kmsg_queue_t queue
,
1184 ipc_kmsg_t next
, prev
;
1186 assert(queue
->ikmq_base
!= IKM_NULL
);
1188 next
= kmsg
->ikm_next
;
1189 prev
= kmsg
->ikm_prev
;
1192 assert(prev
== kmsg
);
1193 assert(queue
->ikmq_base
== kmsg
);
1195 queue
->ikmq_base
= IKM_NULL
;
1197 if (__improbable(next
->ikm_prev
!= kmsg
|| prev
->ikm_next
!= kmsg
)) {
1198 panic("ipc_kmsg_rmqueue: inconsistent prev/next pointers. "
1199 "(prev->next: %p, next->prev: %p, kmsg: %p)",
1200 prev
->ikm_next
, next
->ikm_prev
, kmsg
);
1203 if (queue
->ikmq_base
== kmsg
) {
1204 queue
->ikmq_base
= next
;
1207 next
->ikm_prev
= prev
;
1208 prev
->ikm_next
= next
;
1210 /* XXX Temporary debug logic */
1211 assert((kmsg
->ikm_next
= IKM_BOGUS
) == IKM_BOGUS
);
1212 assert((kmsg
->ikm_prev
= IKM_BOGUS
) == IKM_BOGUS
);
1216 * Routine: ipc_kmsg_queue_next
1218 * Return the kmsg following the given kmsg.
1219 * (Or IKM_NULL if it is the last one in the queue.)
1223 ipc_kmsg_queue_next(
1224 ipc_kmsg_queue_t queue
,
1229 assert(queue
->ikmq_base
!= IKM_NULL
);
1231 next
= kmsg
->ikm_next
;
1232 if (queue
->ikmq_base
== next
) {
1240 * Routine: ipc_kmsg_destroy
1242 * Destroys a kernel message. Releases all rights,
1243 * references, and memory held by the message.
1244 * Frees the message.
1254 * Destroying a message can cause more messages to be destroyed.
1255 * Curtail recursion by putting messages on the deferred
1256 * destruction queue. If this was the first message on the
1257 * queue, this instance must process the full queue.
1259 if (ipc_kmsg_delayed_destroy(kmsg
)) {
1260 ipc_kmsg_reap_delayed();
1265 * Routine: ipc_kmsg_delayed_destroy
1267 * Enqueues a kernel message for deferred destruction.
1269 * Boolean indicator that the caller is responsible to reap
1270 * deferred messages.
1274 ipc_kmsg_delayed_destroy(
1277 ipc_kmsg_queue_t queue
= &(current_thread()->ith_messages
);
1278 boolean_t first
= ipc_kmsg_queue_empty(queue
);
1280 ipc_kmsg_enqueue(queue
, kmsg
);
1285 * Routine: ipc_kmsg_destroy_queue
1287 * Destroys messages from the per-thread
1288 * deferred reaping queue.
1294 ipc_kmsg_reap_delayed(void)
1296 ipc_kmsg_queue_t queue
= &(current_thread()->ith_messages
);
1300 * must leave kmsg in queue while cleaning it to assure
1301 * no nested calls recurse into here.
1303 while ((kmsg
= ipc_kmsg_queue_first(queue
)) != IKM_NULL
) {
1304 ipc_kmsg_clean(kmsg
);
1305 ipc_kmsg_rmqueue(queue
, kmsg
);
1306 ipc_kmsg_free(kmsg
);
1311 * Routine: ipc_kmsg_clean_body
1313 * Cleans the body of a kernel message.
1314 * Releases all rights, references, and memory.
1319 static unsigned int _ipc_kmsg_clean_invalid_desc
= 0;
1321 ipc_kmsg_clean_body(
1322 __unused ipc_kmsg_t kmsg
,
1323 mach_msg_type_number_t number
,
1324 mach_msg_descriptor_t
*saddr
)
1326 mach_msg_type_number_t i
;
1332 for (i
= 0; i
< number
; i
++, saddr
++) {
1333 switch (saddr
->type
.type
) {
1334 case MACH_MSG_PORT_DESCRIPTOR
: {
1335 mach_msg_port_descriptor_t
*dsc
;
1340 * Destroy port rights carried in the message
1342 if (!IP_VALID(dsc
->name
)) {
1345 ipc_object_destroy(ip_to_object(dsc
->name
), dsc
->disposition
);
1348 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
1349 case MACH_MSG_OOL_DESCRIPTOR
: {
1350 mach_msg_ool_descriptor_t
*dsc
;
1352 dsc
= (mach_msg_ool_descriptor_t
*)&saddr
->out_of_line
;
1355 * Destroy memory carried in the message
1357 if (dsc
->size
== 0) {
1358 assert(dsc
->address
== (void *) 0);
1360 vm_map_copy_discard((vm_map_copy_t
) dsc
->address
);
1364 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
1365 ipc_object_t
*objects
;
1366 mach_msg_type_number_t j
;
1367 mach_msg_ool_ports_descriptor_t
*dsc
;
1369 dsc
= (mach_msg_ool_ports_descriptor_t
*)&saddr
->ool_ports
;
1370 objects
= (ipc_object_t
*) dsc
->address
;
1372 if (dsc
->count
== 0) {
1376 assert(objects
!= (ipc_object_t
*) 0);
1378 /* destroy port rights carried in the message */
1380 for (j
= 0; j
< dsc
->count
; j
++) {
1381 ipc_object_t object
= objects
[j
];
1383 if (!IO_VALID(object
)) {
1387 ipc_object_destroy(object
, dsc
->disposition
);
1390 /* destroy memory carried in the message */
1392 assert(dsc
->count
!= 0);
1395 (vm_size_t
) dsc
->count
* sizeof(mach_port_t
));
1398 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
: {
1399 mach_msg_guarded_port_descriptor_t
*dsc
= (typeof(dsc
)) & saddr
->guarded_port
;
1402 * Destroy port rights carried in the message
1404 if (!IP_VALID(dsc
->name
)) {
1407 ipc_object_destroy(ip_to_object(dsc
->name
), dsc
->disposition
);
1411 _ipc_kmsg_clean_invalid_desc
++; /* don't understand this type of descriptor */
1418 * Routine: ipc_kmsg_clean_partial
1420 * Cleans a partially-acquired kernel message.
1421 * number is the index of the type descriptor
1422 * in the body of the message that contained the error.
1423 * If dolast, the memory and port rights in this last
1424 * type spec are also cleaned. In that case, number
1425 * specifies the number of port rights to clean.
1431 ipc_kmsg_clean_partial(
1433 mach_msg_type_number_t number
,
1434 mach_msg_descriptor_t
*desc
,
1438 ipc_object_t object
;
1439 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
1441 /* deal with importance chain while we still have dest and voucher references */
1442 ipc_importance_clean(kmsg
);
1444 object
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
1445 assert(IO_VALID(object
));
1446 ipc_object_destroy_dest(object
, MACH_MSGH_BITS_REMOTE(mbits
));
1448 object
= ip_to_object(kmsg
->ikm_header
->msgh_local_port
);
1449 if (IO_VALID(object
)) {
1450 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
1453 object
= ip_to_object(kmsg
->ikm_voucher
);
1454 if (IO_VALID(object
)) {
1455 assert(MACH_MSGH_BITS_VOUCHER(mbits
) == MACH_MSG_TYPE_MOVE_SEND
);
1456 ipc_object_destroy(object
, MACH_MSG_TYPE_PORT_SEND
);
1457 kmsg
->ikm_voucher
= IP_NULL
;
1461 (void) vm_deallocate(ipc_kernel_copy_map
, paddr
, length
);
1464 ipc_kmsg_clean_body(kmsg
, number
, desc
);
1468 * Routine: ipc_kmsg_clean
1470 * Cleans a kernel message. Releases all rights,
1471 * references, and memory held by the message.
1480 ipc_object_t object
;
1481 mach_msg_bits_t mbits
;
1483 /* deal with importance chain while we still have dest and voucher references */
1484 ipc_importance_clean(kmsg
);
1486 mbits
= kmsg
->ikm_header
->msgh_bits
;
1487 object
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
1488 if (IO_VALID(object
)) {
1489 ipc_object_destroy_dest(object
, MACH_MSGH_BITS_REMOTE(mbits
));
1492 object
= ip_to_object(kmsg
->ikm_header
->msgh_local_port
);
1493 if (IO_VALID(object
)) {
1494 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
1497 object
= ip_to_object(kmsg
->ikm_voucher
);
1498 if (IO_VALID(object
)) {
1499 assert(MACH_MSGH_BITS_VOUCHER(mbits
) == MACH_MSG_TYPE_MOVE_SEND
);
1500 ipc_object_destroy(object
, MACH_MSG_TYPE_PORT_SEND
);
1501 kmsg
->ikm_voucher
= IP_NULL
;
1504 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
1505 mach_msg_body_t
*body
;
1507 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
1508 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
1509 (mach_msg_descriptor_t
*)(body
+ 1));
1514 * Routine: ipc_kmsg_set_prealloc
1516 * Assign a kmsg as a preallocated message buffer to a port.
1522 ipc_kmsg_set_prealloc(
1526 assert(kmsg
->ikm_prealloc
== IP_NULL
);
1528 kmsg
->ikm_prealloc
= IP_NULL
;
1530 assert(port_send_turnstile(port
) == TURNSTILE_NULL
);
1531 kmsg
->ikm_turnstile
= TURNSTILE_NULL
;
1532 IP_SET_PREALLOC(port
, kmsg
);
1536 * Routine: ipc_kmsg_clear_prealloc
1538 * Release the Assignment of a preallocated message buffer from a port.
1543 ipc_kmsg_clear_prealloc(
1547 /* take the mqueue lock since the turnstile is protected under it */
1548 imq_lock(&port
->ip_messages
);
1550 IP_CLEAR_PREALLOC(port
, kmsg
);
1551 set_port_send_turnstile(port
, kmsg
->ikm_turnstile
);
1552 imq_unlock(&port
->ip_messages
);
1556 * Routine: ipc_kmsg_prealloc
1558 * Wraper to ipc_kmsg_alloc() to account for
1559 * header expansion requirements.
1562 ipc_kmsg_prealloc(mach_msg_size_t size
)
1564 #if defined(__LP64__)
1565 if (size
> MACH_MSG_SIZE_MAX
- LEGACY_HEADER_SIZE_DELTA
) {
1569 size
+= LEGACY_HEADER_SIZE_DELTA
;
1571 return ipc_kmsg_alloc(size
);
1576 * Routine: ipc_kmsg_get
1578 * Allocates a kernel message buffer.
1579 * Copies a user message to the message buffer.
1583 * MACH_MSG_SUCCESS Acquired a message buffer.
1584 * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
1585 * MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
1586 * MACH_SEND_TOO_LARGE Message too large to ever be sent.
1587 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1588 * MACH_SEND_INVALID_DATA Couldn't copy message data.
1593 mach_vm_address_t msg_addr
,
1594 mach_msg_size_t size
,
1597 mach_msg_size_t msg_and_trailer_size
;
1599 mach_msg_max_trailer_t
*trailer
;
1600 mach_msg_legacy_base_t legacy_base
;
1601 mach_msg_size_t len_copied
;
1602 legacy_base
.body
.msgh_descriptor_count
= 0;
1604 if ((size
< sizeof(mach_msg_legacy_header_t
)) || (size
& 3)) {
1605 return MACH_SEND_MSG_TOO_SMALL
;
1608 if (size
> ipc_kmsg_max_body_space
) {
1609 return MACH_SEND_TOO_LARGE
;
1612 if (size
== sizeof(mach_msg_legacy_header_t
)) {
1613 len_copied
= sizeof(mach_msg_legacy_header_t
);
1615 len_copied
= sizeof(mach_msg_legacy_base_t
);
1618 if (copyinmsg(msg_addr
, (char *)&legacy_base
, len_copied
)) {
1619 return MACH_SEND_INVALID_DATA
;
1623 * If the message claims to be complex, it must at least
1624 * have the length of a "base" message (header + dsc_count).
1626 if (len_copied
< sizeof(mach_msg_legacy_base_t
) &&
1627 (legacy_base
.header
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
)) {
1628 return MACH_SEND_MSG_TOO_SMALL
;
1631 msg_addr
+= sizeof(legacy_base
.header
);
1632 #if defined(__LP64__)
1633 size
+= LEGACY_HEADER_SIZE_DELTA
;
1635 /* unreachable if !DEBUG */
1636 __unreachable_ok_push
1637 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
1639 for (j
= 0; j
< sizeof(legacy_base
.header
); j
++) {
1640 kprintf("%02x\n", ((unsigned char*)&legacy_base
.header
)[j
]);
1643 __unreachable_ok_pop
1645 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
1646 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
1647 if (kmsg
== IKM_NULL
) {
1648 return MACH_SEND_NO_BUFFER
;
1651 kmsg
->ikm_header
->msgh_size
= size
;
1652 kmsg
->ikm_header
->msgh_bits
= legacy_base
.header
.msgh_bits
;
1653 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(legacy_base
.header
.msgh_remote_port
);
1654 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(legacy_base
.header
.msgh_local_port
);
1655 kmsg
->ikm_header
->msgh_voucher_port
= legacy_base
.header
.msgh_voucher_port
;
1656 kmsg
->ikm_header
->msgh_id
= legacy_base
.header
.msgh_id
;
1658 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
1661 " remote_port: %p\n"
1663 " voucher_port: 0x%.8x\n"
1665 kmsg
->ikm_header
->msgh_size
,
1666 kmsg
->ikm_header
->msgh_bits
,
1667 kmsg
->ikm_header
->msgh_remote_port
,
1668 kmsg
->ikm_header
->msgh_local_port
,
1669 kmsg
->ikm_header
->msgh_voucher_port
,
1670 kmsg
->ikm_header
->msgh_id
);
1672 if (copyinmsg(msg_addr
, (char *)(kmsg
->ikm_header
+ 1), size
- (mach_msg_size_t
)sizeof(mach_msg_header_t
))) {
1673 ipc_kmsg_free(kmsg
);
1674 return MACH_SEND_INVALID_DATA
;
1677 /* unreachable if !DEBUG */
1678 __unreachable_ok_push
1679 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
1680 kprintf("body: size: %lu\n", (size
- sizeof(mach_msg_header_t
)));
1682 for (i
= 0; i
* 4 < (size
- sizeof(mach_msg_header_t
)); i
++) {
1683 kprintf("%.4x\n", ((uint32_t *)(kmsg
->ikm_header
+ 1))[i
]);
1686 __unreachable_ok_pop
1687 DEBUG_IPC_KMSG_PRINT(kmsg
, "ipc_kmsg_get()");
1690 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1691 * However, the internal size field of the trailer (msgh_trailer_size)
1692 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
1693 * the cases where no implicit data is requested.
1695 trailer
= (mach_msg_max_trailer_t
*) ((vm_offset_t
)kmsg
->ikm_header
+ size
);
1696 trailer
->msgh_sender
= current_thread()->task
->sec_token
;
1697 trailer
->msgh_audit
= current_thread()->task
->audit_token
;
1698 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
1699 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
1702 if (trcWork
.traceMask
) {
1703 dbgTrace(0x1100, (unsigned int)kmsg
->ikm_header
->msgh_id
,
1704 (unsigned int)kmsg
->ikm_header
->msgh_remote_port
,
1705 (unsigned int)kmsg
->ikm_header
->msgh_local_port
, 0);
1709 trailer
->msgh_labels
.sender
= 0;
1711 return MACH_MSG_SUCCESS
;
1715 * Routine: ipc_kmsg_get_from_kernel
1717 * First checks for a preallocated message
1718 * reserved for kernel clients. If not found -
1719 * allocates a new kernel message buffer.
1720 * Copies a kernel message to the message buffer.
1721 * Only resource errors are allowed.
1724 * Ports in header are ipc_port_t.
1726 * MACH_MSG_SUCCESS Acquired a message buffer.
1727 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1731 ipc_kmsg_get_from_kernel(
1732 mach_msg_header_t
*msg
,
1733 mach_msg_size_t size
,
1737 mach_msg_size_t msg_and_trailer_size
;
1738 mach_msg_max_trailer_t
*trailer
;
1739 ipc_port_t dest_port
;
1741 assert(size
>= sizeof(mach_msg_header_t
));
1742 assert((size
& 3) == 0);
1744 dest_port
= msg
->msgh_remote_port
;
1746 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
1749 * See if the port has a pre-allocated kmsg for kernel
1750 * clients. These are set up for those kernel clients
1751 * which cannot afford to wait.
1753 if (IP_VALID(dest_port
) && IP_PREALLOC(dest_port
)) {
1754 mach_msg_size_t max_desc
= 0;
1757 if (!ip_active(dest_port
)) {
1758 ip_unlock(dest_port
);
1759 return MACH_SEND_NO_BUFFER
;
1761 assert(IP_PREALLOC(dest_port
));
1762 kmsg
= dest_port
->ip_premsg
;
1763 if (ikm_prealloc_inuse(kmsg
)) {
1764 ip_unlock(dest_port
);
1765 return MACH_SEND_NO_BUFFER
;
1767 #if !defined(__LP64__)
1768 if (msg
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
1769 assert(size
> sizeof(mach_msg_base_t
));
1770 max_desc
= ((mach_msg_base_t
*)msg
)->body
.msgh_descriptor_count
*
1771 DESC_SIZE_ADJUSTMENT
;
1774 if (msg_and_trailer_size
> kmsg
->ikm_size
- max_desc
) {
1775 ip_unlock(dest_port
);
1776 return MACH_SEND_TOO_LARGE
;
1778 ikm_prealloc_set_inuse(kmsg
, dest_port
);
1779 ikm_set_header(kmsg
, msg_and_trailer_size
);
1780 ip_unlock(dest_port
);
1782 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
1783 if (kmsg
== IKM_NULL
) {
1784 return MACH_SEND_NO_BUFFER
;
1788 (void) memcpy((void *) kmsg
->ikm_header
, (const void *) msg
, size
);
1792 kmsg
->ikm_header
->msgh_size
= size
;
1795 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1796 * However, the internal size field of the trailer (msgh_trailer_size)
1797 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
1798 * optimize the cases where no implicit data is requested.
1800 trailer
= (mach_msg_max_trailer_t
*)
1801 ((vm_offset_t
)kmsg
->ikm_header
+ size
);
1802 trailer
->msgh_sender
= KERNEL_SECURITY_TOKEN
;
1803 trailer
->msgh_audit
= KERNEL_AUDIT_TOKEN
;
1804 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
1805 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
1807 trailer
->msgh_labels
.sender
= 0;
1810 return MACH_MSG_SUCCESS
;
1814 * Routine: ipc_kmsg_send
1816 * Send a message. The message holds a reference
1817 * for the destination port in the msgh_remote_port field.
1819 * If unsuccessful, the caller still has possession of
1820 * the message and must do something with it. If successful,
1821 * the message is queued, given to a receiver, destroyed,
1822 * or handled directly by the kernel via mach_msg.
1826 * MACH_MSG_SUCCESS The message was accepted.
1827 * MACH_SEND_TIMED_OUT Caller still has message.
1828 * MACH_SEND_INTERRUPTED Caller still has message.
1829 * MACH_SEND_INVALID_DEST Caller still has message.
1834 mach_msg_option_t option
,
1835 mach_msg_timeout_t send_timeout
)
1838 thread_t th
= current_thread();
1839 mach_msg_return_t error
= MACH_MSG_SUCCESS
;
1840 boolean_t kernel_reply
= FALSE
;
1842 /* Check if honor qlimit flag is set on thread. */
1843 if ((th
->options
& TH_OPT_HONOR_QLIMIT
) == TH_OPT_HONOR_QLIMIT
) {
1844 /* Remove the MACH_SEND_ALWAYS flag to honor queue limit. */
1845 option
&= (~MACH_SEND_ALWAYS
);
1846 /* Add the timeout flag since the message queue might be full. */
1847 option
|= MACH_SEND_TIMEOUT
;
1848 th
->options
&= (~TH_OPT_HONOR_QLIMIT
);
1851 #if IMPORTANCE_INHERITANCE
1852 bool did_importance
= false;
1853 #if IMPORTANCE_TRACE
1854 mach_msg_id_t imp_msgh_id
= -1;
1855 int sender_pid
= -1;
1856 #endif /* IMPORTANCE_TRACE */
1857 #endif /* IMPORTANCE_INHERITANCE */
1859 /* don't allow the creation of a circular loop */
1860 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_CIRCULAR
) {
1861 ipc_kmsg_destroy(kmsg
);
1862 KDBG(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, MACH_MSGH_BITS_CIRCULAR
);
1863 return MACH_MSG_SUCCESS
;
1866 ipc_voucher_send_preprocessing(kmsg
);
1868 port
= kmsg
->ikm_header
->msgh_remote_port
;
1869 assert(IP_VALID(port
));
1873 * If the destination has been guarded with a reply context, and the
1874 * sender is consuming a send-once right, then assume this is a reply
1875 * to an RPC and we need to validate that this sender is currently in
1876 * the correct context.
1878 if (enforce_strict_reply
&& port
->ip_reply_context
!= 0 &&
1879 ((option
& MACH_SEND_KERNEL
) == 0) &&
1880 MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
) == MACH_MSG_TYPE_PORT_SEND_ONCE
) {
1881 error
= ipc_kmsg_validate_reply_context_locked(option
, port
, th
->ith_voucher
, th
->ith_voucher_name
);
1882 if (error
!= MACH_MSG_SUCCESS
) {
1888 #if IMPORTANCE_INHERITANCE
1890 #endif /* IMPORTANCE_INHERITANCE */
1892 * Can't deliver to a dead port.
1893 * However, we can pretend it got sent
1894 * and was then immediately destroyed.
1896 if (!ip_active(port
)) {
1899 if (MACH_NODE_VALID(kmsg
->ikm_node
) && FPORT_VALID(port
->ip_messages
.imq_fport
)) {
1900 flipc_msg_ack(kmsg
->ikm_node
, &port
->ip_messages
, FALSE
);
1903 if (did_importance
) {
1905 * We're going to pretend we delivered this message
1906 * successfully, and just eat the kmsg. However, the
1907 * kmsg is actually visible via the importance_task!
1908 * We need to cleanup this linkage before we destroy
1909 * the message, and more importantly before we set the
1910 * msgh_remote_port to NULL. See: 34302571
1912 ipc_importance_clean(kmsg
);
1914 ip_release(port
); /* JMM - Future: release right, not just ref */
1915 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
1916 ipc_kmsg_destroy(kmsg
);
1917 KDBG(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, MACH_SEND_INVALID_DEST
);
1918 return MACH_MSG_SUCCESS
;
1921 if (port
->ip_receiver
== ipc_space_kernel
) {
1923 * We can check ip_receiver == ipc_space_kernel
1924 * before checking that the port is active because
1925 * ipc_port_dealloc_kernel clears ip_receiver
1926 * before destroying a kernel port.
1928 require_ip_active(port
);
1929 port
->ip_messages
.imq_seqno
++;
1932 current_task()->messages_sent
++;
1935 * Call the server routine, and get the reply message to send.
1937 kmsg
= ipc_kobject_server(kmsg
, option
);
1938 if (kmsg
== IKM_NULL
) {
1939 return MACH_MSG_SUCCESS
;
1942 /* restart the KMSG_INFO tracing for the reply message */
1943 KDBG(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_INFO
) | DBG_FUNC_START
);
1944 port
= kmsg
->ikm_header
->msgh_remote_port
;
1945 assert(IP_VALID(port
));
1947 /* fall thru with reply - same options */
1948 kernel_reply
= TRUE
;
1949 if (!ip_active(port
)) {
1950 error
= MACH_SEND_INVALID_DEST
;
1954 #if IMPORTANCE_INHERITANCE
1956 * Need to see if this message needs importance donation and/or
1957 * propagation. That routine can drop the port lock temporarily.
1958 * If it does we'll have to revalidate the destination.
1960 if (!did_importance
) {
1961 did_importance
= true;
1962 if (ipc_importance_send(kmsg
, option
)) {
1966 #endif /* IMPORTANCE_INHERITANCE */
1968 if (error
!= MACH_MSG_SUCCESS
) {
1972 * We have a valid message and a valid reference on the port.
1973 * we can unlock the port and call mqueue_send() on its message
1974 * queue. Lock message queue while port is locked.
1976 imq_lock(&port
->ip_messages
);
1978 ipc_special_reply_port_msg_sent(port
);
1982 error
= ipc_mqueue_send(&port
->ip_messages
, kmsg
, option
,
1986 #if IMPORTANCE_INHERITANCE
1987 if (did_importance
) {
1988 __unused
int importance_cleared
= 0;
1990 case MACH_SEND_TIMED_OUT
:
1991 case MACH_SEND_NO_BUFFER
:
1992 case MACH_SEND_INTERRUPTED
:
1993 case MACH_SEND_INVALID_DEST
:
1995 * We still have the kmsg and its
1996 * reference on the port. But we
1997 * have to back out the importance
2000 * The port could have changed hands,
2001 * be inflight to another destination,
2002 * etc... But in those cases our
2003 * back-out will find the new owner
2004 * (and all the operations that
2005 * transferred the right should have
2006 * applied their own boost adjustments
2007 * to the old owner(s)).
2009 importance_cleared
= 1;
2010 ipc_importance_clean(kmsg
);
2013 case MACH_MSG_SUCCESS
:
2017 #if IMPORTANCE_TRACE
2018 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
, (IMPORTANCE_CODE(IMP_MSG
, IMP_MSG_SEND
)) | DBG_FUNC_END
,
2019 task_pid(current_task()), sender_pid
, imp_msgh_id
, importance_cleared
, 0);
2020 #endif /* IMPORTANCE_TRACE */
2022 #endif /* IMPORTANCE_INHERITANCE */
2025 * If the port has been destroyed while we wait, treat the message
2026 * as a successful delivery (like we do for an inactive port).
2028 if (error
== MACH_SEND_INVALID_DEST
) {
2030 if (MACH_NODE_VALID(kmsg
->ikm_node
) && FPORT_VALID(port
->ip_messages
.imq_fport
)) {
2031 flipc_msg_ack(kmsg
->ikm_node
, &port
->ip_messages
, FALSE
);
2034 ip_release(port
); /* JMM - Future: release right, not just ref */
2035 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
2036 ipc_kmsg_destroy(kmsg
);
2037 KDBG(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, MACH_SEND_INVALID_DEST
);
2038 return MACH_MSG_SUCCESS
;
2041 if (error
!= MACH_MSG_SUCCESS
&& kernel_reply
) {
2043 * Kernel reply messages that fail can't be allowed to
2044 * pseudo-receive on error conditions. We need to just treat
2045 * the message as a successful delivery.
2048 if (MACH_NODE_VALID(kmsg
->ikm_node
) && FPORT_VALID(port
->ip_messages
.imq_fport
)) {
2049 flipc_msg_ack(kmsg
->ikm_node
, &port
->ip_messages
, FALSE
);
2052 ip_release(port
); /* JMM - Future: release right, not just ref */
2053 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
2054 ipc_kmsg_destroy(kmsg
);
2055 KDBG(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, error
);
2056 return MACH_MSG_SUCCESS
;
2062 * Routine: ipc_kmsg_put
2064 * Copies a message buffer to a user message.
2065 * Copies only the specified number of bytes.
2066 * Frees the message buffer.
2068 * Nothing locked. The message buffer must have clean
2071 * MACH_MSG_SUCCESS Copied data out of message buffer.
2072 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
2078 mach_msg_option_t option
,
2079 mach_vm_address_t rcv_addr
,
2080 mach_msg_size_t rcv_size
,
2081 mach_msg_size_t trailer_size
,
2082 mach_msg_size_t
*sizep
)
2084 mach_msg_size_t size
= kmsg
->ikm_header
->msgh_size
+ trailer_size
;
2085 mach_msg_return_t mr
;
2087 DEBUG_IPC_KMSG_PRINT(kmsg
, "ipc_kmsg_put()");
2090 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
2093 " remote_port: %p\n"
2095 " voucher_port: 0x%.8x\n"
2097 kmsg
->ikm_header
->msgh_size
,
2098 kmsg
->ikm_header
->msgh_bits
,
2099 kmsg
->ikm_header
->msgh_remote_port
,
2100 kmsg
->ikm_header
->msgh_local_port
,
2101 kmsg
->ikm_header
->msgh_voucher_port
,
2102 kmsg
->ikm_header
->msgh_id
);
2104 #if defined(__LP64__)
2105 if (current_task() != kernel_task
) { /* don't if receiver expects fully-cooked in-kernel msg; */
2106 mach_msg_legacy_header_t
*legacy_header
=
2107 (mach_msg_legacy_header_t
*)((vm_offset_t
)(kmsg
->ikm_header
) + LEGACY_HEADER_SIZE_DELTA
);
2109 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
2110 mach_msg_size_t msg_size
= kmsg
->ikm_header
->msgh_size
;
2111 mach_port_name_t remote_port
= CAST_MACH_PORT_TO_NAME(kmsg
->ikm_header
->msgh_remote_port
);
2112 mach_port_name_t local_port
= CAST_MACH_PORT_TO_NAME(kmsg
->ikm_header
->msgh_local_port
);
2113 mach_port_name_t voucher_port
= kmsg
->ikm_header
->msgh_voucher_port
;
2114 mach_msg_id_t id
= kmsg
->ikm_header
->msgh_id
;
2116 legacy_header
->msgh_id
= id
;
2117 legacy_header
->msgh_local_port
= local_port
;
2118 legacy_header
->msgh_remote_port
= remote_port
;
2119 legacy_header
->msgh_voucher_port
= voucher_port
;
2120 legacy_header
->msgh_size
= msg_size
- LEGACY_HEADER_SIZE_DELTA
;
2121 legacy_header
->msgh_bits
= bits
;
2123 size
-= LEGACY_HEADER_SIZE_DELTA
;
2124 kmsg
->ikm_header
= (mach_msg_header_t
*)legacy_header
;
2128 /* unreachable if !DEBUG */
2129 __unreachable_ok_push
2130 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
2131 kprintf("ipc_kmsg_put header+body: %d\n", (size
));
2133 for (i
= 0; i
* 4 < size
; i
++) {
2134 kprintf("%.4x\n", ((uint32_t *)kmsg
->ikm_header
)[i
]);
2136 kprintf("type: %d\n", ((mach_msg_type_descriptor_t
*)(((mach_msg_base_t
*)kmsg
->ikm_header
) + 1))->type
);
2138 __unreachable_ok_pop
2140 /* Re-Compute target address if using stack-style delivery */
2141 if (option
& MACH_RCV_STACK
) {
2142 rcv_addr
+= rcv_size
- size
;
2145 if (copyoutmsg((const char *) kmsg
->ikm_header
, rcv_addr
, size
)) {
2146 mr
= MACH_RCV_INVALID_DATA
;
2149 mr
= MACH_MSG_SUCCESS
;
2152 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_KMSG_LINK
) | DBG_FUNC_NONE
,
2153 (rcv_addr
>= VM_MIN_KERNEL_AND_KEXT_ADDRESS
||
2154 rcv_addr
+ size
>= VM_MIN_KERNEL_AND_KEXT_ADDRESS
) ? (uintptr_t)0 : (uintptr_t)rcv_addr
,
2155 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
2156 1 /* this is on the receive/copyout path */,
2159 ipc_kmsg_free(kmsg
);
2168 * Routine: ipc_kmsg_put_to_kernel
2170 * Copies a message buffer to a kernel message.
2171 * Frees the message buffer.
2172 * No errors allowed.
2178 ipc_kmsg_put_to_kernel(
2179 mach_msg_header_t
*msg
,
2181 mach_msg_size_t size
)
2183 (void) memcpy((void *) msg
, (const void *) kmsg
->ikm_header
, size
);
2185 ipc_kmsg_free(kmsg
);
2188 static mach_msg_priority_t
2189 ipc_get_current_thread_priority(void)
2191 thread_t thread
= current_thread();
2195 qos
= thread_get_requested_qos(thread
, &relpri
);
2197 qos
= thread_user_promotion_qos_for_pri(thread
->base_pri
);
2200 return (mach_msg_priority_t
)_pthread_priority_make_from_thread_qos(qos
, relpri
, 0);
2203 static kern_return_t
2206 mach_msg_option_t options
,
2207 mach_msg_priority_t override
)
2210 ipc_port_t special_reply_port
= kmsg
->ikm_header
->msgh_local_port
;
2211 ipc_port_t dest_port
= kmsg
->ikm_header
->msgh_remote_port
;
2213 kr
= ipc_get_pthpriority_from_kmsg_voucher(kmsg
, &kmsg
->ikm_qos
);
2214 if (kr
!= KERN_SUCCESS
) {
2215 if (options
& MACH_SEND_PROPAGATE_QOS
) {
2216 kmsg
->ikm_qos
= ipc_get_current_thread_priority();
2218 kmsg
->ikm_qos
= MACH_MSG_PRIORITY_UNSPECIFIED
;
2221 kmsg
->ikm_qos_override
= kmsg
->ikm_qos
;
2223 if (options
& MACH_SEND_OVERRIDE
) {
2224 pthread_priority_t pp
= _pthread_priority_normalize_for_ipc(override
);
2225 if (pp
> kmsg
->ikm_qos
) {
2226 kmsg
->ikm_qos_override
= (mach_msg_priority_t
)pp
;
2232 if (IP_VALID(special_reply_port
) &&
2233 MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
) == MACH_MSG_TYPE_PORT_SEND_ONCE
) {
2234 if ((options
& MACH_SEND_SYNC_OVERRIDE
)) {
2235 boolean_t sync_bootstrap_checkin
= !!(options
& MACH_SEND_SYNC_BOOTSTRAP_CHECKIN
);
2237 * Link the destination port to special reply port and make sure that
2238 * dest port has a send turnstile, else allocate one.
2240 ipc_port_link_special_reply_port(special_reply_port
, dest_port
, sync_bootstrap_checkin
);
2247 ipc_kmsg_allow_immovable_send(
2249 ipc_entry_t dest_entry
)
2251 ipc_object_t object
= dest_entry
->ie_object
;
2253 * If the dest port is a kobject, allow copyin of immovable send
2254 * rights in the message body to succeed
2256 if (IO_VALID(object
) && io_is_kobject(object
)) {
2257 kmsg
->ikm_flags
|= IPC_KMSG_FLAGS_ALLOW_IMMOVABLE_SEND
;
2262 * Routine: ipc_kmsg_link_reply_context_locked
2264 * Link any required context from the sending voucher
2265 * to the reply port. The ipc_kmsg_copyin function will
2266 * enforce that the sender calls mach_msg in this context.
2268 * reply port is locked
2271 ipc_kmsg_link_reply_context_locked(
2272 ipc_port_t reply_port
,
2273 ipc_port_t voucher_port
)
2275 kern_return_t __assert_only kr
;
2276 uint32_t persona_id
= 0;
2277 ipc_voucher_t voucher
;
2279 ip_lock_held(reply_port
);
2281 if (!ip_active(reply_port
)) {
2285 voucher
= convert_port_to_voucher(voucher_port
);
2287 kr
= bank_get_bank_ledger_thread_group_and_persona(voucher
, NULL
, NULL
, &persona_id
);
2288 assert(kr
== KERN_SUCCESS
);
2289 ipc_voucher_release(voucher
);
2291 if (persona_id
== 0 || persona_id
== PERSONA_ID_NONE
) {
2292 /* there was no persona context to record */
2297 * Set the persona_id as the context on the reply port.
2298 * This will force the thread that replies to have adopted a voucher
2299 * with a matching persona.
2301 reply_port
->ip_reply_context
= persona_id
;
2306 static kern_return_t
2307 ipc_kmsg_validate_reply_port_locked(ipc_port_t reply_port
, mach_msg_option_t options
)
2309 ip_lock_held(reply_port
);
2311 if (!ip_active(reply_port
)) {
2313 * Ideally, we would enforce that the reply receive right is
2314 * active, but asynchronous XPC cancellation destroys the
2315 * receive right, so we just have to return success here.
2317 return KERN_SUCCESS
;
2320 if (options
& MACH_SEND_MSG
) {
2322 * If the rely port is active, then it should not be
2323 * in-transit, and the receive right should be in the caller's
2326 if (!reply_port
->ip_receiver_name
|| reply_port
->ip_receiver
!= current_task()->itk_space
) {
2327 return KERN_INVALID_CAPABILITY
;
2331 * A port used as a reply port in an RPC should have exactly 1
2332 * extant send-once right which we either just made or are
2333 * moving as part of the IPC.
2335 if (reply_port
->ip_sorights
!= 1) {
2336 return KERN_INVALID_CAPABILITY
;
2339 * XPC uses an extra send-right to keep the name of the reply
2340 * right around through cancellation. That makes it harder to
2341 * enforce a particular semantic kere, so for now, we say that
2342 * you can have a maximum of 1 send right (in addition to your
2343 * send once right). In the future, it would be great to lock
2344 * this down even further.
2346 if (reply_port
->ip_srights
> 1) {
2347 return KERN_INVALID_CAPABILITY
;
2351 * The sender can also specify that the receive right should
2352 * be immovable. Note that this check only applies to
2353 * send-only operations. Combined send/receive or rcv-only
2354 * operations can specify an immovable receive right by
2355 * opt-ing into guarded descriptors (MACH_RCV_GUARDED_DESC)
2356 * and using the MACH_MSG_STRICT_REPLY options flag.
2358 if (MACH_SEND_REPLY_IS_IMMOVABLE(options
)) {
2359 if (!reply_port
->ip_immovable_receive
) {
2360 return KERN_INVALID_CAPABILITY
;
2366 * don't enforce this yet: need a better way of indicating the
2367 * receiver wants this...
2370 if (MACH_RCV_WITH_IMMOVABLE_REPLY(options
)) {
2371 if (!reply_port
->ip_immovable_receive
) {
2372 return KERN_INVALID_CAPABILITY
;
2377 return KERN_SUCCESS
;
2381 * Routine: ipc_kmsg_validate_reply_context_locked
2383 * Validate that the current thread is running in the context
2384 * required by the destination port.
2386 * dest_port is locked
2388 * MACH_MSG_SUCCESS on success.
2389 * On error, an EXC_GUARD exception is also raised.
2390 * This function *always* resets the port reply context.
2392 static mach_msg_return_t
2393 ipc_kmsg_validate_reply_context_locked(
2394 mach_msg_option_t option
,
2395 ipc_port_t dest_port
,
2396 ipc_voucher_t voucher
,
2397 mach_port_name_t voucher_name
)
2399 uint32_t dest_ctx
= dest_port
->ip_reply_context
;
2400 dest_port
->ip_reply_context
= 0;
2402 if (!ip_active(dest_port
)) {
2403 return MACH_MSG_SUCCESS
;
2406 if (voucher
== IPC_VOUCHER_NULL
|| !MACH_PORT_VALID(voucher_name
)) {
2407 if ((option
& MACH_SEND_KERNEL
) == 0) {
2408 mach_port_guard_exception(voucher_name
, 0,
2409 (MPG_FLAGS_STRICT_REPLY_INVALID_VOUCHER
| dest_ctx
),
2410 kGUARD_EXC_STRICT_REPLY
);
2412 return MACH_SEND_INVALID_CONTEXT
;
2415 kern_return_t __assert_only kr
;
2416 uint32_t persona_id
= 0;
2417 kr
= bank_get_bank_ledger_thread_group_and_persona(voucher
, NULL
, NULL
, &persona_id
);
2418 assert(kr
== KERN_SUCCESS
);
2420 if (dest_ctx
!= persona_id
) {
2421 if ((option
& MACH_SEND_KERNEL
) == 0) {
2422 mach_port_guard_exception(voucher_name
, 0,
2423 (MPG_FLAGS_STRICT_REPLY_MISMATCHED_PERSONA
| ((((uint64_t)persona_id
<< 32) & MPG_FLAGS_STRICT_REPLY_MASK
) | dest_ctx
)),
2424 kGUARD_EXC_STRICT_REPLY
);
2426 return MACH_SEND_INVALID_CONTEXT
;
2429 return MACH_MSG_SUCCESS
;
2433 * Routine: ipc_kmsg_copyin_header
2435 * "Copy-in" port rights in the header of a message.
2436 * Operates atomically; if it doesn't succeed the
2437 * message header and the space are left untouched.
2438 * If it does succeed the remote/local port fields
2439 * contain object pointers instead of port names,
2440 * and the bits field is updated. The destination port
2441 * will be a valid port pointer.
2446 * MACH_MSG_SUCCESS Successful copyin.
2447 * MACH_SEND_INVALID_HEADER
2448 * Illegal value in the message header bits.
2449 * MACH_SEND_INVALID_DEST The space is dead.
2450 * MACH_SEND_INVALID_DEST Can't copyin destination port.
2451 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2452 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
2453 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2457 ipc_kmsg_copyin_header(
2460 mach_msg_priority_t override
,
2461 mach_msg_option_t
*optionp
)
2463 mach_msg_header_t
*msg
= kmsg
->ikm_header
;
2464 mach_msg_bits_t mbits
= msg
->msgh_bits
& MACH_MSGH_BITS_USER
;
2465 mach_port_name_t dest_name
= CAST_MACH_PORT_TO_NAME(msg
->msgh_remote_port
);
2466 mach_port_name_t reply_name
= CAST_MACH_PORT_TO_NAME(msg
->msgh_local_port
);
2467 mach_port_name_t voucher_name
= MACH_PORT_NULL
;
2470 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
2471 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
2472 mach_msg_type_name_t voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
2473 ipc_object_t dest_port
= IO_NULL
;
2474 ipc_object_t reply_port
= IO_NULL
;
2475 ipc_port_t dest_soright
= IP_NULL
;
2476 ipc_port_t reply_soright
= IP_NULL
;
2477 ipc_port_t voucher_soright
= IP_NULL
;
2478 ipc_port_t release_port
= IP_NULL
;
2479 ipc_port_t voucher_port
= IP_NULL
;
2480 ipc_port_t voucher_release_port
= IP_NULL
;
2481 ipc_entry_t dest_entry
= IE_NULL
;
2482 ipc_entry_t reply_entry
= IE_NULL
;
2483 ipc_entry_t voucher_entry
= IE_NULL
;
2486 #if IMPORTANCE_INHERITANCE
2487 boolean_t needboost
= FALSE
;
2488 #endif /* IMPORTANCE_INHERITANCE */
2490 if ((mbits
!= msg
->msgh_bits
) ||
2491 (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type
)) ||
2492 ((reply_type
== 0) ?
2493 (reply_name
!= MACH_PORT_NULL
) :
2494 !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type
))) {
2495 return MACH_SEND_INVALID_HEADER
;
2498 if (!MACH_PORT_VALID(dest_name
)) {
2499 return MACH_SEND_INVALID_DEST
;
2502 is_write_lock(space
);
2503 if (!is_active(space
)) {
2504 is_write_unlock(space
);
2505 return MACH_SEND_INVALID_DEST
;
2507 /* space locked and active */
2510 * If there is a voucher specified, make sure the disposition is
2511 * valid and the entry actually refers to a voucher port. Don't
2512 * actually copy in until we validate destination and reply.
2514 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
2515 voucher_name
= msg
->msgh_voucher_port
;
2517 if (voucher_name
== MACH_PORT_DEAD
||
2518 (voucher_type
!= MACH_MSG_TYPE_MOVE_SEND
&&
2519 voucher_type
!= MACH_MSG_TYPE_COPY_SEND
)) {
2520 is_write_unlock(space
);
2521 if ((*optionp
& MACH_SEND_KERNEL
) == 0) {
2522 mach_port_guard_exception(voucher_name
, 0, 0, kGUARD_EXC_SEND_INVALID_VOUCHER
);
2524 return MACH_SEND_INVALID_VOUCHER
;
2527 if (voucher_name
!= MACH_PORT_NULL
) {
2528 voucher_entry
= ipc_entry_lookup(space
, voucher_name
);
2529 if (voucher_entry
== IE_NULL
||
2530 (voucher_entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0 ||
2531 io_kotype(voucher_entry
->ie_object
) != IKOT_VOUCHER
) {
2532 is_write_unlock(space
);
2533 if ((*optionp
& MACH_SEND_KERNEL
) == 0) {
2534 mach_port_guard_exception(voucher_name
, 0, 0, kGUARD_EXC_SEND_INVALID_VOUCHER
);
2536 return MACH_SEND_INVALID_VOUCHER
;
2539 voucher_type
= MACH_MSG_TYPE_MOVE_SEND
;
2543 if (enforce_strict_reply
&& MACH_SEND_WITH_STRICT_REPLY(*optionp
) &&
2544 (!MACH_PORT_VALID(reply_name
) ||
2545 ((reply_type
!= MACH_MSG_TYPE_MAKE_SEND_ONCE
) && (reply_type
!= MACH_MSG_TYPE_MOVE_SEND_ONCE
))
2548 * The caller cannot enforce a reply context with an invalid
2549 * reply port name, or a non-send_once reply disposition.
2551 is_write_unlock(space
);
2552 if ((*optionp
& MACH_SEND_KERNEL
) == 0) {
2553 mach_port_guard_exception(reply_name
, 0,
2554 (MPG_FLAGS_STRICT_REPLY_INVALID_REPLY_DISP
| reply_type
),
2555 kGUARD_EXC_STRICT_REPLY
);
2557 return MACH_SEND_INVALID_REPLY
;
2561 * Handle combinations of validating destination and reply; along
2562 * with copying in destination, reply, and voucher in an atomic way.
2565 if (dest_name
== voucher_name
) {
2567 * If the destination name is the same as the voucher name,
2568 * the voucher_entry must already be known. Either that or
2569 * the destination name is MACH_PORT_NULL (i.e. invalid).
2571 dest_entry
= voucher_entry
;
2572 if (dest_entry
== IE_NULL
) {
2575 /* Check if dest port allows immovable send rights to be sent in the kmsg body */
2576 ipc_kmsg_allow_immovable_send(kmsg
, dest_entry
);
2579 * Make sure a future copyin of the reply port will succeed.
2580 * Once we start copying in the dest/voucher pair, we can't
2583 if (MACH_PORT_VALID(reply_name
)) {
2584 assert(reply_type
!= 0); /* because reply_name not null */
2586 /* It is just WRONG if dest, voucher, and reply are all the same. */
2587 if (voucher_name
== reply_name
) {
2590 reply_entry
= ipc_entry_lookup(space
, reply_name
);
2591 if (reply_entry
== IE_NULL
) {
2594 assert(dest_entry
!= reply_entry
); /* names are not equal */
2595 if (!ipc_right_copyin_check_reply(space
, reply_name
, reply_entry
, reply_type
)) {
2601 * Do the joint copyin of the dest disposition and
2602 * voucher disposition from the one entry/port. We
2603 * already validated that the voucher copyin would
2604 * succeed (above). So, any failure in combining
2605 * the copyins can be blamed on the destination.
2607 kr
= ipc_right_copyin_two(space
, dest_name
, dest_entry
,
2608 dest_type
, voucher_type
, &dest_port
, &dest_soright
,
2610 if (kr
!= KERN_SUCCESS
) {
2611 assert(kr
!= KERN_INVALID_CAPABILITY
);
2614 voucher_port
= ip_object_to_port(dest_port
);
2617 * could not have been one of these dispositions,
2618 * validated the port was a true kernel voucher port above,
2619 * AND was successfully able to copyin both dest and voucher.
2621 assert(dest_type
!= MACH_MSG_TYPE_MAKE_SEND
);
2622 assert(dest_type
!= MACH_MSG_TYPE_MAKE_SEND_ONCE
);
2623 assert(dest_type
!= MACH_MSG_TYPE_MOVE_SEND_ONCE
);
2626 * Perform the delayed reply right copyin (guaranteed success).
2628 if (reply_entry
!= IE_NULL
) {
2629 kr
= ipc_right_copyin(space
, reply_name
, reply_entry
,
2630 reply_type
, IPC_RIGHT_COPYIN_FLAGS_DEADOK
,
2631 &reply_port
, &reply_soright
,
2632 &release_port
, &assertcnt
, 0, NULL
);
2633 assert(assertcnt
== 0);
2634 assert(kr
== KERN_SUCCESS
);
2637 if (dest_name
== reply_name
) {
2639 * Destination and reply ports are the same!
2640 * This is very similar to the case where the
2641 * destination and voucher ports were the same
2642 * (except the reply port disposition is not
2643 * previously validated).
2645 dest_entry
= ipc_entry_lookup(space
, dest_name
);
2646 if (dest_entry
== IE_NULL
) {
2649 ipc_kmsg_allow_immovable_send(kmsg
, dest_entry
);
2651 reply_entry
= dest_entry
;
2652 assert(reply_type
!= 0); /* because name not null */
2655 * Pre-validate that the reply right can be copied in by itself
2657 if (!ipc_right_copyin_check_reply(space
, reply_name
, reply_entry
, reply_type
)) {
2662 * Do the joint copyin of the dest disposition and
2663 * reply disposition from the one entry/port.
2665 kr
= ipc_right_copyin_two(space
, dest_name
, dest_entry
,
2666 dest_type
, reply_type
, &dest_port
, &dest_soright
,
2668 if (kr
== KERN_INVALID_CAPABILITY
) {
2670 } else if (kr
!= KERN_SUCCESS
) {
2673 reply_port
= dest_port
;
2676 * Handle destination and reply independently, as
2677 * they are independent entries (even if the entries
2678 * refer to the same port).
2680 * This can be the tough case to make atomic.
2682 * The difficult problem is serializing with port death.
2683 * The bad case is when dest_port dies after its copyin,
2684 * reply_port dies before its copyin, and dest_port dies before
2685 * reply_port. Then the copyins operated as if dest_port was
2686 * alive and reply_port was dead, which shouldn't have happened
2687 * because they died in the other order.
2689 * Note that it is easy for a user task to tell if
2690 * a copyin happened before or after a port died.
2691 * If a port dies before copyin, a dead-name notification
2692 * is generated and the dead name's urefs are incremented,
2693 * and if the copyin happens first, a port-deleted
2694 * notification is generated.
2696 * Even so, avoiding that potentially detectable race is too
2697 * expensive - and no known code cares about it. So, we just
2698 * do the expedient thing and copy them in one after the other.
2701 dest_entry
= ipc_entry_lookup(space
, dest_name
);
2702 if (dest_entry
== IE_NULL
) {
2705 assert(dest_entry
!= voucher_entry
);
2706 ipc_kmsg_allow_immovable_send(kmsg
, dest_entry
);
2709 * Make sure reply port entry is valid before dest copyin.
2711 if (MACH_PORT_VALID(reply_name
)) {
2712 if (reply_name
== voucher_name
) {
2715 reply_entry
= ipc_entry_lookup(space
, reply_name
);
2716 if (reply_entry
== IE_NULL
) {
2719 assert(dest_entry
!= reply_entry
); /* names are not equal */
2720 assert(reply_type
!= 0); /* because reply_name not null */
2722 if (!ipc_right_copyin_check_reply(space
, reply_name
, reply_entry
, reply_type
)) {
2728 * copyin the destination.
2730 kr
= ipc_right_copyin(space
, dest_name
, dest_entry
,
2731 dest_type
, (IPC_RIGHT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
|
2732 IPC_RIGHT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE
),
2733 &dest_port
, &dest_soright
,
2734 &release_port
, &assertcnt
, 0, NULL
);
2735 assert(assertcnt
== 0);
2736 if (kr
!= KERN_SUCCESS
) {
2739 assert(IO_VALID(dest_port
));
2740 assert(!IP_VALID(release_port
));
2743 * Copyin the pre-validated reply right.
2744 * It's OK if the reply right has gone dead in the meantime.
2746 if (MACH_PORT_VALID(reply_name
)) {
2747 kr
= ipc_right_copyin(space
, reply_name
, reply_entry
,
2748 reply_type
, IPC_RIGHT_COPYIN_FLAGS_DEADOK
,
2749 &reply_port
, &reply_soright
,
2750 &release_port
, &assertcnt
, 0, NULL
);
2751 assert(assertcnt
== 0);
2752 assert(kr
== KERN_SUCCESS
);
2754 /* convert invalid name to equivalent ipc_object type */
2755 reply_port
= ip_to_object(CAST_MACH_NAME_TO_PORT(reply_name
));
2760 * Finally can copyin the voucher right now that dest and reply
2761 * are fully copied in (guaranteed success).
2763 if (IE_NULL
!= voucher_entry
) {
2764 kr
= ipc_right_copyin(space
, voucher_name
, voucher_entry
,
2765 voucher_type
, IPC_RIGHT_COPYIN_FLAGS_NONE
,
2766 (ipc_object_t
*)&voucher_port
,
2768 &voucher_release_port
,
2769 &assertcnt
, 0, NULL
);
2770 assert(assertcnt
== 0);
2771 assert(KERN_SUCCESS
== kr
);
2772 assert(IP_VALID(voucher_port
));
2773 require_ip_active(voucher_port
);
2778 * The entries might need to be deallocated.
2780 * Each entry should be deallocated only once,
2781 * even if it was specified in more than one slot in the header.
2782 * Note that dest can be the same entry as reply or voucher,
2783 * but reply and voucher must be distinct entries.
2785 assert(IE_NULL
!= dest_entry
);
2786 if (IE_NULL
!= reply_entry
) {
2787 assert(reply_entry
!= voucher_entry
);
2790 if (IE_BITS_TYPE(dest_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
2791 ipc_entry_dealloc(space
, dest_name
, dest_entry
);
2793 if (dest_entry
== reply_entry
) {
2794 reply_entry
= IE_NULL
;
2797 if (dest_entry
== voucher_entry
) {
2798 voucher_entry
= IE_NULL
;
2801 dest_entry
= IE_NULL
;
2803 if (IE_NULL
!= reply_entry
&&
2804 IE_BITS_TYPE(reply_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
2805 ipc_entry_dealloc(space
, reply_name
, reply_entry
);
2806 reply_entry
= IE_NULL
;
2808 if (IE_NULL
!= voucher_entry
&&
2809 IE_BITS_TYPE(voucher_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
2810 ipc_entry_dealloc(space
, voucher_name
, voucher_entry
);
2811 voucher_entry
= IE_NULL
;
2814 dest_type
= ipc_object_copyin_type(dest_type
);
2815 reply_type
= ipc_object_copyin_type(reply_type
);
2818 * JMM - Without rdar://problem/6275821, this is the last place we can
2819 * re-arm the send-possible notifications. It may trigger unexpectedly
2820 * early (send may NOT have failed), but better than missing. We assure
2821 * we won't miss by forcing MACH_SEND_ALWAYS if we got past arming.
2823 if (((*optionp
& MACH_SEND_NOTIFY
) != 0) &&
2824 dest_type
!= MACH_MSG_TYPE_PORT_SEND_ONCE
&&
2825 dest_entry
!= IE_NULL
&& dest_entry
->ie_request
!= IE_REQ_NONE
) {
2826 ipc_port_t dport
= ip_object_to_port(dest_port
);
2828 assert(dport
!= IP_NULL
);
2830 if (ip_active(dport
) && dport
->ip_receiver
!= ipc_space_kernel
) {
2831 if (ip_full(dport
)) {
2832 #if IMPORTANCE_INHERITANCE
2833 needboost
= ipc_port_request_sparm(dport
, dest_name
,
2834 dest_entry
->ie_request
,
2837 if (needboost
== FALSE
) {
2841 ipc_port_request_sparm(dport
, dest_name
,
2842 dest_entry
->ie_request
,
2846 #endif /* IMPORTANCE_INHERITANCE */
2848 *optionp
|= MACH_SEND_ALWAYS
;
2856 is_write_unlock(space
);
2858 #if IMPORTANCE_INHERITANCE
2860 * If our request is the first boosting send-possible
2861 * notification this cycle, push the boost down the
2864 if (needboost
== TRUE
) {
2865 ipc_port_t dport
= ip_object_to_port(dest_port
);
2867 /* dport still locked from above */
2868 if (ipc_port_importance_delta(dport
, IPID_OPTION_SENDPOSSIBLE
, 1) == FALSE
) {
2872 #endif /* IMPORTANCE_INHERITANCE */
2874 if (dest_soright
!= IP_NULL
) {
2875 ipc_notify_port_deleted(dest_soright
, dest_name
);
2877 if (reply_soright
!= IP_NULL
) {
2878 ipc_notify_port_deleted(reply_soright
, reply_name
);
2880 if (voucher_soright
!= IP_NULL
) {
2881 ipc_notify_port_deleted(voucher_soright
, voucher_name
);
2885 * No room to store voucher port in in-kernel msg header,
2886 * so we store it back in the kmsg itself. Extract the
2887 * qos, and apply any override before we enqueue the kmsg.
2889 if (IP_VALID(voucher_port
)) {
2890 kmsg
->ikm_voucher
= voucher_port
;
2891 voucher_type
= MACH_MSG_TYPE_MOVE_SEND
;
2894 msg
->msgh_bits
= MACH_MSGH_BITS_SET(dest_type
, reply_type
, voucher_type
, mbits
);
2895 msg
->msgh_remote_port
= ip_object_to_port(dest_port
);
2896 msg
->msgh_local_port
= ip_object_to_port(reply_port
);
2898 /* capture the qos value(s) for the kmsg */
2899 ipc_kmsg_set_qos(kmsg
, *optionp
, override
);
2901 if (release_port
!= IP_NULL
) {
2902 ip_release(release_port
);
2905 if (voucher_release_port
!= IP_NULL
) {
2906 ip_release(voucher_release_port
);
2909 if (enforce_strict_reply
&& MACH_SEND_WITH_STRICT_REPLY(*optionp
) && IP_VALID(msg
->msgh_local_port
)) {
2911 * We've already validated that the reply disposition is a
2912 * [make/move] send-once. Ideally, we should enforce that the
2913 * reply port is also not dead, but XPC asynchronous
2914 * cancellation can make the reply port dead before we
2915 * actually make it to the mach_msg send.
2917 * Here, we ensure that if we have a non-dead reply port, then
2918 * the reply port's receive right should not be in-transit,
2919 * and should live in the caller's IPC space.
2921 ipc_port_t rport
= msg
->msgh_local_port
;
2923 kr
= ipc_kmsg_validate_reply_port_locked(rport
, *optionp
);
2925 if (kr
!= KERN_SUCCESS
) {
2927 * no descriptors have been copied in yet, but the
2928 * full header has been copied in: clean it up
2930 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
2931 if ((*optionp
& MACH_SEND_KERNEL
) == 0) {
2932 mach_port_guard_exception(reply_name
, 0,
2933 (MPG_FLAGS_STRICT_REPLY_INVALID_REPLY_PORT
| kr
),
2934 kGUARD_EXC_STRICT_REPLY
);
2936 return MACH_SEND_INVALID_REPLY
;
2940 return MACH_MSG_SUCCESS
;
2943 is_write_unlock(space
);
2945 if (release_port
!= IP_NULL
) {
2946 ip_release(release_port
);
2949 assert(voucher_port
== IP_NULL
);
2950 assert(voucher_soright
== IP_NULL
);
2952 if ((*optionp
& MACH_SEND_KERNEL
) == 0) {
2953 mach_port_guard_exception(reply_name
, 0, 0, kGUARD_EXC_SEND_INVALID_REPLY
);
2955 return MACH_SEND_INVALID_REPLY
;
2958 is_write_unlock(space
);
2960 if (release_port
!= IP_NULL
) {
2961 ip_release(release_port
);
2964 if (reply_soright
!= IP_NULL
) {
2965 ipc_notify_port_deleted(reply_soright
, reply_name
);
2968 assert(voucher_port
== IP_NULL
);
2969 assert(voucher_soright
== IP_NULL
);
2971 return MACH_SEND_INVALID_DEST
;
2974 static mach_msg_descriptor_t
*
2975 ipc_kmsg_copyin_port_descriptor(
2976 volatile mach_msg_port_descriptor_t
*dsc
,
2977 mach_msg_legacy_port_descriptor_t
*user_dsc_in
,
2981 mach_msg_option_t
*optionp
,
2982 mach_msg_return_t
*mr
)
2984 volatile mach_msg_legacy_port_descriptor_t
*user_dsc
= user_dsc_in
;
2985 mach_msg_type_name_t user_disp
;
2986 mach_msg_type_name_t result_disp
;
2987 mach_port_name_t name
;
2988 ipc_object_t object
;
2990 user_disp
= user_dsc
->disposition
;
2991 result_disp
= ipc_object_copyin_type(user_disp
);
2993 name
= (mach_port_name_t
)user_dsc
->name
;
2994 if (MACH_PORT_VALID(name
)) {
2995 kern_return_t kr
= ipc_object_copyin(space
, name
, user_disp
, &object
, 0, NULL
, kmsg
->ikm_flags
);
2996 if (kr
!= KERN_SUCCESS
) {
2997 if (((*optionp
& MACH_SEND_KERNEL
) == 0) && (kr
== KERN_INVALID_RIGHT
)) {
2998 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_SEND_INVALID_RIGHT
);
3000 *mr
= MACH_SEND_INVALID_RIGHT
;
3004 if ((result_disp
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3005 ipc_port_check_circularity(ip_object_to_port(object
),
3006 ip_object_to_port(dest
))) {
3007 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
3009 dsc
->name
= ip_object_to_port(object
);
3011 dsc
->name
= CAST_MACH_NAME_TO_PORT(name
);
3013 dsc
->disposition
= result_disp
;
3014 dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
3016 dsc
->pad_end
= 0; // debug, unnecessary
3018 return (mach_msg_descriptor_t
*)(user_dsc_in
+ 1);
3021 static mach_msg_descriptor_t
*
3022 ipc_kmsg_copyin_ool_descriptor(
3023 mach_msg_ool_descriptor_t
*dsc
,
3024 mach_msg_descriptor_t
*user_dsc
,
3027 vm_map_copy_t
*copy
,
3028 vm_size_t
*space_needed
,
3030 __unused mach_msg_option_t
*optionp
,
3031 mach_msg_return_t
*mr
)
3035 mach_msg_copy_options_t copy_options
;
3036 mach_vm_offset_t addr
;
3037 mach_msg_descriptor_type_t dsc_type
;
3040 mach_msg_ool_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3042 addr
= (mach_vm_offset_t
) user_ool_dsc
->address
;
3043 length
= user_ool_dsc
->size
;
3044 dealloc
= user_ool_dsc
->deallocate
;
3045 copy_options
= user_ool_dsc
->copy
;
3046 dsc_type
= user_ool_dsc
->type
;
3048 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+ 1);
3050 mach_msg_ool_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3052 addr
= CAST_USER_ADDR_T(user_ool_dsc
->address
);
3053 dealloc
= user_ool_dsc
->deallocate
;
3054 copy_options
= user_ool_dsc
->copy
;
3055 dsc_type
= user_ool_dsc
->type
;
3056 length
= user_ool_dsc
->size
;
3058 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+ 1);
3061 dsc
->size
= (mach_msg_size_t
)length
;
3062 dsc
->deallocate
= dealloc
;
3063 dsc
->copy
= copy_options
;
3064 dsc
->type
= dsc_type
;
3067 dsc
->address
= NULL
;
3068 } else if ((length
>= MSG_OOL_SIZE_SMALL
) &&
3069 (copy_options
== MACH_MSG_PHYSICAL_COPY
) && !dealloc
) {
3071 * If the request is a physical copy and the source
3072 * is not being deallocated, then allocate space
3073 * in the kernel's pageable ipc copy map and copy
3074 * the data in. The semantics guarantee that the
3075 * data will have been physically copied before
3076 * the send operation terminates. Thus if the data
3077 * is not being deallocated, we must be prepared
3078 * to page if the region is sufficiently large.
3080 if (copyin(addr
, (char *)*paddr
, length
)) {
3081 *mr
= MACH_SEND_INVALID_MEMORY
;
3086 * The kernel ipc copy map is marked no_zero_fill.
3087 * If the transfer is not a page multiple, we need
3088 * to zero fill the balance.
3090 if (!page_aligned(length
)) {
3091 (void) memset((void *) (*paddr
+ length
), 0,
3092 round_page(length
) - length
);
3094 if (vm_map_copyin(ipc_kernel_copy_map
, (vm_map_address_t
)*paddr
,
3095 (vm_map_size_t
)length
, TRUE
, copy
) != KERN_SUCCESS
) {
3096 *mr
= MACH_MSG_VM_KERNEL
;
3099 dsc
->address
= (void *)*copy
;
3100 *paddr
+= round_page(length
);
3101 *space_needed
-= round_page(length
);
3104 * Make a vm_map_copy_t of the of the data. If the
3105 * data is small, this will do an optimized physical
3106 * copy. Otherwise, it will do a virtual copy.
3108 * NOTE: A virtual copy is OK if the original is being
3109 * deallocted, even if a physical copy was requested.
3111 kern_return_t kr
= vm_map_copyin(map
, addr
,
3112 (vm_map_size_t
)length
, dealloc
, copy
);
3113 if (kr
!= KERN_SUCCESS
) {
3114 *mr
= (kr
== KERN_RESOURCE_SHORTAGE
) ?
3115 MACH_MSG_VM_KERNEL
:
3116 MACH_SEND_INVALID_MEMORY
;
3119 dsc
->address
= (void *)*copy
;
3124 static mach_msg_descriptor_t
*
3125 ipc_kmsg_copyin_ool_ports_descriptor(
3126 mach_msg_ool_ports_descriptor_t
*dsc
,
3127 mach_msg_descriptor_t
*user_dsc
,
3133 mach_msg_option_t
*optionp
,
3134 mach_msg_return_t
*mr
)
3137 ipc_object_t
*objects
;
3139 mach_vm_offset_t addr
;
3140 mach_msg_type_name_t user_disp
;
3141 mach_msg_type_name_t result_disp
;
3142 mach_msg_type_number_t count
;
3143 mach_msg_copy_options_t copy_option
;
3144 boolean_t deallocate
;
3145 mach_msg_descriptor_type_t type
;
3146 vm_size_t ports_length
, names_length
;
3149 mach_msg_ool_ports_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3151 addr
= (mach_vm_offset_t
)user_ool_dsc
->address
;
3152 count
= user_ool_dsc
->count
;
3153 deallocate
= user_ool_dsc
->deallocate
;
3154 copy_option
= user_ool_dsc
->copy
;
3155 user_disp
= user_ool_dsc
->disposition
;
3156 type
= user_ool_dsc
->type
;
3158 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+ 1);
3160 mach_msg_ool_ports_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
3162 addr
= CAST_USER_ADDR_T(user_ool_dsc
->address
);
3163 count
= user_ool_dsc
->count
;
3164 deallocate
= user_ool_dsc
->deallocate
;
3165 copy_option
= user_ool_dsc
->copy
;
3166 user_disp
= user_ool_dsc
->disposition
;
3167 type
= user_ool_dsc
->type
;
3169 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+ 1);
3172 dsc
->deallocate
= deallocate
;
3173 dsc
->copy
= copy_option
;
3176 dsc
->address
= NULL
; /* for now */
3178 result_disp
= ipc_object_copyin_type(user_disp
);
3179 dsc
->disposition
= result_disp
;
3181 /* We always do a 'physical copy', but you have to specify something valid */
3182 if (copy_option
!= MACH_MSG_PHYSICAL_COPY
&&
3183 copy_option
!= MACH_MSG_VIRTUAL_COPY
) {
3184 *mr
= MACH_SEND_INVALID_TYPE
;
3188 /* calculate length of data in bytes, rounding up */
3190 if (os_mul_overflow(count
, sizeof(mach_port_t
), &ports_length
)) {
3191 *mr
= MACH_SEND_TOO_LARGE
;
3195 if (os_mul_overflow(count
, sizeof(mach_port_name_t
), &names_length
)) {
3196 *mr
= MACH_SEND_TOO_LARGE
;
3200 if (ports_length
== 0) {
3204 data
= kalloc(ports_length
);
3207 *mr
= MACH_SEND_NO_BUFFER
;
3212 mach_port_name_t
*names
= &((mach_port_name_t
*)data
)[count
];
3214 mach_port_name_t
*names
= ((mach_port_name_t
*)data
);
3217 if (copyinmap(map
, addr
, names
, names_length
) != KERN_SUCCESS
) {
3218 kfree(data
, ports_length
);
3219 *mr
= MACH_SEND_INVALID_MEMORY
;
3224 (void) mach_vm_deallocate(map
, addr
, (mach_vm_size_t
)ports_length
);
3227 objects
= (ipc_object_t
*) data
;
3228 dsc
->address
= data
;
3230 for (i
= 0; i
< count
; i
++) {
3231 mach_port_name_t name
= names
[i
];
3232 ipc_object_t object
;
3234 if (!MACH_PORT_VALID(name
)) {
3235 objects
[i
] = ip_to_object(CAST_MACH_NAME_TO_PORT(name
));
3239 kern_return_t kr
= ipc_object_copyin(space
, name
, user_disp
, &object
, 0, NULL
, kmsg
->ikm_flags
);
3241 if (kr
!= KERN_SUCCESS
) {
3244 for (j
= 0; j
< i
; j
++) {
3245 object
= objects
[j
];
3246 if (IPC_OBJECT_VALID(object
)) {
3247 ipc_object_destroy(object
, result_disp
);
3250 kfree(data
, ports_length
);
3251 dsc
->address
= NULL
;
3252 if (((*optionp
& MACH_SEND_KERNEL
) == 0) && (kr
== KERN_INVALID_RIGHT
)) {
3253 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_SEND_INVALID_RIGHT
);
3255 *mr
= MACH_SEND_INVALID_RIGHT
;
3259 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3260 ipc_port_check_circularity(ip_object_to_port(object
),
3261 ip_object_to_port(dest
))) {
3262 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
3265 objects
[i
] = object
;
3271 static mach_msg_descriptor_t
*
3272 ipc_kmsg_copyin_guarded_port_descriptor(
3273 mach_msg_guarded_port_descriptor_t
*dsc
,
3274 mach_msg_descriptor_t
*user_addr
,
3279 mach_msg_option_t
*optionp
,
3280 mach_msg_return_t
*mr
)
3282 mach_msg_descriptor_t
*user_dsc
;
3283 mach_msg_type_name_t disp
;
3284 mach_msg_type_name_t result_disp
;
3285 mach_port_name_t name
;
3286 mach_msg_guard_flags_t guard_flags
;
3287 ipc_object_t object
;
3288 mach_port_context_t context
;
3291 mach_msg_guarded_port_descriptor32_t
*user_gp_dsc
= (typeof(user_gp_dsc
))user_addr
;
3292 name
= user_gp_dsc
->name
;
3293 guard_flags
= user_gp_dsc
->flags
;
3294 disp
= user_gp_dsc
->disposition
;
3295 context
= user_gp_dsc
->context
;
3296 user_dsc
= (mach_msg_descriptor_t
*)(user_gp_dsc
+ 1);
3298 mach_msg_guarded_port_descriptor64_t
*user_gp_dsc
= (typeof(user_gp_dsc
))user_addr
;
3299 name
= user_gp_dsc
->name
;
3300 guard_flags
= user_gp_dsc
->flags
;
3301 disp
= user_gp_dsc
->disposition
;
3302 context
= user_gp_dsc
->context
;
3303 user_dsc
= (mach_msg_descriptor_t
*)(user_gp_dsc
+ 1);
3306 guard_flags
&= MACH_MSG_GUARD_FLAGS_MASK
;
3307 result_disp
= ipc_object_copyin_type(disp
);
3309 if (MACH_PORT_VALID(name
)) {
3310 kern_return_t kr
= ipc_object_copyin(space
, name
, disp
, &object
, context
, &guard_flags
, kmsg
->ikm_flags
);
3311 if (kr
!= KERN_SUCCESS
) {
3312 if (((*optionp
& MACH_SEND_KERNEL
) == 0) && (kr
== KERN_INVALID_RIGHT
)) {
3313 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_SEND_INVALID_RIGHT
);
3315 *mr
= MACH_SEND_INVALID_RIGHT
;
3319 if ((result_disp
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3320 ipc_port_check_circularity(ip_object_to_port(object
),
3321 ip_object_to_port(dest
))) {
3322 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
3324 dsc
->name
= ip_object_to_port(object
);
3326 dsc
->name
= CAST_MACH_NAME_TO_PORT(name
);
3328 dsc
->flags
= guard_flags
;
3329 dsc
->disposition
= result_disp
;
3330 dsc
->type
= MACH_MSG_GUARDED_PORT_DESCRIPTOR
;
3333 dsc
->pad_end
= 0; // debug, unnecessary
3340 * Routine: ipc_kmsg_copyin_body
3342 * "Copy-in" port rights and out-of-line memory
3343 * in the message body.
3345 * In all failure cases, the message is left holding
3346 * no rights or memory. However, the message buffer
3347 * is not deallocated. If successful, the message
3348 * contains a valid destination port.
3352 * MACH_MSG_SUCCESS Successful copyin.
3353 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
3354 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
3355 * MACH_SEND_INVALID_TYPE Bad type specification.
3356 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
3357 * MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
3358 * MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
3359 * MACH_SEND_NO_GRANT_DEST Dest port doesn't accept ports in body
3363 ipc_kmsg_copyin_body(
3367 mach_msg_option_t
*optionp
)
3370 mach_msg_body_t
*body
;
3371 mach_msg_descriptor_t
*daddr
, *naddr
, *end
;
3372 mach_msg_descriptor_t
*user_addr
, *kern_addr
;
3373 mach_msg_type_number_t dsc_count
;
3374 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
3375 boolean_t
complex = FALSE
;
3376 boolean_t contains_port_desc
= FALSE
;
3377 vm_size_t space_needed
= 0;
3378 vm_offset_t paddr
= 0;
3379 vm_map_copy_t copy
= VM_MAP_COPY_NULL
;
3380 mach_msg_type_number_t i
;
3381 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
3382 ipc_port_t remote_port
= kmsg
->ikm_header
->msgh_remote_port
;
3384 vm_size_t descriptor_size
= 0;
3386 mach_msg_type_number_t total_ool_port_count
= 0;
3387 mach_msg_guard_flags_t guard_flags
= 0;
3388 mach_port_context_t context
;
3389 mach_msg_type_name_t disp
;
3392 * Determine if the target is a kernel port.
3394 dest
= ip_to_object(remote_port
);
3395 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3396 naddr
= (mach_msg_descriptor_t
*) (body
+ 1);
3397 end
= (mach_msg_descriptor_t
*) ((vm_offset_t
)kmsg
->ikm_header
+ kmsg
->ikm_header
->msgh_size
);
3399 dsc_count
= body
->msgh_descriptor_count
;
3400 if (dsc_count
== 0) {
3401 return MACH_MSG_SUCCESS
;
3405 * Make an initial pass to determine kernal VM space requirements for
3406 * physical copies and possible contraction of the descriptors from
3407 * processes with pointers larger than the kernel's.
3410 for (i
= 0; i
< dsc_count
; i
++) {
3411 mach_msg_size_t size
;
3412 mach_msg_type_number_t ool_port_count
= 0;
3416 /* make sure the descriptor fits in the message */
3417 if (is_task_64bit
) {
3418 if ((mach_msg_descriptor_t
*)((vm_offset_t
)daddr
+ 12) > end
) {
3419 mr
= MACH_SEND_MSG_TOO_SMALL
;
3423 switch (daddr
->type
.type
) {
3424 case MACH_MSG_OOL_DESCRIPTOR
:
3425 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3426 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3427 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
3428 descriptor_size
+= 16;
3429 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 16);
3432 descriptor_size
+= 12;
3433 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 12);
3437 descriptor_size
+= 12;
3438 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 12);
3442 mr
= MACH_SEND_MSG_TOO_SMALL
;
3446 switch (daddr
->type
.type
) {
3447 case MACH_MSG_OOL_DESCRIPTOR
:
3448 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3449 size
= (is_task_64bit
) ?
3450 ((mach_msg_ool_descriptor64_t
*)daddr
)->size
:
3451 daddr
->out_of_line
.size
;
3453 if (daddr
->out_of_line
.copy
!= MACH_MSG_PHYSICAL_COPY
&&
3454 daddr
->out_of_line
.copy
!= MACH_MSG_VIRTUAL_COPY
) {
3456 * Invalid copy option
3458 mr
= MACH_SEND_INVALID_TYPE
;
3462 if ((size
>= MSG_OOL_SIZE_SMALL
) &&
3463 (daddr
->out_of_line
.copy
== MACH_MSG_PHYSICAL_COPY
) &&
3464 !(daddr
->out_of_line
.deallocate
)) {
3466 * Out-of-line memory descriptor, accumulate kernel
3467 * memory requirements
3469 if (space_needed
+ round_page(size
) <= space_needed
) {
3470 /* Overflow dectected */
3471 mr
= MACH_MSG_VM_KERNEL
;
3475 space_needed
+= round_page(size
);
3476 if (space_needed
> ipc_kmsg_max_vm_space
) {
3477 /* Per message kernel memory limit exceeded */
3478 mr
= MACH_MSG_VM_KERNEL
;
3483 case MACH_MSG_PORT_DESCRIPTOR
:
3484 if (os_add_overflow(total_ool_port_count
, 1, &total_ool_port_count
)) {
3485 /* Overflow detected */
3486 mr
= MACH_SEND_TOO_LARGE
;
3489 contains_port_desc
= TRUE
;
3491 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3492 ool_port_count
= (is_task_64bit
) ?
3493 ((mach_msg_ool_ports_descriptor64_t
*)daddr
)->count
:
3494 daddr
->ool_ports
.count
;
3496 if (os_add_overflow(total_ool_port_count
, ool_port_count
, &total_ool_port_count
)) {
3497 /* Overflow detected */
3498 mr
= MACH_SEND_TOO_LARGE
;
3502 if (ool_port_count
> (ipc_kmsg_max_vm_space
/ sizeof(mach_port_t
))) {
3503 /* Per message kernel memory limit exceeded */
3504 mr
= MACH_SEND_TOO_LARGE
;
3507 contains_port_desc
= TRUE
;
3509 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
3510 guard_flags
= (is_task_64bit
) ?
3511 ((mach_msg_guarded_port_descriptor64_t
*)daddr
)->flags
:
3512 ((mach_msg_guarded_port_descriptor32_t
*)daddr
)->flags
;
3513 context
= (is_task_64bit
) ?
3514 ((mach_msg_guarded_port_descriptor64_t
*)daddr
)->context
:
3515 ((mach_msg_guarded_port_descriptor32_t
*)daddr
)->context
;
3516 disp
= (is_task_64bit
) ?
3517 ((mach_msg_guarded_port_descriptor64_t
*)daddr
)->disposition
:
3518 ((mach_msg_guarded_port_descriptor32_t
*)daddr
)->disposition
;
3520 /* Only MACH_MSG_TYPE_MOVE_RECEIVE is supported for now */
3521 if (!guard_flags
|| ((guard_flags
& ~MACH_MSG_GUARD_FLAGS_MASK
) != 0) ||
3522 ((guard_flags
& MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
) && (context
!= 0)) ||
3523 (disp
!= MACH_MSG_TYPE_MOVE_RECEIVE
)) {
3525 * Invalid guard flags, context or disposition
3527 mr
= MACH_SEND_INVALID_TYPE
;
3530 if (os_add_overflow(total_ool_port_count
, 1, &total_ool_port_count
)) {
3531 /* Overflow detected */
3532 mr
= MACH_SEND_TOO_LARGE
;
3535 contains_port_desc
= TRUE
;
3540 /* Sending more than 16383 rights in one message seems crazy */
3541 if (total_ool_port_count
>= (MACH_PORT_UREFS_MAX
/ 4)) {
3542 mr
= MACH_SEND_TOO_LARGE
;
3547 * Check if dest is a no-grant port; Since this bit is set only on
3548 * port construction and cannot be unset later, we can peek at the
3549 * bit without paying the cost of locking the port.
3551 if (contains_port_desc
&& remote_port
->ip_no_grant
) {
3552 mr
= MACH_SEND_NO_GRANT_DEST
;
3557 * Allocate space in the pageable kernel ipc copy map for all the
3558 * ool data that is to be physically copied. Map is marked wait for
3562 if (vm_allocate_kernel(ipc_kernel_copy_map
, &paddr
, space_needed
,
3563 VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IPC
) != KERN_SUCCESS
) {
3564 mr
= MACH_MSG_VM_KERNEL
;
3569 /* user_addr = just after base as it was copied in */
3570 user_addr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
3572 /* Shift the mach_msg_base_t down to make room for dsc_count*16bytes of descriptors on 64 bit kernels
3574 if (descriptor_size
!= 16 * dsc_count
) {
3575 vm_offset_t dsc_adjust
= 16 * dsc_count
- descriptor_size
;
3577 memmove((char *)(((vm_offset_t
)kmsg
->ikm_header
) - dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
3578 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
- dsc_adjust
);
3580 /* Update the message size for the larger in-kernel representation */
3581 kmsg
->ikm_header
->msgh_size
+= (mach_msg_size_t
)dsc_adjust
;
3585 /* kern_addr = just after base after it has been (conditionally) moved */
3586 kern_addr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
3588 /* handle the OOL regions and port descriptors. */
3589 for (i
= 0; i
< dsc_count
; i
++) {
3590 switch (user_addr
->type
.type
) {
3591 case MACH_MSG_PORT_DESCRIPTOR
:
3592 user_addr
= ipc_kmsg_copyin_port_descriptor((mach_msg_port_descriptor_t
*)kern_addr
,
3593 (mach_msg_legacy_port_descriptor_t
*)user_addr
, space
, dest
, kmsg
, optionp
, &mr
);
3597 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3598 case MACH_MSG_OOL_DESCRIPTOR
:
3599 user_addr
= ipc_kmsg_copyin_ool_descriptor((mach_msg_ool_descriptor_t
*)kern_addr
,
3600 user_addr
, is_task_64bit
, &paddr
, ©
, &space_needed
, map
, optionp
, &mr
);
3604 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3605 user_addr
= ipc_kmsg_copyin_ool_ports_descriptor((mach_msg_ool_ports_descriptor_t
*)kern_addr
,
3606 user_addr
, is_task_64bit
, map
, space
, dest
, kmsg
, optionp
, &mr
);
3610 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
3611 user_addr
= ipc_kmsg_copyin_guarded_port_descriptor((mach_msg_guarded_port_descriptor_t
*)kern_addr
,
3612 user_addr
, is_task_64bit
, space
, dest
, kmsg
, optionp
, &mr
);
3617 /* Invalid descriptor */
3618 mr
= MACH_SEND_INVALID_TYPE
;
3622 if (MACH_MSG_SUCCESS
!= mr
) {
3623 /* clean from start of message descriptors to i */
3624 ipc_kmsg_clean_partial(kmsg
, i
,
3625 (mach_msg_descriptor_t
*)((mach_msg_base_t
*)kmsg
->ikm_header
+ 1),
3626 paddr
, space_needed
);
3632 kmsg
->ikm_header
->msgh_bits
&= ~MACH_MSGH_BITS_COMPLEX
;
3638 /* no descriptors have been copied in yet */
3639 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
3645 * Routine: ipc_kmsg_copyin
3647 * "Copy-in" port rights and out-of-line memory
3650 * In all failure cases, the message is left holding
3651 * no rights or memory. However, the message buffer
3652 * is not deallocated. If successful, the message
3653 * contains a valid destination port.
3657 * MACH_MSG_SUCCESS Successful copyin.
3658 * MACH_SEND_INVALID_HEADER
3659 * Illegal value in the message header bits.
3660 * MACH_SEND_INVALID_DEST Can't copyin destination port.
3661 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
3662 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
3663 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
3664 * MACH_SEND_INVALID_TYPE Bad type specification.
3665 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
3673 mach_msg_priority_t override
,
3674 mach_msg_option_t
*optionp
)
3676 mach_msg_return_t mr
;
3678 kmsg
->ikm_header
->msgh_bits
&= MACH_MSGH_BITS_USER
;
3680 mr
= ipc_kmsg_copyin_header(kmsg
, space
, override
, optionp
);
3682 if (mr
!= MACH_MSG_SUCCESS
) {
3686 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_MSG_SEND
) | DBG_FUNC_NONE
,
3687 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
3688 (uintptr_t)kmsg
->ikm_header
->msgh_bits
,
3689 (uintptr_t)kmsg
->ikm_header
->msgh_id
,
3690 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(kmsg
->ikm_voucher
)),
3693 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_copyin header:\n%.8x\n%.8x\n%p\n%p\n%p\n%.8x\n",
3694 kmsg
->ikm_header
->msgh_size
,
3695 kmsg
->ikm_header
->msgh_bits
,
3696 kmsg
->ikm_header
->msgh_remote_port
,
3697 kmsg
->ikm_header
->msgh_local_port
,
3699 kmsg
->ikm_header
->msgh_id
);
3701 if ((kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) == 0) {
3702 return MACH_MSG_SUCCESS
;
3705 mr
= ipc_kmsg_copyin_body( kmsg
, space
, map
, optionp
);
3706 /* unreachable if !DEBUG */
3707 __unreachable_ok_push
3708 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
3711 for (i
= 0; i
* 4 < (kmsg
->ikm_header
->msgh_size
- sizeof(mach_msg_header_t
)); i
++) {
3712 kprintf("%.4x\n", ((uint32_t *)(kmsg
->ikm_header
+ 1))[i
]);
3715 __unreachable_ok_pop
3721 * Routine: ipc_kmsg_copyin_from_kernel
3723 * "Copy-in" port rights and out-of-line memory
3724 * in a message sent from the kernel.
3726 * Because the message comes from the kernel,
3727 * the implementation assumes there are no errors
3728 * or peculiarities in the message.
3734 ipc_kmsg_copyin_from_kernel(
3737 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
3738 mach_msg_type_name_t rname
= MACH_MSGH_BITS_REMOTE(bits
);
3739 mach_msg_type_name_t lname
= MACH_MSGH_BITS_LOCAL(bits
);
3740 ipc_object_t remote
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
3741 ipc_object_t local
= ip_to_object(kmsg
->ikm_header
->msgh_local_port
);
3742 ipc_port_t dest
= kmsg
->ikm_header
->msgh_remote_port
;
3744 /* translate the destination and reply ports */
3745 if (!IO_VALID(remote
)) {
3746 return MACH_SEND_INVALID_DEST
;
3749 ipc_object_copyin_from_kernel(remote
, rname
);
3750 if (IO_VALID(local
)) {
3751 ipc_object_copyin_from_kernel(local
, lname
);
3755 * The common case is a complex message with no reply port,
3756 * because that is what the memory_object interface uses.
3759 if (bits
== (MACH_MSGH_BITS_COMPLEX
|
3760 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0))) {
3761 bits
= (MACH_MSGH_BITS_COMPLEX
|
3762 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND
, 0));
3764 kmsg
->ikm_header
->msgh_bits
= bits
;
3766 bits
= (MACH_MSGH_BITS_OTHER(bits
) |
3767 MACH_MSGH_BITS(ipc_object_copyin_type(rname
),
3768 ipc_object_copyin_type(lname
)));
3770 kmsg
->ikm_header
->msgh_bits
= bits
;
3771 if ((bits
& MACH_MSGH_BITS_COMPLEX
) == 0) {
3772 return MACH_MSG_SUCCESS
;
3777 * Check if the remote port accepts ports in the body.
3779 if (dest
->ip_no_grant
) {
3780 mach_msg_descriptor_t
*saddr
;
3781 mach_msg_body_t
*body
;
3782 mach_msg_type_number_t i
, count
;
3784 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3785 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
3786 count
= body
->msgh_descriptor_count
;
3788 for (i
= 0; i
< count
; i
++, saddr
++) {
3789 switch (saddr
->type
.type
) {
3790 case MACH_MSG_PORT_DESCRIPTOR
:
3791 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3792 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
3793 /* no descriptors have been copied in yet */
3794 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
3795 return MACH_SEND_NO_GRANT_DEST
;
3800 mach_msg_descriptor_t
*saddr
;
3801 mach_msg_body_t
*body
;
3802 mach_msg_type_number_t i
, count
;
3804 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3805 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
3806 count
= body
->msgh_descriptor_count
;
3808 for (i
= 0; i
< count
; i
++, saddr
++) {
3809 switch (saddr
->type
.type
) {
3810 case MACH_MSG_PORT_DESCRIPTOR
: {
3811 mach_msg_type_name_t name
;
3812 ipc_object_t object
;
3813 mach_msg_port_descriptor_t
*dsc
;
3817 /* this is really the type SEND, SEND_ONCE, etc. */
3818 name
= dsc
->disposition
;
3819 object
= ip_to_object(dsc
->name
);
3820 dsc
->disposition
= ipc_object_copyin_type(name
);
3822 if (!IO_VALID(object
)) {
3826 ipc_object_copyin_from_kernel(object
, name
);
3828 /* CDY avoid circularity when the destination is also */
3829 /* the kernel. This check should be changed into an */
3830 /* assert when the new kobject model is in place since*/
3831 /* ports will not be used in kernel to kernel chats */
3833 if (ip_object_to_port(remote
)->ip_receiver
!= ipc_space_kernel
) {
3834 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3835 ipc_port_check_circularity(ip_object_to_port(object
),
3836 ip_object_to_port(remote
))) {
3837 kmsg
->ikm_header
->msgh_bits
|=
3838 MACH_MSGH_BITS_CIRCULAR
;
3843 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3844 case MACH_MSG_OOL_DESCRIPTOR
: {
3846 * The sender should supply ready-made memory, i.e.
3847 * a vm_map_copy_t, so we don't need to do anything.
3851 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
3852 ipc_object_t
*objects
;
3854 mach_msg_type_name_t name
;
3855 mach_msg_ool_ports_descriptor_t
*dsc
;
3857 dsc
= (mach_msg_ool_ports_descriptor_t
*)&saddr
->ool_ports
;
3859 /* this is really the type SEND, SEND_ONCE, etc. */
3860 name
= dsc
->disposition
;
3861 dsc
->disposition
= ipc_object_copyin_type(name
);
3863 objects
= (ipc_object_t
*) dsc
->address
;
3865 for (j
= 0; j
< dsc
->count
; j
++) {
3866 ipc_object_t object
= objects
[j
];
3868 if (!IO_VALID(object
)) {
3872 ipc_object_copyin_from_kernel(object
, name
);
3874 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3875 ipc_port_check_circularity(ip_object_to_port(object
),
3876 ip_object_to_port(remote
))) {
3877 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
3882 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
: {
3883 mach_msg_guarded_port_descriptor_t
*dsc
= (typeof(dsc
)) & saddr
->guarded_port
;
3884 mach_msg_type_name_t disp
= dsc
->disposition
;
3885 ipc_object_t object
= ip_to_object(dsc
->name
);
3886 dsc
->disposition
= ipc_object_copyin_type(disp
);
3887 assert(dsc
->flags
== 0);
3889 if (!IO_VALID(object
)) {
3893 ipc_object_copyin_from_kernel(object
, disp
);
3895 * avoid circularity when the destination is also
3896 * the kernel. This check should be changed into an
3897 * assert when the new kobject model is in place since
3898 * ports will not be used in kernel to kernel chats
3901 if (ip_object_to_port(remote
)->ip_receiver
!= ipc_space_kernel
) {
3902 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3903 ipc_port_check_circularity(ip_object_to_port(object
),
3904 ip_object_to_port(remote
))) {
3905 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
3912 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3913 #endif /* MACH_ASSERT */
3918 return MACH_MSG_SUCCESS
;
3921 #if IKM_SUPPORT_LEGACY
3923 ipc_kmsg_copyin_from_kernel_legacy(
3926 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
3927 mach_msg_type_name_t rname
= MACH_MSGH_BITS_REMOTE(bits
);
3928 mach_msg_type_name_t lname
= MACH_MSGH_BITS_LOCAL(bits
);
3929 ipc_object_t remote
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
3930 ipc_object_t local
= ip_to_object(kmsg
->ikm_header
->msgh_local_port
);
3931 ipc_port_t dest
= kmsg
->ikm_header
->msgh_remote_port
;
3933 /* translate the destination and reply ports */
3934 if (!IO_VALID(remote
)) {
3935 return MACH_SEND_INVALID_DEST
;
3938 ipc_object_copyin_from_kernel(remote
, rname
);
3939 if (IO_VALID(local
)) {
3940 ipc_object_copyin_from_kernel(local
, lname
);
3944 * The common case is a complex message with no reply port,
3945 * because that is what the memory_object interface uses.
3948 if (bits
== (MACH_MSGH_BITS_COMPLEX
|
3949 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0))) {
3950 bits
= (MACH_MSGH_BITS_COMPLEX
|
3951 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND
, 0));
3953 kmsg
->ikm_header
->msgh_bits
= bits
;
3955 bits
= (MACH_MSGH_BITS_OTHER(bits
) |
3956 MACH_MSGH_BITS(ipc_object_copyin_type(rname
),
3957 ipc_object_copyin_type(lname
)));
3959 kmsg
->ikm_header
->msgh_bits
= bits
;
3960 if ((bits
& MACH_MSGH_BITS_COMPLEX
) == 0) {
3961 return MACH_MSG_SUCCESS
;
3965 if (dest
->ip_no_grant
) {
3966 mach_msg_descriptor_t
*saddr
;
3967 mach_msg_body_t
*body
;
3968 mach_msg_type_number_t i
, count
;
3970 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3971 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
3972 count
= body
->msgh_descriptor_count
;
3974 for (i
= 0; i
< count
; i
++, saddr
++) {
3975 switch (saddr
->type
.type
) {
3976 case MACH_MSG_PORT_DESCRIPTOR
:
3977 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3978 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
3979 /* no descriptors have been copied in yet */
3980 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
3981 return MACH_SEND_NO_GRANT_DEST
;
3987 mach_msg_legacy_descriptor_t
*saddr
;
3988 mach_msg_descriptor_t
*daddr
;
3989 mach_msg_body_t
*body
;
3990 mach_msg_type_number_t i
, count
;
3992 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3993 saddr
= (typeof(saddr
))(body
+ 1);
3994 count
= body
->msgh_descriptor_count
;
3997 vm_offset_t dsc_adjust
= 4 * count
;
3998 memmove((char *)(((vm_offset_t
)kmsg
->ikm_header
) - dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
3999 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
- dsc_adjust
);
4000 /* Update the message size for the larger in-kernel representation */
4001 kmsg
->ikm_header
->msgh_size
+= dsc_adjust
;
4003 daddr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
4005 for (i
= 0; i
< count
; i
++, saddr
++, daddr
++) {
4006 switch (saddr
->type
.type
) {
4007 case MACH_MSG_PORT_DESCRIPTOR
: {
4008 mach_msg_type_name_t name
;
4009 ipc_object_t object
;
4010 mach_msg_legacy_port_descriptor_t
*dsc
;
4011 mach_msg_port_descriptor_t
*dest_dsc
;
4013 dsc
= (typeof(dsc
)) & saddr
->port
;
4014 dest_dsc
= &daddr
->port
;
4016 /* this is really the type SEND, SEND_ONCE, etc. */
4017 name
= dsc
->disposition
;
4018 object
= ip_to_object(CAST_MACH_NAME_TO_PORT(dsc
->name
));
4019 dest_dsc
->disposition
= ipc_object_copyin_type(name
);
4020 dest_dsc
->name
= ip_object_to_port(object
);
4021 dest_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
4023 if (!IO_VALID(object
)) {
4027 ipc_object_copyin_from_kernel(object
, name
);
4029 /* CDY avoid circularity when the destination is also */
4030 /* the kernel. This check should be changed into an */
4031 /* assert when the new kobject model is in place since*/
4032 /* ports will not be used in kernel to kernel chats */
4034 if (ip_object_to_port(remote
)->ip_receiver
!= ipc_space_kernel
) {
4035 if ((dest_dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
4036 ipc_port_check_circularity(ip_object_to_port(object
),
4037 ip_object_to_port(remote
))) {
4038 kmsg
->ikm_header
->msgh_bits
|=
4039 MACH_MSGH_BITS_CIRCULAR
;
4044 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4045 case MACH_MSG_OOL_DESCRIPTOR
: {
4046 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
4047 * so we don't need to do anything special. */
4049 mach_msg_ool_descriptor32_t
*source_dsc
= &saddr
->out_of_line32
;
4050 mach_msg_ool_descriptor_t
*dest_dsc
= (typeof(dest_dsc
)) & daddr
->out_of_line
;
4052 vm_offset_t address
= source_dsc
->address
;
4053 vm_size_t size
= source_dsc
->size
;
4054 boolean_t deallocate
= source_dsc
->deallocate
;
4055 mach_msg_copy_options_t copy
= source_dsc
->copy
;
4056 mach_msg_descriptor_type_t type
= source_dsc
->type
;
4058 dest_dsc
->address
= (void *)address
;
4059 dest_dsc
->size
= size
;
4060 dest_dsc
->deallocate
= deallocate
;
4061 dest_dsc
->copy
= copy
;
4062 dest_dsc
->type
= type
;
4065 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
4066 ipc_object_t
*objects
;
4068 mach_msg_type_name_t name
;
4069 mach_msg_ool_ports_descriptor_t
*dest_dsc
;
4071 mach_msg_ool_ports_descriptor32_t
*source_dsc
= &saddr
->ool_ports32
;
4072 dest_dsc
= (typeof(dest_dsc
)) & daddr
->ool_ports
;
4074 boolean_t deallocate
= source_dsc
->deallocate
;
4075 mach_msg_copy_options_t copy
= source_dsc
->copy
;
4076 mach_msg_size_t port_count
= source_dsc
->count
;
4077 mach_msg_type_name_t disposition
= source_dsc
->disposition
;
4079 /* this is really the type SEND, SEND_ONCE, etc. */
4081 disposition
= ipc_object_copyin_type(name
);
4083 objects
= (ipc_object_t
*) (uintptr_t)source_dsc
->address
;
4085 for (j
= 0; j
< port_count
; j
++) {
4086 ipc_object_t object
= objects
[j
];
4088 if (!IO_VALID(object
)) {
4092 ipc_object_copyin_from_kernel(object
, name
);
4094 if ((disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
4095 ipc_port_check_circularity(ip_object_to_port(object
),
4096 ip_object_to_port(remote
))) {
4097 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
4101 dest_dsc
->address
= objects
;
4102 dest_dsc
->deallocate
= deallocate
;
4103 dest_dsc
->copy
= copy
;
4104 dest_dsc
->disposition
= disposition
;
4105 dest_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
4106 dest_dsc
->count
= port_count
;
4109 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
: {
4110 mach_msg_type_name_t disp
;
4111 ipc_object_t object
;
4112 mach_msg_guarded_port_descriptor32_t
*dsc
;
4113 mach_msg_guarded_port_descriptor_t
*dest_dsc
;
4115 dsc
= (typeof(dsc
)) & saddr
->guarded_port32
;
4116 dest_dsc
= &daddr
->guarded_port
;
4118 disp
= dsc
->disposition
;
4119 object
= ip_to_object(CAST_MACH_NAME_TO_PORT(dsc
->name
));
4120 assert(dsc
->flags
== 0);
4121 assert(dsc
->context
== 0);
4123 dest_dsc
->disposition
= ipc_object_copyin_type(disp
);
4124 dest_dsc
->name
= ip_object_to_port(object
);
4125 dest_dsc
->type
= MACH_MSG_GUARDED_PORT_DESCRIPTOR
;
4126 dest_dsc
->flags
= 0;
4128 if (!IO_VALID(object
)) {
4132 ipc_object_copyin_from_kernel(object
, disp
);
4134 /* CDY avoid circularity when the destination is also */
4135 /* the kernel. This check should be changed into an */
4136 /* assert when the new kobject model is in place since*/
4137 /* ports will not be used in kernel to kernel chats */
4139 if (ip_object_to_port(remote
)->ip_receiver
!= ipc_space_kernel
) {
4140 if ((dest_dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
4141 ipc_port_check_circularity(ip_object_to_port(object
),
4142 ip_object_to_port(remote
))) {
4143 kmsg
->ikm_header
->msgh_bits
|=
4144 MACH_MSGH_BITS_CIRCULAR
;
4151 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
4152 #endif /* MACH_ASSERT */
4157 return MACH_MSG_SUCCESS
;
4159 #endif /* IKM_SUPPORT_LEGACY */
4162 * Routine: ipc_kmsg_copyout_header
4164 * "Copy-out" port rights in the header of a message.
4165 * Operates atomically; if it doesn't succeed the
4166 * message header and the space are left untouched.
4167 * If it does succeed the remote/local port fields
4168 * contain port names instead of object pointers,
4169 * and the bits field is updated.
4173 * MACH_MSG_SUCCESS Copied out port rights.
4174 * MACH_RCV_INVALID_NOTIFY
4175 * Notify is non-null and doesn't name a receive right.
4176 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
4177 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
4178 * The space is dead.
4179 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
4180 * No room in space for another name.
4181 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
4182 * Couldn't allocate memory for the reply port.
4183 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
4184 * Couldn't allocate memory for the dead-name request.
4188 ipc_kmsg_copyout_header(
4191 mach_msg_option_t option
)
4193 mach_msg_header_t
*msg
= kmsg
->ikm_header
;
4194 mach_msg_bits_t mbits
= msg
->msgh_bits
;
4195 ipc_port_t dest
= msg
->msgh_remote_port
;
4197 assert(IP_VALID(dest
));
4200 * While we still hold a reference on the received-from port,
4201 * process all send-possible notfications we received along with
4204 ipc_port_spnotify(dest
);
4207 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
4208 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
4209 mach_msg_type_name_t voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
4210 ipc_port_t reply
= msg
->msgh_local_port
;
4211 ipc_port_t release_reply_port
= IP_NULL
;
4212 mach_port_name_t dest_name
, reply_name
;
4214 ipc_port_t voucher
= kmsg
->ikm_voucher
;
4215 ipc_port_t release_voucher_port
= IP_NULL
;
4216 mach_port_name_t voucher_name
;
4218 uint32_t entries_held
= 0;
4219 boolean_t need_write_lock
= FALSE
;
4223 * Reserve any potentially needed entries in the target space.
4224 * We'll free any unused before unlocking the space.
4226 if (IP_VALID(reply
)) {
4228 need_write_lock
= TRUE
;
4230 if (IP_VALID(voucher
)) {
4231 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
4233 if ((option
& MACH_RCV_VOUCHER
) != 0) {
4236 need_write_lock
= TRUE
;
4239 if (need_write_lock
) {
4240 is_write_lock(space
);
4242 while (entries_held
) {
4243 if (!is_active(space
)) {
4244 is_write_unlock(space
);
4245 return MACH_RCV_HEADER_ERROR
|
4249 kr
= ipc_entries_hold(space
, entries_held
);
4250 if (KERN_SUCCESS
== kr
) {
4254 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
4255 if (KERN_SUCCESS
!= kr
) {
4256 return MACH_RCV_HEADER_ERROR
|
4259 /* space was unlocked and relocked - retry */
4262 /* Handle reply port. */
4263 if (IP_VALID(reply
)) {
4266 /* Is there already an entry we can use? */
4267 if ((reply_type
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
4268 ipc_right_reverse(space
, ip_to_object(reply
), &reply_name
, &entry
)) {
4269 /* reply port is locked and active */
4270 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
4273 if (!ip_active(reply
)) {
4274 /* clear the context value */
4275 reply
->ip_reply_context
= 0;
4278 release_reply_port
= reply
;
4280 reply_name
= MACH_PORT_DEAD
;
4281 goto done_with_reply
;
4284 /* claim a held entry for the reply port */
4285 assert(entries_held
> 0);
4287 ipc_entry_claim(space
, &reply_name
, &entry
);
4288 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
4289 assert(entry
->ie_object
== IO_NULL
);
4290 entry
->ie_object
= ip_to_object(reply
);
4293 /* space and reply port are locked and active */
4294 ip_reference(reply
); /* hold onto the reply port */
4297 * If the receiver would like to enforce strict reply
4298 * semantics, and the message looks like it expects a reply,
4299 * and contains a voucher, then link the context in the
4300 * voucher with the reply port so that the next message sent
4301 * to the reply port must come from a thread that has a
4302 * matching context (voucher).
4304 if (enforce_strict_reply
&& MACH_RCV_WITH_STRICT_REPLY(option
) && IP_VALID(voucher
)) {
4305 if (ipc_kmsg_validate_reply_port_locked(reply
, option
) != KERN_SUCCESS
) {
4306 /* if the receiver isn't happy with the reply port: fail the receive. */
4308 ipc_entry_dealloc(space
, reply_name
, entry
);
4309 is_write_unlock(space
);
4311 return MACH_RCV_INVALID_REPLY
;
4313 ipc_kmsg_link_reply_context_locked(reply
, voucher
);
4316 * if the receive did not choose to participate
4317 * in the strict reply/RPC, then don't enforce
4318 * anything (as this could lead to booby-trapped
4319 * messages that kill the server).
4321 reply
->ip_reply_context
= 0;
4324 kr
= ipc_right_copyout(space
, reply_name
, entry
,
4325 reply_type
, NULL
, NULL
, ip_to_object(reply
));
4326 assert(kr
== KERN_SUCCESS
);
4327 /* reply port is unlocked */
4329 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
4334 /* Handle voucher port. */
4335 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
4336 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
4338 if (!IP_VALID(voucher
)) {
4339 if ((option
& MACH_RCV_VOUCHER
) == 0) {
4340 voucher_type
= MACH_MSGH_BITS_ZERO
;
4342 voucher_name
= MACH_PORT_NULL
;
4343 goto done_with_voucher
;
4346 /* clear voucher from its hiding place back in the kmsg */
4347 kmsg
->ikm_voucher
= IP_NULL
;
4349 if ((option
& MACH_RCV_VOUCHER
) != 0) {
4352 if (ipc_right_reverse(space
, ip_to_object(voucher
),
4353 &voucher_name
, &entry
)) {
4354 /* voucher port locked */
4355 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND
);
4357 assert(entries_held
> 0);
4359 ipc_entry_claim(space
, &voucher_name
, &entry
);
4360 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
4361 assert(entry
->ie_object
== IO_NULL
);
4362 entry
->ie_object
= ip_to_object(voucher
);
4365 /* space is locked and active */
4366 require_ip_active(voucher
);
4367 assert(ip_kotype(voucher
) == IKOT_VOUCHER
);
4368 kr
= ipc_right_copyout(space
, voucher_name
, entry
,
4369 MACH_MSG_TYPE_MOVE_SEND
, NULL
, NULL
,
4370 ip_to_object(voucher
));
4371 /* voucher port is unlocked */
4373 voucher_type
= MACH_MSGH_BITS_ZERO
;
4374 release_voucher_port
= voucher
;
4375 voucher_name
= MACH_PORT_NULL
;
4378 voucher_name
= msg
->msgh_voucher_port
;
4384 is_write_unlock(space
);
4387 * No reply or voucher port! This is an easy case.
4388 * We only need to have the space locked
4389 * when locking the destination.
4392 is_read_lock(space
);
4393 if (!is_active(space
)) {
4394 is_read_unlock(space
);
4395 return MACH_RCV_HEADER_ERROR
| MACH_MSG_IPC_SPACE
;
4399 is_read_unlock(space
);
4401 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
4403 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
4404 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
4405 if ((option
& MACH_RCV_VOUCHER
) == 0) {
4406 voucher_type
= MACH_MSGH_BITS_ZERO
;
4408 voucher_name
= MACH_PORT_NULL
;
4410 voucher_name
= msg
->msgh_voucher_port
;
4415 * At this point, the space is unlocked and the destination
4416 * port is locked. (Lock taken while space was locked.)
4417 * reply_name is taken care of; we still need dest_name.
4418 * We still hold a ref for reply (if it is valid).
4420 * If the space holds receive rights for the destination,
4421 * we return its name for the right. Otherwise the task
4422 * managed to destroy or give away the receive right between
4423 * receiving the message and this copyout. If the destination
4424 * is dead, return MACH_PORT_DEAD, and if the receive right
4425 * exists somewhere else (another space, in transit)
4426 * return MACH_PORT_NULL.
4428 * Making this copyout operation atomic with the previous
4429 * copyout of the reply port is a bit tricky. If there was
4430 * no real reply port (it wasn't IP_VALID) then this isn't
4431 * an issue. If the reply port was dead at copyout time,
4432 * then we are OK, because if dest is dead we serialize
4433 * after the death of both ports and if dest is alive
4434 * we serialize after reply died but before dest's (later) death.
4435 * So assume reply was alive when we copied it out. If dest
4436 * is alive, then we are OK because we serialize before
4437 * the ports' deaths. So assume dest is dead when we look at it.
4438 * If reply dies/died after dest, then we are OK because
4439 * we serialize after dest died but before reply dies.
4440 * So the hard case is when reply is alive at copyout,
4441 * dest is dead at copyout, and reply died before dest died.
4442 * In this case pretend that dest is still alive, so
4443 * we serialize while both ports are alive.
4445 * Because the space lock is held across the copyout of reply
4446 * and locking dest, the receive right for dest can't move
4447 * in or out of the space while the copyouts happen, so
4448 * that isn't an atomicity problem. In the last hard case
4449 * above, this implies that when dest is dead that the
4450 * space couldn't have had receive rights for dest at
4451 * the time reply was copied-out, so when we pretend
4452 * that dest is still alive, we can return MACH_PORT_NULL.
4454 * If dest == reply, then we have to make it look like
4455 * either both copyouts happened before the port died,
4456 * or both happened after the port died. This special
4457 * case works naturally if the timestamp comparison
4458 * is done correctly.
4461 if (ip_active(dest
)) {
4462 ipc_object_copyout_dest(space
, ip_to_object(dest
),
4463 dest_type
, &dest_name
);
4464 /* dest is unlocked */
4466 ipc_port_timestamp_t timestamp
;
4468 timestamp
= dest
->ip_timestamp
;
4472 if (IP_VALID(reply
)) {
4474 if (ip_active(reply
) ||
4475 IP_TIMESTAMP_ORDER(timestamp
,
4476 reply
->ip_timestamp
)) {
4477 dest_name
= MACH_PORT_DEAD
;
4479 dest_name
= MACH_PORT_NULL
;
4483 dest_name
= MACH_PORT_DEAD
;
4487 if (IP_VALID(reply
)) {
4491 if (IP_VALID(release_reply_port
)) {
4492 if (reply_type
== MACH_MSG_TYPE_PORT_SEND_ONCE
) {
4493 ipc_port_release_sonce(release_reply_port
);
4495 ipc_port_release_send(release_reply_port
);
4499 if ((option
& MACH_RCV_VOUCHER
) != 0) {
4500 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_MSG_RECV
) | DBG_FUNC_NONE
,
4501 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
4502 (uintptr_t)kmsg
->ikm_header
->msgh_bits
,
4503 (uintptr_t)kmsg
->ikm_header
->msgh_id
,
4504 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(voucher
)),
4507 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_MSG_RECV_VOUCHER_REFUSED
) | DBG_FUNC_NONE
,
4508 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
4509 (uintptr_t)kmsg
->ikm_header
->msgh_bits
,
4510 (uintptr_t)kmsg
->ikm_header
->msgh_id
,
4511 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(voucher
)),
4515 if (IP_VALID(release_voucher_port
)) {
4516 ipc_port_release_send(release_voucher_port
);
4519 msg
->msgh_bits
= MACH_MSGH_BITS_SET(reply_type
, dest_type
,
4520 voucher_type
, mbits
);
4521 msg
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
4522 msg
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
4523 msg
->msgh_voucher_port
= voucher_name
;
4526 return MACH_MSG_SUCCESS
;
4530 * Routine: ipc_kmsg_copyout_object
4532 * Copy-out a port right. Always returns a name,
4533 * even for unsuccessful return codes. Always
4534 * consumes the supplied object.
4538 * MACH_MSG_SUCCESS The space acquired the right
4539 * (name is valid) or the object is dead (MACH_PORT_DEAD).
4540 * MACH_MSG_IPC_SPACE No room in space for the right,
4541 * or the space is dead. (Name is MACH_PORT_NULL.)
4542 * MACH_MSG_IPC_KERNEL Kernel resource shortage.
4543 * (Name is MACH_PORT_NULL.)
4547 ipc_kmsg_copyout_object(
4549 ipc_object_t object
,
4550 mach_msg_type_name_t msgt_name
,
4551 mach_port_context_t
*context
,
4552 mach_msg_guard_flags_t
*guard_flags
,
4553 mach_port_name_t
*namep
)
4557 if (!IO_VALID(object
)) {
4558 *namep
= CAST_MACH_PORT_TO_NAME(object
);
4559 return MACH_MSG_SUCCESS
;
4562 kr
= ipc_object_copyout(space
, object
, msgt_name
, context
, guard_flags
, namep
);
4563 if (kr
!= KERN_SUCCESS
) {
4564 ipc_object_destroy(object
, msgt_name
);
4566 if (kr
== KERN_INVALID_CAPABILITY
) {
4567 *namep
= MACH_PORT_DEAD
;
4569 *namep
= MACH_PORT_NULL
;
4571 if (kr
== KERN_RESOURCE_SHORTAGE
) {
4572 return MACH_MSG_IPC_KERNEL
;
4574 return MACH_MSG_IPC_SPACE
;
4579 return MACH_MSG_SUCCESS
;
4582 static mach_msg_descriptor_t
*
4583 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t
*dsc
,
4584 mach_msg_descriptor_t
*dest_dsc
,
4589 mach_port_name_t name
;
4590 mach_msg_type_name_t disp
;
4592 /* Copyout port right carried in the message */
4593 port
= dsc
->port
.name
;
4594 disp
= dsc
->port
.disposition
;
4595 *mr
|= ipc_kmsg_copyout_object(space
,
4596 ip_to_object(port
), disp
, NULL
, NULL
, &name
);
4598 if (current_task() == kernel_task
) {
4599 mach_msg_port_descriptor_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
4600 user_dsc
--; // point to the start of this port descriptor
4601 bzero((void *)user_dsc
, sizeof(*user_dsc
));
4602 user_dsc
->name
= CAST_MACH_NAME_TO_PORT(name
);
4603 user_dsc
->disposition
= disp
;
4604 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
4605 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
4607 mach_msg_legacy_port_descriptor_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
4608 user_dsc
--; // point to the start of this port descriptor
4609 bzero((void *)user_dsc
, sizeof(*user_dsc
));
4610 user_dsc
->name
= CAST_MACH_PORT_TO_NAME(name
);
4611 user_dsc
->disposition
= disp
;
4612 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
4613 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
4616 return (mach_msg_descriptor_t
*)dest_dsc
;
4619 mach_msg_descriptor_t
*
4620 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
);
4621 mach_msg_descriptor_t
*
4622 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
)
4625 vm_map_address_t rcv_addr
;
4626 mach_msg_copy_options_t copy_options
;
4628 mach_msg_descriptor_type_t dsc_type
;
4630 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4632 copy
= (vm_map_copy_t
)dsc
->address
;
4633 size
= (vm_map_size_t
)dsc
->size
;
4634 copy_options
= dsc
->copy
;
4635 assert(copy_options
!= MACH_MSG_KALLOC_COPY_T
);
4636 dsc_type
= dsc
->type
;
4638 if (copy
!= VM_MAP_COPY_NULL
) {
4642 if (vm_map_copy_validate_size(map
, copy
, &size
) == FALSE
) {
4643 panic("Inconsistent OOL/copyout size on %p: expected %d, got %lld @%p",
4644 dsc
, dsc
->size
, (unsigned long long)copy
->size
, copy
);
4646 kr
= vm_map_copyout_size(map
, &rcv_addr
, copy
, size
);
4647 if (kr
!= KERN_SUCCESS
) {
4648 if (kr
== KERN_RESOURCE_SHORTAGE
) {
4649 *mr
|= MACH_MSG_VM_KERNEL
;
4651 *mr
|= MACH_MSG_VM_SPACE
;
4653 vm_map_copy_discard(copy
);
4663 * Now update the descriptor as the user would see it.
4664 * This may require expanding the descriptor to the user
4665 * visible size. There is already space allocated for
4666 * this in what naddr points to.
4668 if (current_task() == kernel_task
) {
4669 mach_msg_ool_descriptor_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4671 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4673 user_ool_dsc
->address
= (void *)(uintptr_t)rcv_addr
;
4674 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4676 user_ool_dsc
->copy
= copy_options
;
4677 user_ool_dsc
->type
= dsc_type
;
4678 user_ool_dsc
->size
= (mach_msg_size_t
)size
;
4680 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4681 } else if (is_64bit
) {
4682 mach_msg_ool_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4684 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4686 user_ool_dsc
->address
= rcv_addr
;
4687 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4689 user_ool_dsc
->copy
= copy_options
;
4690 user_ool_dsc
->type
= dsc_type
;
4691 user_ool_dsc
->size
= (mach_msg_size_t
)size
;
4693 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4695 mach_msg_ool_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4697 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4699 user_ool_dsc
->address
= CAST_DOWN_EXPLICIT(uint32_t, rcv_addr
);
4700 user_ool_dsc
->size
= (mach_msg_size_t
)size
;
4701 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4703 user_ool_dsc
->copy
= copy_options
;
4704 user_ool_dsc
->type
= dsc_type
;
4706 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4711 mach_msg_descriptor_t
*
4712 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t
*dsc
,
4713 mach_msg_descriptor_t
*user_dsc
,
4718 mach_msg_return_t
*mr
);
4719 mach_msg_descriptor_t
*
4720 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t
*dsc
,
4721 mach_msg_descriptor_t
*user_dsc
,
4726 mach_msg_return_t
*mr
)
4728 mach_vm_offset_t rcv_addr
= 0;
4729 mach_msg_type_name_t disp
;
4730 mach_msg_type_number_t count
, i
;
4731 vm_size_t ports_length
, names_length
;
4733 mach_msg_copy_options_t copy_options
= MACH_MSG_VIRTUAL_COPY
;
4735 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4738 disp
= dsc
->disposition
;
4739 ports_length
= count
* sizeof(mach_port_t
);
4740 names_length
= count
* sizeof(mach_port_name_t
);
4742 if (ports_length
!= 0 && dsc
->address
!= 0) {
4744 * Check to see if there is an overwrite descriptor
4745 * specified in the scatter list for this ool data.
4746 * The descriptor has already been verified.
4749 if (saddr
!= MACH_MSG_DESCRIPTOR_NULL
) {
4751 OTHER_OOL_DESCRIPTOR
*scatter_dsc
;
4753 scatter_dsc
= (OTHER_OOL_DESCRIPTOR
*)saddr
;
4754 rcv_addr
= (mach_vm_offset_t
) scatter_dsc
->address
;
4755 copy_options
= scatter_dsc
->copy
;
4757 mach_msg_ool_descriptor_t
*scatter_dsc
;
4759 scatter_dsc
= &saddr
->out_of_line
;
4760 rcv_addr
= CAST_USER_ADDR_T(scatter_dsc
->address
);
4761 copy_options
= scatter_dsc
->copy
;
4763 INCREMENT_SCATTER(saddr
, sdsc_count
, differs
);
4767 if (copy_options
== MACH_MSG_VIRTUAL_COPY
) {
4769 * Dynamically allocate the region
4772 if (vm_kernel_map_is_kernel(map
)) {
4773 tag
= VM_KERN_MEMORY_IPC
;
4775 tag
= VM_MEMORY_MACH_MSG
;
4779 if ((kr
= mach_vm_allocate_kernel(map
, &rcv_addr
,
4780 (mach_vm_size_t
)names_length
,
4781 VM_FLAGS_ANYWHERE
, tag
)) != KERN_SUCCESS
) {
4782 ipc_kmsg_clean_body(kmsg
, 1, (mach_msg_descriptor_t
*)dsc
);
4785 if (kr
== KERN_RESOURCE_SHORTAGE
) {
4786 *mr
|= MACH_MSG_VM_KERNEL
;
4788 *mr
|= MACH_MSG_VM_SPACE
;
4794 * Handle the port rights and copy out the names
4795 * for those rights out to user-space.
4797 if (rcv_addr
!= 0) {
4798 ipc_object_t
*objects
= (ipc_object_t
*) dsc
->address
;
4799 mach_port_name_t
*names
= (mach_port_name_t
*) dsc
->address
;
4801 /* copyout port rights carried in the message */
4803 for (i
= 0; i
< count
; i
++) {
4804 ipc_object_t object
= objects
[i
];
4806 *mr
|= ipc_kmsg_copyout_object(space
, object
,
4807 disp
, NULL
, NULL
, &names
[i
]);
4810 /* copyout to memory allocated above */
4811 void *data
= dsc
->address
;
4812 if (copyoutmap(map
, data
, rcv_addr
, names_length
) != KERN_SUCCESS
) {
4813 *mr
|= MACH_MSG_VM_SPACE
;
4815 kfree(data
, ports_length
);
4822 * Now update the descriptor based on the information
4825 if (current_task() == kernel_task
) {
4826 mach_msg_ool_ports_descriptor_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4828 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4830 user_ool_dsc
->address
= (void *)(uintptr_t)rcv_addr
;
4831 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4833 user_ool_dsc
->copy
= copy_options
;
4834 user_ool_dsc
->disposition
= disp
;
4835 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
4836 user_ool_dsc
->count
= count
;
4838 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4839 } else if (is_64bit
) {
4840 mach_msg_ool_ports_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4842 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4844 user_ool_dsc
->address
= rcv_addr
;
4845 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4847 user_ool_dsc
->copy
= copy_options
;
4848 user_ool_dsc
->disposition
= disp
;
4849 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
4850 user_ool_dsc
->count
= count
;
4852 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4854 mach_msg_ool_ports_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4856 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4858 user_ool_dsc
->address
= CAST_DOWN_EXPLICIT(uint32_t, rcv_addr
);
4859 user_ool_dsc
->count
= count
;
4860 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4862 user_ool_dsc
->copy
= copy_options
;
4863 user_ool_dsc
->disposition
= disp
;
4864 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
4866 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4871 static mach_msg_descriptor_t
*
4872 ipc_kmsg_copyout_guarded_port_descriptor(
4873 mach_msg_guarded_port_descriptor_t
*dsc
,
4874 mach_msg_descriptor_t
*dest_dsc
,
4876 __unused ipc_kmsg_t kmsg
,
4878 mach_msg_option_t option
,
4882 mach_port_name_t name
= MACH_PORT_NULL
;
4883 mach_msg_type_name_t disp
;
4884 mach_msg_guard_flags_t guard_flags
;
4885 mach_port_context_t context
;
4887 /* Copyout port right carried in the message */
4889 disp
= dsc
->disposition
;
4890 guard_flags
= dsc
->flags
;
4893 /* Currently kernel_task doesnt support receiving guarded port descriptors */
4894 struct knote
*kn
= current_thread()->ith_knote
;
4895 if ((kn
!= ITH_KNOTE_PSEUDO
) && (((option
& MACH_RCV_GUARDED_DESC
) == 0) ||
4896 (current_task() == kernel_task
))) {
4897 #if DEVELOPMENT || DEBUG
4898 if (current_task() != kernel_task
) {
4900 * Simulated crash needed for debugging, notifies the receiver to opt into receiving
4901 * guarded descriptors.
4903 mach_port_guard_exception(current_thread()->ith_receiver_name
, 0, 0, kGUARD_EXC_RCV_GUARDED_DESC
);
4906 KDBG(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_DESTROY_GUARDED_DESC
), current_thread()->ith_receiver_name
,
4907 VM_KERNEL_ADDRPERM(port
), disp
, guard_flags
);
4908 ipc_object_destroy(ip_to_object(port
), disp
);
4909 mach_msg_legacy_port_descriptor_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
4910 user_dsc
--; // point to the start of this port descriptor
4911 bzero((void *)user_dsc
, sizeof(*user_dsc
));
4912 user_dsc
->name
= name
;
4913 user_dsc
->disposition
= disp
;
4914 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
4915 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
4917 *mr
|= ipc_kmsg_copyout_object(space
,
4918 ip_to_object(port
), disp
, &context
, &guard_flags
, &name
);
4921 mach_msg_guarded_port_descriptor32_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
4922 user_dsc
--; // point to the start of this port descriptor
4923 bzero((void *)user_dsc
, sizeof(*user_dsc
));
4924 user_dsc
->name
= name
;
4925 user_dsc
->flags
= guard_flags
;
4926 user_dsc
->disposition
= disp
;
4927 user_dsc
->type
= MACH_MSG_GUARDED_PORT_DESCRIPTOR
;
4928 user_dsc
->context
= CAST_DOWN_EXPLICIT(uint32_t, context
);
4929 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
4931 mach_msg_guarded_port_descriptor64_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
4932 user_dsc
--; // point to the start of this port descriptor
4933 bzero((void *)user_dsc
, sizeof(*user_dsc
));
4934 user_dsc
->name
= name
;
4935 user_dsc
->flags
= guard_flags
;
4936 user_dsc
->disposition
= disp
;
4937 user_dsc
->type
= MACH_MSG_GUARDED_PORT_DESCRIPTOR
;
4938 user_dsc
->context
= context
;
4939 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
4943 return (mach_msg_descriptor_t
*)dest_dsc
;
4947 * Routine: ipc_kmsg_copyout_body
4949 * "Copy-out" port rights and out-of-line memory
4950 * in the body of a message.
4952 * The error codes are a combination of special bits.
4953 * The copyout proceeds despite errors.
4957 * MACH_MSG_SUCCESS Successful copyout.
4958 * MACH_MSG_IPC_SPACE No room for port right in name space.
4959 * MACH_MSG_VM_SPACE No room for memory in address space.
4960 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
4961 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
4962 * MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
4966 ipc_kmsg_copyout_body(
4970 mach_msg_option_t option
,
4971 mach_msg_body_t
*slist
)
4973 mach_msg_body_t
*body
;
4974 mach_msg_descriptor_t
*kern_dsc
, *user_dsc
;
4975 mach_msg_descriptor_t
*saddr
;
4976 mach_msg_type_number_t dsc_count
, sdsc_count
;
4978 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
4979 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
4981 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
4982 dsc_count
= body
->msgh_descriptor_count
;
4983 kern_dsc
= (mach_msg_descriptor_t
*) (body
+ 1);
4984 /* Point user_dsc just after the end of all the descriptors */
4985 user_dsc
= &kern_dsc
[dsc_count
];
4987 /* Do scatter list setup */
4988 if (slist
!= MACH_MSG_BODY_NULL
) {
4989 panic("Scatter lists disabled");
4990 saddr
= (mach_msg_descriptor_t
*) (slist
+ 1);
4991 sdsc_count
= slist
->msgh_descriptor_count
;
4993 saddr
= MACH_MSG_DESCRIPTOR_NULL
;
4997 /* Now process the descriptors */
4998 for (i
= dsc_count
- 1; i
>= 0; i
--) {
4999 switch (kern_dsc
[i
].type
.type
) {
5000 case MACH_MSG_PORT_DESCRIPTOR
:
5001 user_dsc
= ipc_kmsg_copyout_port_descriptor(&kern_dsc
[i
], user_dsc
, space
, &mr
);
5003 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
5004 case MACH_MSG_OOL_DESCRIPTOR
:
5005 user_dsc
= ipc_kmsg_copyout_ool_descriptor(
5006 (mach_msg_ool_descriptor_t
*)&kern_dsc
[i
], user_dsc
, is_task_64bit
, map
, &mr
);
5008 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
5009 user_dsc
= ipc_kmsg_copyout_ool_ports_descriptor(
5010 (mach_msg_ool_ports_descriptor_t
*)&kern_dsc
[i
], user_dsc
, is_task_64bit
, map
, space
, kmsg
, &mr
);
5012 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
5013 user_dsc
= ipc_kmsg_copyout_guarded_port_descriptor(
5014 (mach_msg_guarded_port_descriptor_t
*)&kern_dsc
[i
], user_dsc
, is_task_64bit
, kmsg
, space
, option
, &mr
);
5017 panic("untyped IPC copyout body: invalid message descriptor");
5022 if (user_dsc
!= kern_dsc
) {
5023 vm_offset_t dsc_adjust
= (vm_offset_t
)user_dsc
- (vm_offset_t
)kern_dsc
;
5024 memmove((char *)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
5025 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
);
5026 /* Update the message size for the smaller user representation */
5027 kmsg
->ikm_header
->msgh_size
-= (mach_msg_size_t
)dsc_adjust
;
5034 * Routine: ipc_kmsg_copyout_size
5036 * Compute the size of the message as copied out to the given
5037 * map. If the destination map's pointers are a different size
5038 * than the kernel's, we have to allow for expansion/
5039 * contraction of the descriptors as appropriate.
5043 * size of the message as it would be received.
5047 ipc_kmsg_copyout_size(
5051 mach_msg_size_t send_size
;
5053 send_size
= kmsg
->ikm_header
->msgh_size
;
5055 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
5057 #if defined(__LP64__)
5058 send_size
-= LEGACY_HEADER_SIZE_DELTA
;
5061 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
5062 mach_msg_body_t
*body
;
5063 mach_msg_descriptor_t
*saddr
, *eaddr
;
5065 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
5066 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
5067 eaddr
= saddr
+ body
->msgh_descriptor_count
;
5069 for (; saddr
< eaddr
; saddr
++) {
5070 switch (saddr
->type
.type
) {
5071 case MACH_MSG_OOL_DESCRIPTOR
:
5072 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
5073 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
5074 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
:
5075 if (!is_task_64bit
) {
5076 send_size
-= DESC_SIZE_ADJUSTMENT
;
5079 case MACH_MSG_PORT_DESCRIPTOR
:
5080 send_size
-= DESC_SIZE_ADJUSTMENT
;
5091 * Routine: ipc_kmsg_copyout
5093 * "Copy-out" port rights and out-of-line memory
5098 * MACH_MSG_SUCCESS Copied out all rights and memory.
5099 * MACH_RCV_HEADER_ERROR + special bits
5100 * Rights and memory in the message are intact.
5101 * MACH_RCV_BODY_ERROR + special bits
5102 * The message header was successfully copied out.
5103 * As much of the body was handled as possible.
5111 mach_msg_body_t
*slist
,
5112 mach_msg_option_t option
)
5114 mach_msg_return_t mr
;
5116 mr
= ipc_kmsg_copyout_header(kmsg
, space
, option
);
5117 if (mr
!= MACH_MSG_SUCCESS
) {
5121 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
5122 mr
= ipc_kmsg_copyout_body(kmsg
, space
, map
, option
, slist
);
5124 if (mr
!= MACH_MSG_SUCCESS
) {
5125 mr
|= MACH_RCV_BODY_ERROR
;
5133 * Routine: ipc_kmsg_copyout_pseudo
5135 * Does a pseudo-copyout of the message.
5136 * This is like a regular copyout, except
5137 * that the ports in the header are handled
5138 * as if they are in the body. They aren't reversed.
5140 * The error codes are a combination of special bits.
5141 * The copyout proceeds despite errors.
5145 * MACH_MSG_SUCCESS Successful copyout.
5146 * MACH_MSG_IPC_SPACE No room for port right in name space.
5147 * MACH_MSG_VM_SPACE No room for memory in address space.
5148 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
5149 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
5153 ipc_kmsg_copyout_pseudo(
5157 mach_msg_body_t
*slist
)
5159 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
5160 ipc_object_t dest
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
5161 ipc_object_t reply
= ip_to_object(kmsg
->ikm_header
->msgh_local_port
);
5162 ipc_object_t voucher
= ip_to_object(kmsg
->ikm_voucher
);
5163 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
5164 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
5165 mach_msg_type_name_t voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
5166 mach_port_name_t voucher_name
= kmsg
->ikm_header
->msgh_voucher_port
;
5167 mach_port_name_t dest_name
, reply_name
;
5168 mach_msg_return_t mr
;
5170 /* Set ith_knote to ITH_KNOTE_PSEUDO */
5171 current_thread()->ith_knote
= ITH_KNOTE_PSEUDO
;
5173 assert(IO_VALID(dest
));
5177 * If we did this here, it looks like we wouldn't need the undo logic
5178 * at the end of ipc_kmsg_send() in the error cases. Not sure which
5179 * would be more elegant to keep.
5181 ipc_importance_clean(kmsg
);
5183 /* just assert it is already clean */
5184 ipc_importance_assert_clean(kmsg
);
5187 mr
= (ipc_kmsg_copyout_object(space
, dest
, dest_type
, NULL
, NULL
, &dest_name
) |
5188 ipc_kmsg_copyout_object(space
, reply
, reply_type
, NULL
, NULL
, &reply_name
));
5190 kmsg
->ikm_header
->msgh_bits
= mbits
& MACH_MSGH_BITS_USER
;
5191 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
5192 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
5194 if (IO_VALID(voucher
)) {
5195 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
5197 kmsg
->ikm_voucher
= IP_NULL
;
5198 mr
|= ipc_kmsg_copyout_object(space
, voucher
, voucher_type
, NULL
, NULL
, &voucher_name
);
5199 kmsg
->ikm_header
->msgh_voucher_port
= voucher_name
;
5202 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
5203 mr
|= ipc_kmsg_copyout_body(kmsg
, space
, map
, 0, slist
);
5210 * Routine: ipc_kmsg_copyout_dest
5212 * Copies out the destination port in the message.
5213 * Destroys all other rights and memory in the message.
5219 ipc_kmsg_copyout_dest(
5223 mach_msg_bits_t mbits
;
5226 ipc_object_t voucher
;
5227 mach_msg_type_name_t dest_type
;
5228 mach_msg_type_name_t reply_type
;
5229 mach_msg_type_name_t voucher_type
;
5230 mach_port_name_t dest_name
, reply_name
, voucher_name
;
5232 mbits
= kmsg
->ikm_header
->msgh_bits
;
5233 dest
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
5234 reply
= ip_to_object(kmsg
->ikm_header
->msgh_local_port
);
5235 voucher
= ip_to_object(kmsg
->ikm_voucher
);
5236 voucher_name
= kmsg
->ikm_header
->msgh_voucher_port
;
5237 dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
5238 reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
5239 voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
5241 assert(IO_VALID(dest
));
5243 ipc_importance_assert_clean(kmsg
);
5246 if (io_active(dest
)) {
5247 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
5248 /* dest is unlocked */
5252 dest_name
= MACH_PORT_DEAD
;
5255 if (IO_VALID(reply
)) {
5256 ipc_object_destroy(reply
, reply_type
);
5257 reply_name
= MACH_PORT_NULL
;
5259 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
5262 if (IO_VALID(voucher
)) {
5263 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
5265 kmsg
->ikm_voucher
= IP_NULL
;
5266 ipc_object_destroy(voucher
, voucher_type
);
5267 voucher_name
= MACH_PORT_NULL
;
5270 kmsg
->ikm_header
->msgh_bits
= MACH_MSGH_BITS_SET(reply_type
, dest_type
,
5271 voucher_type
, mbits
);
5272 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
5273 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
5274 kmsg
->ikm_header
->msgh_voucher_port
= voucher_name
;
5276 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
5277 mach_msg_body_t
*body
;
5279 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
5280 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
5281 (mach_msg_descriptor_t
*)(body
+ 1));
5286 * Routine: ipc_kmsg_copyout_to_kernel
5288 * Copies out the destination and reply ports in the message.
5289 * Leaves all other rights and memory in the message alone.
5293 * Derived from ipc_kmsg_copyout_dest.
5294 * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
5295 * We really do want to save rights and memory.
5299 ipc_kmsg_copyout_to_kernel(
5305 mach_msg_type_name_t dest_type
;
5306 mach_msg_type_name_t reply_type
;
5307 mach_port_name_t dest_name
;
5309 dest
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
5310 reply
= kmsg
->ikm_header
->msgh_local_port
;
5311 dest_type
= MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
);
5312 reply_type
= MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
);
5314 assert(IO_VALID(dest
));
5317 if (io_active(dest
)) {
5318 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
5319 /* dest is unlocked */
5323 dest_name
= MACH_PORT_DEAD
;
5327 * While MIG kernel users don't receive vouchers, the
5328 * msgh_voucher_port field is intended to be round-tripped through the
5329 * kernel if there is no voucher disposition set. Here we check for a
5330 * non-zero voucher disposition, and consume the voucher send right as
5331 * there is no possible way to specify MACH_RCV_VOUCHER semantics.
5333 mach_msg_type_name_t voucher_type
;
5334 voucher_type
= MACH_MSGH_BITS_VOUCHER(kmsg
->ikm_header
->msgh_bits
);
5335 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
5336 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
5338 * someone managed to send this kernel routine a message with
5339 * a voucher in it. Cleanup the reference in
5340 * kmsg->ikm_voucher.
5342 if (IP_VALID(kmsg
->ikm_voucher
)) {
5343 ipc_port_release_send(kmsg
->ikm_voucher
);
5345 kmsg
->ikm_voucher
= IP_NULL
;
5346 kmsg
->ikm_header
->msgh_voucher_port
= 0;
5349 kmsg
->ikm_header
->msgh_bits
=
5350 (MACH_MSGH_BITS_OTHER(kmsg
->ikm_header
->msgh_bits
) |
5351 MACH_MSGH_BITS(reply_type
, dest_type
));
5352 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
5353 kmsg
->ikm_header
->msgh_remote_port
= reply
;
5356 #if IKM_SUPPORT_LEGACY
5358 ipc_kmsg_copyout_to_kernel_legacy(
5364 mach_msg_type_name_t dest_type
;
5365 mach_msg_type_name_t reply_type
;
5366 mach_port_name_t dest_name
;
5368 dest
= ip_to_object(kmsg
->ikm_header
->msgh_remote_port
);
5369 reply
= kmsg
->ikm_header
->msgh_local_port
;
5370 dest_type
= MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
);
5371 reply_type
= MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
);
5373 assert(IO_VALID(dest
));
5376 if (io_active(dest
)) {
5377 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
5378 /* dest is unlocked */
5382 dest_name
= MACH_PORT_DEAD
;
5385 mach_msg_type_name_t voucher_type
;
5386 voucher_type
= MACH_MSGH_BITS_VOUCHER(kmsg
->ikm_header
->msgh_bits
);
5387 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
5388 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
5389 assert(IP_VALID(kmsg
->ikm_voucher
));
5391 * someone managed to send this kernel routine a message with
5392 * a voucher in it. Cleanup the reference in
5393 * kmsg->ikm_voucher.
5395 ipc_port_release_send(kmsg
->ikm_voucher
);
5396 kmsg
->ikm_voucher
= IP_NULL
;
5397 kmsg
->ikm_header
->msgh_voucher_port
= 0;
5400 kmsg
->ikm_header
->msgh_bits
=
5401 (MACH_MSGH_BITS_OTHER(kmsg
->ikm_header
->msgh_bits
) |
5402 MACH_MSGH_BITS(reply_type
, dest_type
));
5403 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
5404 kmsg
->ikm_header
->msgh_remote_port
= reply
;
5406 mach_msg_descriptor_t
*saddr
;
5407 mach_msg_legacy_descriptor_t
*daddr
;
5408 mach_msg_type_number_t i
, count
= ((mach_msg_base_t
*)kmsg
->ikm_header
)->body
.msgh_descriptor_count
;
5409 saddr
= (mach_msg_descriptor_t
*) (((mach_msg_base_t
*)kmsg
->ikm_header
) + 1);
5410 saddr
= &saddr
[count
- 1];
5411 daddr
= (mach_msg_legacy_descriptor_t
*)&saddr
[count
];
5414 vm_offset_t dsc_adjust
= 0;
5416 for (i
= 0; i
< count
; i
++, saddr
--, daddr
--) {
5417 switch (saddr
->type
.type
) {
5418 case MACH_MSG_PORT_DESCRIPTOR
: {
5419 mach_msg_port_descriptor_t
*dsc
= &saddr
->port
;
5420 mach_msg_legacy_port_descriptor_t
*dest_dsc
= &daddr
->port
;
5422 mach_port_t name
= dsc
->name
;
5423 mach_msg_type_name_t disposition
= dsc
->disposition
;
5425 dest_dsc
->name
= CAST_MACH_PORT_TO_NAME(name
);
5426 dest_dsc
->disposition
= disposition
;
5427 dest_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
5430 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
5431 case MACH_MSG_OOL_DESCRIPTOR
: {
5432 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
5433 * so we don't need to do anything special. */
5435 mach_msg_ool_descriptor_t
*source_dsc
= (typeof(source_dsc
)) & saddr
->out_of_line
;
5437 mach_msg_ool_descriptor32_t
*dest_dsc
= &daddr
->out_of_line32
;
5439 vm_offset_t address
= (vm_offset_t
)source_dsc
->address
;
5440 vm_size_t size
= source_dsc
->size
;
5441 boolean_t deallocate
= source_dsc
->deallocate
;
5442 mach_msg_copy_options_t copy
= source_dsc
->copy
;
5443 mach_msg_descriptor_type_t type
= source_dsc
->type
;
5445 dest_dsc
->address
= address
;
5446 dest_dsc
->size
= size
;
5447 dest_dsc
->deallocate
= deallocate
;
5448 dest_dsc
->copy
= copy
;
5449 dest_dsc
->type
= type
;
5452 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
5453 mach_msg_ool_ports_descriptor_t
*source_dsc
= (typeof(source_dsc
)) & saddr
->ool_ports
;
5455 mach_msg_ool_ports_descriptor32_t
*dest_dsc
= &daddr
->ool_ports32
;
5457 vm_offset_t address
= (vm_offset_t
)source_dsc
->address
;
5458 vm_size_t port_count
= source_dsc
->count
;
5459 boolean_t deallocate
= source_dsc
->deallocate
;
5460 mach_msg_copy_options_t copy
= source_dsc
->copy
;
5461 mach_msg_descriptor_type_t type
= source_dsc
->type
;
5463 dest_dsc
->address
= address
;
5464 dest_dsc
->count
= port_count
;
5465 dest_dsc
->deallocate
= deallocate
;
5466 dest_dsc
->copy
= copy
;
5467 dest_dsc
->type
= type
;
5470 case MACH_MSG_GUARDED_PORT_DESCRIPTOR
: {
5471 mach_msg_guarded_port_descriptor_t
*source_dsc
= (typeof(source_dsc
)) & saddr
->guarded_port
;
5472 mach_msg_guarded_port_descriptor32_t
*dest_dsc
= &daddr
->guarded_port32
;
5474 dest_dsc
->name
= CAST_MACH_PORT_TO_NAME(source_dsc
->name
);
5475 dest_dsc
->disposition
= source_dsc
->disposition
;
5476 dest_dsc
->flags
= 0;
5477 dest_dsc
->type
= MACH_MSG_GUARDED_PORT_DESCRIPTOR
;
5478 dest_dsc
->context
= 0;
5483 panic("ipc_kmsg_copyout_to_kernel_legacy: bad descriptor");
5484 #endif /* MACH_ASSERT */
5490 dsc_adjust
= 4 * count
;
5491 memmove((char *)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
5492 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
);
5493 /* Update the message size for the smaller user representation */
5494 kmsg
->ikm_header
->msgh_size
-= dsc_adjust
;
5497 #endif /* IKM_SUPPORT_LEGACY */
5501 * Just sets those parts of the trailer that aren't set up at allocation time.
5504 ipc_kmsg_munge_trailer(mach_msg_max_trailer_t
*in
, void *_out
, boolean_t is64bit
)
5507 mach_msg_max_trailer64_t
*out
= (mach_msg_max_trailer64_t
*)_out
;
5508 out
->msgh_seqno
= in
->msgh_seqno
;
5509 out
->msgh_context
= in
->msgh_context
;
5510 out
->msgh_trailer_size
= in
->msgh_trailer_size
;
5511 out
->msgh_ad
= in
->msgh_ad
;
5513 mach_msg_max_trailer32_t
*out
= (mach_msg_max_trailer32_t
*)_out
;
5514 out
->msgh_seqno
= in
->msgh_seqno
;
5515 out
->msgh_context
= (mach_port_context32_t
)in
->msgh_context
;
5516 out
->msgh_trailer_size
= in
->msgh_trailer_size
;
5517 out
->msgh_ad
= in
->msgh_ad
;
5520 #endif /* __arm64__ */
5522 mach_msg_trailer_size_t
5523 ipc_kmsg_add_trailer(ipc_kmsg_t kmsg
, ipc_space_t space __unused
,
5524 mach_msg_option_t option
, thread_t thread
,
5525 mach_port_seqno_t seqno
, boolean_t minimal_trailer
,
5526 mach_vm_offset_t context
)
5528 mach_msg_max_trailer_t
*trailer
;
5531 mach_msg_max_trailer_t tmp_trailer
; /* This accommodates U64, and we'll munge */
5532 void *real_trailer_out
= (void*)(mach_msg_max_trailer_t
*)
5533 ((vm_offset_t
)kmsg
->ikm_header
+
5534 round_msg(kmsg
->ikm_header
->msgh_size
));
5537 * Populate scratch with initial values set up at message allocation time.
5538 * After, we reinterpret the space in the message as the right type
5539 * of trailer for the address space in question.
5541 bcopy(real_trailer_out
, &tmp_trailer
, MAX_TRAILER_SIZE
);
5542 trailer
= &tmp_trailer
;
5543 #else /* __arm64__ */
5545 trailer
= (mach_msg_max_trailer_t
*)
5546 ((vm_offset_t
)kmsg
->ikm_header
+
5547 round_msg(kmsg
->ikm_header
->msgh_size
));
5548 #endif /* __arm64__ */
5550 if (!(option
& MACH_RCV_TRAILER_MASK
)) {
5551 return trailer
->msgh_trailer_size
;
5554 trailer
->msgh_seqno
= seqno
;
5555 trailer
->msgh_context
= context
;
5556 trailer
->msgh_trailer_size
= REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread
), option
);
5558 if (minimal_trailer
) {
5562 if (GET_RCV_ELEMENTS(option
) >= MACH_RCV_TRAILER_AV
) {
5563 trailer
->msgh_ad
= 0;
5567 * The ipc_kmsg_t holds a reference to the label of a label
5568 * handle, not the port. We must get a reference to the port
5569 * and a send right to copyout to the receiver.
5572 if (option
& MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_LABELS
)) {
5573 trailer
->msgh_labels
.sender
= 0;
5578 ipc_kmsg_munge_trailer(trailer
, real_trailer_out
, thread_is_64bit_addr(thread
));
5579 #endif /* __arm64__ */
5581 return trailer
->msgh_trailer_size
;
5585 ipc_kmsg_msg_header(ipc_kmsg_t kmsg
)
5590 return kmsg
->ikm_header
;