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 <machine/machlimits.h>
99 #include <vm/vm_map.h>
100 #include <vm/vm_object.h>
101 #include <vm/vm_kern.h>
103 #include <ipc/port.h>
104 #include <ipc/ipc_types.h>
105 #include <ipc/ipc_entry.h>
106 #include <ipc/ipc_kmsg.h>
107 #include <ipc/ipc_notify.h>
108 #include <ipc/ipc_object.h>
109 #include <ipc/ipc_space.h>
110 #include <ipc/ipc_port.h>
111 #include <ipc/ipc_right.h>
112 #include <ipc/ipc_hash.h>
113 #include <ipc/ipc_table.h>
114 #include <ipc/ipc_importance.h>
116 #include <kern/mach_node.h>
117 #include <ipc/flipc.h>
120 #include <os/overflow.h>
122 #include <security/mac_mach_internal.h>
124 #include <device/device_server.h>
129 #include <ppc/Firmware.h>
130 #include <ppc/low_trace.h>
134 #define DEBUG_MSGS_K64 1
137 #include <sys/kdebug.h>
138 #include <libkern/OSAtomic.h>
144 mach_msg_bits_t msgh_bits
;
145 mach_msg_size_t msgh_size
;
146 mach_port_name_t msgh_remote_port
;
147 mach_port_name_t msgh_local_port
;
148 mach_port_name_t msgh_voucher_port
;
149 mach_msg_id_t msgh_id
;
150 } mach_msg_legacy_header_t
;
154 mach_msg_legacy_header_t header
;
155 mach_msg_body_t body
;
156 } mach_msg_legacy_base_t
;
160 mach_port_name_t name
;
161 mach_msg_size_t pad1
;
163 mach_msg_type_name_t disposition
: 8;
164 mach_msg_descriptor_type_t type
: 8;
165 } mach_msg_legacy_port_descriptor_t
;
170 mach_msg_legacy_port_descriptor_t port
;
171 mach_msg_ool_descriptor32_t out_of_line32
;
172 mach_msg_ool_ports_descriptor32_t ool_ports32
;
173 mach_msg_type_descriptor_t type
;
174 } mach_msg_legacy_descriptor_t
;
178 #define LEGACY_HEADER_SIZE_DELTA ((mach_msg_size_t)(sizeof(mach_msg_header_t) - sizeof(mach_msg_legacy_header_t)))
184 extern void ipc_pset_print64(
187 extern void ipc_kmsg_print64(
191 extern void ipc_msg_print64(
192 mach_msg_header_t
*msgh
);
194 extern ipc_port_t
ipc_name_to_data64(
196 mach_port_name_t name
);
199 * Forward declarations
201 void ipc_msg_print_untyped64(
202 mach_msg_body_t
*body
);
204 const char * ipc_type_name64(
208 void ipc_print_type_name64(
213 mach_msg_bits_t bit
);
216 mm_copy_options_string64(
217 mach_msg_copy_options_t option
);
219 void db_print_msg_uid64(mach_msg_header_t
*);
222 ipc_msg_body_print64(void *body
, int size
)
224 uint32_t *word
= (uint32_t *) body
;
225 uint32_t *end
= (uint32_t *)(((uintptr_t) body
) + size
226 - sizeof(mach_msg_header_t
));
229 kprintf(" body(%p-%p):\n %p: ", body
, end
, word
);
231 for (i
= 0; i
< 8; i
++, word
++) {
236 kprintf("%08x ", *word
);
238 kprintf("\n %p: ", word
);
249 case MACH_MSG_TYPE_PORT_NAME
:
252 case MACH_MSG_TYPE_MOVE_RECEIVE
:
254 return "port_receive";
256 return "move_receive";
259 case MACH_MSG_TYPE_MOVE_SEND
:
266 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
268 return "port_send_once";
270 return "move_send_once";
273 case MACH_MSG_TYPE_COPY_SEND
:
276 case MACH_MSG_TYPE_MAKE_SEND
:
279 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
280 return "make_send_once";
288 ipc_print_type_name64(
291 const char *name
= ipc_type_name64(type_name
, TRUE
);
295 kprintf("type%d", type_name
);
300 * ipc_kmsg_print64 [ debug ]
307 kprintf("%s kmsg=%p:\n", str
, kmsg
);
308 kprintf(" next=%p, prev=%p, size=%d",
313 ipc_msg_print64(kmsg
->ikm_header
);
321 case MACH_MSGH_BITS_COMPLEX
: return "complex";
322 case MACH_MSGH_BITS_CIRCULAR
: return "circular";
323 default: return (char *) 0;
328 * ipc_msg_print64 [ debug ]
332 mach_msg_header_t
*msgh
)
334 mach_msg_bits_t mbits
;
336 const char *bit_name
;
339 mbits
= msgh
->msgh_bits
;
340 kprintf(" msgh_bits=0x%x: l=0x%x,r=0x%x\n",
342 MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
),
343 MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
345 mbits
= MACH_MSGH_BITS_OTHER(mbits
) & MACH_MSGH_BITS_USED
;
346 kprintf(" decoded bits: ");
348 for (i
= 0, bit
= 1; i
< sizeof(mbits
) * 8; ++i
, bit
<<= 1) {
349 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
);
358 if (msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
) {
359 kprintf("%sunused=0x%x,", needs_comma
? "," : "",
360 msgh
->msgh_bits
& ~MACH_MSGH_BITS_USED
);
365 if (msgh
->msgh_remote_port
) {
366 kprintf(" remote=%p(", msgh
->msgh_remote_port
);
367 ipc_print_type_name64(MACH_MSGH_BITS_REMOTE(msgh
->msgh_bits
));
370 kprintf(" remote=null");
373 if (msgh
->msgh_local_port
) {
374 kprintf("%slocal=%p(", needs_comma
? "," : "",
375 msgh
->msgh_local_port
);
376 ipc_print_type_name64(MACH_MSGH_BITS_LOCAL(msgh
->msgh_bits
));
379 kprintf("local=null\n");
382 kprintf(" msgh_id=%d, size=%d\n",
386 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
387 ipc_msg_print_untyped64((mach_msg_body_t
*) (msgh
+ 1));
390 ipc_msg_body_print64((void *)(msgh
+ 1), msgh
->msgh_size
);
395 mm_copy_options_string64(
396 mach_msg_copy_options_t option
)
401 case MACH_MSG_PHYSICAL_COPY
:
404 case MACH_MSG_VIRTUAL_COPY
:
407 case MACH_MSG_OVERWRITE
:
408 name
= "OVERWRITE(DEPRECATED)";
410 case MACH_MSG_ALLOCATE
:
413 case MACH_MSG_KALLOC_COPY_T
:
414 name
= "KALLOC_COPY_T";
424 ipc_msg_print_untyped64(
425 mach_msg_body_t
*body
)
427 mach_msg_descriptor_t
*saddr
, *send
;
428 mach_msg_descriptor_type_t type
;
430 kprintf(" %d descriptors: \n", body
->msgh_descriptor_count
);
432 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
433 send
= saddr
+ body
->msgh_descriptor_count
;
435 for ( ; saddr
< send
; saddr
++ ) {
437 type
= saddr
->type
.type
;
441 case MACH_MSG_PORT_DESCRIPTOR
: {
442 mach_msg_port_descriptor_t
*dsc
;
445 kprintf(" PORT name = %p disp = ", dsc
->name
);
446 ipc_print_type_name64(dsc
->disposition
);
450 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
451 case MACH_MSG_OOL_DESCRIPTOR
: {
452 mach_msg_ool_descriptor_t
*dsc
;
454 dsc
= (mach_msg_ool_descriptor_t
*) &saddr
->out_of_line
;
455 kprintf(" OOL%s addr = %p size = 0x%x copy = %s %s\n",
456 type
== MACH_MSG_OOL_DESCRIPTOR
? "" : " VOLATILE",
457 dsc
->address
, dsc
->size
,
458 mm_copy_options_string64(dsc
->copy
),
459 dsc
->deallocate
? "DEALLOC" : "");
462 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
463 mach_msg_ool_ports_descriptor_t
*dsc
;
465 dsc
= (mach_msg_ool_ports_descriptor_t
*) &saddr
->ool_ports
;
467 kprintf(" OOL_PORTS addr = %p count = 0x%x ",
468 dsc
->address
, dsc
->count
);
470 ipc_print_type_name64(dsc
->disposition
);
471 kprintf(" copy = %s %s\n",
472 mm_copy_options_string64(dsc
->copy
),
473 dsc
->deallocate
? "DEALLOC" : "");
478 kprintf(" UNKNOWN DESCRIPTOR 0x%x\n", type
);
485 #define DEBUG_IPC_KMSG_PRINT(kmsg,string) \
486 __unreachable_ok_push \
487 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
488 ipc_kmsg_print64(kmsg, string); \
492 #define DEBUG_IPC_MSG_BODY_PRINT(body,size) \
493 __unreachable_ok_push \
494 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
495 ipc_msg_body_print64(body,size);\
498 #else /* !DEBUG_MSGS_K64 */
499 #define DEBUG_IPC_KMSG_PRINT(kmsg,string)
500 #define DEBUG_IPC_MSG_BODY_PRINT(body,size)
501 #endif /* !DEBUG_MSGS_K64 */
503 extern vm_map_t ipc_kernel_copy_map
;
504 extern vm_size_t ipc_kmsg_max_space
;
505 extern vm_size_t ipc_kmsg_max_vm_space
;
506 extern vm_size_t ipc_kmsg_max_body_space
;
507 extern vm_size_t msg_ool_size_small
;
509 #define MSG_OOL_SIZE_SMALL msg_ool_size_small
511 #if defined(__LP64__)
512 #define MAP_SIZE_DIFFERS(map) (map->max_offset < MACH_VM_MAX_ADDRESS)
513 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor32_t
514 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor32_t
516 #define MAP_SIZE_DIFFERS(map) (map->max_offset > VM_MAX_ADDRESS)
517 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor64_t
518 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor64_t
521 #define DESC_SIZE_ADJUSTMENT ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
522 sizeof(mach_msg_ool_descriptor32_t)))
524 /* scatter list macros */
526 #define SKIP_PORT_DESCRIPTORS(s, c) \
528 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
530 if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
535 (s) = MACH_MSG_DESCRIPTOR_NULL; \
539 #define INCREMENT_SCATTER(s, c, d) \
541 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
542 s = (d) ? (mach_msg_descriptor_t *) \
543 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) : \
549 #define KMSG_TRACE_FLAG_TRACED 0x000001
550 #define KMSG_TRACE_FLAG_COMPLEX 0x000002
551 #define KMSG_TRACE_FLAG_OOLMEM 0x000004
552 #define KMSG_TRACE_FLAG_VCPY 0x000008
553 #define KMSG_TRACE_FLAG_PCPY 0x000010
554 #define KMSG_TRACE_FLAG_SND64 0x000020
555 #define KMSG_TRACE_FLAG_RAISEIMP 0x000040
556 #define KMSG_TRACE_FLAG_APP_SRC 0x000080
557 #define KMSG_TRACE_FLAG_APP_DST 0x000100
558 #define KMSG_TRACE_FLAG_DAEMON_SRC 0x000200
559 #define KMSG_TRACE_FLAG_DAEMON_DST 0x000400
560 #define KMSG_TRACE_FLAG_DST_NDFLTQ 0x000800
561 #define KMSG_TRACE_FLAG_SRC_NDFLTQ 0x001000
562 #define KMSG_TRACE_FLAG_DST_SONCE 0x002000
563 #define KMSG_TRACE_FLAG_SRC_SONCE 0x004000
564 #define KMSG_TRACE_FLAG_CHECKIN 0x008000
565 #define KMSG_TRACE_FLAG_ONEWAY 0x010000
566 #define KMSG_TRACE_FLAG_IOKIT 0x020000
567 #define KMSG_TRACE_FLAG_SNDRCV 0x040000
568 #define KMSG_TRACE_FLAG_DSTQFULL 0x080000
569 #define KMSG_TRACE_FLAG_VOUCHER 0x100000
570 #define KMSG_TRACE_FLAG_TIMER 0x200000
571 #define KMSG_TRACE_FLAG_SEMA 0x400000
572 #define KMSG_TRACE_FLAG_DTMPOWNER 0x800000
574 #define KMSG_TRACE_FLAGS_MASK 0xffffff
575 #define KMSG_TRACE_FLAGS_SHIFT 8
577 #define KMSG_TRACE_PORTS_MASK 0xff
578 #define KMSG_TRACE_PORTS_SHIFT 0
580 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
582 extern boolean_t
kdebug_debugid_enabled(uint32_t debugid
);
584 void ipc_kmsg_trace_send(ipc_kmsg_t kmsg
,
585 mach_msg_option_t option
)
587 task_t send_task
= TASK_NULL
;
588 ipc_port_t dst_port
, src_port
;
589 boolean_t is_task_64bit
;
590 mach_msg_header_t
*msg
;
591 mach_msg_trailer_t
*trailer
;
594 uint32_t msg_size
= 0;
595 uint32_t msg_flags
= KMSG_TRACE_FLAG_TRACED
;
596 uint32_t num_ports
= 0;
597 uint32_t send_pid
, dst_pid
;
600 * check to see not only if ktracing is enabled, but if we will
601 * _actually_ emit the KMSG_INFO tracepoint. This saves us a
602 * significant amount of processing (and a port lock hold) in
603 * the non-tracing case.
605 if (__probable((kdebug_enable
& KDEBUG_TRACE
) == 0))
607 if (!kdebug_debugid_enabled(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_INFO
)))
610 msg
= kmsg
->ikm_header
;
612 dst_port
= (ipc_port_t
)(msg
->msgh_remote_port
);
613 if (!IPC_PORT_VALID(dst_port
))
617 * Message properties / options
619 if ((option
& (MACH_SEND_MSG
|MACH_RCV_MSG
)) == (MACH_SEND_MSG
|MACH_RCV_MSG
))
620 msg_flags
|= KMSG_TRACE_FLAG_SNDRCV
;
622 if (msg
->msgh_id
>= is_iokit_subsystem
.start
&&
623 msg
->msgh_id
< is_iokit_subsystem
.end
+ 100)
624 msg_flags
|= KMSG_TRACE_FLAG_IOKIT
;
625 /* magic XPC checkin message id (XPC_MESSAGE_ID_CHECKIN) from libxpc */
626 else if (msg
->msgh_id
== 0x77303074u
/* w00t */)
627 msg_flags
|= KMSG_TRACE_FLAG_CHECKIN
;
629 if (msg
->msgh_bits
& MACH_MSGH_BITS_RAISEIMP
)
630 msg_flags
|= KMSG_TRACE_FLAG_RAISEIMP
;
632 if (unsafe_convert_port_to_voucher(kmsg
->ikm_voucher
))
633 msg_flags
|= KMSG_TRACE_FLAG_VOUCHER
;
636 * Sending task / port
638 send_task
= current_task();
639 send_pid
= task_pid(send_task
);
642 if (task_is_daemon(send_task
))
643 msg_flags
|= KMSG_TRACE_FLAG_DAEMON_SRC
;
644 else if (task_is_app(send_task
))
645 msg_flags
|= KMSG_TRACE_FLAG_APP_SRC
;
648 is_task_64bit
= (send_task
->map
->max_offset
> VM_MAX_ADDRESS
);
650 msg_flags
|= KMSG_TRACE_FLAG_SND64
;
652 src_port
= (ipc_port_t
)(msg
->msgh_local_port
);
654 if (src_port
->ip_messages
.imq_qlimit
!= MACH_PORT_QLIMIT_DEFAULT
)
655 msg_flags
|= KMSG_TRACE_FLAG_SRC_NDFLTQ
;
656 switch (MACH_MSGH_BITS_LOCAL(msg
->msgh_bits
)) {
657 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
658 msg_flags
|= KMSG_TRACE_FLAG_SRC_SONCE
;
664 msg_flags
|= KMSG_TRACE_FLAG_ONEWAY
;
669 * Destination task / port
672 if (!ip_active(dst_port
)) {
673 /* dst port is being torn down */
674 dst_pid
= (uint32_t)0xfffffff0;
675 } else if (dst_port
->ip_tempowner
) {
676 msg_flags
|= KMSG_TRACE_FLAG_DTMPOWNER
;
677 if (IIT_NULL
!= dst_port
->ip_imp_task
)
678 dst_pid
= task_pid(dst_port
->ip_imp_task
->iit_task
);
680 dst_pid
= (uint32_t)0xfffffff1;
681 } else if (dst_port
->ip_receiver_name
== MACH_PORT_NULL
) {
682 /* dst_port is otherwise in-transit */
683 dst_pid
= (uint32_t)0xfffffff2;
685 if (dst_port
->ip_receiver
== ipc_space_kernel
) {
688 ipc_space_t dst_space
;
689 dst_space
= dst_port
->ip_receiver
;
690 if (dst_space
&& is_active(dst_space
)) {
691 dst_pid
= task_pid(dst_space
->is_task
);
692 if (task_is_daemon(dst_space
->is_task
))
693 msg_flags
|= KMSG_TRACE_FLAG_DAEMON_DST
;
694 else if (task_is_app(dst_space
->is_task
))
695 msg_flags
|= KMSG_TRACE_FLAG_APP_DST
;
697 /* receiving task is being torn down */
698 dst_pid
= (uint32_t)0xfffffff3;
703 if (dst_port
->ip_messages
.imq_qlimit
!= MACH_PORT_QLIMIT_DEFAULT
)
704 msg_flags
|= KMSG_TRACE_FLAG_DST_NDFLTQ
;
705 if (imq_full(&dst_port
->ip_messages
))
706 msg_flags
|= KMSG_TRACE_FLAG_DSTQFULL
;
708 kotype
= ip_kotype(dst_port
);
714 msg_flags
|= KMSG_TRACE_FLAG_SEMA
;
718 msg_flags
|= KMSG_TRACE_FLAG_TIMER
;
720 case IKOT_MASTER_DEVICE
:
721 case IKOT_IOKIT_CONNECT
:
722 case IKOT_IOKIT_OBJECT
:
723 case IKOT_IOKIT_SPARE
:
724 msg_flags
|= KMSG_TRACE_FLAG_IOKIT
;
730 switch(MACH_MSGH_BITS_REMOTE(msg
->msgh_bits
)) {
731 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
732 msg_flags
|= KMSG_TRACE_FLAG_DST_SONCE
;
740 * Message size / content
742 msg_size
= msg
->msgh_size
- sizeof(mach_msg_header_t
);
744 if (msg
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
745 mach_msg_body_t
*msg_body
;
746 mach_msg_descriptor_t
*kern_dsc
;
749 msg_flags
|= KMSG_TRACE_FLAG_COMPLEX
;
751 msg_body
= (mach_msg_body_t
*)(kmsg
->ikm_header
+ 1);
752 dsc_count
= (int)msg_body
->msgh_descriptor_count
;
753 kern_dsc
= (mach_msg_descriptor_t
*)(msg_body
+ 1);
755 /* this is gross: see ipc_kmsg_copyin_body()... */
757 msg_size
-= (dsc_count
* 12);
759 for (int i
= 0; i
< dsc_count
; i
++) {
760 switch (kern_dsc
[i
].type
.type
) {
761 case MACH_MSG_PORT_DESCRIPTOR
:
766 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
767 case MACH_MSG_OOL_DESCRIPTOR
: {
768 mach_msg_ool_descriptor_t
*dsc
;
769 dsc
= (mach_msg_ool_descriptor_t
*)&kern_dsc
[i
];
770 msg_flags
|= KMSG_TRACE_FLAG_OOLMEM
;
771 msg_size
+= dsc
->size
;
772 if ((dsc
->size
>= MSG_OOL_SIZE_SMALL
) &&
773 (dsc
->copy
== MACH_MSG_PHYSICAL_COPY
) &&
775 msg_flags
|= KMSG_TRACE_FLAG_PCPY
;
776 else if (dsc
->size
<= MSG_OOL_SIZE_SMALL
)
777 msg_flags
|= KMSG_TRACE_FLAG_PCPY
;
779 msg_flags
|= KMSG_TRACE_FLAG_VCPY
;
783 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
784 mach_msg_ool_ports_descriptor_t
*dsc
;
785 dsc
= (mach_msg_ool_ports_descriptor_t
*)&kern_dsc
[i
];
786 num_ports
+= dsc
->count
;
799 trailer
= (mach_msg_trailer_t
*)((vm_offset_t
)msg
+
800 (vm_offset_t
)msg
->msgh_size
);
801 if (trailer
->msgh_trailer_size
<= sizeof(mach_msg_security_trailer_t
)) {
802 extern security_token_t KERNEL_SECURITY_TOKEN
;
803 mach_msg_security_trailer_t
*strailer
;
804 strailer
= (mach_msg_security_trailer_t
*)trailer
;
806 * verify the sender PID: replies from the kernel often look
807 * like self-talk because the sending port is not reset.
809 if (memcmp(&strailer
->msgh_sender
,
810 &KERNEL_SECURITY_TOKEN
,
811 sizeof(KERNEL_SECURITY_TOKEN
)) == 0) {
813 msg_flags
&= ~(KMSG_TRACE_FLAG_APP_SRC
| KMSG_TRACE_FLAG_DAEMON_SRC
);
817 KDBG(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
,
822 ((msg_flags
& KMSG_TRACE_FLAGS_MASK
) << KMSG_TRACE_FLAGS_SHIFT
) |
823 ((num_ports
& KMSG_TRACE_PORTS_MASK
) << KMSG_TRACE_PORTS_SHIFT
)
829 /* zone for cached ipc_kmsg_t structures */
830 zone_t ipc_kmsg_zone
;
833 * Forward declarations
839 void ipc_kmsg_clean_body(
841 mach_msg_type_number_t number
,
842 mach_msg_descriptor_t
*desc
);
844 void ipc_kmsg_clean_partial(
846 mach_msg_type_number_t number
,
847 mach_msg_descriptor_t
*desc
,
851 mach_msg_return_t
ipc_kmsg_copyin_body(
856 extern int thread_qos_from_pthread_priority(unsigned long, unsigned long *);
859 * We keep a per-processor cache of kernel message buffers.
860 * The cache saves the overhead/locking of using kalloc/kfree.
861 * The per-processor cache seems to miss less than a per-thread cache,
862 * and it also uses less memory. Access to the cache doesn't
867 * Routine: ipc_kmsg_alloc
869 * Allocate a kernel message structure. If we can get one from
870 * the cache, that is best. Otherwise, allocate a new one.
876 mach_msg_size_t msg_and_trailer_size
)
878 mach_msg_size_t max_expanded_size
;
883 * Pad the allocation in case we need to expand the
884 * message descrptors for user spaces with pointers larger than
885 * the kernel's own, or vice versa. We don't know how many descriptors
886 * there are yet, so just assume the whole body could be
887 * descriptors (if there could be any at all).
889 * The expansion space is left in front of the header,
890 * because it is easier to pull the header and descriptors
891 * forward as we process them than it is to push all the
894 mach_msg_size_t size
= msg_and_trailer_size
- MAX_TRAILER_SIZE
;
896 /* compare against implementation upper limit for the body */
897 if (size
> ipc_kmsg_max_body_space
)
900 if (size
> sizeof(mach_msg_base_t
)) {
901 mach_msg_size_t max_desc
= (mach_msg_size_t
)(((size
- sizeof(mach_msg_base_t
)) /
902 sizeof(mach_msg_ool_descriptor32_t
)) *
903 DESC_SIZE_ADJUSTMENT
);
905 /* make sure expansion won't cause wrap */
906 if (msg_and_trailer_size
> MACH_MSG_SIZE_MAX
- max_desc
)
909 max_expanded_size
= msg_and_trailer_size
+ max_desc
;
911 max_expanded_size
= msg_and_trailer_size
;
913 if (max_expanded_size
< IKM_SAVED_MSG_SIZE
)
914 max_expanded_size
= IKM_SAVED_MSG_SIZE
; /* round up for ikm_cache */
916 if (max_expanded_size
== IKM_SAVED_MSG_SIZE
) {
917 struct ikm_cache
*cache
;
920 disable_preemption();
921 cache
= &PROCESSOR_DATA(current_processor(), ikm_cache
);
922 if ((i
= cache
->avail
) > 0) {
923 assert(i
<= IKM_STASH
);
924 kmsg
= cache
->entries
[--i
];
927 ikm_check_init(kmsg
, max_expanded_size
);
928 ikm_set_header(kmsg
, msg_and_trailer_size
);
932 kmsg
= (ipc_kmsg_t
)zalloc(ipc_kmsg_zone
);
934 kmsg
= (ipc_kmsg_t
)kalloc(ikm_plus_overhead(max_expanded_size
));
937 if (kmsg
!= IKM_NULL
) {
938 ikm_init(kmsg
, max_expanded_size
);
939 ikm_set_header(kmsg
, msg_and_trailer_size
);
946 * Routine: ipc_kmsg_free
948 * Free a kernel message buffer. If the kms is preallocated
949 * to a port, just "put it back (marked unused)." We have to
950 * do this with the port locked. The port may have its hold
951 * on our message released. In that case, we have to just
952 * revert the message to a traditional one and free it normally.
961 mach_msg_size_t size
= kmsg
->ikm_size
;
964 assert(!IP_VALID(kmsg
->ikm_voucher
));
966 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_FREE
) | DBG_FUNC_NONE
,
967 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
971 * Check to see if the message is bound to the port. If so,
972 * mark it not in use. If the port isn't already dead, then
973 * leave the message associated with it. Otherwise, free it.
975 port
= ikm_prealloc_inuse_port(kmsg
);
976 if (port
!= IP_NULL
) {
978 ikm_prealloc_clear_inuse(kmsg
, port
);
979 if (ip_active(port
) && (port
->ip_premsg
== kmsg
)) {
980 assert(IP_PREALLOC(port
));
986 ip_release(port
); /* May be last reference */
990 * Peek and see if it has to go back in the cache.
992 if (kmsg
->ikm_size
== IKM_SAVED_MSG_SIZE
) {
993 struct ikm_cache
*cache
;
996 disable_preemption();
997 cache
= &PROCESSOR_DATA(current_processor(), ikm_cache
);
998 if ((i
= cache
->avail
) < IKM_STASH
) {
999 cache
->entries
[i
] = kmsg
;
1000 cache
->avail
= i
+ 1;
1001 enable_preemption();
1004 enable_preemption();
1005 zfree(ipc_kmsg_zone
, kmsg
);
1008 kfree(kmsg
, ikm_plus_overhead(size
));
1013 * Routine: ipc_kmsg_enqueue
1020 ipc_kmsg_queue_t queue
,
1023 ipc_kmsg_t first
= queue
->ikmq_base
;
1026 if (first
== IKM_NULL
) {
1027 queue
->ikmq_base
= kmsg
;
1028 kmsg
->ikm_next
= kmsg
;
1029 kmsg
->ikm_prev
= kmsg
;
1031 last
= first
->ikm_prev
;
1032 kmsg
->ikm_next
= first
;
1033 kmsg
->ikm_prev
= last
;
1034 first
->ikm_prev
= kmsg
;
1035 last
->ikm_next
= kmsg
;
1040 * Routine: ipc_kmsg_enqueue_qos
1042 * Enqueue a kmsg, propagating qos
1043 * overrides towards the head of the queue.
1046 * whether the head of the queue had
1047 * it's override-qos adjusted because
1048 * of this insertion.
1052 ipc_kmsg_enqueue_qos(
1053 ipc_kmsg_queue_t queue
,
1056 ipc_kmsg_t first
= queue
->ikmq_base
;
1058 mach_msg_priority_t override
;
1060 if (first
== IKM_NULL
) {
1061 /* insert a first message */
1062 queue
->ikmq_base
= kmsg
;
1063 kmsg
->ikm_next
= kmsg
;
1064 kmsg
->ikm_prev
= kmsg
;
1068 /* insert at the tail */
1069 prev
= first
->ikm_prev
;
1070 kmsg
->ikm_next
= first
;
1071 kmsg
->ikm_prev
= prev
;
1072 first
->ikm_prev
= kmsg
;
1073 prev
->ikm_next
= kmsg
;
1075 /* apply QoS overrides towards the head */
1076 override
= kmsg
->ikm_qos_override
;
1077 while (prev
!= kmsg
&&
1078 override
> prev
->ikm_qos_override
) {
1079 prev
->ikm_qos_override
= override
;
1080 prev
= prev
->ikm_prev
;
1083 /* did we adjust everything? */
1084 return (prev
== kmsg
);
1088 * Routine: ipc_kmsg_override_qos
1090 * Update the override for a given kmsg already
1091 * enqueued, propagating qos override adjustments
1092 * towards the head of the queue.
1095 * whether the head of the queue had
1096 * it's override-qos adjusted because
1097 * of this insertion.
1101 ipc_kmsg_override_qos(
1102 ipc_kmsg_queue_t queue
,
1104 mach_msg_priority_t override
)
1106 ipc_kmsg_t first
= queue
->ikmq_base
;
1107 ipc_kmsg_t cur
= kmsg
;
1109 /* apply QoS overrides towards the head */
1110 while (override
> cur
->ikm_qos_override
) {
1111 cur
->ikm_qos_override
= override
;
1114 cur
= cur
->ikm_prev
;
1120 * Routine: ipc_kmsg_dequeue
1122 * Dequeue and return a kmsg.
1127 ipc_kmsg_queue_t queue
)
1131 first
= ipc_kmsg_queue_first(queue
);
1133 if (first
!= IKM_NULL
)
1134 ipc_kmsg_rmqueue(queue
, first
);
1140 * Routine: ipc_kmsg_rmqueue
1142 * Pull a kmsg out of a queue.
1147 ipc_kmsg_queue_t queue
,
1150 ipc_kmsg_t next
, prev
;
1152 assert(queue
->ikmq_base
!= IKM_NULL
);
1154 next
= kmsg
->ikm_next
;
1155 prev
= kmsg
->ikm_prev
;
1158 assert(prev
== kmsg
);
1159 assert(queue
->ikmq_base
== kmsg
);
1161 queue
->ikmq_base
= IKM_NULL
;
1163 if (queue
->ikmq_base
== kmsg
)
1164 queue
->ikmq_base
= next
;
1166 next
->ikm_prev
= prev
;
1167 prev
->ikm_next
= next
;
1169 /* XXX Temporary debug logic */
1170 assert((kmsg
->ikm_next
= IKM_BOGUS
) == IKM_BOGUS
);
1171 assert((kmsg
->ikm_prev
= IKM_BOGUS
) == IKM_BOGUS
);
1175 * Routine: ipc_kmsg_queue_next
1177 * Return the kmsg following the given kmsg.
1178 * (Or IKM_NULL if it is the last one in the queue.)
1182 ipc_kmsg_queue_next(
1183 ipc_kmsg_queue_t queue
,
1188 assert(queue
->ikmq_base
!= IKM_NULL
);
1190 next
= kmsg
->ikm_next
;
1191 if (queue
->ikmq_base
== next
)
1198 * Routine: ipc_kmsg_destroy
1200 * Destroys a kernel message. Releases all rights,
1201 * references, and memory held by the message.
1202 * Frees the message.
1212 * Destroying a message can cause more messages to be destroyed.
1213 * Curtail recursion by putting messages on the deferred
1214 * destruction queue. If this was the first message on the
1215 * queue, this instance must process the full queue.
1217 if (ipc_kmsg_delayed_destroy(kmsg
))
1218 ipc_kmsg_reap_delayed();
1222 * Routine: ipc_kmsg_delayed_destroy
1224 * Enqueues a kernel message for deferred destruction.
1226 * Boolean indicator that the caller is responsible to reap
1227 * deferred messages.
1230 boolean_t
ipc_kmsg_delayed_destroy(
1233 ipc_kmsg_queue_t queue
= &(current_thread()->ith_messages
);
1234 boolean_t first
= ipc_kmsg_queue_empty(queue
);
1236 ipc_kmsg_enqueue(queue
, kmsg
);
1241 * Routine: ipc_kmsg_destroy_queue
1243 * Destroys messages from the per-thread
1244 * deferred reaping queue.
1250 ipc_kmsg_reap_delayed(void)
1252 ipc_kmsg_queue_t queue
= &(current_thread()->ith_messages
);
1256 * must leave kmsg in queue while cleaning it to assure
1257 * no nested calls recurse into here.
1259 while ((kmsg
= ipc_kmsg_queue_first(queue
)) != IKM_NULL
) {
1260 ipc_kmsg_clean(kmsg
);
1261 ipc_kmsg_rmqueue(queue
, kmsg
);
1262 ipc_kmsg_free(kmsg
);
1267 * Routine: ipc_kmsg_clean_body
1269 * Cleans the body of a kernel message.
1270 * Releases all rights, references, and memory.
1275 static unsigned int _ipc_kmsg_clean_invalid_desc
= 0;
1277 ipc_kmsg_clean_body(
1278 __unused ipc_kmsg_t kmsg
,
1279 mach_msg_type_number_t number
,
1280 mach_msg_descriptor_t
*saddr
)
1282 mach_msg_type_number_t i
;
1287 for (i
= 0 ; i
< number
; i
++, saddr
++ ) {
1289 switch (saddr
->type
.type
) {
1291 case MACH_MSG_PORT_DESCRIPTOR
: {
1292 mach_msg_port_descriptor_t
*dsc
;
1297 * Destroy port rights carried in the message
1299 if (!IO_VALID((ipc_object_t
) dsc
->name
))
1301 ipc_object_destroy((ipc_object_t
) dsc
->name
, dsc
->disposition
);
1304 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
1305 case MACH_MSG_OOL_DESCRIPTOR
: {
1306 mach_msg_ool_descriptor_t
*dsc
;
1308 dsc
= (mach_msg_ool_descriptor_t
*)&saddr
->out_of_line
;
1311 * Destroy memory carried in the message
1313 if (dsc
->size
== 0) {
1314 assert(dsc
->address
== (void *) 0);
1316 vm_map_copy_discard((vm_map_copy_t
) dsc
->address
);
1320 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
1321 ipc_object_t
*objects
;
1322 mach_msg_type_number_t j
;
1323 mach_msg_ool_ports_descriptor_t
*dsc
;
1325 dsc
= (mach_msg_ool_ports_descriptor_t
*)&saddr
->ool_ports
;
1326 objects
= (ipc_object_t
*) dsc
->address
;
1328 if (dsc
->count
== 0) {
1332 assert(objects
!= (ipc_object_t
*) 0);
1334 /* destroy port rights carried in the message */
1336 for (j
= 0; j
< dsc
->count
; j
++) {
1337 ipc_object_t object
= objects
[j
];
1339 if (!IO_VALID(object
))
1342 ipc_object_destroy(object
, dsc
->disposition
);
1345 /* destroy memory carried in the message */
1347 assert(dsc
->count
!= 0);
1350 (vm_size_t
) dsc
->count
* sizeof(mach_port_t
));
1354 _ipc_kmsg_clean_invalid_desc
++; /* don't understand this type of descriptor */
1361 * Routine: ipc_kmsg_clean_partial
1363 * Cleans a partially-acquired kernel message.
1364 * number is the index of the type descriptor
1365 * in the body of the message that contained the error.
1366 * If dolast, the memory and port rights in this last
1367 * type spec are also cleaned. In that case, number
1368 * specifies the number of port rights to clean.
1374 ipc_kmsg_clean_partial(
1376 mach_msg_type_number_t number
,
1377 mach_msg_descriptor_t
*desc
,
1381 ipc_object_t object
;
1382 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
1384 /* deal with importance chain while we still have dest and voucher references */
1385 ipc_importance_clean(kmsg
);
1387 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
1388 assert(IO_VALID(object
));
1389 ipc_object_destroy_dest(object
, MACH_MSGH_BITS_REMOTE(mbits
));
1391 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
1392 if (IO_VALID(object
))
1393 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
1395 object
= (ipc_object_t
) kmsg
->ikm_voucher
;
1396 if (IO_VALID(object
)) {
1397 assert(MACH_MSGH_BITS_VOUCHER(mbits
) == MACH_MSG_TYPE_MOVE_SEND
);
1398 ipc_object_destroy(object
, MACH_MSG_TYPE_PORT_SEND
);
1399 kmsg
->ikm_voucher
= IP_NULL
;
1403 (void) vm_deallocate(ipc_kernel_copy_map
, paddr
, length
);
1406 ipc_kmsg_clean_body(kmsg
, number
, desc
);
1410 * Routine: ipc_kmsg_clean
1412 * Cleans a kernel message. Releases all rights,
1413 * references, and memory held by the message.
1422 ipc_object_t object
;
1423 mach_msg_bits_t mbits
;
1425 /* deal with importance chain while we still have dest and voucher references */
1426 ipc_importance_clean(kmsg
);
1428 mbits
= kmsg
->ikm_header
->msgh_bits
;
1429 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
1430 if (IO_VALID(object
))
1431 ipc_object_destroy_dest(object
, MACH_MSGH_BITS_REMOTE(mbits
));
1433 object
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
1434 if (IO_VALID(object
))
1435 ipc_object_destroy(object
, MACH_MSGH_BITS_LOCAL(mbits
));
1437 object
= (ipc_object_t
) kmsg
->ikm_voucher
;
1438 if (IO_VALID(object
)) {
1439 assert(MACH_MSGH_BITS_VOUCHER(mbits
) == MACH_MSG_TYPE_MOVE_SEND
);
1440 ipc_object_destroy(object
, MACH_MSG_TYPE_PORT_SEND
);
1441 kmsg
->ikm_voucher
= IP_NULL
;
1444 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
1445 mach_msg_body_t
*body
;
1447 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
1448 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
1449 (mach_msg_descriptor_t
*)(body
+ 1));
1454 * Routine: ipc_kmsg_set_prealloc
1456 * Assign a kmsg as a preallocated message buffer to a port.
1462 ipc_kmsg_set_prealloc(
1466 assert(kmsg
->ikm_prealloc
== IP_NULL
);
1468 kmsg
->ikm_prealloc
= IP_NULL
;
1469 /* take the mqueue lock since the sync qos is protected under it */
1470 imq_lock(&port
->ip_messages
);
1472 /* copy the sync qos values to kmsg */
1473 for (int i
= 0; i
< THREAD_QOS_LAST
; i
++) {
1474 kmsg
->sync_qos
[i
] = port_sync_qos(port
, i
);
1476 kmsg
->special_port_qos
= port_special_qos(port
);
1477 IP_SET_PREALLOC(port
, kmsg
);
1478 imq_unlock(&port
->ip_messages
);
1482 * Routine: ipc_kmsg_clear_prealloc
1484 * Release the Assignment of a preallocated message buffer from a port.
1489 ipc_kmsg_clear_prealloc(
1493 assert(kmsg
->ikm_prealloc
== port
);
1495 kmsg
->ikm_prealloc
= IP_NULL
;
1497 /* take the mqueue lock since the sync qos is protected under it */
1498 imq_lock(&port
->ip_messages
);
1500 IP_CLEAR_PREALLOC(port
, kmsg
);
1502 /* copy the sync qos values from kmsg to port */
1503 for (int i
= 0; i
< THREAD_QOS_LAST
; i
++) {
1504 set_port_sync_qos(port
, i
, kmsg
->sync_qos
[i
]);
1506 set_port_special_qos(port
, kmsg
->special_port_qos
);
1507 imq_unlock(&port
->ip_messages
);
1511 * Routine: ipc_kmsg_prealloc
1513 * Wraper to ipc_kmsg_alloc() to account for
1514 * header expansion requirements.
1517 ipc_kmsg_prealloc(mach_msg_size_t size
)
1519 #if defined(__LP64__)
1520 if (size
> MACH_MSG_SIZE_MAX
- LEGACY_HEADER_SIZE_DELTA
)
1523 size
+= LEGACY_HEADER_SIZE_DELTA
;
1525 return ipc_kmsg_alloc(size
);
1530 * Routine: ipc_kmsg_get
1532 * Allocates a kernel message buffer.
1533 * Copies a user message to the message buffer.
1537 * MACH_MSG_SUCCESS Acquired a message buffer.
1538 * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
1539 * MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
1540 * MACH_SEND_TOO_LARGE Message too large to ever be sent.
1541 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1542 * MACH_SEND_INVALID_DATA Couldn't copy message data.
1547 mach_vm_address_t msg_addr
,
1548 mach_msg_size_t size
,
1551 mach_msg_size_t msg_and_trailer_size
;
1553 mach_msg_max_trailer_t
*trailer
;
1554 mach_msg_legacy_base_t legacy_base
;
1555 mach_msg_size_t len_copied
;
1556 legacy_base
.body
.msgh_descriptor_count
= 0;
1558 if ((size
< sizeof(mach_msg_legacy_header_t
)) || (size
& 3))
1559 return MACH_SEND_MSG_TOO_SMALL
;
1561 if (size
> ipc_kmsg_max_body_space
)
1562 return MACH_SEND_TOO_LARGE
;
1564 if(size
== sizeof(mach_msg_legacy_header_t
))
1565 len_copied
= sizeof(mach_msg_legacy_header_t
);
1567 len_copied
= sizeof(mach_msg_legacy_base_t
);
1569 if (copyinmsg(msg_addr
, (char *)&legacy_base
, len_copied
))
1570 return MACH_SEND_INVALID_DATA
;
1573 * If the message claims to be complex, it must at least
1574 * have the length of a "base" message (header + dsc_count).
1576 if (len_copied
< sizeof(mach_msg_legacy_base_t
) &&
1577 (legacy_base
.header
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
))
1578 return MACH_SEND_MSG_TOO_SMALL
;
1580 msg_addr
+= sizeof(legacy_base
.header
);
1581 #if defined(__LP64__)
1582 size
+= LEGACY_HEADER_SIZE_DELTA
;
1584 /* unreachable if !DEBUG */
1585 __unreachable_ok_push
1586 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
1588 for (j
=0; j
<sizeof(legacy_base
.header
); j
++) {
1589 kprintf("%02x\n", ((unsigned char*)&legacy_base
.header
)[j
]);
1592 __unreachable_ok_pop
1594 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
1595 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
1596 if (kmsg
== IKM_NULL
)
1597 return MACH_SEND_NO_BUFFER
;
1599 kmsg
->ikm_header
->msgh_size
= size
;
1600 kmsg
->ikm_header
->msgh_bits
= legacy_base
.header
.msgh_bits
;
1601 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(legacy_base
.header
.msgh_remote_port
);
1602 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(legacy_base
.header
.msgh_local_port
);
1603 kmsg
->ikm_header
->msgh_voucher_port
= legacy_base
.header
.msgh_voucher_port
;
1604 kmsg
->ikm_header
->msgh_id
= legacy_base
.header
.msgh_id
;
1606 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
1609 " remote_port: %p\n"
1611 " voucher_port: 0x%.8x\n"
1613 kmsg
->ikm_header
->msgh_size
,
1614 kmsg
->ikm_header
->msgh_bits
,
1615 kmsg
->ikm_header
->msgh_remote_port
,
1616 kmsg
->ikm_header
->msgh_local_port
,
1617 kmsg
->ikm_header
->msgh_voucher_port
,
1618 kmsg
->ikm_header
->msgh_id
);
1620 if (copyinmsg(msg_addr
, (char *)(kmsg
->ikm_header
+ 1), size
- (mach_msg_size_t
)sizeof(mach_msg_header_t
))) {
1621 ipc_kmsg_free(kmsg
);
1622 return MACH_SEND_INVALID_DATA
;
1625 /* unreachable if !DEBUG */
1626 __unreachable_ok_push
1627 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
))
1629 kprintf("body: size: %lu\n", (size
- sizeof(mach_msg_header_t
)));
1631 for(i
=0;i
*4 < (size
- sizeof(mach_msg_header_t
));i
++)
1633 kprintf("%.4x\n",((uint32_t *)(kmsg
->ikm_header
+ 1))[i
]);
1636 __unreachable_ok_pop
1637 DEBUG_IPC_KMSG_PRINT(kmsg
, "ipc_kmsg_get()");
1640 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1641 * However, the internal size field of the trailer (msgh_trailer_size)
1642 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
1643 * the cases where no implicit data is requested.
1645 trailer
= (mach_msg_max_trailer_t
*) ((vm_offset_t
)kmsg
->ikm_header
+ size
);
1646 trailer
->msgh_sender
= current_thread()->task
->sec_token
;
1647 trailer
->msgh_audit
= current_thread()->task
->audit_token
;
1648 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
1649 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
1652 if(trcWork
.traceMask
) dbgTrace(0x1100, (unsigned int)kmsg
->ikm_header
->msgh_id
,
1653 (unsigned int)kmsg
->ikm_header
->msgh_remote_port
,
1654 (unsigned int)kmsg
->ikm_header
->msgh_local_port
, 0);
1657 trailer
->msgh_labels
.sender
= 0;
1659 return MACH_MSG_SUCCESS
;
1663 * Routine: ipc_kmsg_get_from_kernel
1665 * First checks for a preallocated message
1666 * reserved for kernel clients. If not found -
1667 * allocates a new kernel message buffer.
1668 * Copies a kernel message to the message buffer.
1669 * Only resource errors are allowed.
1672 * Ports in header are ipc_port_t.
1674 * MACH_MSG_SUCCESS Acquired a message buffer.
1675 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1679 ipc_kmsg_get_from_kernel(
1680 mach_msg_header_t
*msg
,
1681 mach_msg_size_t size
,
1685 mach_msg_size_t msg_and_trailer_size
;
1686 mach_msg_max_trailer_t
*trailer
;
1687 ipc_port_t dest_port
;
1689 assert(size
>= sizeof(mach_msg_header_t
));
1690 assert((size
& 3) == 0);
1692 dest_port
= (ipc_port_t
)msg
->msgh_remote_port
;
1694 msg_and_trailer_size
= size
+ MAX_TRAILER_SIZE
;
1697 * See if the port has a pre-allocated kmsg for kernel
1698 * clients. These are set up for those kernel clients
1699 * which cannot afford to wait.
1701 if (IP_VALID(dest_port
) && IP_PREALLOC(dest_port
)) {
1702 mach_msg_size_t max_desc
= 0;
1705 if (!ip_active(dest_port
)) {
1706 ip_unlock(dest_port
);
1707 return MACH_SEND_NO_BUFFER
;
1709 assert(IP_PREALLOC(dest_port
));
1710 kmsg
= dest_port
->ip_premsg
;
1711 if (ikm_prealloc_inuse(kmsg
)) {
1712 ip_unlock(dest_port
);
1713 return MACH_SEND_NO_BUFFER
;
1715 #if !defined(__LP64__)
1716 if (msg
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
1717 assert(size
> sizeof(mach_msg_base_t
));
1718 max_desc
= ((mach_msg_base_t
*)msg
)->body
.msgh_descriptor_count
*
1719 DESC_SIZE_ADJUSTMENT
;
1722 if (msg_and_trailer_size
> kmsg
->ikm_size
- max_desc
) {
1723 ip_unlock(dest_port
);
1724 return MACH_SEND_TOO_LARGE
;
1726 ikm_prealloc_set_inuse(kmsg
, dest_port
);
1727 ikm_set_header(kmsg
, msg_and_trailer_size
);
1728 ip_unlock(dest_port
);
1732 kmsg
= ipc_kmsg_alloc(msg_and_trailer_size
);
1733 if (kmsg
== IKM_NULL
)
1734 return MACH_SEND_NO_BUFFER
;
1737 (void) memcpy((void *) kmsg
->ikm_header
, (const void *) msg
, size
);
1741 kmsg
->ikm_header
->msgh_size
= size
;
1744 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1745 * However, the internal size field of the trailer (msgh_trailer_size)
1746 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
1747 * optimize the cases where no implicit data is requested.
1749 trailer
= (mach_msg_max_trailer_t
*)
1750 ((vm_offset_t
)kmsg
->ikm_header
+ size
);
1751 trailer
->msgh_sender
= KERNEL_SECURITY_TOKEN
;
1752 trailer
->msgh_audit
= KERNEL_AUDIT_TOKEN
;
1753 trailer
->msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
1754 trailer
->msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
1756 trailer
->msgh_labels
.sender
= 0;
1759 return MACH_MSG_SUCCESS
;
1763 * Routine: ipc_kmsg_send
1765 * Send a message. The message holds a reference
1766 * for the destination port in the msgh_remote_port field.
1768 * If unsuccessful, the caller still has possession of
1769 * the message and must do something with it. If successful,
1770 * the message is queued, given to a receiver, destroyed,
1771 * or handled directly by the kernel via mach_msg.
1775 * MACH_MSG_SUCCESS The message was accepted.
1776 * MACH_SEND_TIMED_OUT Caller still has message.
1777 * MACH_SEND_INTERRUPTED Caller still has message.
1778 * MACH_SEND_INVALID_DEST Caller still has message.
1785 mach_msg_option_t option
,
1786 mach_msg_timeout_t send_timeout
)
1789 thread_t th
= current_thread();
1790 mach_msg_return_t error
= MACH_MSG_SUCCESS
;
1791 boolean_t kernel_reply
= FALSE
;
1793 /* Check if honor qlimit flag is set on thread. */
1794 if ((th
->options
& TH_OPT_HONOR_QLIMIT
) == TH_OPT_HONOR_QLIMIT
) {
1795 /* Remove the MACH_SEND_ALWAYS flag to honor queue limit. */
1796 option
&= (~MACH_SEND_ALWAYS
);
1797 /* Add the timeout flag since the message queue might be full. */
1798 option
|= MACH_SEND_TIMEOUT
;
1799 th
->options
&= (~TH_OPT_HONOR_QLIMIT
);
1802 #if IMPORTANCE_INHERITANCE
1803 boolean_t did_importance
= FALSE
;
1804 #if IMPORTANCE_TRACE
1805 mach_msg_id_t imp_msgh_id
= -1;
1806 int sender_pid
= -1;
1807 #endif /* IMPORTANCE_TRACE */
1808 #endif /* IMPORTANCE_INHERITANCE */
1810 /* don't allow the creation of a circular loop */
1811 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_CIRCULAR
) {
1812 ipc_kmsg_destroy(kmsg
);
1813 KDBG(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, MACH_MSGH_BITS_CIRCULAR
);
1814 return MACH_MSG_SUCCESS
;
1817 ipc_voucher_send_preprocessing(kmsg
);
1819 port
= (ipc_port_t
) kmsg
->ikm_header
->msgh_remote_port
;
1820 assert(IP_VALID(port
));
1823 #if IMPORTANCE_INHERITANCE
1825 #endif /* IMPORTANCE_INHERITANCE */
1827 * Can't deliver to a dead port.
1828 * However, we can pretend it got sent
1829 * and was then immediately destroyed.
1831 if (!ip_active(port
)) {
1834 if (MACH_NODE_VALID(kmsg
->ikm_node
) && FPORT_VALID(port
->ip_messages
.imq_fport
))
1835 flipc_msg_ack(kmsg
->ikm_node
, &port
->ip_messages
, FALSE
);
1837 ip_release(port
); /* JMM - Future: release right, not just ref */
1838 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
1839 ipc_kmsg_destroy(kmsg
);
1840 KDBG(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, MACH_SEND_INVALID_DEST
);
1841 return MACH_MSG_SUCCESS
;
1844 if (port
->ip_receiver
== ipc_space_kernel
) {
1847 * We can check ip_receiver == ipc_space_kernel
1848 * before checking that the port is active because
1849 * ipc_port_dealloc_kernel clears ip_receiver
1850 * before destroying a kernel port.
1852 assert(ip_active(port
));
1853 port
->ip_messages
.imq_seqno
++;
1856 current_task()->messages_sent
++;
1859 * Call the server routine, and get the reply message to send.
1861 kmsg
= ipc_kobject_server(kmsg
, option
);
1862 if (kmsg
== IKM_NULL
)
1863 return MACH_MSG_SUCCESS
;
1865 /* restart the KMSG_INFO tracing for the reply message */
1866 KDBG(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_INFO
) | DBG_FUNC_START
);
1867 port
= (ipc_port_t
) kmsg
->ikm_header
->msgh_remote_port
;
1868 assert(IP_VALID(port
));
1870 /* fall thru with reply - same options */
1871 kernel_reply
= TRUE
;
1872 if (!ip_active(port
))
1873 error
= MACH_SEND_INVALID_DEST
;
1876 #if IMPORTANCE_INHERITANCE
1878 * Need to see if this message needs importance donation and/or
1879 * propagation. That routine can drop the port lock temporarily.
1880 * If it does we'll have to revalidate the destination.
1882 if (did_importance
== FALSE
) {
1883 did_importance
= TRUE
;
1884 if (ipc_importance_send(kmsg
, option
))
1887 #endif /* IMPORTANCE_INHERITANCE */
1889 if (error
!= MACH_MSG_SUCCESS
) {
1893 * We have a valid message and a valid reference on the port.
1894 * we can unlock the port and call mqueue_send() on its message
1895 * queue. Lock message queue while port is locked.
1897 imq_lock(&port
->ip_messages
);
1900 error
= ipc_mqueue_send(&port
->ip_messages
, kmsg
, option
,
1904 #if IMPORTANCE_INHERITANCE
1905 if (did_importance
== TRUE
) {
1906 __unused
int importance_cleared
= 0;
1908 case MACH_SEND_TIMED_OUT
:
1909 case MACH_SEND_NO_BUFFER
:
1910 case MACH_SEND_INTERRUPTED
:
1911 case MACH_SEND_INVALID_DEST
:
1913 * We still have the kmsg and its
1914 * reference on the port. But we
1915 * have to back out the importance
1918 * The port could have changed hands,
1919 * be inflight to another destination,
1920 * etc... But in those cases our
1921 * back-out will find the new owner
1922 * (and all the operations that
1923 * transferred the right should have
1924 * applied their own boost adjustments
1925 * to the old owner(s)).
1927 importance_cleared
= 1;
1928 ipc_importance_clean(kmsg
);
1931 case MACH_MSG_SUCCESS
:
1935 #if IMPORTANCE_TRACE
1936 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
, (IMPORTANCE_CODE(IMP_MSG
, IMP_MSG_SEND
)) | DBG_FUNC_END
,
1937 task_pid(current_task()), sender_pid
, imp_msgh_id
, importance_cleared
, 0);
1938 #endif /* IMPORTANCE_TRACE */
1940 #endif /* IMPORTANCE_INHERITANCE */
1943 * If the port has been destroyed while we wait, treat the message
1944 * as a successful delivery (like we do for an inactive port).
1946 if (error
== MACH_SEND_INVALID_DEST
) {
1948 if (MACH_NODE_VALID(kmsg
->ikm_node
) && FPORT_VALID(port
->ip_messages
.imq_fport
))
1949 flipc_msg_ack(kmsg
->ikm_node
, &port
->ip_messages
, FALSE
);
1951 ip_release(port
); /* JMM - Future: release right, not just ref */
1952 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
1953 ipc_kmsg_destroy(kmsg
);
1954 KDBG(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, MACH_SEND_INVALID_DEST
);
1955 return MACH_MSG_SUCCESS
;
1958 if (error
!= MACH_MSG_SUCCESS
&& kernel_reply
) {
1960 * Kernel reply messages that fail can't be allowed to
1961 * pseudo-receive on error conditions. We need to just treat
1962 * the message as a successful delivery.
1965 if (MACH_NODE_VALID(kmsg
->ikm_node
) && FPORT_VALID(port
->ip_messages
.imq_fport
))
1966 flipc_msg_ack(kmsg
->ikm_node
, &port
->ip_messages
, FALSE
);
1968 ip_release(port
); /* JMM - Future: release right, not just ref */
1969 kmsg
->ikm_header
->msgh_remote_port
= MACH_PORT_NULL
;
1970 ipc_kmsg_destroy(kmsg
);
1971 KDBG(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_INFO
) | DBG_FUNC_END
, error
);
1972 return MACH_MSG_SUCCESS
;
1978 * Routine: ipc_kmsg_put
1980 * Copies a message buffer to a user message.
1981 * Copies only the specified number of bytes.
1982 * Frees the message buffer.
1984 * Nothing locked. The message buffer must have clean
1987 * MACH_MSG_SUCCESS Copied data out of message buffer.
1988 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
1994 mach_msg_option_t option
,
1995 mach_vm_address_t rcv_addr
,
1996 mach_msg_size_t rcv_size
,
1997 mach_msg_size_t trailer_size
,
1998 mach_msg_size_t
*sizep
)
2000 mach_msg_size_t size
= kmsg
->ikm_header
->msgh_size
+ trailer_size
;
2001 mach_msg_return_t mr
;
2003 DEBUG_IPC_KMSG_PRINT(kmsg
, "ipc_kmsg_put()");
2006 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
2009 " remote_port: %p\n"
2011 " voucher_port: 0x%.8x\n"
2013 kmsg
->ikm_header
->msgh_size
,
2014 kmsg
->ikm_header
->msgh_bits
,
2015 kmsg
->ikm_header
->msgh_remote_port
,
2016 kmsg
->ikm_header
->msgh_local_port
,
2017 kmsg
->ikm_header
->msgh_voucher_port
,
2018 kmsg
->ikm_header
->msgh_id
);
2020 #if defined(__LP64__)
2021 if (current_task() != kernel_task
) { /* don't if receiver expects fully-cooked in-kernel msg; ux_exception */
2022 mach_msg_legacy_header_t
*legacy_header
=
2023 (mach_msg_legacy_header_t
*)((vm_offset_t
)(kmsg
->ikm_header
) + LEGACY_HEADER_SIZE_DELTA
);
2025 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
2026 mach_msg_size_t msg_size
= kmsg
->ikm_header
->msgh_size
;
2027 mach_port_name_t remote_port
= CAST_MACH_PORT_TO_NAME(kmsg
->ikm_header
->msgh_remote_port
);
2028 mach_port_name_t local_port
= CAST_MACH_PORT_TO_NAME(kmsg
->ikm_header
->msgh_local_port
);
2029 mach_port_name_t voucher_port
= kmsg
->ikm_header
->msgh_voucher_port
;
2030 mach_msg_id_t id
= kmsg
->ikm_header
->msgh_id
;
2032 legacy_header
->msgh_id
= id
;
2033 legacy_header
->msgh_local_port
= local_port
;
2034 legacy_header
->msgh_remote_port
= remote_port
;
2035 legacy_header
->msgh_voucher_port
= voucher_port
;
2036 legacy_header
->msgh_size
= msg_size
- LEGACY_HEADER_SIZE_DELTA
;
2037 legacy_header
->msgh_bits
= bits
;
2039 size
-= LEGACY_HEADER_SIZE_DELTA
;
2040 kmsg
->ikm_header
= (mach_msg_header_t
*)legacy_header
;
2044 /* unreachable if !DEBUG */
2045 __unreachable_ok_push
2046 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
)) {
2047 kprintf("ipc_kmsg_put header+body: %d\n", (size
));
2049 for(i
=0;i
*4 < size
;i
++)
2051 kprintf("%.4x\n",((uint32_t *)kmsg
->ikm_header
)[i
]);
2053 kprintf("type: %d\n", ((mach_msg_type_descriptor_t
*)(((mach_msg_base_t
*)kmsg
->ikm_header
)+1))->type
);
2055 __unreachable_ok_pop
2057 /* Re-Compute target address if using stack-style delivery */
2058 if (option
& MACH_RCV_STACK
) {
2059 rcv_addr
+= rcv_size
- size
;
2062 if (copyoutmsg((const char *) kmsg
->ikm_header
, rcv_addr
, size
)) {
2063 mr
= MACH_RCV_INVALID_DATA
;
2066 mr
= MACH_MSG_SUCCESS
;
2068 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_KMSG_LINK
) | DBG_FUNC_NONE
,
2069 (rcv_addr
>= VM_MIN_KERNEL_AND_KEXT_ADDRESS
||
2070 rcv_addr
+ size
>= VM_MIN_KERNEL_AND_KEXT_ADDRESS
) ? (uintptr_t)0 : (uintptr_t)rcv_addr
,
2071 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
2072 1 /* this is on the receive/copyout path */,
2075 ipc_kmsg_free(kmsg
);
2083 * Routine: ipc_kmsg_put_to_kernel
2085 * Copies a message buffer to a kernel message.
2086 * Frees the message buffer.
2087 * No errors allowed.
2093 ipc_kmsg_put_to_kernel(
2094 mach_msg_header_t
*msg
,
2096 mach_msg_size_t size
)
2098 (void) memcpy((void *) msg
, (const void *) kmsg
->ikm_header
, size
);
2100 ipc_kmsg_free(kmsg
);
2103 unsigned long pthread_priority_canonicalize(unsigned long priority
, boolean_t propagation
);
2105 static kern_return_t
2108 mach_msg_option_t options
,
2109 mach_msg_priority_t override
)
2112 unsigned long flags
= 0;
2113 ipc_port_t special_reply_port
= kmsg
->ikm_header
->msgh_local_port
;
2114 ipc_port_t dest_port
= kmsg
->ikm_header
->msgh_remote_port
;
2116 kr
= ipc_get_pthpriority_from_kmsg_voucher(kmsg
, &kmsg
->ikm_qos
);
2117 if (kr
!= KERN_SUCCESS
) {
2118 kmsg
->ikm_qos
= MACH_MSG_PRIORITY_UNSPECIFIED
;
2120 kmsg
->ikm_qos_override
= kmsg
->ikm_qos
;
2122 if (options
& MACH_SEND_OVERRIDE
) {
2123 unsigned long canonical
;
2124 mach_msg_priority_t canon
;
2126 canonical
= pthread_priority_canonicalize(override
, TRUE
);
2127 canon
= (mach_msg_priority_t
)canonical
;
2128 if (canon
> kmsg
->ikm_qos
)
2129 kmsg
->ikm_qos_override
= canon
;
2133 if ((options
& MACH_SEND_SYNC_OVERRIDE
)) {
2134 if (IP_VALID(special_reply_port
) &&
2135 MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
) == MACH_MSG_TYPE_PORT_SEND_ONCE
) {
2137 * Update the sync override count if the reply port is a special reply port,
2138 * link the destination port to special reply port and update the qos count
2139 * of destination port.
2141 * Use the qos value passed by voucher and not the one passed by notify field.
2143 kr
= ipc_port_link_special_reply_port_with_qos(special_reply_port
, dest_port
,
2144 thread_qos_from_pthread_priority(kmsg
->ikm_qos
, &flags
));
2153 * Routine: ipc_kmsg_copyin_header
2155 * "Copy-in" port rights in the header of a message.
2156 * Operates atomically; if it doesn't succeed the
2157 * message header and the space are left untouched.
2158 * If it does succeed the remote/local port fields
2159 * contain object pointers instead of port names,
2160 * and the bits field is updated. The destination port
2161 * will be a valid port pointer.
2166 * MACH_MSG_SUCCESS Successful copyin.
2167 * MACH_SEND_INVALID_HEADER
2168 * Illegal value in the message header bits.
2169 * MACH_SEND_INVALID_DEST The space is dead.
2170 * MACH_SEND_INVALID_DEST Can't copyin destination port.
2171 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2172 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
2173 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2177 ipc_kmsg_copyin_header(
2180 mach_msg_priority_t override
,
2181 mach_msg_option_t
*optionp
)
2183 mach_msg_header_t
*msg
= kmsg
->ikm_header
;
2184 mach_msg_bits_t mbits
= msg
->msgh_bits
& MACH_MSGH_BITS_USER
;
2185 mach_port_name_t dest_name
= CAST_MACH_PORT_TO_NAME(msg
->msgh_remote_port
);
2186 mach_port_name_t reply_name
= CAST_MACH_PORT_TO_NAME(msg
->msgh_local_port
);
2187 mach_port_name_t voucher_name
= MACH_PORT_NULL
;
2190 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
2191 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
2192 mach_msg_type_name_t voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
2193 ipc_object_t dest_port
= IO_NULL
;
2194 ipc_object_t reply_port
= IO_NULL
;
2195 ipc_port_t dest_soright
= IP_NULL
;
2196 ipc_port_t reply_soright
= IP_NULL
;
2197 ipc_port_t voucher_soright
= IP_NULL
;
2198 ipc_port_t release_port
= IP_NULL
;
2199 ipc_port_t voucher_port
= IP_NULL
;
2200 ipc_port_t voucher_release_port
= IP_NULL
;
2201 ipc_entry_t dest_entry
= IE_NULL
;
2202 ipc_entry_t reply_entry
= IE_NULL
;
2203 ipc_entry_t voucher_entry
= IE_NULL
;
2206 #if IMPORTANCE_INHERITANCE
2207 boolean_t needboost
= FALSE
;
2208 #endif /* IMPORTANCE_INHERITANCE */
2210 if ((mbits
!= msg
->msgh_bits
) ||
2211 (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type
)) ||
2212 ((reply_type
== 0) ?
2213 (reply_name
!= MACH_PORT_NULL
) :
2214 !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type
)))
2215 return MACH_SEND_INVALID_HEADER
;
2217 if (!MACH_PORT_VALID(dest_name
))
2218 return MACH_SEND_INVALID_DEST
;
2220 is_write_lock(space
);
2221 if (!is_active(space
)) {
2222 is_write_unlock(space
);
2223 return MACH_SEND_INVALID_DEST
;
2225 /* space locked and active */
2228 * If there is a voucher specified, make sure the disposition is
2229 * valid and the entry actually refers to a voucher port. Don't
2230 * actually copy in until we validate destination and reply.
2232 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
2234 voucher_name
= msg
->msgh_voucher_port
;
2236 if (voucher_name
== MACH_PORT_DEAD
||
2237 (voucher_type
!= MACH_MSG_TYPE_MOVE_SEND
&&
2238 voucher_type
!= MACH_MSG_TYPE_COPY_SEND
)) {
2239 is_write_unlock(space
);
2240 return MACH_SEND_INVALID_VOUCHER
;
2243 if (voucher_name
!= MACH_PORT_NULL
) {
2244 voucher_entry
= ipc_entry_lookup(space
, voucher_name
);
2245 if (voucher_entry
== IE_NULL
||
2246 (voucher_entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0 ||
2247 io_kotype(voucher_entry
->ie_object
) != IKOT_VOUCHER
) {
2248 is_write_unlock(space
);
2249 return MACH_SEND_INVALID_VOUCHER
;
2252 voucher_type
= MACH_MSG_TYPE_MOVE_SEND
;
2257 * Handle combinations of validating destination and reply; along
2258 * with copying in destination, reply, and voucher in an atomic way.
2261 if (dest_name
== voucher_name
) {
2264 * If the destination name is the same as the voucher name,
2265 * the voucher_entry must already be known. Either that or
2266 * the destination name is MACH_PORT_NULL (i.e. invalid).
2268 dest_entry
= voucher_entry
;
2269 if (dest_entry
== IE_NULL
) {
2274 * Make sure a future copyin of the reply port will succeed.
2275 * Once we start copying in the dest/voucher pair, we can't
2278 if (MACH_PORT_VALID(reply_name
)) {
2279 assert(reply_type
!= 0); /* because reply_name not null */
2281 /* It is just WRONG if dest, voucher, and reply are all the same. */
2282 if (voucher_name
== reply_name
) {
2285 reply_entry
= ipc_entry_lookup(space
, reply_name
);
2286 if (reply_entry
== IE_NULL
) {
2289 assert(dest_entry
!= reply_entry
); /* names are not equal */
2290 if (!ipc_right_copyin_check(space
, reply_name
, reply_entry
, reply_type
)) {
2296 * Do the joint copyin of the dest disposition and
2297 * voucher disposition from the one entry/port. We
2298 * already validated that the voucher copyin would
2299 * succeed (above). So, any failure in combining
2300 * the copyins can be blamed on the destination.
2302 kr
= ipc_right_copyin_two(space
, dest_name
, dest_entry
,
2303 dest_type
, voucher_type
,
2304 &dest_port
, &dest_soright
,
2306 if (kr
!= KERN_SUCCESS
) {
2307 assert(kr
!= KERN_INVALID_CAPABILITY
);
2310 voucher_port
= (ipc_port_t
)dest_port
;
2313 * could not have been one of these dispositions,
2314 * validated the port was a true kernel voucher port above,
2315 * AND was successfully able to copyin both dest and voucher.
2317 assert(dest_type
!= MACH_MSG_TYPE_MAKE_SEND
);
2318 assert(dest_type
!= MACH_MSG_TYPE_MAKE_SEND_ONCE
);
2319 assert(dest_type
!= MACH_MSG_TYPE_MOVE_SEND_ONCE
);
2322 * Perform the delayed reply right copyin (guaranteed success).
2324 if (reply_entry
!= IE_NULL
) {
2325 kr
= ipc_right_copyin(space
, reply_name
, reply_entry
,
2327 &reply_port
, &reply_soright
,
2328 &release_port
, &assertcnt
);
2329 assert(assertcnt
== 0);
2330 assert(kr
== KERN_SUCCESS
);
2334 if (dest_name
== reply_name
) {
2336 * Destination and reply ports are the same!
2337 * This is very similar to the case where the
2338 * destination and voucher ports were the same
2339 * (except the reply port disposition is not
2340 * previously validated).
2342 dest_entry
= ipc_entry_lookup(space
, dest_name
);
2343 if (dest_entry
== IE_NULL
) {
2346 reply_entry
= dest_entry
;
2347 assert(reply_type
!= 0); /* because name not null */
2350 * Do the joint copyin of the dest disposition and
2351 * reply disposition from the one entry/port.
2353 kr
= ipc_right_copyin_two(space
, dest_name
, dest_entry
,
2354 dest_type
, reply_type
,
2355 &dest_port
, &dest_soright
,
2357 if (kr
== KERN_INVALID_CAPABILITY
) {
2359 } else if (kr
!= KERN_SUCCESS
) {
2362 reply_port
= dest_port
;
2367 * Handle destination and reply independently, as
2368 * they are independent entries (even if the entries
2369 * refer to the same port).
2371 * This can be the tough case to make atomic.
2373 * The difficult problem is serializing with port death.
2374 * The bad case is when dest_port dies after its copyin,
2375 * reply_port dies before its copyin, and dest_port dies before
2376 * reply_port. Then the copyins operated as if dest_port was
2377 * alive and reply_port was dead, which shouldn't have happened
2378 * because they died in the other order.
2380 * Note that it is easy for a user task to tell if
2381 * a copyin happened before or after a port died.
2382 * If a port dies before copyin, a dead-name notification
2383 * is generated and the dead name's urefs are incremented,
2384 * and if the copyin happens first, a port-deleted
2385 * notification is generated.
2387 * Even so, avoiding that potentially detectable race is too
2388 * expensive - and no known code cares about it. So, we just
2389 * do the expedient thing and copy them in one after the other.
2392 dest_entry
= ipc_entry_lookup(space
, dest_name
);
2393 if (dest_entry
== IE_NULL
) {
2396 assert(dest_entry
!= voucher_entry
);
2399 * Make sure reply port entry is valid before dest copyin.
2401 if (MACH_PORT_VALID(reply_name
)) {
2402 if (reply_name
== voucher_name
) {
2405 reply_entry
= ipc_entry_lookup(space
, reply_name
);
2406 if (reply_entry
== IE_NULL
) {
2409 assert(dest_entry
!= reply_entry
); /* names are not equal */
2410 assert(reply_type
!= 0); /* because reply_name not null */
2412 if (!ipc_right_copyin_check(space
, reply_name
, reply_entry
, reply_type
)) {
2418 * copyin the destination.
2420 kr
= ipc_right_copyin(space
, dest_name
, dest_entry
,
2422 &dest_port
, &dest_soright
,
2423 &release_port
, &assertcnt
);
2424 assert(assertcnt
== 0);
2425 if (kr
!= KERN_SUCCESS
) {
2428 assert(IO_VALID(dest_port
));
2429 assert(!IP_VALID(release_port
));
2432 * Copyin the pre-validated reply right.
2433 * It's OK if the reply right has gone dead in the meantime.
2435 if (MACH_PORT_VALID(reply_name
)) {
2436 kr
= ipc_right_copyin(space
, reply_name
, reply_entry
,
2438 &reply_port
, &reply_soright
,
2439 &release_port
, &assertcnt
);
2440 assert(assertcnt
== 0);
2441 assert(kr
== KERN_SUCCESS
);
2443 /* convert invalid name to equivalent ipc_object type */
2444 reply_port
= (ipc_object_t
)CAST_MACH_NAME_TO_PORT(reply_name
);
2449 * Finally can copyin the voucher right now that dest and reply
2450 * are fully copied in (guaranteed success).
2452 if (IE_NULL
!= voucher_entry
) {
2453 kr
= ipc_right_copyin(space
, voucher_name
, voucher_entry
,
2454 voucher_type
, FALSE
,
2455 (ipc_object_t
*)&voucher_port
,
2457 &voucher_release_port
,
2459 assert(assertcnt
== 0);
2460 assert(KERN_SUCCESS
== kr
);
2461 assert(IP_VALID(voucher_port
));
2462 assert(ip_active(voucher_port
));
2467 * The entries might need to be deallocated.
2469 * Each entry should be deallocated only once,
2470 * even if it was specified in more than one slot in the header.
2471 * Note that dest can be the same entry as reply or voucher,
2472 * but reply and voucher must be distinct entries.
2474 assert(IE_NULL
!= dest_entry
);
2475 if (IE_NULL
!= reply_entry
)
2476 assert(reply_entry
!= voucher_entry
);
2478 if (IE_BITS_TYPE(dest_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
2479 ipc_entry_dealloc(space
, dest_name
, dest_entry
);
2481 if (dest_entry
== reply_entry
) {
2482 reply_entry
= IE_NULL
;
2485 if (dest_entry
== voucher_entry
) {
2486 voucher_entry
= IE_NULL
;
2489 dest_entry
= IE_NULL
;
2491 if (IE_NULL
!= reply_entry
&&
2492 IE_BITS_TYPE(reply_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
2493 ipc_entry_dealloc(space
, reply_name
, reply_entry
);
2494 reply_entry
= IE_NULL
;
2496 if (IE_NULL
!= voucher_entry
&&
2497 IE_BITS_TYPE(voucher_entry
->ie_bits
) == MACH_PORT_TYPE_NONE
) {
2498 ipc_entry_dealloc(space
, voucher_name
, voucher_entry
);
2499 voucher_entry
= IE_NULL
;
2502 dest_type
= ipc_object_copyin_type(dest_type
);
2503 reply_type
= ipc_object_copyin_type(reply_type
);
2506 * JMM - Without rdar://problem/6275821, this is the last place we can
2507 * re-arm the send-possible notifications. It may trigger unexpectedly
2508 * early (send may NOT have failed), but better than missing. We assure
2509 * we won't miss by forcing MACH_SEND_ALWAYS if we got past arming.
2511 if (((*optionp
& MACH_SEND_NOTIFY
) != 0) &&
2512 dest_type
!= MACH_MSG_TYPE_PORT_SEND_ONCE
&&
2513 dest_entry
!= IE_NULL
&& dest_entry
->ie_request
!= IE_REQ_NONE
) {
2514 ipc_port_t dport
= (ipc_port_t
)dest_port
;
2516 assert(dport
!= IP_NULL
);
2518 if (ip_active(dport
) && dport
->ip_receiver
!= ipc_space_kernel
) {
2519 if (ip_full(dport
)) {
2520 #if IMPORTANCE_INHERITANCE
2521 needboost
= ipc_port_request_sparm(dport
, dest_name
,
2522 dest_entry
->ie_request
,
2525 if (needboost
== FALSE
)
2528 ipc_port_request_sparm(dport
, dest_name
,
2529 dest_entry
->ie_request
,
2533 #endif /* IMPORTANCE_INHERITANCE */
2535 *optionp
|= MACH_SEND_ALWAYS
;
2543 is_write_unlock(space
);
2545 #if IMPORTANCE_INHERITANCE
2547 * If our request is the first boosting send-possible
2548 * notification this cycle, push the boost down the
2551 if (needboost
== TRUE
) {
2552 ipc_port_t dport
= (ipc_port_t
)dest_port
;
2554 /* dport still locked from above */
2555 if (ipc_port_importance_delta(dport
, IPID_OPTION_SENDPOSSIBLE
, 1) == FALSE
) {
2559 #endif /* IMPORTANCE_INHERITANCE */
2561 if (dest_soright
!= IP_NULL
) {
2562 ipc_notify_port_deleted(dest_soright
, dest_name
);
2564 if (reply_soright
!= IP_NULL
) {
2565 ipc_notify_port_deleted(reply_soright
, reply_name
);
2567 if (voucher_soright
!= IP_NULL
) {
2568 ipc_notify_port_deleted(voucher_soright
, voucher_name
);
2572 * No room to store voucher port in in-kernel msg header,
2573 * so we store it back in the kmsg itself. Extract the
2574 * qos, and apply any override before we enqueue the kmsg.
2576 if (IP_VALID(voucher_port
)) {
2578 kmsg
->ikm_voucher
= voucher_port
;
2579 voucher_type
= MACH_MSG_TYPE_MOVE_SEND
;
2582 msg
->msgh_bits
= MACH_MSGH_BITS_SET(dest_type
, reply_type
, voucher_type
, mbits
);
2583 msg
->msgh_remote_port
= (ipc_port_t
)dest_port
;
2584 msg
->msgh_local_port
= (ipc_port_t
)reply_port
;
2586 /* capture the qos value(s) for the kmsg */
2587 ipc_kmsg_set_qos(kmsg
, *optionp
, override
);
2589 if (release_port
!= IP_NULL
)
2590 ip_release(release_port
);
2592 if (voucher_release_port
!= IP_NULL
)
2593 ip_release(voucher_release_port
);
2595 return MACH_MSG_SUCCESS
;
2598 is_write_unlock(space
);
2600 if (release_port
!= IP_NULL
)
2601 ip_release(release_port
);
2603 assert(voucher_port
== IP_NULL
);
2604 assert(voucher_soright
== IP_NULL
);
2606 return MACH_SEND_INVALID_REPLY
;
2609 is_write_unlock(space
);
2611 if (release_port
!= IP_NULL
)
2612 ip_release(release_port
);
2614 if (reply_soright
!= IP_NULL
)
2615 ipc_notify_port_deleted(reply_soright
, reply_name
);
2617 assert(voucher_port
== IP_NULL
);
2618 assert(voucher_soright
== IP_NULL
);
2620 return MACH_SEND_INVALID_DEST
;
2623 mach_msg_descriptor_t
*ipc_kmsg_copyin_port_descriptor(
2624 volatile mach_msg_port_descriptor_t
*dsc
,
2625 mach_msg_legacy_port_descriptor_t
*user_dsc
,
2629 mach_msg_return_t
*mr
);
2631 void ipc_print_type_name(
2633 mach_msg_descriptor_t
*
2634 ipc_kmsg_copyin_port_descriptor(
2635 volatile mach_msg_port_descriptor_t
*dsc
,
2636 mach_msg_legacy_port_descriptor_t
*user_dsc_in
,
2640 mach_msg_return_t
*mr
)
2642 volatile mach_msg_legacy_port_descriptor_t
*user_dsc
= user_dsc_in
;
2643 mach_msg_type_name_t user_disp
;
2644 mach_msg_type_name_t result_disp
;
2645 mach_port_name_t name
;
2646 ipc_object_t object
;
2648 user_disp
= user_dsc
->disposition
;
2649 result_disp
= ipc_object_copyin_type(user_disp
);
2651 name
= (mach_port_name_t
)user_dsc
->name
;
2652 if (MACH_PORT_VALID(name
)) {
2654 kern_return_t kr
= ipc_object_copyin(space
, name
, user_disp
, &object
);
2655 if (kr
!= KERN_SUCCESS
) {
2656 *mr
= MACH_SEND_INVALID_RIGHT
;
2660 if ((result_disp
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2661 ipc_port_check_circularity((ipc_port_t
) object
,
2662 (ipc_port_t
) dest
)) {
2663 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
2665 dsc
->name
= (ipc_port_t
) object
;
2667 dsc
->name
= CAST_MACH_NAME_TO_PORT(name
);
2669 dsc
->disposition
= result_disp
;
2670 dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
2672 dsc
->pad_end
= 0; // debug, unnecessary
2674 return (mach_msg_descriptor_t
*)(user_dsc_in
+1);
2677 mach_msg_descriptor_t
* ipc_kmsg_copyin_ool_descriptor(
2678 mach_msg_ool_descriptor_t
*dsc
,
2679 mach_msg_descriptor_t
*user_dsc
,
2682 vm_map_copy_t
*copy
,
2683 vm_size_t
*space_needed
,
2685 mach_msg_return_t
*mr
);
2686 mach_msg_descriptor_t
*
2687 ipc_kmsg_copyin_ool_descriptor(
2688 mach_msg_ool_descriptor_t
*dsc
,
2689 mach_msg_descriptor_t
*user_dsc
,
2692 vm_map_copy_t
*copy
,
2693 vm_size_t
*space_needed
,
2695 mach_msg_return_t
*mr
)
2699 mach_msg_copy_options_t copy_options
;
2700 mach_vm_offset_t addr
;
2701 mach_msg_descriptor_type_t dsc_type
;
2704 mach_msg_ool_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2706 addr
= (mach_vm_offset_t
) user_ool_dsc
->address
;
2707 length
= user_ool_dsc
->size
;
2708 dealloc
= user_ool_dsc
->deallocate
;
2709 copy_options
= user_ool_dsc
->copy
;
2710 dsc_type
= user_ool_dsc
->type
;
2712 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2714 mach_msg_ool_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2716 addr
= CAST_USER_ADDR_T(user_ool_dsc
->address
);
2717 dealloc
= user_ool_dsc
->deallocate
;
2718 copy_options
= user_ool_dsc
->copy
;
2719 dsc_type
= user_ool_dsc
->type
;
2720 length
= user_ool_dsc
->size
;
2722 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2725 dsc
->size
= (mach_msg_size_t
)length
;
2726 dsc
->deallocate
= dealloc
;
2727 dsc
->copy
= copy_options
;
2728 dsc
->type
= dsc_type
;
2731 dsc
->address
= NULL
;
2732 } else if ((length
>= MSG_OOL_SIZE_SMALL
) &&
2733 (copy_options
== MACH_MSG_PHYSICAL_COPY
) && !dealloc
) {
2736 * If the request is a physical copy and the source
2737 * is not being deallocated, then allocate space
2738 * in the kernel's pageable ipc copy map and copy
2739 * the data in. The semantics guarantee that the
2740 * data will have been physically copied before
2741 * the send operation terminates. Thus if the data
2742 * is not being deallocated, we must be prepared
2743 * to page if the region is sufficiently large.
2745 if (copyin(addr
, (char *)*paddr
, length
)) {
2746 *mr
= MACH_SEND_INVALID_MEMORY
;
2751 * The kernel ipc copy map is marked no_zero_fill.
2752 * If the transfer is not a page multiple, we need
2753 * to zero fill the balance.
2755 if (!page_aligned(length
)) {
2756 (void) memset((void *) (*paddr
+ length
), 0,
2757 round_page(length
) - length
);
2759 if (vm_map_copyin(ipc_kernel_copy_map
, (vm_map_address_t
)*paddr
,
2760 (vm_map_size_t
)length
, TRUE
, copy
) != KERN_SUCCESS
) {
2761 *mr
= MACH_MSG_VM_KERNEL
;
2764 dsc
->address
= (void *)*copy
;
2765 *paddr
+= round_page(length
);
2766 *space_needed
-= round_page(length
);
2770 * Make a vm_map_copy_t of the of the data. If the
2771 * data is small, this will do an optimized physical
2772 * copy. Otherwise, it will do a virtual copy.
2774 * NOTE: A virtual copy is OK if the original is being
2775 * deallocted, even if a physical copy was requested.
2777 kern_return_t kr
= vm_map_copyin(map
, addr
,
2778 (vm_map_size_t
)length
, dealloc
, copy
);
2779 if (kr
!= KERN_SUCCESS
) {
2780 *mr
= (kr
== KERN_RESOURCE_SHORTAGE
) ?
2781 MACH_MSG_VM_KERNEL
:
2782 MACH_SEND_INVALID_MEMORY
;
2785 dsc
->address
= (void *)*copy
;
2790 mach_msg_descriptor_t
* ipc_kmsg_copyin_ool_ports_descriptor(
2791 mach_msg_ool_ports_descriptor_t
*dsc
,
2792 mach_msg_descriptor_t
*user_dsc
,
2798 mach_msg_return_t
*mr
);
2799 mach_msg_descriptor_t
*
2800 ipc_kmsg_copyin_ool_ports_descriptor(
2801 mach_msg_ool_ports_descriptor_t
*dsc
,
2802 mach_msg_descriptor_t
*user_dsc
,
2808 mach_msg_return_t
*mr
)
2811 ipc_object_t
*objects
;
2813 mach_vm_offset_t addr
;
2814 mach_msg_type_name_t user_disp
;
2815 mach_msg_type_name_t result_disp
;
2816 mach_msg_type_number_t count
;
2817 mach_msg_copy_options_t copy_option
;
2818 boolean_t deallocate
;
2819 mach_msg_descriptor_type_t type
;
2820 vm_size_t ports_length
, names_length
;
2823 mach_msg_ool_ports_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2825 addr
= (mach_vm_offset_t
)user_ool_dsc
->address
;
2826 count
= user_ool_dsc
->count
;
2827 deallocate
= user_ool_dsc
->deallocate
;
2828 copy_option
= user_ool_dsc
->copy
;
2829 user_disp
= user_ool_dsc
->disposition
;
2830 type
= user_ool_dsc
->type
;
2832 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2834 mach_msg_ool_ports_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
2836 addr
= CAST_USER_ADDR_T(user_ool_dsc
->address
);
2837 count
= user_ool_dsc
->count
;
2838 deallocate
= user_ool_dsc
->deallocate
;
2839 copy_option
= user_ool_dsc
->copy
;
2840 user_disp
= user_ool_dsc
->disposition
;
2841 type
= user_ool_dsc
->type
;
2843 user_dsc
= (typeof(user_dsc
))(user_ool_dsc
+1);
2846 dsc
->deallocate
= deallocate
;
2847 dsc
->copy
= copy_option
;
2850 dsc
->address
= NULL
; /* for now */
2852 result_disp
= ipc_object_copyin_type(user_disp
);
2853 dsc
->disposition
= result_disp
;
2855 /* We always do a 'physical copy', but you have to specify something valid */
2856 if (copy_option
!= MACH_MSG_PHYSICAL_COPY
&&
2857 copy_option
!= MACH_MSG_VIRTUAL_COPY
) {
2858 *mr
= MACH_SEND_INVALID_TYPE
;
2862 /* calculate length of data in bytes, rounding up */
2864 if (os_mul_overflow(count
, sizeof(mach_port_t
), &ports_length
)) {
2865 *mr
= MACH_SEND_TOO_LARGE
;
2869 if (os_mul_overflow(count
, sizeof(mach_port_name_t
), &names_length
)) {
2870 *mr
= MACH_SEND_TOO_LARGE
;
2874 if (ports_length
== 0) {
2878 data
= kalloc(ports_length
);
2881 *mr
= MACH_SEND_NO_BUFFER
;
2886 mach_port_name_t
*names
= &((mach_port_name_t
*)data
)[count
];
2888 mach_port_name_t
*names
= ((mach_port_name_t
*)data
);
2891 if (copyinmap(map
, addr
, names
, names_length
) != KERN_SUCCESS
) {
2892 kfree(data
, ports_length
);
2893 *mr
= MACH_SEND_INVALID_MEMORY
;
2898 (void) mach_vm_deallocate(map
, addr
, (mach_vm_size_t
)ports_length
);
2901 objects
= (ipc_object_t
*) data
;
2902 dsc
->address
= data
;
2904 for ( i
= 0; i
< count
; i
++) {
2905 mach_port_name_t name
= names
[i
];
2906 ipc_object_t object
;
2908 if (!MACH_PORT_VALID(name
)) {
2909 objects
[i
] = (ipc_object_t
)CAST_MACH_NAME_TO_PORT(name
);
2913 kern_return_t kr
= ipc_object_copyin(space
, name
, user_disp
, &object
);
2915 if (kr
!= KERN_SUCCESS
) {
2918 for(j
= 0; j
< i
; j
++) {
2919 object
= objects
[j
];
2920 if (IPC_OBJECT_VALID(object
))
2921 ipc_object_destroy(object
, result_disp
);
2923 kfree(data
, ports_length
);
2924 dsc
->address
= NULL
;
2925 *mr
= MACH_SEND_INVALID_RIGHT
;
2929 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
2930 ipc_port_check_circularity(
2931 (ipc_port_t
) object
,
2933 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
2935 objects
[i
] = object
;
2942 * Routine: ipc_kmsg_copyin_body
2944 * "Copy-in" port rights and out-of-line memory
2945 * in the message body.
2947 * In all failure cases, the message is left holding
2948 * no rights or memory. However, the message buffer
2949 * is not deallocated. If successful, the message
2950 * contains a valid destination port.
2954 * MACH_MSG_SUCCESS Successful copyin.
2955 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2956 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2957 * MACH_SEND_INVALID_TYPE Bad type specification.
2958 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2959 * MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
2960 * MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
2964 ipc_kmsg_copyin_body(
2970 mach_msg_body_t
*body
;
2971 mach_msg_descriptor_t
*daddr
, *naddr
;
2972 mach_msg_descriptor_t
*user_addr
, *kern_addr
;
2973 mach_msg_type_number_t dsc_count
;
2974 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
2975 boolean_t
complex = FALSE
;
2976 vm_size_t space_needed
= 0;
2977 vm_offset_t paddr
= 0;
2978 vm_map_copy_t copy
= VM_MAP_COPY_NULL
;
2979 mach_msg_type_number_t i
;
2980 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
2982 vm_size_t descriptor_size
= 0;
2984 mach_msg_type_number_t total_ool_port_count
= 0;
2987 * Determine if the target is a kernel port.
2989 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
2990 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
2991 naddr
= (mach_msg_descriptor_t
*) (body
+ 1);
2993 dsc_count
= body
->msgh_descriptor_count
;
2995 return MACH_MSG_SUCCESS
;
2998 * Make an initial pass to determine kernal VM space requirements for
2999 * physical copies and possible contraction of the descriptors from
3000 * processes with pointers larger than the kernel's.
3003 for (i
= 0; i
< dsc_count
; i
++) {
3004 mach_msg_size_t size
;
3005 mach_msg_type_number_t ool_port_count
= 0;
3009 /* make sure the descriptor fits in the message */
3010 if (is_task_64bit
) {
3011 switch (daddr
->type
.type
) {
3012 case MACH_MSG_OOL_DESCRIPTOR
:
3013 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3014 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3015 descriptor_size
+= 16;
3016 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 16);
3019 descriptor_size
+= 12;
3020 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 12);
3024 descriptor_size
+= 12;
3025 naddr
= (typeof(naddr
))((vm_offset_t
)daddr
+ 12);
3028 if (naddr
> (mach_msg_descriptor_t
*)
3029 ((vm_offset_t
)kmsg
->ikm_header
+ kmsg
->ikm_header
->msgh_size
)) {
3030 mr
= MACH_SEND_MSG_TOO_SMALL
;
3034 switch (daddr
->type
.type
) {
3035 case MACH_MSG_OOL_DESCRIPTOR
:
3036 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3037 size
= (is_task_64bit
) ?
3038 ((mach_msg_ool_descriptor64_t
*)daddr
)->size
:
3039 daddr
->out_of_line
.size
;
3041 if (daddr
->out_of_line
.copy
!= MACH_MSG_PHYSICAL_COPY
&&
3042 daddr
->out_of_line
.copy
!= MACH_MSG_VIRTUAL_COPY
) {
3044 * Invalid copy option
3046 mr
= MACH_SEND_INVALID_TYPE
;
3050 if ((size
>= MSG_OOL_SIZE_SMALL
) &&
3051 (daddr
->out_of_line
.copy
== MACH_MSG_PHYSICAL_COPY
) &&
3052 !(daddr
->out_of_line
.deallocate
)) {
3055 * Out-of-line memory descriptor, accumulate kernel
3056 * memory requirements
3058 if (space_needed
+ round_page(size
) <= space_needed
) {
3059 /* Overflow dectected */
3060 mr
= MACH_MSG_VM_KERNEL
;
3064 space_needed
+= round_page(size
);
3065 if (space_needed
> ipc_kmsg_max_vm_space
) {
3066 /* Per message kernel memory limit exceeded */
3067 mr
= MACH_MSG_VM_KERNEL
;
3072 case MACH_MSG_PORT_DESCRIPTOR
:
3073 if (os_add_overflow(total_ool_port_count
, 1, &total_ool_port_count
)) {
3074 /* Overflow detected */
3075 mr
= MACH_SEND_TOO_LARGE
;
3079 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3080 ool_port_count
= (is_task_64bit
) ?
3081 ((mach_msg_ool_ports_descriptor64_t
*)daddr
)->count
:
3082 daddr
->ool_ports
.count
;
3084 if (os_add_overflow(total_ool_port_count
, ool_port_count
, &total_ool_port_count
)) {
3085 /* Overflow detected */
3086 mr
= MACH_SEND_TOO_LARGE
;
3090 if (ool_port_count
> (ipc_kmsg_max_vm_space
/sizeof(mach_port_t
))) {
3091 /* Per message kernel memory limit exceeded */
3092 mr
= MACH_SEND_TOO_LARGE
;
3099 /* Sending more than 16383 rights in one message seems crazy */
3100 if (total_ool_port_count
>= (MACH_PORT_UREFS_MAX
/ 4)) {
3101 mr
= MACH_SEND_TOO_LARGE
;
3106 * Allocate space in the pageable kernel ipc copy map for all the
3107 * ool data that is to be physically copied. Map is marked wait for
3111 if (vm_allocate_kernel(ipc_kernel_copy_map
, &paddr
, space_needed
,
3112 VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IPC
) != KERN_SUCCESS
) {
3113 mr
= MACH_MSG_VM_KERNEL
;
3118 /* user_addr = just after base as it was copied in */
3119 user_addr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
3121 /* Shift the mach_msg_base_t down to make room for dsc_count*16bytes of descriptors */
3122 if(descriptor_size
!= 16*dsc_count
) {
3123 vm_offset_t dsc_adjust
= 16*dsc_count
- descriptor_size
;
3125 memmove((char *)(((vm_offset_t
)kmsg
->ikm_header
) - dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
3126 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
- dsc_adjust
);
3128 /* Update the message size for the larger in-kernel representation */
3129 kmsg
->ikm_header
->msgh_size
+= (mach_msg_size_t
)dsc_adjust
;
3133 /* kern_addr = just after base after it has been (conditionally) moved */
3134 kern_addr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
3136 /* handle the OOL regions and port descriptors. */
3137 for(i
=0;i
<dsc_count
;i
++) {
3138 switch (user_addr
->type
.type
) {
3139 case MACH_MSG_PORT_DESCRIPTOR
:
3140 user_addr
= ipc_kmsg_copyin_port_descriptor((mach_msg_port_descriptor_t
*)kern_addr
,
3141 (mach_msg_legacy_port_descriptor_t
*)user_addr
, space
, dest
, kmsg
, &mr
);
3145 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3146 case MACH_MSG_OOL_DESCRIPTOR
:
3147 user_addr
= ipc_kmsg_copyin_ool_descriptor((mach_msg_ool_descriptor_t
*)kern_addr
,
3148 user_addr
, is_task_64bit
, &paddr
, ©
, &space_needed
, map
, &mr
);
3152 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
3153 user_addr
= ipc_kmsg_copyin_ool_ports_descriptor((mach_msg_ool_ports_descriptor_t
*)kern_addr
,
3154 user_addr
, is_task_64bit
, map
, space
, dest
, kmsg
, &mr
);
3159 /* Invalid descriptor */
3160 mr
= MACH_SEND_INVALID_TYPE
;
3164 if (MACH_MSG_SUCCESS
!= mr
) {
3165 /* clean from start of message descriptors to i */
3166 ipc_kmsg_clean_partial(kmsg
, i
,
3167 (mach_msg_descriptor_t
*)((mach_msg_base_t
*)kmsg
->ikm_header
+ 1),
3168 paddr
, space_needed
);
3174 kmsg
->ikm_header
->msgh_bits
&= ~MACH_MSGH_BITS_COMPLEX
;
3180 /* no descriptors have been copied in yet */
3181 ipc_kmsg_clean_partial(kmsg
, 0, NULL
, 0, 0);
3187 * Routine: ipc_kmsg_copyin
3189 * "Copy-in" port rights and out-of-line memory
3192 * In all failure cases, the message is left holding
3193 * no rights or memory. However, the message buffer
3194 * is not deallocated. If successful, the message
3195 * contains a valid destination port.
3199 * MACH_MSG_SUCCESS Successful copyin.
3200 * MACH_SEND_INVALID_HEADER
3201 * Illegal value in the message header bits.
3202 * MACH_SEND_INVALID_DEST Can't copyin destination port.
3203 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
3204 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
3205 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
3206 * MACH_SEND_INVALID_TYPE Bad type specification.
3207 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
3215 mach_msg_priority_t override
,
3216 mach_msg_option_t
*optionp
)
3218 mach_msg_return_t mr
;
3220 kmsg
->ikm_header
->msgh_bits
&= MACH_MSGH_BITS_USER
;
3222 mr
= ipc_kmsg_copyin_header(kmsg
, space
, override
, optionp
);
3224 if (mr
!= MACH_MSG_SUCCESS
)
3227 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
,MACH_IPC_MSG_SEND
) | DBG_FUNC_NONE
,
3228 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
3229 (uintptr_t)kmsg
->ikm_header
->msgh_bits
,
3230 (uintptr_t)kmsg
->ikm_header
->msgh_id
,
3231 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(kmsg
->ikm_voucher
)),
3234 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_copyin header:\n%.8x\n%.8x\n%p\n%p\n%p\n%.8x\n",
3235 kmsg
->ikm_header
->msgh_size
,
3236 kmsg
->ikm_header
->msgh_bits
,
3237 kmsg
->ikm_header
->msgh_remote_port
,
3238 kmsg
->ikm_header
->msgh_local_port
,
3240 kmsg
->ikm_header
->msgh_id
);
3242 if ((kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
3243 return MACH_MSG_SUCCESS
;
3245 mr
= ipc_kmsg_copyin_body( kmsg
, space
, map
);
3247 /* unreachable if !DEBUG */
3248 __unreachable_ok_push
3249 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK
))
3253 for(i
=0;i
*4 < (kmsg
->ikm_header
->msgh_size
- sizeof(mach_msg_header_t
));i
++)
3255 kprintf("%.4x\n",((uint32_t *)(kmsg
->ikm_header
+ 1))[i
]);
3258 __unreachable_ok_pop
3264 * Routine: ipc_kmsg_copyin_from_kernel
3266 * "Copy-in" port rights and out-of-line memory
3267 * in a message sent from the kernel.
3269 * Because the message comes from the kernel,
3270 * the implementation assumes there are no errors
3271 * or peculiarities in the message.
3277 ipc_kmsg_copyin_from_kernel(
3280 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
3281 mach_msg_type_name_t rname
= MACH_MSGH_BITS_REMOTE(bits
);
3282 mach_msg_type_name_t lname
= MACH_MSGH_BITS_LOCAL(bits
);
3283 ipc_object_t remote
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
3284 ipc_object_t local
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
3286 /* translate the destination and reply ports */
3287 if (!IO_VALID(remote
))
3288 return MACH_SEND_INVALID_DEST
;
3290 ipc_object_copyin_from_kernel(remote
, rname
);
3291 if (IO_VALID(local
))
3292 ipc_object_copyin_from_kernel(local
, lname
);
3295 * The common case is a complex message with no reply port,
3296 * because that is what the memory_object interface uses.
3299 if (bits
== (MACH_MSGH_BITS_COMPLEX
|
3300 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0))) {
3301 bits
= (MACH_MSGH_BITS_COMPLEX
|
3302 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND
, 0));
3304 kmsg
->ikm_header
->msgh_bits
= bits
;
3306 bits
= (MACH_MSGH_BITS_OTHER(bits
) |
3307 MACH_MSGH_BITS(ipc_object_copyin_type(rname
),
3308 ipc_object_copyin_type(lname
)));
3310 kmsg
->ikm_header
->msgh_bits
= bits
;
3311 if ((bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
3312 return MACH_MSG_SUCCESS
;
3315 mach_msg_descriptor_t
*saddr
;
3316 mach_msg_body_t
*body
;
3317 mach_msg_type_number_t i
, count
;
3319 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3320 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
3321 count
= body
->msgh_descriptor_count
;
3323 for (i
= 0; i
< count
; i
++, saddr
++) {
3325 switch (saddr
->type
.type
) {
3327 case MACH_MSG_PORT_DESCRIPTOR
: {
3328 mach_msg_type_name_t name
;
3329 ipc_object_t object
;
3330 mach_msg_port_descriptor_t
*dsc
;
3334 /* this is really the type SEND, SEND_ONCE, etc. */
3335 name
= dsc
->disposition
;
3336 object
= (ipc_object_t
) dsc
->name
;
3337 dsc
->disposition
= ipc_object_copyin_type(name
);
3339 if (!IO_VALID(object
)) {
3343 ipc_object_copyin_from_kernel(object
, name
);
3345 /* CDY avoid circularity when the destination is also */
3346 /* the kernel. This check should be changed into an */
3347 /* assert when the new kobject model is in place since*/
3348 /* ports will not be used in kernel to kernel chats */
3350 if (((ipc_port_t
)remote
)->ip_receiver
!= ipc_space_kernel
) {
3351 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3352 ipc_port_check_circularity((ipc_port_t
) object
,
3353 (ipc_port_t
) remote
)) {
3354 kmsg
->ikm_header
->msgh_bits
|=
3355 MACH_MSGH_BITS_CIRCULAR
;
3360 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3361 case MACH_MSG_OOL_DESCRIPTOR
: {
3363 * The sender should supply ready-made memory, i.e.
3364 * a vm_map_copy_t, so we don't need to do anything.
3368 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
3369 ipc_object_t
*objects
;
3371 mach_msg_type_name_t name
;
3372 mach_msg_ool_ports_descriptor_t
*dsc
;
3374 dsc
= (mach_msg_ool_ports_descriptor_t
*)&saddr
->ool_ports
;
3376 /* this is really the type SEND, SEND_ONCE, etc. */
3377 name
= dsc
->disposition
;
3378 dsc
->disposition
= ipc_object_copyin_type(name
);
3380 objects
= (ipc_object_t
*) dsc
->address
;
3382 for ( j
= 0; j
< dsc
->count
; j
++) {
3383 ipc_object_t object
= objects
[j
];
3385 if (!IO_VALID(object
))
3388 ipc_object_copyin_from_kernel(object
, name
);
3390 if ((dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3391 ipc_port_check_circularity(
3392 (ipc_port_t
) object
,
3393 (ipc_port_t
) remote
))
3394 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
3400 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3401 #endif /* MACH_ASSERT */
3406 return MACH_MSG_SUCCESS
;
3409 #if IKM_SUPPORT_LEGACY
3411 ipc_kmsg_copyin_from_kernel_legacy(
3414 mach_msg_bits_t bits
= kmsg
->ikm_header
->msgh_bits
;
3415 mach_msg_type_name_t rname
= MACH_MSGH_BITS_REMOTE(bits
);
3416 mach_msg_type_name_t lname
= MACH_MSGH_BITS_LOCAL(bits
);
3417 ipc_object_t remote
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
3418 ipc_object_t local
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
3420 /* translate the destination and reply ports */
3421 if (!IO_VALID(remote
))
3422 return MACH_SEND_INVALID_DEST
;
3424 ipc_object_copyin_from_kernel(remote
, rname
);
3425 if (IO_VALID(local
))
3426 ipc_object_copyin_from_kernel(local
, lname
);
3429 * The common case is a complex message with no reply port,
3430 * because that is what the memory_object interface uses.
3433 if (bits
== (MACH_MSGH_BITS_COMPLEX
|
3434 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0))) {
3435 bits
= (MACH_MSGH_BITS_COMPLEX
|
3436 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND
, 0));
3438 kmsg
->ikm_header
->msgh_bits
= bits
;
3440 bits
= (MACH_MSGH_BITS_OTHER(bits
) |
3441 MACH_MSGH_BITS(ipc_object_copyin_type(rname
),
3442 ipc_object_copyin_type(lname
)));
3444 kmsg
->ikm_header
->msgh_bits
= bits
;
3445 if ((bits
& MACH_MSGH_BITS_COMPLEX
) == 0)
3446 return MACH_MSG_SUCCESS
;
3449 mach_msg_legacy_descriptor_t
*saddr
;
3450 mach_msg_descriptor_t
*daddr
;
3451 mach_msg_body_t
*body
;
3452 mach_msg_type_number_t i
, count
;
3454 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
3455 saddr
= (typeof(saddr
)) (body
+ 1);
3456 count
= body
->msgh_descriptor_count
;
3459 vm_offset_t dsc_adjust
= 4*count
;
3460 memmove((char *)(((vm_offset_t
)kmsg
->ikm_header
) - dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
3461 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
- dsc_adjust
);
3462 /* Update the message size for the larger in-kernel representation */
3463 kmsg
->ikm_header
->msgh_size
+= dsc_adjust
;
3465 daddr
= (mach_msg_descriptor_t
*)((vm_offset_t
)kmsg
->ikm_header
+ sizeof(mach_msg_base_t
));
3467 for (i
= 0; i
< count
; i
++, saddr
++, daddr
++) {
3468 switch (saddr
->type
.type
) {
3470 case MACH_MSG_PORT_DESCRIPTOR
: {
3471 mach_msg_type_name_t name
;
3472 ipc_object_t object
;
3473 mach_msg_legacy_port_descriptor_t
*dsc
;
3474 mach_msg_port_descriptor_t
*dest_dsc
;
3476 dsc
= (typeof(dsc
))&saddr
->port
;
3477 dest_dsc
= &daddr
->port
;
3479 /* this is really the type SEND, SEND_ONCE, etc. */
3480 name
= dsc
->disposition
;
3481 object
= (ipc_object_t
) CAST_MACH_NAME_TO_PORT(dsc
->name
);
3482 dest_dsc
->disposition
= ipc_object_copyin_type(name
);
3483 dest_dsc
->name
= (mach_port_t
)object
;
3484 dest_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
3486 if (!IO_VALID(object
)) {
3490 ipc_object_copyin_from_kernel(object
, name
);
3492 /* CDY avoid circularity when the destination is also */
3493 /* the kernel. This check should be changed into an */
3494 /* assert when the new kobject model is in place since*/
3495 /* ports will not be used in kernel to kernel chats */
3497 if (((ipc_port_t
)remote
)->ip_receiver
!= ipc_space_kernel
) {
3498 if ((dest_dsc
->disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3499 ipc_port_check_circularity((ipc_port_t
) object
,
3500 (ipc_port_t
) remote
)) {
3501 kmsg
->ikm_header
->msgh_bits
|=
3502 MACH_MSGH_BITS_CIRCULAR
;
3507 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
3508 case MACH_MSG_OOL_DESCRIPTOR
: {
3509 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
3510 * so we don't need to do anything special. */
3512 mach_msg_ool_descriptor32_t
*source_dsc
= &saddr
->out_of_line32
;
3513 mach_msg_ool_descriptor_t
*dest_dsc
= (typeof(dest_dsc
))&daddr
->out_of_line
;
3515 vm_offset_t address
= source_dsc
->address
;
3516 vm_size_t size
= source_dsc
->size
;
3517 boolean_t deallocate
= source_dsc
->deallocate
;
3518 mach_msg_copy_options_t copy
= source_dsc
->copy
;
3519 mach_msg_descriptor_type_t type
= source_dsc
->type
;
3521 dest_dsc
->address
= (void *)address
;
3522 dest_dsc
->size
= size
;
3523 dest_dsc
->deallocate
= deallocate
;
3524 dest_dsc
->copy
= copy
;
3525 dest_dsc
->type
= type
;
3528 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
3529 ipc_object_t
*objects
;
3531 mach_msg_type_name_t name
;
3532 mach_msg_ool_ports_descriptor_t
*dest_dsc
;
3534 mach_msg_ool_ports_descriptor32_t
*source_dsc
= &saddr
->ool_ports32
;
3535 dest_dsc
= (typeof(dest_dsc
))&daddr
->ool_ports
;
3537 boolean_t deallocate
= source_dsc
->deallocate
;
3538 mach_msg_copy_options_t copy
= source_dsc
->copy
;
3539 mach_msg_size_t port_count
= source_dsc
->count
;
3540 mach_msg_type_name_t disposition
= source_dsc
->disposition
;
3542 /* this is really the type SEND, SEND_ONCE, etc. */
3544 disposition
= ipc_object_copyin_type(name
);
3546 objects
= (ipc_object_t
*) (uintptr_t)source_dsc
->address
;
3548 for ( j
= 0; j
< port_count
; j
++) {
3549 ipc_object_t object
= objects
[j
];
3551 if (!IO_VALID(object
))
3554 ipc_object_copyin_from_kernel(object
, name
);
3556 if ((disposition
== MACH_MSG_TYPE_PORT_RECEIVE
) &&
3557 ipc_port_check_circularity(
3558 (ipc_port_t
) object
,
3559 (ipc_port_t
) remote
))
3560 kmsg
->ikm_header
->msgh_bits
|= MACH_MSGH_BITS_CIRCULAR
;
3563 dest_dsc
->address
= objects
;
3564 dest_dsc
->deallocate
= deallocate
;
3565 dest_dsc
->copy
= copy
;
3566 dest_dsc
->disposition
= disposition
;
3567 dest_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
3568 dest_dsc
->count
= port_count
;
3573 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3574 #endif /* MACH_ASSERT */
3579 return MACH_MSG_SUCCESS
;
3581 #endif /* IKM_SUPPORT_LEGACY */
3584 * Routine: ipc_kmsg_copyout_header
3586 * "Copy-out" port rights in the header of a message.
3587 * Operates atomically; if it doesn't succeed the
3588 * message header and the space are left untouched.
3589 * If it does succeed the remote/local port fields
3590 * contain port names instead of object pointers,
3591 * and the bits field is updated.
3595 * MACH_MSG_SUCCESS Copied out port rights.
3596 * MACH_RCV_INVALID_NOTIFY
3597 * Notify is non-null and doesn't name a receive right.
3598 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
3599 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
3600 * The space is dead.
3601 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
3602 * No room in space for another name.
3603 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
3604 * Couldn't allocate memory for the reply port.
3605 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
3606 * Couldn't allocate memory for the dead-name request.
3610 ipc_kmsg_copyout_header(
3613 mach_msg_option_t option
)
3615 mach_msg_header_t
*msg
= kmsg
->ikm_header
;
3616 mach_msg_bits_t mbits
= msg
->msgh_bits
;
3617 ipc_port_t dest
= (ipc_port_t
) msg
->msgh_remote_port
;
3619 assert(IP_VALID(dest
));
3622 * While we still hold a reference on the received-from port,
3623 * process all send-possible notfications we received along with
3626 ipc_port_spnotify(dest
);
3629 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
3630 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
3631 mach_msg_type_name_t voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
3632 ipc_port_t reply
= msg
->msgh_local_port
;
3633 ipc_port_t release_reply_port
= IP_NULL
;
3634 mach_port_name_t dest_name
, reply_name
;
3636 ipc_port_t voucher
= kmsg
->ikm_voucher
;
3637 ipc_port_t release_voucher_port
= IP_NULL
;
3638 mach_port_name_t voucher_name
;
3640 uint32_t entries_held
= 0;
3641 boolean_t need_write_lock
= FALSE
;
3645 * Reserve any potentially needed entries in the target space.
3646 * We'll free any unused before unlocking the space.
3648 if (IP_VALID(reply
)) {
3650 need_write_lock
= TRUE
;
3652 if (IP_VALID(voucher
)) {
3653 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
3655 if ((option
& MACH_RCV_VOUCHER
) != 0)
3657 need_write_lock
= TRUE
;
3660 if (need_write_lock
) {
3662 is_write_lock(space
);
3664 while(entries_held
) {
3665 if (!is_active(space
)) {
3666 is_write_unlock(space
);
3667 return (MACH_RCV_HEADER_ERROR
|
3668 MACH_MSG_IPC_SPACE
);
3671 kr
= ipc_entries_hold(space
, entries_held
);
3672 if (KERN_SUCCESS
== kr
)
3675 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
3676 if (KERN_SUCCESS
!= kr
)
3677 return(MACH_RCV_HEADER_ERROR
|
3678 MACH_MSG_IPC_SPACE
);
3679 /* space was unlocked and relocked - retry */
3682 /* Handle reply port. */
3683 if (IP_VALID(reply
)) {
3686 /* Is there already an entry we can use? */
3687 if ((reply_type
!= MACH_MSG_TYPE_PORT_SEND_ONCE
) &&
3688 ipc_right_reverse(space
, (ipc_object_t
) reply
, &reply_name
, &entry
)) {
3689 /* reply port is locked and active */
3690 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND_RECEIVE
);
3693 if (!ip_active(reply
)) {
3696 release_reply_port
= reply
;
3698 reply_name
= MACH_PORT_DEAD
;
3699 goto done_with_reply
;
3702 /* claim a held entry for the reply port */
3703 assert(entries_held
> 0);
3705 ipc_entry_claim(space
, &reply_name
, &entry
);
3706 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
3707 assert(entry
->ie_object
== IO_NULL
);
3708 entry
->ie_object
= (ipc_object_t
) reply
;
3711 /* space and reply port are locked and active */
3712 ip_reference(reply
); /* hold onto the reply port */
3714 kr
= ipc_right_copyout(space
, reply_name
, entry
,
3715 reply_type
, TRUE
, (ipc_object_t
) reply
);
3716 assert(kr
== KERN_SUCCESS
);
3717 /* reply port is unlocked */
3719 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
3723 /* Handle voucher port. */
3724 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
3725 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
3727 if (!IP_VALID(voucher
)) {
3728 if ((option
& MACH_RCV_VOUCHER
) == 0) {
3729 voucher_type
= MACH_MSGH_BITS_ZERO
;
3731 voucher_name
= MACH_PORT_NULL
;
3732 goto done_with_voucher
;
3735 /* clear voucher from its hiding place back in the kmsg */
3736 kmsg
->ikm_voucher
= IP_NULL
;
3738 if ((option
& MACH_RCV_VOUCHER
) != 0) {
3741 if (ipc_right_reverse(space
, (ipc_object_t
) voucher
,
3742 &voucher_name
, &entry
)) {
3743 /* voucher port locked */
3744 assert(entry
->ie_bits
& MACH_PORT_TYPE_SEND
);
3746 assert(entries_held
> 0);
3748 ipc_entry_claim(space
, &voucher_name
, &entry
);
3749 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
);
3750 assert(entry
->ie_object
== IO_NULL
);
3751 entry
->ie_object
= (ipc_object_t
) voucher
;
3754 /* space is locked and active */
3756 assert(ip_active(voucher
));
3757 assert(ip_kotype(voucher
) == IKOT_VOUCHER
);
3758 kr
= ipc_right_copyout(space
, voucher_name
, entry
,
3759 MACH_MSG_TYPE_MOVE_SEND
, TRUE
,
3760 (ipc_object_t
) voucher
);
3761 /* voucher port is unlocked */
3763 voucher_type
= MACH_MSGH_BITS_ZERO
;
3764 release_voucher_port
= voucher
;
3765 voucher_name
= MACH_PORT_NULL
;
3768 voucher_name
= msg
->msgh_voucher_port
;
3774 is_write_unlock(space
);
3778 * No reply or voucher port! This is an easy case.
3779 * We only need to have the space locked
3780 * when locking the destination.
3783 is_read_lock(space
);
3784 if (!is_active(space
)) {
3785 is_read_unlock(space
);
3786 return MACH_RCV_HEADER_ERROR
|MACH_MSG_IPC_SPACE
;
3790 is_read_unlock(space
);
3792 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
3794 if (voucher_type
!= MACH_MSGH_BITS_ZERO
) {
3795 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
3796 if ((option
& MACH_RCV_VOUCHER
) == 0) {
3797 voucher_type
= MACH_MSGH_BITS_ZERO
;
3799 voucher_name
= MACH_PORT_NULL
;
3801 voucher_name
= msg
->msgh_voucher_port
;
3806 * At this point, the space is unlocked and the destination
3807 * port is locked. (Lock taken while space was locked.)
3808 * reply_name is taken care of; we still need dest_name.
3809 * We still hold a ref for reply (if it is valid).
3811 * If the space holds receive rights for the destination,
3812 * we return its name for the right. Otherwise the task
3813 * managed to destroy or give away the receive right between
3814 * receiving the message and this copyout. If the destination
3815 * is dead, return MACH_PORT_DEAD, and if the receive right
3816 * exists somewhere else (another space, in transit)
3817 * return MACH_PORT_NULL.
3819 * Making this copyout operation atomic with the previous
3820 * copyout of the reply port is a bit tricky. If there was
3821 * no real reply port (it wasn't IP_VALID) then this isn't
3822 * an issue. If the reply port was dead at copyout time,
3823 * then we are OK, because if dest is dead we serialize
3824 * after the death of both ports and if dest is alive
3825 * we serialize after reply died but before dest's (later) death.
3826 * So assume reply was alive when we copied it out. If dest
3827 * is alive, then we are OK because we serialize before
3828 * the ports' deaths. So assume dest is dead when we look at it.
3829 * If reply dies/died after dest, then we are OK because
3830 * we serialize after dest died but before reply dies.
3831 * So the hard case is when reply is alive at copyout,
3832 * dest is dead at copyout, and reply died before dest died.
3833 * In this case pretend that dest is still alive, so
3834 * we serialize while both ports are alive.
3836 * Because the space lock is held across the copyout of reply
3837 * and locking dest, the receive right for dest can't move
3838 * in or out of the space while the copyouts happen, so
3839 * that isn't an atomicity problem. In the last hard case
3840 * above, this implies that when dest is dead that the
3841 * space couldn't have had receive rights for dest at
3842 * the time reply was copied-out, so when we pretend
3843 * that dest is still alive, we can return MACH_PORT_NULL.
3845 * If dest == reply, then we have to make it look like
3846 * either both copyouts happened before the port died,
3847 * or both happened after the port died. This special
3848 * case works naturally if the timestamp comparison
3849 * is done correctly.
3852 if (ip_active(dest
)) {
3853 ipc_object_copyout_dest(space
, (ipc_object_t
) dest
,
3854 dest_type
, &dest_name
);
3855 /* dest is unlocked */
3858 ipc_port_timestamp_t timestamp
;
3860 timestamp
= dest
->ip_timestamp
;
3864 if (IP_VALID(reply
)) {
3866 if (ip_active(reply
) ||
3867 IP_TIMESTAMP_ORDER(timestamp
,
3868 reply
->ip_timestamp
))
3869 dest_name
= MACH_PORT_DEAD
;
3871 dest_name
= MACH_PORT_NULL
;
3874 dest_name
= MACH_PORT_DEAD
;
3877 if (IP_VALID(reply
))
3880 if (IP_VALID(release_reply_port
)) {
3881 if (reply_type
== MACH_MSG_TYPE_PORT_SEND_ONCE
)
3882 ipc_port_release_sonce(release_reply_port
);
3884 ipc_port_release_send(release_reply_port
);
3887 if (IP_VALID(release_voucher_port
))
3888 ipc_port_release_send(release_voucher_port
);
3891 if ((option
& MACH_RCV_VOUCHER
) != 0) {
3892 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_MSG_RECV
) | DBG_FUNC_NONE
,
3893 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
3894 (uintptr_t)kmsg
->ikm_header
->msgh_bits
,
3895 (uintptr_t)kmsg
->ikm_header
->msgh_id
,
3896 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(voucher
)),
3899 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC
, MACH_IPC_MSG_RECV_VOUCHER_REFUSED
) | DBG_FUNC_NONE
,
3900 VM_KERNEL_ADDRPERM((uintptr_t)kmsg
),
3901 (uintptr_t)kmsg
->ikm_header
->msgh_bits
,
3902 (uintptr_t)kmsg
->ikm_header
->msgh_id
,
3903 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(voucher
)),
3907 msg
->msgh_bits
= MACH_MSGH_BITS_SET(reply_type
, dest_type
,
3908 voucher_type
, mbits
);
3909 msg
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
3910 msg
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
3911 msg
->msgh_voucher_port
= voucher_name
;
3914 return MACH_MSG_SUCCESS
;
3918 * Routine: ipc_kmsg_copyout_object
3920 * Copy-out a port right. Always returns a name,
3921 * even for unsuccessful return codes. Always
3922 * consumes the supplied object.
3926 * MACH_MSG_SUCCESS The space acquired the right
3927 * (name is valid) or the object is dead (MACH_PORT_DEAD).
3928 * MACH_MSG_IPC_SPACE No room in space for the right,
3929 * or the space is dead. (Name is MACH_PORT_NULL.)
3930 * MACH_MSG_IPC_KERNEL Kernel resource shortage.
3931 * (Name is MACH_PORT_NULL.)
3935 ipc_kmsg_copyout_object(
3937 ipc_object_t object
,
3938 mach_msg_type_name_t msgt_name
,
3939 mach_port_name_t
*namep
)
3943 if (!IO_VALID(object
)) {
3944 *namep
= CAST_MACH_PORT_TO_NAME(object
);
3945 return MACH_MSG_SUCCESS
;
3948 kr
= ipc_object_copyout(space
, object
, msgt_name
, TRUE
, namep
);
3949 if (kr
!= KERN_SUCCESS
) {
3950 ipc_object_destroy(object
, msgt_name
);
3952 if (kr
== KERN_INVALID_CAPABILITY
)
3953 *namep
= MACH_PORT_DEAD
;
3955 *namep
= MACH_PORT_NULL
;
3957 if (kr
== KERN_RESOURCE_SHORTAGE
)
3958 return MACH_MSG_IPC_KERNEL
;
3960 return MACH_MSG_IPC_SPACE
;
3964 return MACH_MSG_SUCCESS
;
3967 mach_msg_descriptor_t
*
3968 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t
*dsc
,
3969 mach_msg_descriptor_t
*user_dsc
,
3972 mach_msg_descriptor_t
*
3973 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t
*dsc
,
3974 mach_msg_descriptor_t
*dest_dsc
,
3979 mach_port_name_t name
;
3980 mach_msg_type_name_t disp
;
3983 /* Copyout port right carried in the message */
3984 port
= dsc
->port
.name
;
3985 disp
= dsc
->port
.disposition
;
3986 *mr
|= ipc_kmsg_copyout_object(space
,
3991 if(current_task() == kernel_task
)
3993 mach_msg_port_descriptor_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
3994 user_dsc
--; // point to the start of this port descriptor
3995 bzero((void *)user_dsc
, sizeof(*user_dsc
));
3996 user_dsc
->name
= CAST_MACH_NAME_TO_PORT(name
);
3997 user_dsc
->disposition
= disp
;
3998 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
3999 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
4001 mach_msg_legacy_port_descriptor_t
*user_dsc
= (typeof(user_dsc
))dest_dsc
;
4002 user_dsc
--; // point to the start of this port descriptor
4003 bzero((void *)user_dsc
, sizeof(*user_dsc
));
4004 user_dsc
->name
= CAST_MACH_PORT_TO_NAME(name
);
4005 user_dsc
->disposition
= disp
;
4006 user_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
4007 dest_dsc
= (typeof(dest_dsc
))user_dsc
;
4010 return (mach_msg_descriptor_t
*)dest_dsc
;
4013 mach_msg_descriptor_t
*
4014 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
);
4015 mach_msg_descriptor_t
*
4016 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
)
4019 vm_map_address_t rcv_addr
;
4020 mach_msg_copy_options_t copy_options
;
4022 mach_msg_descriptor_type_t dsc_type
;
4024 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4026 copy
= (vm_map_copy_t
)dsc
->address
;
4027 size
= (vm_map_size_t
)dsc
->size
;
4028 copy_options
= dsc
->copy
;
4029 assert(copy_options
!= MACH_MSG_KALLOC_COPY_T
);
4030 dsc_type
= dsc
->type
;
4032 if (copy
!= VM_MAP_COPY_NULL
) {
4036 if (vm_map_copy_validate_size(map
, copy
, &size
) == FALSE
)
4037 panic("Inconsistent OOL/copyout size on %p: expected %d, got %lld @%p",
4038 dsc
, dsc
->size
, (unsigned long long)copy
->size
, copy
);
4039 kr
= vm_map_copyout_size(map
, &rcv_addr
, copy
, size
);
4040 if (kr
!= KERN_SUCCESS
) {
4041 if (kr
== KERN_RESOURCE_SHORTAGE
)
4042 *mr
|= MACH_MSG_VM_KERNEL
;
4044 *mr
|= MACH_MSG_VM_SPACE
;
4045 vm_map_copy_discard(copy
);
4055 * Now update the descriptor as the user would see it.
4056 * This may require expanding the descriptor to the user
4057 * visible size. There is already space allocated for
4058 * this in what naddr points to.
4060 if(current_task() == kernel_task
)
4062 mach_msg_ool_descriptor_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4064 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4066 user_ool_dsc
->address
= (void *)(uintptr_t)rcv_addr
;
4067 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4069 user_ool_dsc
->copy
= copy_options
;
4070 user_ool_dsc
->type
= dsc_type
;
4071 user_ool_dsc
->size
= (mach_msg_size_t
)size
;
4073 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4074 } else if (is_64bit
) {
4075 mach_msg_ool_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4077 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4079 user_ool_dsc
->address
= rcv_addr
;
4080 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4082 user_ool_dsc
->copy
= copy_options
;
4083 user_ool_dsc
->type
= dsc_type
;
4084 user_ool_dsc
->size
= (mach_msg_size_t
)size
;
4086 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4088 mach_msg_ool_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4090 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4092 user_ool_dsc
->address
= CAST_DOWN_EXPLICIT(uint32_t, rcv_addr
);
4093 user_ool_dsc
->size
= (mach_msg_size_t
)size
;
4094 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4096 user_ool_dsc
->copy
= copy_options
;
4097 user_ool_dsc
->type
= dsc_type
;
4099 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4104 mach_msg_descriptor_t
*
4105 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t
*dsc
,
4106 mach_msg_descriptor_t
*user_dsc
,
4111 mach_msg_return_t
*mr
);
4112 mach_msg_descriptor_t
*
4113 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t
*dsc
,
4114 mach_msg_descriptor_t
*user_dsc
,
4119 mach_msg_return_t
*mr
)
4121 mach_vm_offset_t rcv_addr
= 0;
4122 mach_msg_type_name_t disp
;
4123 mach_msg_type_number_t count
, i
;
4124 vm_size_t ports_length
, names_length
;
4126 mach_msg_copy_options_t copy_options
= MACH_MSG_VIRTUAL_COPY
;
4128 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4131 disp
= dsc
->disposition
;
4132 ports_length
= count
* sizeof(mach_port_t
);
4133 names_length
= count
* sizeof(mach_port_name_t
);
4135 if (ports_length
!= 0 && dsc
->address
!= 0) {
4138 * Check to see if there is an overwrite descriptor
4139 * specified in the scatter list for this ool data.
4140 * The descriptor has already been verified.
4143 if (saddr
!= MACH_MSG_DESCRIPTOR_NULL
) {
4145 OTHER_OOL_DESCRIPTOR
*scatter_dsc
;
4147 scatter_dsc
= (OTHER_OOL_DESCRIPTOR
*)saddr
;
4148 rcv_addr
= (mach_vm_offset_t
) scatter_dsc
->address
;
4149 copy_options
= scatter_dsc
->copy
;
4151 mach_msg_ool_descriptor_t
*scatter_dsc
;
4153 scatter_dsc
= &saddr
->out_of_line
;
4154 rcv_addr
= CAST_USER_ADDR_T(scatter_dsc
->address
);
4155 copy_options
= scatter_dsc
->copy
;
4157 INCREMENT_SCATTER(saddr
, sdsc_count
, differs
);
4161 if (copy_options
== MACH_MSG_VIRTUAL_COPY
) {
4163 * Dynamically allocate the region
4166 if (vm_kernel_map_is_kernel(map
)) tag
= VM_KERN_MEMORY_IPC
;
4167 else tag
= VM_MEMORY_MACH_MSG
;
4170 if ((kr
= mach_vm_allocate_kernel(map
, &rcv_addr
,
4171 (mach_vm_size_t
)names_length
,
4172 VM_FLAGS_ANYWHERE
, tag
)) != KERN_SUCCESS
) {
4173 ipc_kmsg_clean_body(kmsg
, 1, (mach_msg_descriptor_t
*)dsc
);
4176 if (kr
== KERN_RESOURCE_SHORTAGE
){
4177 *mr
|= MACH_MSG_VM_KERNEL
;
4179 *mr
|= MACH_MSG_VM_SPACE
;
4185 * Handle the port rights and copy out the names
4186 * for those rights out to user-space.
4188 if (rcv_addr
!= 0) {
4189 mach_port_t
*objects
= (mach_port_t
*) dsc
->address
;
4190 mach_port_name_t
*names
= (mach_port_name_t
*) dsc
->address
;
4192 /* copyout port rights carried in the message */
4194 for ( i
= 0; i
< count
; i
++) {
4195 ipc_object_t object
= (ipc_object_t
)objects
[i
];
4197 *mr
|= ipc_kmsg_copyout_object(space
, object
,
4201 /* copyout to memory allocated above */
4202 void *data
= dsc
->address
;
4203 if (copyoutmap(map
, data
, rcv_addr
, names_length
) != KERN_SUCCESS
)
4204 *mr
|= MACH_MSG_VM_SPACE
;
4205 kfree(data
, ports_length
);
4212 * Now update the descriptor based on the information
4215 if(current_task() == kernel_task
) {
4216 mach_msg_ool_ports_descriptor_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4218 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4220 user_ool_dsc
->address
= (void *)(uintptr_t)rcv_addr
;
4221 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4223 user_ool_dsc
->copy
= copy_options
;
4224 user_ool_dsc
->disposition
= disp
;
4225 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
4226 user_ool_dsc
->count
= count
;
4228 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4230 mach_msg_ool_ports_descriptor64_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4232 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4234 user_ool_dsc
->address
= rcv_addr
;
4235 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4237 user_ool_dsc
->copy
= copy_options
;
4238 user_ool_dsc
->disposition
= disp
;
4239 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
4240 user_ool_dsc
->count
= count
;
4242 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4244 mach_msg_ool_ports_descriptor32_t
*user_ool_dsc
= (typeof(user_ool_dsc
))user_dsc
;
4246 bzero((void *)user_ool_dsc
, sizeof(*user_ool_dsc
));
4248 user_ool_dsc
->address
= CAST_DOWN_EXPLICIT(uint32_t, rcv_addr
);
4249 user_ool_dsc
->count
= count
;
4250 user_ool_dsc
->deallocate
= (copy_options
== MACH_MSG_VIRTUAL_COPY
) ?
4252 user_ool_dsc
->copy
= copy_options
;
4253 user_ool_dsc
->disposition
= disp
;
4254 user_ool_dsc
->type
= MACH_MSG_OOL_PORTS_DESCRIPTOR
;
4256 user_dsc
= (typeof(user_dsc
))user_ool_dsc
;
4262 * Routine: ipc_kmsg_copyout_body
4264 * "Copy-out" port rights and out-of-line memory
4265 * in the body of a message.
4267 * The error codes are a combination of special bits.
4268 * The copyout proceeds despite errors.
4272 * MACH_MSG_SUCCESS Successful copyout.
4273 * MACH_MSG_IPC_SPACE No room for port right in name space.
4274 * MACH_MSG_VM_SPACE No room for memory in address space.
4275 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
4276 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
4277 * MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
4281 ipc_kmsg_copyout_body(
4285 mach_msg_body_t
*slist
)
4287 mach_msg_body_t
*body
;
4288 mach_msg_descriptor_t
*kern_dsc
, *user_dsc
;
4289 mach_msg_descriptor_t
*saddr
;
4290 mach_msg_type_number_t dsc_count
, sdsc_count
;
4292 mach_msg_return_t mr
= MACH_MSG_SUCCESS
;
4293 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
4295 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
4296 dsc_count
= body
->msgh_descriptor_count
;
4297 kern_dsc
= (mach_msg_descriptor_t
*) (body
+ 1);
4298 /* Point user_dsc just after the end of all the descriptors */
4299 user_dsc
= &kern_dsc
[dsc_count
];
4301 /* Do scatter list setup */
4302 if (slist
!= MACH_MSG_BODY_NULL
) {
4303 panic("Scatter lists disabled");
4304 saddr
= (mach_msg_descriptor_t
*) (slist
+ 1);
4305 sdsc_count
= slist
->msgh_descriptor_count
;
4308 saddr
= MACH_MSG_DESCRIPTOR_NULL
;
4312 /* Now process the descriptors */
4313 for (i
= dsc_count
-1; i
>= 0; i
--) {
4314 switch (kern_dsc
[i
].type
.type
) {
4316 case MACH_MSG_PORT_DESCRIPTOR
:
4317 user_dsc
= ipc_kmsg_copyout_port_descriptor(&kern_dsc
[i
], user_dsc
, space
, &mr
);
4319 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4320 case MACH_MSG_OOL_DESCRIPTOR
:
4321 user_dsc
= ipc_kmsg_copyout_ool_descriptor(
4322 (mach_msg_ool_descriptor_t
*)&kern_dsc
[i
], user_dsc
, is_task_64bit
, map
, &mr
);
4324 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
4325 user_dsc
= ipc_kmsg_copyout_ool_ports_descriptor(
4326 (mach_msg_ool_ports_descriptor_t
*)&kern_dsc
[i
], user_dsc
, is_task_64bit
, map
, space
, kmsg
, &mr
);
4329 panic("untyped IPC copyout body: invalid message descriptor");
4334 if(user_dsc
!= kern_dsc
) {
4335 vm_offset_t dsc_adjust
= (vm_offset_t
)user_dsc
- (vm_offset_t
)kern_dsc
;
4336 memmove((char *)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
4337 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
);
4338 /* Update the message size for the smaller user representation */
4339 kmsg
->ikm_header
->msgh_size
-= (mach_msg_size_t
)dsc_adjust
;
4346 * Routine: ipc_kmsg_copyout_size
4348 * Compute the size of the message as copied out to the given
4349 * map. If the destination map's pointers are a different size
4350 * than the kernel's, we have to allow for expansion/
4351 * contraction of the descriptors as appropriate.
4355 * size of the message as it would be received.
4359 ipc_kmsg_copyout_size(
4363 mach_msg_size_t send_size
;
4365 send_size
= kmsg
->ikm_header
->msgh_size
;
4367 boolean_t is_task_64bit
= (map
->max_offset
> VM_MAX_ADDRESS
);
4369 #if defined(__LP64__)
4370 send_size
-= LEGACY_HEADER_SIZE_DELTA
;
4373 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
4375 mach_msg_body_t
*body
;
4376 mach_msg_descriptor_t
*saddr
, *eaddr
;
4378 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
4379 saddr
= (mach_msg_descriptor_t
*) (body
+ 1);
4380 eaddr
= saddr
+ body
->msgh_descriptor_count
;
4382 for ( ; saddr
< eaddr
; saddr
++ ) {
4383 switch (saddr
->type
.type
) {
4384 case MACH_MSG_OOL_DESCRIPTOR
:
4385 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4386 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
4388 send_size
-= DESC_SIZE_ADJUSTMENT
;
4390 case MACH_MSG_PORT_DESCRIPTOR
:
4391 send_size
-= DESC_SIZE_ADJUSTMENT
;
4402 * Routine: ipc_kmsg_copyout
4404 * "Copy-out" port rights and out-of-line memory
4409 * MACH_MSG_SUCCESS Copied out all rights and memory.
4410 * MACH_RCV_HEADER_ERROR + special bits
4411 * Rights and memory in the message are intact.
4412 * MACH_RCV_BODY_ERROR + special bits
4413 * The message header was successfully copied out.
4414 * As much of the body was handled as possible.
4422 mach_msg_body_t
*slist
,
4423 mach_msg_option_t option
)
4425 mach_msg_return_t mr
;
4427 mr
= ipc_kmsg_copyout_header(kmsg
, space
, option
);
4428 if (mr
!= MACH_MSG_SUCCESS
) {
4432 if (kmsg
->ikm_header
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
4433 mr
= ipc_kmsg_copyout_body(kmsg
, space
, map
, slist
);
4435 if (mr
!= MACH_MSG_SUCCESS
)
4436 mr
|= MACH_RCV_BODY_ERROR
;
4443 * Routine: ipc_kmsg_copyout_pseudo
4445 * Does a pseudo-copyout of the message.
4446 * This is like a regular copyout, except
4447 * that the ports in the header are handled
4448 * as if they are in the body. They aren't reversed.
4450 * The error codes are a combination of special bits.
4451 * The copyout proceeds despite errors.
4455 * MACH_MSG_SUCCESS Successful copyout.
4456 * MACH_MSG_IPC_SPACE No room for port right in name space.
4457 * MACH_MSG_VM_SPACE No room for memory in address space.
4458 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
4459 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
4463 ipc_kmsg_copyout_pseudo(
4467 mach_msg_body_t
*slist
)
4469 mach_msg_bits_t mbits
= kmsg
->ikm_header
->msgh_bits
;
4470 ipc_object_t dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
4471 ipc_object_t reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
4472 ipc_object_t voucher
= (ipc_object_t
) kmsg
->ikm_voucher
;
4473 mach_msg_type_name_t dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
4474 mach_msg_type_name_t reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
4475 mach_msg_type_name_t voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
4476 mach_port_name_t voucher_name
= kmsg
->ikm_header
->msgh_voucher_port
;
4477 mach_port_name_t dest_name
, reply_name
;
4478 mach_msg_return_t mr
;
4480 /* Set ith_knote to ITH_KNOTE_PSEUDO */
4481 current_thread()->ith_knote
= ITH_KNOTE_PSEUDO
;
4483 assert(IO_VALID(dest
));
4487 * If we did this here, it looks like we wouldn't need the undo logic
4488 * at the end of ipc_kmsg_send() in the error cases. Not sure which
4489 * would be more elegant to keep.
4491 ipc_importance_clean(kmsg
);
4493 /* just assert it is already clean */
4494 ipc_importance_assert_clean(kmsg
);
4497 mr
= (ipc_kmsg_copyout_object(space
, dest
, dest_type
, &dest_name
) |
4498 ipc_kmsg_copyout_object(space
, reply
, reply_type
, &reply_name
));
4500 kmsg
->ikm_header
->msgh_bits
= mbits
& MACH_MSGH_BITS_USER
;
4501 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
4502 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
4504 if (IO_VALID(voucher
)) {
4505 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
4507 kmsg
->ikm_voucher
= IP_NULL
;
4508 mr
|= ipc_kmsg_copyout_object(space
, voucher
, voucher_type
, &voucher_name
);
4509 kmsg
->ikm_header
->msgh_voucher_port
= voucher_name
;
4512 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
4513 mr
|= ipc_kmsg_copyout_body(kmsg
, space
, map
, slist
);
4520 * Routine: ipc_kmsg_copyout_dest
4522 * Copies out the destination port in the message.
4523 * Destroys all other rights and memory in the message.
4529 ipc_kmsg_copyout_dest(
4533 mach_msg_bits_t mbits
;
4536 ipc_object_t voucher
;
4537 mach_msg_type_name_t dest_type
;
4538 mach_msg_type_name_t reply_type
;
4539 mach_msg_type_name_t voucher_type
;
4540 mach_port_name_t dest_name
, reply_name
, voucher_name
;
4542 mbits
= kmsg
->ikm_header
->msgh_bits
;
4543 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
4544 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
4545 voucher
= (ipc_object_t
) kmsg
->ikm_voucher
;
4546 voucher_name
= kmsg
->ikm_header
->msgh_voucher_port
;
4547 dest_type
= MACH_MSGH_BITS_REMOTE(mbits
);
4548 reply_type
= MACH_MSGH_BITS_LOCAL(mbits
);
4549 voucher_type
= MACH_MSGH_BITS_VOUCHER(mbits
);
4551 assert(IO_VALID(dest
));
4553 ipc_importance_assert_clean(kmsg
);
4556 if (io_active(dest
)) {
4557 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
4558 /* dest is unlocked */
4562 dest_name
= MACH_PORT_DEAD
;
4565 if (IO_VALID(reply
)) {
4566 ipc_object_destroy(reply
, reply_type
);
4567 reply_name
= MACH_PORT_NULL
;
4569 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
4571 if (IO_VALID(voucher
)) {
4572 assert(voucher_type
== MACH_MSG_TYPE_MOVE_SEND
);
4574 kmsg
->ikm_voucher
= IP_NULL
;
4575 ipc_object_destroy((ipc_object_t
)voucher
, voucher_type
);
4576 voucher_name
= MACH_PORT_NULL
;
4579 kmsg
->ikm_header
->msgh_bits
= MACH_MSGH_BITS_SET(reply_type
, dest_type
,
4580 voucher_type
, mbits
);
4581 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
4582 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
4583 kmsg
->ikm_header
->msgh_voucher_port
= voucher_name
;
4585 if (mbits
& MACH_MSGH_BITS_COMPLEX
) {
4586 mach_msg_body_t
*body
;
4588 body
= (mach_msg_body_t
*) (kmsg
->ikm_header
+ 1);
4589 ipc_kmsg_clean_body(kmsg
, body
->msgh_descriptor_count
,
4590 (mach_msg_descriptor_t
*)(body
+ 1));
4595 * Routine: ipc_kmsg_copyout_to_kernel
4597 * Copies out the destination and reply ports in the message.
4598 * Leaves all other rights and memory in the message alone.
4602 * Derived from ipc_kmsg_copyout_dest.
4603 * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
4604 * We really do want to save rights and memory.
4608 ipc_kmsg_copyout_to_kernel(
4614 mach_msg_type_name_t dest_type
;
4615 mach_msg_type_name_t reply_type
;
4616 mach_port_name_t dest_name
, reply_name
;
4618 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
4619 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
4620 dest_type
= MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
);
4621 reply_type
= MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
);
4623 assert(IO_VALID(dest
));
4626 if (io_active(dest
)) {
4627 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
4628 /* dest is unlocked */
4632 dest_name
= MACH_PORT_DEAD
;
4635 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
4637 kmsg
->ikm_header
->msgh_bits
=
4638 (MACH_MSGH_BITS_OTHER(kmsg
->ikm_header
->msgh_bits
) |
4639 MACH_MSGH_BITS(reply_type
, dest_type
));
4640 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
4641 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
4644 #if IKM_SUPPORT_LEGACY
4646 ipc_kmsg_copyout_to_kernel_legacy(
4652 mach_msg_type_name_t dest_type
;
4653 mach_msg_type_name_t reply_type
;
4654 mach_port_name_t dest_name
, reply_name
;
4656 dest
= (ipc_object_t
) kmsg
->ikm_header
->msgh_remote_port
;
4657 reply
= (ipc_object_t
) kmsg
->ikm_header
->msgh_local_port
;
4658 dest_type
= MACH_MSGH_BITS_REMOTE(kmsg
->ikm_header
->msgh_bits
);
4659 reply_type
= MACH_MSGH_BITS_LOCAL(kmsg
->ikm_header
->msgh_bits
);
4661 assert(IO_VALID(dest
));
4664 if (io_active(dest
)) {
4665 ipc_object_copyout_dest(space
, dest
, dest_type
, &dest_name
);
4666 /* dest is unlocked */
4670 dest_name
= MACH_PORT_DEAD
;
4673 reply_name
= CAST_MACH_PORT_TO_NAME(reply
);
4675 kmsg
->ikm_header
->msgh_bits
=
4676 (MACH_MSGH_BITS_OTHER(kmsg
->ikm_header
->msgh_bits
) |
4677 MACH_MSGH_BITS(reply_type
, dest_type
));
4678 kmsg
->ikm_header
->msgh_local_port
= CAST_MACH_NAME_TO_PORT(dest_name
);
4679 kmsg
->ikm_header
->msgh_remote_port
= CAST_MACH_NAME_TO_PORT(reply_name
);
4681 mach_msg_descriptor_t
*saddr
;
4682 mach_msg_legacy_descriptor_t
*daddr
;
4683 mach_msg_type_number_t i
, count
= ((mach_msg_base_t
*)kmsg
->ikm_header
)->body
.msgh_descriptor_count
;
4684 saddr
= (mach_msg_descriptor_t
*) (((mach_msg_base_t
*)kmsg
->ikm_header
) + 1);
4685 saddr
= &saddr
[count
-1];
4686 daddr
= (mach_msg_legacy_descriptor_t
*)&saddr
[count
];
4689 vm_offset_t dsc_adjust
= 0;
4691 for (i
= 0; i
< count
; i
++, saddr
--, daddr
--) {
4692 switch (saddr
->type
.type
) {
4693 case MACH_MSG_PORT_DESCRIPTOR
: {
4694 mach_msg_port_descriptor_t
*dsc
= &saddr
->port
;
4695 mach_msg_legacy_port_descriptor_t
*dest_dsc
= &daddr
->port
;
4697 mach_port_t name
= dsc
->name
;
4698 mach_msg_type_name_t disposition
= dsc
->disposition
;
4700 dest_dsc
->name
= CAST_MACH_PORT_TO_NAME(name
);
4701 dest_dsc
->disposition
= disposition
;
4702 dest_dsc
->type
= MACH_MSG_PORT_DESCRIPTOR
;
4705 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4706 case MACH_MSG_OOL_DESCRIPTOR
: {
4707 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
4708 * so we don't need to do anything special. */
4710 mach_msg_ool_descriptor_t
*source_dsc
= (typeof(source_dsc
))&saddr
->out_of_line
;
4712 mach_msg_ool_descriptor32_t
*dest_dsc
= &daddr
->out_of_line32
;
4714 vm_offset_t address
= (vm_offset_t
)source_dsc
->address
;
4715 vm_size_t size
= source_dsc
->size
;
4716 boolean_t deallocate
= source_dsc
->deallocate
;
4717 mach_msg_copy_options_t copy
= source_dsc
->copy
;
4718 mach_msg_descriptor_type_t type
= source_dsc
->type
;
4720 dest_dsc
->address
= address
;
4721 dest_dsc
->size
= size
;
4722 dest_dsc
->deallocate
= deallocate
;
4723 dest_dsc
->copy
= copy
;
4724 dest_dsc
->type
= type
;
4727 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: {
4728 mach_msg_ool_ports_descriptor_t
*source_dsc
= (typeof(source_dsc
))&saddr
->ool_ports
;
4730 mach_msg_ool_ports_descriptor32_t
*dest_dsc
= &daddr
->ool_ports32
;
4732 vm_offset_t address
= (vm_offset_t
)source_dsc
->address
;
4733 vm_size_t port_count
= source_dsc
->count
;
4734 boolean_t deallocate
= source_dsc
->deallocate
;
4735 mach_msg_copy_options_t copy
= source_dsc
->copy
;
4736 mach_msg_descriptor_type_t type
= source_dsc
->type
;
4738 dest_dsc
->address
= address
;
4739 dest_dsc
->count
= port_count
;
4740 dest_dsc
->deallocate
= deallocate
;
4741 dest_dsc
->copy
= copy
;
4742 dest_dsc
->type
= type
;
4747 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
4748 #endif /* MACH_ASSERT */
4754 dsc_adjust
= 4*count
;
4755 memmove((char *)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
), kmsg
->ikm_header
, sizeof(mach_msg_base_t
));
4756 kmsg
->ikm_header
= (mach_msg_header_t
*)((vm_offset_t
)kmsg
->ikm_header
+ dsc_adjust
);
4757 /* Update the message size for the smaller user representation */
4758 kmsg
->ikm_header
->msgh_size
-= dsc_adjust
;
4761 #endif /* IKM_SUPPORT_LEGACY */
4765 * Just sets those parts of the trailer that aren't set up at allocation time.
4768 ipc_kmsg_munge_trailer(mach_msg_max_trailer_t
*in
, void *_out
, boolean_t is64bit
)
4771 mach_msg_max_trailer64_t
*out
= (mach_msg_max_trailer64_t
*)_out
;
4772 out
->msgh_seqno
= in
->msgh_seqno
;
4773 out
->msgh_context
= in
->msgh_context
;
4774 out
->msgh_trailer_size
= in
->msgh_trailer_size
;
4775 out
->msgh_ad
= in
->msgh_ad
;
4777 mach_msg_max_trailer32_t
*out
= (mach_msg_max_trailer32_t
*)_out
;
4778 out
->msgh_seqno
= in
->msgh_seqno
;
4779 out
->msgh_context
= (mach_port_context32_t
)in
->msgh_context
;
4780 out
->msgh_trailer_size
= in
->msgh_trailer_size
;
4781 out
->msgh_ad
= in
->msgh_ad
;
4784 #endif /* __arm64__ */
4786 mach_msg_trailer_size_t
4787 ipc_kmsg_add_trailer(ipc_kmsg_t kmsg
, ipc_space_t space __unused
,
4788 mach_msg_option_t option
, thread_t thread
,
4789 mach_port_seqno_t seqno
, boolean_t minimal_trailer
,
4790 mach_vm_offset_t context
)
4792 mach_msg_max_trailer_t
*trailer
;
4795 mach_msg_max_trailer_t tmp_trailer
; /* This accommodates U64, and we'll munge */
4796 void *real_trailer_out
= (void*)(mach_msg_max_trailer_t
*)
4797 ((vm_offset_t
)kmsg
->ikm_header
+
4798 round_msg(kmsg
->ikm_header
->msgh_size
));
4801 * Populate scratch with initial values set up at message allocation time.
4802 * After, we reinterpret the space in the message as the right type
4803 * of trailer for the address space in question.
4805 bcopy(real_trailer_out
, &tmp_trailer
, MAX_TRAILER_SIZE
);
4806 trailer
= &tmp_trailer
;
4807 #else /* __arm64__ */
4809 trailer
= (mach_msg_max_trailer_t
*)
4810 ((vm_offset_t
)kmsg
->ikm_header
+
4811 round_msg(kmsg
->ikm_header
->msgh_size
));
4812 #endif /* __arm64__ */
4814 if (!(option
& MACH_RCV_TRAILER_MASK
)) {
4815 return trailer
->msgh_trailer_size
;
4818 trailer
->msgh_seqno
= seqno
;
4819 trailer
->msgh_context
= context
;
4820 trailer
->msgh_trailer_size
= REQUESTED_TRAILER_SIZE(thread_is_64bit(thread
), option
);
4822 if (minimal_trailer
) {
4826 if (MACH_RCV_TRAILER_ELEMENTS(option
) >=
4827 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV
)){
4828 trailer
->msgh_ad
= 0;
4832 * The ipc_kmsg_t holds a reference to the label of a label
4833 * handle, not the port. We must get a reference to the port
4834 * and a send right to copyout to the receiver.
4837 if (option
& MACH_RCV_TRAILER_ELEMENTS (MACH_RCV_TRAILER_LABELS
)) {
4838 trailer
->msgh_labels
.sender
= 0;
4843 ipc_kmsg_munge_trailer(trailer
, real_trailer_out
, thread_is_64bit(thread
));
4844 #endif /* __arm64__ */
4846 return trailer
->msgh_trailer_size
;