]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/ipc_kmsg.c
xnu-4570.20.62.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_kmsg.c
1 /*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
35 *
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.
41 *
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.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56 /*
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,
60 * Version 2.0.
61 * Copyright (c) 2005 SPARTA, Inc.
62 */
63 /*
64 */
65 /*
66 * File: ipc/ipc_kmsg.c
67 * Author: Rich Draves
68 * Date: 1989
69 *
70 * Operations on kernel messages.
71 */
72
73
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>
82
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>
96
97 #include <machine/machlimits.h>
98
99 #include <vm/vm_map.h>
100 #include <vm/vm_object.h>
101 #include <vm/vm_kern.h>
102
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>
115 #if MACH_FLIPC
116 #include <kern/mach_node.h>
117 #include <ipc/flipc.h>
118 #endif
119
120 #include <os/overflow.h>
121
122 #include <security/mac_mach_internal.h>
123
124 #include <device/device_server.h>
125
126 #include <string.h>
127
128 #ifdef ppc
129 #include <ppc/Firmware.h>
130 #include <ppc/low_trace.h>
131 #endif
132
133 #if DEBUG
134 #define DEBUG_MSGS_K64 1
135 #endif
136
137 #include <sys/kdebug.h>
138 #include <libkern/OSAtomic.h>
139
140 #pragma pack(4)
141
142 typedef struct
143 {
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;
151
152 typedef struct
153 {
154 mach_msg_legacy_header_t header;
155 mach_msg_body_t body;
156 } mach_msg_legacy_base_t;
157
158 typedef struct
159 {
160 mach_port_name_t name;
161 mach_msg_size_t pad1;
162 uint32_t pad2 : 16;
163 mach_msg_type_name_t disposition : 8;
164 mach_msg_descriptor_type_t type : 8;
165 } mach_msg_legacy_port_descriptor_t;
166
167
168 typedef union
169 {
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;
175
176 #pragma pack()
177
178 #define LEGACY_HEADER_SIZE_DELTA ((mach_msg_size_t)(sizeof(mach_msg_header_t) - sizeof(mach_msg_legacy_header_t)))
179
180 // END LP64 fixes
181
182
183 #if DEBUG_MSGS_K64
184 extern void ipc_pset_print64(
185 ipc_pset_t pset);
186
187 extern void ipc_kmsg_print64(
188 ipc_kmsg_t kmsg,
189 const char *str);
190
191 extern void ipc_msg_print64(
192 mach_msg_header_t *msgh);
193
194 extern ipc_port_t ipc_name_to_data64(
195 task_t task,
196 mach_port_name_t name);
197
198 /*
199 * Forward declarations
200 */
201 void ipc_msg_print_untyped64(
202 mach_msg_body_t *body);
203
204 const char * ipc_type_name64(
205 int type_name,
206 boolean_t received);
207
208 void ipc_print_type_name64(
209 int type_name);
210
211 const char *
212 msgh_bit_decode64(
213 mach_msg_bits_t bit);
214
215 const char *
216 mm_copy_options_string64(
217 mach_msg_copy_options_t option);
218
219 void db_print_msg_uid64(mach_msg_header_t *);
220
221 static void
222 ipc_msg_body_print64(void *body, int size)
223 {
224 uint32_t *word = (uint32_t *) body;
225 uint32_t *end = (uint32_t *)(((uintptr_t) body) + size
226 - sizeof(mach_msg_header_t));
227 int i;
228
229 kprintf(" body(%p-%p):\n %p: ", body, end, word);
230 for (;;) {
231 for (i = 0; i < 8; i++, word++) {
232 if (word >= end) {
233 kprintf("\n");
234 return;
235 }
236 kprintf("%08x ", *word);
237 }
238 kprintf("\n %p: ", word);
239 }
240 }
241
242
243 const char *
244 ipc_type_name64(
245 int type_name,
246 boolean_t received)
247 {
248 switch (type_name) {
249 case MACH_MSG_TYPE_PORT_NAME:
250 return "port_name";
251
252 case MACH_MSG_TYPE_MOVE_RECEIVE:
253 if (received) {
254 return "port_receive";
255 } else {
256 return "move_receive";
257 }
258
259 case MACH_MSG_TYPE_MOVE_SEND:
260 if (received) {
261 return "port_send";
262 } else {
263 return "move_send";
264 }
265
266 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
267 if (received) {
268 return "port_send_once";
269 } else {
270 return "move_send_once";
271 }
272
273 case MACH_MSG_TYPE_COPY_SEND:
274 return "copy_send";
275
276 case MACH_MSG_TYPE_MAKE_SEND:
277 return "make_send";
278
279 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
280 return "make_send_once";
281
282 default:
283 return (char *) 0;
284 }
285 }
286
287 void
288 ipc_print_type_name64(
289 int type_name)
290 {
291 const char *name = ipc_type_name64(type_name, TRUE);
292 if (name) {
293 kprintf("%s", name);
294 } else {
295 kprintf("type%d", type_name);
296 }
297 }
298
299 /*
300 * ipc_kmsg_print64 [ debug ]
301 */
302 void
303 ipc_kmsg_print64(
304 ipc_kmsg_t kmsg,
305 const char *str)
306 {
307 kprintf("%s kmsg=%p:\n", str, kmsg);
308 kprintf(" next=%p, prev=%p, size=%d",
309 kmsg->ikm_next,
310 kmsg->ikm_prev,
311 kmsg->ikm_size);
312 kprintf("\n");
313 ipc_msg_print64(kmsg->ikm_header);
314 }
315
316 const char *
317 msgh_bit_decode64(
318 mach_msg_bits_t bit)
319 {
320 switch (bit) {
321 case MACH_MSGH_BITS_COMPLEX: return "complex";
322 case MACH_MSGH_BITS_CIRCULAR: return "circular";
323 default: return (char *) 0;
324 }
325 }
326
327 /*
328 * ipc_msg_print64 [ debug ]
329 */
330 void
331 ipc_msg_print64(
332 mach_msg_header_t *msgh)
333 {
334 mach_msg_bits_t mbits;
335 unsigned int bit, i;
336 const char *bit_name;
337 int needs_comma;
338
339 mbits = msgh->msgh_bits;
340 kprintf(" msgh_bits=0x%x: l=0x%x,r=0x%x\n",
341 mbits,
342 MACH_MSGH_BITS_LOCAL(msgh->msgh_bits),
343 MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
344
345 mbits = MACH_MSGH_BITS_OTHER(mbits) & MACH_MSGH_BITS_USED;
346 kprintf(" decoded bits: ");
347 needs_comma = 0;
348 for (i = 0, bit = 1; i < sizeof(mbits) * 8; ++i, bit <<= 1) {
349 if ((mbits & bit) == 0)
350 continue;
351 bit_name = msgh_bit_decode64((mach_msg_bits_t)bit);
352 if (bit_name)
353 kprintf("%s%s", needs_comma ? "," : "", bit_name);
354 else
355 kprintf("%sunknown(0x%x),", needs_comma ? "," : "", bit);
356 ++needs_comma;
357 }
358 if (msgh->msgh_bits & ~MACH_MSGH_BITS_USED) {
359 kprintf("%sunused=0x%x,", needs_comma ? "," : "",
360 msgh->msgh_bits & ~MACH_MSGH_BITS_USED);
361 }
362 kprintf("\n");
363
364 needs_comma = 1;
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));
368 kprintf(")");
369 } else {
370 kprintf(" remote=null");
371 }
372
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));
377 kprintf(")\n");
378 } else {
379 kprintf("local=null\n");
380 }
381
382 kprintf(" msgh_id=%d, size=%d\n",
383 msgh->msgh_id,
384 msgh->msgh_size);
385
386 if (mbits & MACH_MSGH_BITS_COMPLEX) {
387 ipc_msg_print_untyped64((mach_msg_body_t *) (msgh + 1));
388 }
389
390 ipc_msg_body_print64((void *)(msgh + 1), msgh->msgh_size);
391 }
392
393
394 const char *
395 mm_copy_options_string64(
396 mach_msg_copy_options_t option)
397 {
398 const char *name;
399
400 switch (option) {
401 case MACH_MSG_PHYSICAL_COPY:
402 name = "PHYSICAL";
403 break;
404 case MACH_MSG_VIRTUAL_COPY:
405 name = "VIRTUAL";
406 break;
407 case MACH_MSG_OVERWRITE:
408 name = "OVERWRITE(DEPRECATED)";
409 break;
410 case MACH_MSG_ALLOCATE:
411 name = "ALLOCATE";
412 break;
413 case MACH_MSG_KALLOC_COPY_T:
414 name = "KALLOC_COPY_T";
415 break;
416 default:
417 name = "unknown";
418 break;
419 }
420 return name;
421 }
422
423 void
424 ipc_msg_print_untyped64(
425 mach_msg_body_t *body)
426 {
427 mach_msg_descriptor_t *saddr, *send;
428 mach_msg_descriptor_type_t type;
429
430 kprintf(" %d descriptors: \n", body->msgh_descriptor_count);
431
432 saddr = (mach_msg_descriptor_t *) (body + 1);
433 send = saddr + body->msgh_descriptor_count;
434
435 for ( ; saddr < send; saddr++ ) {
436
437 type = saddr->type.type;
438
439 switch (type) {
440
441 case MACH_MSG_PORT_DESCRIPTOR: {
442 mach_msg_port_descriptor_t *dsc;
443
444 dsc = &saddr->port;
445 kprintf(" PORT name = %p disp = ", dsc->name);
446 ipc_print_type_name64(dsc->disposition);
447 kprintf("\n");
448 break;
449 }
450 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
451 case MACH_MSG_OOL_DESCRIPTOR: {
452 mach_msg_ool_descriptor_t *dsc;
453
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" : "");
460 break;
461 }
462 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
463 mach_msg_ool_ports_descriptor_t *dsc;
464
465 dsc = (mach_msg_ool_ports_descriptor_t *) &saddr->ool_ports;
466
467 kprintf(" OOL_PORTS addr = %p count = 0x%x ",
468 dsc->address, dsc->count);
469 kprintf("disp = ");
470 ipc_print_type_name64(dsc->disposition);
471 kprintf(" copy = %s %s\n",
472 mm_copy_options_string64(dsc->copy),
473 dsc->deallocate ? "DEALLOC" : "");
474 break;
475 }
476
477 default: {
478 kprintf(" UNKNOWN DESCRIPTOR 0x%x\n", type);
479 break;
480 }
481 }
482 }
483 }
484
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); \
489 } \
490 __unreachable_ok_pop
491
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);\
496 } \
497 __unreachable_ok_pop
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 */
502
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;
508
509 #define MSG_OOL_SIZE_SMALL msg_ool_size_small
510
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
515 #else
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
519 #endif
520
521 #define DESC_SIZE_ADJUSTMENT ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
522 sizeof(mach_msg_ool_descriptor32_t)))
523
524 /* scatter list macros */
525
526 #define SKIP_PORT_DESCRIPTORS(s, c) \
527 MACRO_BEGIN \
528 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
529 while ((c) > 0) { \
530 if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
531 break; \
532 (s)++; (c)--; \
533 } \
534 if (c == 0) \
535 (s) = MACH_MSG_DESCRIPTOR_NULL; \
536 } \
537 MACRO_END
538
539 #define INCREMENT_SCATTER(s, c, d) \
540 MACRO_BEGIN \
541 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
542 s = (d) ? (mach_msg_descriptor_t *) \
543 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) : \
544 (s + 1); \
545 (c)--; \
546 } \
547 MACRO_END
548
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
573
574 #define KMSG_TRACE_FLAGS_MASK 0xffffff
575 #define KMSG_TRACE_FLAGS_SHIFT 8
576
577 #define KMSG_TRACE_PORTS_MASK 0xff
578 #define KMSG_TRACE_PORTS_SHIFT 0
579
580 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
581 #include <stdint.h>
582 extern boolean_t kdebug_debugid_enabled(uint32_t debugid);
583
584 void ipc_kmsg_trace_send(ipc_kmsg_t kmsg,
585 mach_msg_option_t option)
586 {
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;
592
593 int kotype = 0;
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;
598
599 /*
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.
604 */
605 if (__probable((kdebug_enable & KDEBUG_TRACE) == 0))
606 return;
607 if (!kdebug_debugid_enabled(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_INFO)))
608 return;
609
610 msg = kmsg->ikm_header;
611
612 dst_port = (ipc_port_t)(msg->msgh_remote_port);
613 if (!IPC_PORT_VALID(dst_port))
614 return;
615
616 /*
617 * Message properties / options
618 */
619 if ((option & (MACH_SEND_MSG|MACH_RCV_MSG)) == (MACH_SEND_MSG|MACH_RCV_MSG))
620 msg_flags |= KMSG_TRACE_FLAG_SNDRCV;
621
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;
628
629 if (msg->msgh_bits & MACH_MSGH_BITS_RAISEIMP)
630 msg_flags |= KMSG_TRACE_FLAG_RAISEIMP;
631
632 if (unsafe_convert_port_to_voucher(kmsg->ikm_voucher))
633 msg_flags |= KMSG_TRACE_FLAG_VOUCHER;
634
635 /*
636 * Sending task / port
637 */
638 send_task = current_task();
639 send_pid = task_pid(send_task);
640
641 if (send_pid != 0) {
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;
646 }
647
648 is_task_64bit = (send_task->map->max_offset > VM_MAX_ADDRESS);
649 if (is_task_64bit)
650 msg_flags |= KMSG_TRACE_FLAG_SND64;
651
652 src_port = (ipc_port_t)(msg->msgh_local_port);
653 if (src_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;
659 break;
660 default:
661 break;
662 }
663 } else {
664 msg_flags |= KMSG_TRACE_FLAG_ONEWAY;
665 }
666
667
668 /*
669 * Destination task / port
670 */
671 ip_lock(dst_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);
679 else
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;
684 } else {
685 if (dst_port->ip_receiver == ipc_space_kernel) {
686 dst_pid = 0;
687 } else {
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;
696 } else {
697 /* receiving task is being torn down */
698 dst_pid = (uint32_t)0xfffffff3;
699 }
700 }
701 }
702
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;
707
708 kotype = ip_kotype(dst_port);
709
710 ip_unlock(dst_port);
711
712 switch (kotype) {
713 case IKOT_SEMAPHORE:
714 msg_flags |= KMSG_TRACE_FLAG_SEMA;
715 break;
716 case IKOT_TIMER:
717 case IKOT_CLOCK:
718 msg_flags |= KMSG_TRACE_FLAG_TIMER;
719 break;
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;
725 break;
726 default:
727 break;
728 }
729
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;
733 break;
734 default:
735 break;
736 }
737
738
739 /*
740 * Message size / content
741 */
742 msg_size = msg->msgh_size - sizeof(mach_msg_header_t);
743
744 if (msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
745 mach_msg_body_t *msg_body;
746 mach_msg_descriptor_t *kern_dsc;
747 int dsc_count;
748
749 msg_flags |= KMSG_TRACE_FLAG_COMPLEX;
750
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);
754
755 /* this is gross: see ipc_kmsg_copyin_body()... */
756 if (!is_task_64bit)
757 msg_size -= (dsc_count * 12);
758
759 for (int i = 0; i < dsc_count; i++) {
760 switch (kern_dsc[i].type.type) {
761 case MACH_MSG_PORT_DESCRIPTOR:
762 num_ports++;
763 if (is_task_64bit)
764 msg_size -= 12;
765 break;
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) &&
774 !dsc->deallocate)
775 msg_flags |= KMSG_TRACE_FLAG_PCPY;
776 else if (dsc->size <= MSG_OOL_SIZE_SMALL)
777 msg_flags |= KMSG_TRACE_FLAG_PCPY;
778 else
779 msg_flags |= KMSG_TRACE_FLAG_VCPY;
780 if (is_task_64bit)
781 msg_size -= 16;
782 } break;
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;
787 if (is_task_64bit)
788 msg_size -= 16;
789 } break;
790 default:
791 break;
792 }
793 }
794 }
795
796 /*
797 * Trailer contents
798 */
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;
805 /*
806 * verify the sender PID: replies from the kernel often look
807 * like self-talk because the sending port is not reset.
808 */
809 if (memcmp(&strailer->msgh_sender,
810 &KERNEL_SECURITY_TOKEN,
811 sizeof(KERNEL_SECURITY_TOKEN)) == 0) {
812 send_pid = 0;
813 msg_flags &= ~(KMSG_TRACE_FLAG_APP_SRC | KMSG_TRACE_FLAG_DAEMON_SRC);
814 }
815 }
816
817 KDBG(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_INFO) | DBG_FUNC_END,
818 (uintptr_t)send_pid,
819 (uintptr_t)dst_pid,
820 (uintptr_t)msg_size,
821 (uintptr_t)(
822 ((msg_flags & KMSG_TRACE_FLAGS_MASK) << KMSG_TRACE_FLAGS_SHIFT) |
823 ((num_ports & KMSG_TRACE_PORTS_MASK) << KMSG_TRACE_PORTS_SHIFT)
824 )
825 );
826 }
827 #endif
828
829 /* zone for cached ipc_kmsg_t structures */
830 zone_t ipc_kmsg_zone;
831
832 /*
833 * Forward declarations
834 */
835
836 void ipc_kmsg_clean(
837 ipc_kmsg_t kmsg);
838
839 void ipc_kmsg_clean_body(
840 ipc_kmsg_t kmsg,
841 mach_msg_type_number_t number,
842 mach_msg_descriptor_t *desc);
843
844 void ipc_kmsg_clean_partial(
845 ipc_kmsg_t kmsg,
846 mach_msg_type_number_t number,
847 mach_msg_descriptor_t *desc,
848 vm_offset_t paddr,
849 vm_size_t length);
850
851 mach_msg_return_t ipc_kmsg_copyin_body(
852 ipc_kmsg_t kmsg,
853 ipc_space_t space,
854 vm_map_t map);
855
856 extern int thread_qos_from_pthread_priority(unsigned long, unsigned long *);
857
858 /*
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
863 * require locking.
864 */
865
866 /*
867 * Routine: ipc_kmsg_alloc
868 * Purpose:
869 * Allocate a kernel message structure. If we can get one from
870 * the cache, that is best. Otherwise, allocate a new one.
871 * Conditions:
872 * Nothing locked.
873 */
874 ipc_kmsg_t
875 ipc_kmsg_alloc(
876 mach_msg_size_t msg_and_trailer_size)
877 {
878 mach_msg_size_t max_expanded_size;
879 ipc_kmsg_t kmsg;
880
881 /*
882 * LP64support -
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).
888 *
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
892 * data backwards.
893 */
894 mach_msg_size_t size = msg_and_trailer_size - MAX_TRAILER_SIZE;
895
896 /* compare against implementation upper limit for the body */
897 if (size > ipc_kmsg_max_body_space)
898 return IKM_NULL;
899
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);
904
905 /* make sure expansion won't cause wrap */
906 if (msg_and_trailer_size > MACH_MSG_SIZE_MAX - max_desc)
907 return IKM_NULL;
908
909 max_expanded_size = msg_and_trailer_size + max_desc;
910 } else
911 max_expanded_size = msg_and_trailer_size;
912
913 if (max_expanded_size < IKM_SAVED_MSG_SIZE)
914 max_expanded_size = IKM_SAVED_MSG_SIZE; /* round up for ikm_cache */
915
916 if (max_expanded_size == IKM_SAVED_MSG_SIZE) {
917 struct ikm_cache *cache;
918 unsigned int i;
919
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];
925 cache->avail = i;
926 enable_preemption();
927 ikm_check_init(kmsg, max_expanded_size);
928 ikm_set_header(kmsg, msg_and_trailer_size);
929 return (kmsg);
930 }
931 enable_preemption();
932 kmsg = (ipc_kmsg_t)zalloc(ipc_kmsg_zone);
933 } else {
934 kmsg = (ipc_kmsg_t)kalloc(ikm_plus_overhead(max_expanded_size));
935 }
936
937 if (kmsg != IKM_NULL) {
938 ikm_init(kmsg, max_expanded_size);
939 ikm_set_header(kmsg, msg_and_trailer_size);
940 }
941
942 return(kmsg);
943 }
944
945 /*
946 * Routine: ipc_kmsg_free
947 * Purpose:
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.
953 * Conditions:
954 * Nothing locked.
955 */
956
957 void
958 ipc_kmsg_free(
959 ipc_kmsg_t kmsg)
960 {
961 mach_msg_size_t size = kmsg->ikm_size;
962 ipc_port_t port;
963
964 assert(!IP_VALID(kmsg->ikm_voucher));
965
966 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_FREE) | DBG_FUNC_NONE,
967 VM_KERNEL_ADDRPERM((uintptr_t)kmsg),
968 0, 0, 0, 0);
969
970 /*
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.
974 */
975 port = ikm_prealloc_inuse_port(kmsg);
976 if (port != IP_NULL) {
977 ip_lock(port);
978 ikm_prealloc_clear_inuse(kmsg, port);
979 if (ip_active(port) && (port->ip_premsg == kmsg)) {
980 assert(IP_PREALLOC(port));
981 ip_unlock(port);
982 ip_release(port);
983 return;
984 }
985 ip_unlock(port);
986 ip_release(port); /* May be last reference */
987 }
988
989 /*
990 * Peek and see if it has to go back in the cache.
991 */
992 if (kmsg->ikm_size == IKM_SAVED_MSG_SIZE) {
993 struct ikm_cache *cache;
994 unsigned int i;
995
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();
1002 return;
1003 }
1004 enable_preemption();
1005 zfree(ipc_kmsg_zone, kmsg);
1006 return;
1007 }
1008 kfree(kmsg, ikm_plus_overhead(size));
1009 }
1010
1011
1012 /*
1013 * Routine: ipc_kmsg_enqueue
1014 * Purpose:
1015 * Enqueue a kmsg.
1016 */
1017
1018 void
1019 ipc_kmsg_enqueue(
1020 ipc_kmsg_queue_t queue,
1021 ipc_kmsg_t kmsg)
1022 {
1023 ipc_kmsg_t first = queue->ikmq_base;
1024 ipc_kmsg_t last;
1025
1026 if (first == IKM_NULL) {
1027 queue->ikmq_base = kmsg;
1028 kmsg->ikm_next = kmsg;
1029 kmsg->ikm_prev = kmsg;
1030 } else {
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;
1036 }
1037 }
1038
1039 /*
1040 * Routine: ipc_kmsg_enqueue_qos
1041 * Purpose:
1042 * Enqueue a kmsg, propagating qos
1043 * overrides towards the head of the queue.
1044 *
1045 * Returns:
1046 * whether the head of the queue had
1047 * it's override-qos adjusted because
1048 * of this insertion.
1049 */
1050
1051 boolean_t
1052 ipc_kmsg_enqueue_qos(
1053 ipc_kmsg_queue_t queue,
1054 ipc_kmsg_t kmsg)
1055 {
1056 ipc_kmsg_t first = queue->ikmq_base;
1057 ipc_kmsg_t prev;
1058 mach_msg_priority_t override;
1059
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;
1065 return TRUE;
1066 }
1067
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;
1074
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;
1081 }
1082
1083 /* did we adjust everything? */
1084 return (prev == kmsg);
1085 }
1086
1087 /*
1088 * Routine: ipc_kmsg_override_qos
1089 * Purpose:
1090 * Update the override for a given kmsg already
1091 * enqueued, propagating qos override adjustments
1092 * towards the head of the queue.
1093 *
1094 * Returns:
1095 * whether the head of the queue had
1096 * it's override-qos adjusted because
1097 * of this insertion.
1098 */
1099
1100 boolean_t
1101 ipc_kmsg_override_qos(
1102 ipc_kmsg_queue_t queue,
1103 ipc_kmsg_t kmsg,
1104 mach_msg_priority_t override)
1105 {
1106 ipc_kmsg_t first = queue->ikmq_base;
1107 ipc_kmsg_t cur = kmsg;
1108
1109 /* apply QoS overrides towards the head */
1110 while (override > cur->ikm_qos_override) {
1111 cur->ikm_qos_override = override;
1112 if (cur == first)
1113 return TRUE;
1114 cur = cur->ikm_prev;
1115 }
1116 return FALSE;
1117 }
1118
1119 /*
1120 * Routine: ipc_kmsg_dequeue
1121 * Purpose:
1122 * Dequeue and return a kmsg.
1123 */
1124
1125 ipc_kmsg_t
1126 ipc_kmsg_dequeue(
1127 ipc_kmsg_queue_t queue)
1128 {
1129 ipc_kmsg_t first;
1130
1131 first = ipc_kmsg_queue_first(queue);
1132
1133 if (first != IKM_NULL)
1134 ipc_kmsg_rmqueue(queue, first);
1135
1136 return first;
1137 }
1138
1139 /*
1140 * Routine: ipc_kmsg_rmqueue
1141 * Purpose:
1142 * Pull a kmsg out of a queue.
1143 */
1144
1145 void
1146 ipc_kmsg_rmqueue(
1147 ipc_kmsg_queue_t queue,
1148 ipc_kmsg_t kmsg)
1149 {
1150 ipc_kmsg_t next, prev;
1151
1152 assert(queue->ikmq_base != IKM_NULL);
1153
1154 next = kmsg->ikm_next;
1155 prev = kmsg->ikm_prev;
1156
1157 if (next == kmsg) {
1158 assert(prev == kmsg);
1159 assert(queue->ikmq_base == kmsg);
1160
1161 queue->ikmq_base = IKM_NULL;
1162 } else {
1163 if (queue->ikmq_base == kmsg)
1164 queue->ikmq_base = next;
1165
1166 next->ikm_prev = prev;
1167 prev->ikm_next = next;
1168 }
1169 /* XXX Temporary debug logic */
1170 assert((kmsg->ikm_next = IKM_BOGUS) == IKM_BOGUS);
1171 assert((kmsg->ikm_prev = IKM_BOGUS) == IKM_BOGUS);
1172 }
1173
1174 /*
1175 * Routine: ipc_kmsg_queue_next
1176 * Purpose:
1177 * Return the kmsg following the given kmsg.
1178 * (Or IKM_NULL if it is the last one in the queue.)
1179 */
1180
1181 ipc_kmsg_t
1182 ipc_kmsg_queue_next(
1183 ipc_kmsg_queue_t queue,
1184 ipc_kmsg_t kmsg)
1185 {
1186 ipc_kmsg_t next;
1187
1188 assert(queue->ikmq_base != IKM_NULL);
1189
1190 next = kmsg->ikm_next;
1191 if (queue->ikmq_base == next)
1192 next = IKM_NULL;
1193
1194 return next;
1195 }
1196
1197 /*
1198 * Routine: ipc_kmsg_destroy
1199 * Purpose:
1200 * Destroys a kernel message. Releases all rights,
1201 * references, and memory held by the message.
1202 * Frees the message.
1203 * Conditions:
1204 * No locks held.
1205 */
1206
1207 void
1208 ipc_kmsg_destroy(
1209 ipc_kmsg_t kmsg)
1210 {
1211 /*
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.
1216 */
1217 if (ipc_kmsg_delayed_destroy(kmsg))
1218 ipc_kmsg_reap_delayed();
1219 }
1220
1221 /*
1222 * Routine: ipc_kmsg_delayed_destroy
1223 * Purpose:
1224 * Enqueues a kernel message for deferred destruction.
1225 * Returns:
1226 * Boolean indicator that the caller is responsible to reap
1227 * deferred messages.
1228 */
1229
1230 boolean_t ipc_kmsg_delayed_destroy(
1231 ipc_kmsg_t kmsg)
1232 {
1233 ipc_kmsg_queue_t queue = &(current_thread()->ith_messages);
1234 boolean_t first = ipc_kmsg_queue_empty(queue);
1235
1236 ipc_kmsg_enqueue(queue, kmsg);
1237 return first;
1238 }
1239
1240 /*
1241 * Routine: ipc_kmsg_destroy_queue
1242 * Purpose:
1243 * Destroys messages from the per-thread
1244 * deferred reaping queue.
1245 * Conditions:
1246 * No locks held.
1247 */
1248
1249 void
1250 ipc_kmsg_reap_delayed(void)
1251 {
1252 ipc_kmsg_queue_t queue = &(current_thread()->ith_messages);
1253 ipc_kmsg_t kmsg;
1254
1255 /*
1256 * must leave kmsg in queue while cleaning it to assure
1257 * no nested calls recurse into here.
1258 */
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);
1263 }
1264 }
1265
1266 /*
1267 * Routine: ipc_kmsg_clean_body
1268 * Purpose:
1269 * Cleans the body of a kernel message.
1270 * Releases all rights, references, and memory.
1271 *
1272 * Conditions:
1273 * No locks held.
1274 */
1275 static unsigned int _ipc_kmsg_clean_invalid_desc = 0;
1276 void
1277 ipc_kmsg_clean_body(
1278 __unused ipc_kmsg_t kmsg,
1279 mach_msg_type_number_t number,
1280 mach_msg_descriptor_t *saddr)
1281 {
1282 mach_msg_type_number_t i;
1283
1284 if ( number == 0 )
1285 return;
1286
1287 for (i = 0 ; i < number; i++, saddr++ ) {
1288
1289 switch (saddr->type.type) {
1290
1291 case MACH_MSG_PORT_DESCRIPTOR: {
1292 mach_msg_port_descriptor_t *dsc;
1293
1294 dsc = &saddr->port;
1295
1296 /*
1297 * Destroy port rights carried in the message
1298 */
1299 if (!IO_VALID((ipc_object_t) dsc->name))
1300 continue;
1301 ipc_object_destroy((ipc_object_t) dsc->name, dsc->disposition);
1302 break;
1303 }
1304 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
1305 case MACH_MSG_OOL_DESCRIPTOR : {
1306 mach_msg_ool_descriptor_t *dsc;
1307
1308 dsc = (mach_msg_ool_descriptor_t *)&saddr->out_of_line;
1309
1310 /*
1311 * Destroy memory carried in the message
1312 */
1313 if (dsc->size == 0) {
1314 assert(dsc->address == (void *) 0);
1315 } else {
1316 vm_map_copy_discard((vm_map_copy_t) dsc->address);
1317 }
1318 break;
1319 }
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;
1324
1325 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
1326 objects = (ipc_object_t *) dsc->address;
1327
1328 if (dsc->count == 0) {
1329 break;
1330 }
1331
1332 assert(objects != (ipc_object_t *) 0);
1333
1334 /* destroy port rights carried in the message */
1335
1336 for (j = 0; j < dsc->count; j++) {
1337 ipc_object_t object = objects[j];
1338
1339 if (!IO_VALID(object))
1340 continue;
1341
1342 ipc_object_destroy(object, dsc->disposition);
1343 }
1344
1345 /* destroy memory carried in the message */
1346
1347 assert(dsc->count != 0);
1348
1349 kfree(dsc->address,
1350 (vm_size_t) dsc->count * sizeof(mach_port_t));
1351 break;
1352 }
1353 default : {
1354 _ipc_kmsg_clean_invalid_desc++; /* don't understand this type of descriptor */
1355 }
1356 }
1357 }
1358 }
1359
1360 /*
1361 * Routine: ipc_kmsg_clean_partial
1362 * Purpose:
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.
1369 * Conditions:
1370 * Nothing locked.
1371 */
1372
1373 void
1374 ipc_kmsg_clean_partial(
1375 ipc_kmsg_t kmsg,
1376 mach_msg_type_number_t number,
1377 mach_msg_descriptor_t *desc,
1378 vm_offset_t paddr,
1379 vm_size_t length)
1380 {
1381 ipc_object_t object;
1382 mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
1383
1384 /* deal with importance chain while we still have dest and voucher references */
1385 ipc_importance_clean(kmsg);
1386
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));
1390
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));
1394
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;
1400 }
1401
1402 if (paddr) {
1403 (void) vm_deallocate(ipc_kernel_copy_map, paddr, length);
1404 }
1405
1406 ipc_kmsg_clean_body(kmsg, number, desc);
1407 }
1408
1409 /*
1410 * Routine: ipc_kmsg_clean
1411 * Purpose:
1412 * Cleans a kernel message. Releases all rights,
1413 * references, and memory held by the message.
1414 * Conditions:
1415 * No locks held.
1416 */
1417
1418 void
1419 ipc_kmsg_clean(
1420 ipc_kmsg_t kmsg)
1421 {
1422 ipc_object_t object;
1423 mach_msg_bits_t mbits;
1424
1425 /* deal with importance chain while we still have dest and voucher references */
1426 ipc_importance_clean(kmsg);
1427
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));
1432
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));
1436
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;
1442 }
1443
1444 if (mbits & MACH_MSGH_BITS_COMPLEX) {
1445 mach_msg_body_t *body;
1446
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));
1450 }
1451 }
1452
1453 /*
1454 * Routine: ipc_kmsg_set_prealloc
1455 * Purpose:
1456 * Assign a kmsg as a preallocated message buffer to a port.
1457 * Conditions:
1458 * port locked.
1459 */
1460
1461 void
1462 ipc_kmsg_set_prealloc(
1463 ipc_kmsg_t kmsg,
1464 ipc_port_t port)
1465 {
1466 assert(kmsg->ikm_prealloc == IP_NULL);
1467
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);
1471
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);
1475 }
1476 kmsg->special_port_qos = port_special_qos(port);
1477 IP_SET_PREALLOC(port, kmsg);
1478 imq_unlock(&port->ip_messages);
1479 }
1480
1481 /*
1482 * Routine: ipc_kmsg_clear_prealloc
1483 * Purpose:
1484 * Release the Assignment of a preallocated message buffer from a port.
1485 * Conditions:
1486 * port locked.
1487 */
1488 void
1489 ipc_kmsg_clear_prealloc(
1490 ipc_kmsg_t kmsg,
1491 ipc_port_t port)
1492 {
1493 assert(kmsg->ikm_prealloc == port);
1494
1495 kmsg->ikm_prealloc = IP_NULL;
1496
1497 /* take the mqueue lock since the sync qos is protected under it */
1498 imq_lock(&port->ip_messages);
1499
1500 IP_CLEAR_PREALLOC(port, kmsg);
1501
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]);
1505 }
1506 set_port_special_qos(port, kmsg->special_port_qos);
1507 imq_unlock(&port->ip_messages);
1508 }
1509
1510 /*
1511 * Routine: ipc_kmsg_prealloc
1512 * Purpose:
1513 * Wraper to ipc_kmsg_alloc() to account for
1514 * header expansion requirements.
1515 */
1516 ipc_kmsg_t
1517 ipc_kmsg_prealloc(mach_msg_size_t size)
1518 {
1519 #if defined(__LP64__)
1520 if (size > MACH_MSG_SIZE_MAX - LEGACY_HEADER_SIZE_DELTA)
1521 return IKM_NULL;
1522
1523 size += LEGACY_HEADER_SIZE_DELTA;
1524 #endif
1525 return ipc_kmsg_alloc(size);
1526 }
1527
1528
1529 /*
1530 * Routine: ipc_kmsg_get
1531 * Purpose:
1532 * Allocates a kernel message buffer.
1533 * Copies a user message to the message buffer.
1534 * Conditions:
1535 * Nothing locked.
1536 * Returns:
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.
1543 */
1544
1545 mach_msg_return_t
1546 ipc_kmsg_get(
1547 mach_vm_address_t msg_addr,
1548 mach_msg_size_t size,
1549 ipc_kmsg_t *kmsgp)
1550 {
1551 mach_msg_size_t msg_and_trailer_size;
1552 ipc_kmsg_t kmsg;
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;
1557
1558 if ((size < sizeof(mach_msg_legacy_header_t)) || (size & 3))
1559 return MACH_SEND_MSG_TOO_SMALL;
1560
1561 if (size > ipc_kmsg_max_body_space)
1562 return MACH_SEND_TOO_LARGE;
1563
1564 if(size == sizeof(mach_msg_legacy_header_t))
1565 len_copied = sizeof(mach_msg_legacy_header_t);
1566 else
1567 len_copied = sizeof(mach_msg_legacy_base_t);
1568
1569 if (copyinmsg(msg_addr, (char *)&legacy_base, len_copied))
1570 return MACH_SEND_INVALID_DATA;
1571
1572 /*
1573 * If the message claims to be complex, it must at least
1574 * have the length of a "base" message (header + dsc_count).
1575 */
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;
1579
1580 msg_addr += sizeof(legacy_base.header);
1581 #if defined(__LP64__)
1582 size += LEGACY_HEADER_SIZE_DELTA;
1583 #endif
1584 /* unreachable if !DEBUG */
1585 __unreachable_ok_push
1586 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
1587 unsigned int j;
1588 for (j=0; j<sizeof(legacy_base.header); j++) {
1589 kprintf("%02x\n", ((unsigned char*)&legacy_base.header)[j]);
1590 }
1591 }
1592 __unreachable_ok_pop
1593
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;
1598
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;
1605
1606 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
1607 " size: 0x%.8x\n"
1608 " bits: 0x%.8x\n"
1609 " remote_port: %p\n"
1610 " local_port: %p\n"
1611 " voucher_port: 0x%.8x\n"
1612 " id: %.8d\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);
1619
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;
1623 }
1624
1625 /* unreachable if !DEBUG */
1626 __unreachable_ok_push
1627 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
1628 {
1629 kprintf("body: size: %lu\n", (size - sizeof(mach_msg_header_t)));
1630 uint32_t i;
1631 for(i=0;i*4 < (size - sizeof(mach_msg_header_t));i++)
1632 {
1633 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
1634 }
1635 }
1636 __unreachable_ok_pop
1637 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_get()");
1638
1639 /*
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.
1644 */
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;
1650
1651 #ifdef ppc
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);
1655 #endif
1656
1657 trailer->msgh_labels.sender = 0;
1658 *kmsgp = kmsg;
1659 return MACH_MSG_SUCCESS;
1660 }
1661
1662 /*
1663 * Routine: ipc_kmsg_get_from_kernel
1664 * Purpose:
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.
1670 * Conditions:
1671 * Nothing locked.
1672 * Ports in header are ipc_port_t.
1673 * Returns:
1674 * MACH_MSG_SUCCESS Acquired a message buffer.
1675 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1676 */
1677
1678 mach_msg_return_t
1679 ipc_kmsg_get_from_kernel(
1680 mach_msg_header_t *msg,
1681 mach_msg_size_t size,
1682 ipc_kmsg_t *kmsgp)
1683 {
1684 ipc_kmsg_t kmsg;
1685 mach_msg_size_t msg_and_trailer_size;
1686 mach_msg_max_trailer_t *trailer;
1687 ipc_port_t dest_port;
1688
1689 assert(size >= sizeof(mach_msg_header_t));
1690 assert((size & 3) == 0);
1691
1692 dest_port = (ipc_port_t)msg->msgh_remote_port;
1693
1694 msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1695
1696 /*
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.
1700 */
1701 if (IP_VALID(dest_port) && IP_PREALLOC(dest_port)) {
1702 mach_msg_size_t max_desc = 0;
1703
1704 ip_lock(dest_port);
1705 if (!ip_active(dest_port)) {
1706 ip_unlock(dest_port);
1707 return MACH_SEND_NO_BUFFER;
1708 }
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;
1714 }
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;
1720 }
1721 #endif
1722 if (msg_and_trailer_size > kmsg->ikm_size - max_desc) {
1723 ip_unlock(dest_port);
1724 return MACH_SEND_TOO_LARGE;
1725 }
1726 ikm_prealloc_set_inuse(kmsg, dest_port);
1727 ikm_set_header(kmsg, msg_and_trailer_size);
1728 ip_unlock(dest_port);
1729 }
1730 else
1731 {
1732 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1733 if (kmsg == IKM_NULL)
1734 return MACH_SEND_NO_BUFFER;
1735 }
1736
1737 (void) memcpy((void *) kmsg->ikm_header, (const void *) msg, size);
1738
1739 ikm_qos_init(kmsg);
1740
1741 kmsg->ikm_header->msgh_size = size;
1742
1743 /*
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.
1748 */
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;
1755
1756 trailer->msgh_labels.sender = 0;
1757
1758 *kmsgp = kmsg;
1759 return MACH_MSG_SUCCESS;
1760 }
1761
1762 /*
1763 * Routine: ipc_kmsg_send
1764 * Purpose:
1765 * Send a message. The message holds a reference
1766 * for the destination port in the msgh_remote_port field.
1767 *
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.
1772 * Conditions:
1773 * Nothing locked.
1774 * Returns:
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.
1779 */
1780
1781
1782 mach_msg_return_t
1783 ipc_kmsg_send(
1784 ipc_kmsg_t kmsg,
1785 mach_msg_option_t option,
1786 mach_msg_timeout_t send_timeout)
1787 {
1788 ipc_port_t port;
1789 thread_t th = current_thread();
1790 mach_msg_return_t error = MACH_MSG_SUCCESS;
1791 boolean_t kernel_reply = FALSE;
1792
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);
1800 }
1801
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 */
1809
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;
1815 }
1816
1817 ipc_voucher_send_preprocessing(kmsg);
1818
1819 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1820 assert(IP_VALID(port));
1821 ip_lock(port);
1822
1823 #if IMPORTANCE_INHERITANCE
1824 retry:
1825 #endif /* IMPORTANCE_INHERITANCE */
1826 /*
1827 * Can't deliver to a dead port.
1828 * However, we can pretend it got sent
1829 * and was then immediately destroyed.
1830 */
1831 if (!ip_active(port)) {
1832 ip_unlock(port);
1833 #if MACH_FLIPC
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);
1836 #endif
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;
1842 }
1843
1844 if (port->ip_receiver == ipc_space_kernel) {
1845
1846 /*
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.
1851 */
1852 assert(ip_active(port));
1853 port->ip_messages.imq_seqno++;
1854 ip_unlock(port);
1855
1856 current_task()->messages_sent++;
1857
1858 /*
1859 * Call the server routine, and get the reply message to send.
1860 */
1861 kmsg = ipc_kobject_server(kmsg, option);
1862 if (kmsg == IKM_NULL)
1863 return MACH_MSG_SUCCESS;
1864
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));
1869 ip_lock(port);
1870 /* fall thru with reply - same options */
1871 kernel_reply = TRUE;
1872 if (!ip_active(port))
1873 error = MACH_SEND_INVALID_DEST;
1874 }
1875
1876 #if IMPORTANCE_INHERITANCE
1877 /*
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.
1881 */
1882 if (did_importance == FALSE) {
1883 did_importance = TRUE;
1884 if (ipc_importance_send(kmsg, option))
1885 goto retry;
1886 }
1887 #endif /* IMPORTANCE_INHERITANCE */
1888
1889 if (error != MACH_MSG_SUCCESS) {
1890 ip_unlock(port);
1891 } else {
1892 /*
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.
1896 */
1897 imq_lock(&port->ip_messages);
1898 ip_unlock(port);
1899
1900 error = ipc_mqueue_send(&port->ip_messages, kmsg, option,
1901 send_timeout);
1902 }
1903
1904 #if IMPORTANCE_INHERITANCE
1905 if (did_importance == TRUE) {
1906 __unused int importance_cleared = 0;
1907 switch (error) {
1908 case MACH_SEND_TIMED_OUT:
1909 case MACH_SEND_NO_BUFFER:
1910 case MACH_SEND_INTERRUPTED:
1911 case MACH_SEND_INVALID_DEST:
1912 /*
1913 * We still have the kmsg and its
1914 * reference on the port. But we
1915 * have to back out the importance
1916 * boost.
1917 *
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)).
1926 */
1927 importance_cleared = 1;
1928 ipc_importance_clean(kmsg);
1929 break;
1930
1931 case MACH_MSG_SUCCESS:
1932 default:
1933 break;
1934 }
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 */
1939 }
1940 #endif /* IMPORTANCE_INHERITANCE */
1941
1942 /*
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).
1945 */
1946 if (error == MACH_SEND_INVALID_DEST) {
1947 #if MACH_FLIPC
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);
1950 #endif
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;
1956 }
1957
1958 if (error != MACH_MSG_SUCCESS && kernel_reply) {
1959 /*
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.
1963 */
1964 #if MACH_FLIPC
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);
1967 #endif
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;
1973 }
1974 return error;
1975 }
1976
1977 /*
1978 * Routine: ipc_kmsg_put
1979 * Purpose:
1980 * Copies a message buffer to a user message.
1981 * Copies only the specified number of bytes.
1982 * Frees the message buffer.
1983 * Conditions:
1984 * Nothing locked. The message buffer must have clean
1985 * header fields.
1986 * Returns:
1987 * MACH_MSG_SUCCESS Copied data out of message buffer.
1988 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
1989 */
1990
1991 mach_msg_return_t
1992 ipc_kmsg_put(
1993 ipc_kmsg_t kmsg,
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)
1999 {
2000 mach_msg_size_t size = kmsg->ikm_header->msgh_size + trailer_size;
2001 mach_msg_return_t mr;
2002
2003 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_put()");
2004
2005
2006 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
2007 " size: 0x%.8x\n"
2008 " bits: 0x%.8x\n"
2009 " remote_port: %p\n"
2010 " local_port: %p\n"
2011 " voucher_port: 0x%.8x\n"
2012 " id: %.8d\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);
2019
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);
2024
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;
2031
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;
2038
2039 size -= LEGACY_HEADER_SIZE_DELTA;
2040 kmsg->ikm_header = (mach_msg_header_t *)legacy_header;
2041 }
2042 #endif
2043
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));
2048 uint32_t i;
2049 for(i=0;i*4 < size;i++)
2050 {
2051 kprintf("%.4x\n",((uint32_t *)kmsg->ikm_header)[i]);
2052 }
2053 kprintf("type: %d\n", ((mach_msg_type_descriptor_t *)(((mach_msg_base_t *)kmsg->ikm_header)+1))->type);
2054 }
2055 __unreachable_ok_pop
2056
2057 /* Re-Compute target address if using stack-style delivery */
2058 if (option & MACH_RCV_STACK) {
2059 rcv_addr += rcv_size - size;
2060 }
2061
2062 if (copyoutmsg((const char *) kmsg->ikm_header, rcv_addr, size)) {
2063 mr = MACH_RCV_INVALID_DATA;
2064 size = 0;
2065 } else
2066 mr = MACH_MSG_SUCCESS;
2067
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 */,
2073 0,
2074 0);
2075 ipc_kmsg_free(kmsg);
2076
2077 if (sizep)
2078 *sizep = size;
2079 return mr;
2080 }
2081
2082 /*
2083 * Routine: ipc_kmsg_put_to_kernel
2084 * Purpose:
2085 * Copies a message buffer to a kernel message.
2086 * Frees the message buffer.
2087 * No errors allowed.
2088 * Conditions:
2089 * Nothing locked.
2090 */
2091
2092 void
2093 ipc_kmsg_put_to_kernel(
2094 mach_msg_header_t *msg,
2095 ipc_kmsg_t kmsg,
2096 mach_msg_size_t size)
2097 {
2098 (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, size);
2099
2100 ipc_kmsg_free(kmsg);
2101 }
2102
2103 unsigned long pthread_priority_canonicalize(unsigned long priority, boolean_t propagation);
2104
2105 static kern_return_t
2106 ipc_kmsg_set_qos(
2107 ipc_kmsg_t kmsg,
2108 mach_msg_option_t options,
2109 mach_msg_priority_t override)
2110 {
2111 kern_return_t kr;
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;
2115
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;
2119 }
2120 kmsg->ikm_qos_override = kmsg->ikm_qos;
2121
2122 if (options & MACH_SEND_OVERRIDE) {
2123 unsigned long canonical;
2124 mach_msg_priority_t canon;
2125
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;
2130 }
2131
2132 kr = KERN_SUCCESS;
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) {
2136 /*
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.
2140 *
2141 * Use the qos value passed by voucher and not the one passed by notify field.
2142 */
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));
2145 } else {
2146 kr = KERN_FAILURE;
2147 }
2148 }
2149 return kr;
2150 }
2151
2152 /*
2153 * Routine: ipc_kmsg_copyin_header
2154 * Purpose:
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.
2162 *
2163 * Conditions:
2164 * Nothing locked.
2165 * Returns:
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.)
2174 */
2175
2176 mach_msg_return_t
2177 ipc_kmsg_copyin_header(
2178 ipc_kmsg_t kmsg,
2179 ipc_space_t space,
2180 mach_msg_priority_t override,
2181 mach_msg_option_t *optionp)
2182 {
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;
2188 kern_return_t kr;
2189
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;
2204
2205 int assertcnt = 0;
2206 #if IMPORTANCE_INHERITANCE
2207 boolean_t needboost = FALSE;
2208 #endif /* IMPORTANCE_INHERITANCE */
2209
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;
2216
2217 if (!MACH_PORT_VALID(dest_name))
2218 return MACH_SEND_INVALID_DEST;
2219
2220 is_write_lock(space);
2221 if (!is_active(space)) {
2222 is_write_unlock(space);
2223 return MACH_SEND_INVALID_DEST;
2224 }
2225 /* space locked and active */
2226
2227 /*
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.
2231 */
2232 if (voucher_type != MACH_MSGH_BITS_ZERO) {
2233
2234 voucher_name = msg->msgh_voucher_port;
2235
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;
2241 }
2242
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;
2250 }
2251 } else {
2252 voucher_type = MACH_MSG_TYPE_MOVE_SEND;
2253 }
2254 }
2255
2256 /*
2257 * Handle combinations of validating destination and reply; along
2258 * with copying in destination, reply, and voucher in an atomic way.
2259 */
2260
2261 if (dest_name == voucher_name) {
2262
2263 /*
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).
2267 */
2268 dest_entry = voucher_entry;
2269 if (dest_entry == IE_NULL) {
2270 goto invalid_dest;
2271 }
2272
2273 /*
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
2276 * back out.
2277 */
2278 if (MACH_PORT_VALID(reply_name)) {
2279 assert(reply_type != 0); /* because reply_name not null */
2280
2281 /* It is just WRONG if dest, voucher, and reply are all the same. */
2282 if (voucher_name == reply_name) {
2283 goto invalid_reply;
2284 }
2285 reply_entry = ipc_entry_lookup(space, reply_name);
2286 if (reply_entry == IE_NULL) {
2287 goto invalid_reply;
2288 }
2289 assert(dest_entry != reply_entry); /* names are not equal */
2290 if (!ipc_right_copyin_check(space, reply_name, reply_entry, reply_type)) {
2291 goto invalid_reply;
2292 }
2293 }
2294
2295 /*
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.
2301 */
2302 kr = ipc_right_copyin_two(space, dest_name, dest_entry,
2303 dest_type, voucher_type,
2304 &dest_port, &dest_soright,
2305 &release_port);
2306 if (kr != KERN_SUCCESS) {
2307 assert(kr != KERN_INVALID_CAPABILITY);
2308 goto invalid_dest;
2309 }
2310 voucher_port = (ipc_port_t)dest_port;
2311
2312 /*
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.
2316 */
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);
2320
2321 /*
2322 * Perform the delayed reply right copyin (guaranteed success).
2323 */
2324 if (reply_entry != IE_NULL) {
2325 kr = ipc_right_copyin(space, reply_name, reply_entry,
2326 reply_type, TRUE,
2327 &reply_port, &reply_soright,
2328 &release_port, &assertcnt);
2329 assert(assertcnt == 0);
2330 assert(kr == KERN_SUCCESS);
2331 }
2332
2333 } else {
2334 if (dest_name == reply_name) {
2335 /*
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).
2341 */
2342 dest_entry = ipc_entry_lookup(space, dest_name);
2343 if (dest_entry == IE_NULL) {
2344 goto invalid_dest;
2345 }
2346 reply_entry = dest_entry;
2347 assert(reply_type != 0); /* because name not null */
2348
2349 /*
2350 * Do the joint copyin of the dest disposition and
2351 * reply disposition from the one entry/port.
2352 */
2353 kr = ipc_right_copyin_two(space, dest_name, dest_entry,
2354 dest_type, reply_type,
2355 &dest_port, &dest_soright,
2356 &release_port);
2357 if (kr == KERN_INVALID_CAPABILITY) {
2358 goto invalid_reply;
2359 } else if (kr != KERN_SUCCESS) {
2360 goto invalid_dest;
2361 }
2362 reply_port = dest_port;
2363
2364
2365 } else {
2366 /*
2367 * Handle destination and reply independently, as
2368 * they are independent entries (even if the entries
2369 * refer to the same port).
2370 *
2371 * This can be the tough case to make atomic.
2372 *
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.
2379 *
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.
2386 *
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.
2390 */
2391
2392 dest_entry = ipc_entry_lookup(space, dest_name);
2393 if (dest_entry == IE_NULL) {
2394 goto invalid_dest;
2395 }
2396 assert(dest_entry != voucher_entry);
2397
2398 /*
2399 * Make sure reply port entry is valid before dest copyin.
2400 */
2401 if (MACH_PORT_VALID(reply_name)) {
2402 if (reply_name == voucher_name) {
2403 goto invalid_reply;
2404 }
2405 reply_entry = ipc_entry_lookup(space, reply_name);
2406 if (reply_entry == IE_NULL) {
2407 goto invalid_reply;
2408 }
2409 assert(dest_entry != reply_entry); /* names are not equal */
2410 assert(reply_type != 0); /* because reply_name not null */
2411
2412 if (!ipc_right_copyin_check(space, reply_name, reply_entry, reply_type)) {
2413 goto invalid_reply;
2414 }
2415 }
2416
2417 /*
2418 * copyin the destination.
2419 */
2420 kr = ipc_right_copyin(space, dest_name, dest_entry,
2421 dest_type, FALSE,
2422 &dest_port, &dest_soright,
2423 &release_port, &assertcnt);
2424 assert(assertcnt == 0);
2425 if (kr != KERN_SUCCESS) {
2426 goto invalid_dest;
2427 }
2428 assert(IO_VALID(dest_port));
2429 assert(!IP_VALID(release_port));
2430
2431 /*
2432 * Copyin the pre-validated reply right.
2433 * It's OK if the reply right has gone dead in the meantime.
2434 */
2435 if (MACH_PORT_VALID(reply_name)) {
2436 kr = ipc_right_copyin(space, reply_name, reply_entry,
2437 reply_type, TRUE,
2438 &reply_port, &reply_soright,
2439 &release_port, &assertcnt);
2440 assert(assertcnt == 0);
2441 assert(kr == KERN_SUCCESS);
2442 } else {
2443 /* convert invalid name to equivalent ipc_object type */
2444 reply_port = (ipc_object_t)CAST_MACH_NAME_TO_PORT(reply_name);
2445 }
2446 }
2447
2448 /*
2449 * Finally can copyin the voucher right now that dest and reply
2450 * are fully copied in (guaranteed success).
2451 */
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,
2456 &voucher_soright,
2457 &voucher_release_port,
2458 &assertcnt);
2459 assert(assertcnt == 0);
2460 assert(KERN_SUCCESS == kr);
2461 assert(IP_VALID(voucher_port));
2462 assert(ip_active(voucher_port));
2463 }
2464 }
2465
2466 /*
2467 * The entries might need to be deallocated.
2468 *
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.
2473 */
2474 assert(IE_NULL != dest_entry);
2475 if (IE_NULL != reply_entry)
2476 assert(reply_entry != voucher_entry);
2477
2478 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
2479 ipc_entry_dealloc(space, dest_name, dest_entry);
2480
2481 if (dest_entry == reply_entry) {
2482 reply_entry = IE_NULL;
2483 }
2484
2485 if (dest_entry == voucher_entry) {
2486 voucher_entry = IE_NULL;
2487 }
2488
2489 dest_entry = IE_NULL;
2490 }
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;
2495 }
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;
2500 }
2501
2502 dest_type = ipc_object_copyin_type(dest_type);
2503 reply_type = ipc_object_copyin_type(reply_type);
2504
2505 /*
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.
2510 */
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;
2515
2516 assert(dport != IP_NULL);
2517 ip_lock(dport);
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,
2523 *optionp,
2524 override);
2525 if (needboost == FALSE)
2526 ip_unlock(dport);
2527 #else
2528 ipc_port_request_sparm(dport, dest_name,
2529 dest_entry->ie_request,
2530 *optionp,
2531 override);
2532 ip_unlock(dport);
2533 #endif /* IMPORTANCE_INHERITANCE */
2534 } else {
2535 *optionp |= MACH_SEND_ALWAYS;
2536 ip_unlock(dport);
2537 }
2538 } else {
2539 ip_unlock(dport);
2540 }
2541 }
2542
2543 is_write_unlock(space);
2544
2545 #if IMPORTANCE_INHERITANCE
2546 /*
2547 * If our request is the first boosting send-possible
2548 * notification this cycle, push the boost down the
2549 * destination port.
2550 */
2551 if (needboost == TRUE) {
2552 ipc_port_t dport = (ipc_port_t)dest_port;
2553
2554 /* dport still locked from above */
2555 if (ipc_port_importance_delta(dport, IPID_OPTION_SENDPOSSIBLE, 1) == FALSE) {
2556 ip_unlock(dport);
2557 }
2558 }
2559 #endif /* IMPORTANCE_INHERITANCE */
2560
2561 if (dest_soright != IP_NULL) {
2562 ipc_notify_port_deleted(dest_soright, dest_name);
2563 }
2564 if (reply_soright != IP_NULL) {
2565 ipc_notify_port_deleted(reply_soright, reply_name);
2566 }
2567 if (voucher_soright != IP_NULL) {
2568 ipc_notify_port_deleted(voucher_soright, voucher_name);
2569 }
2570
2571 /*
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.
2575 */
2576 if (IP_VALID(voucher_port)) {
2577
2578 kmsg->ikm_voucher = voucher_port;
2579 voucher_type = MACH_MSG_TYPE_MOVE_SEND;
2580 }
2581
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;
2585
2586 /* capture the qos value(s) for the kmsg */
2587 ipc_kmsg_set_qos(kmsg, *optionp, override);
2588
2589 if (release_port != IP_NULL)
2590 ip_release(release_port);
2591
2592 if (voucher_release_port != IP_NULL)
2593 ip_release(voucher_release_port);
2594
2595 return MACH_MSG_SUCCESS;
2596
2597 invalid_reply:
2598 is_write_unlock(space);
2599
2600 if (release_port != IP_NULL)
2601 ip_release(release_port);
2602
2603 assert(voucher_port == IP_NULL);
2604 assert(voucher_soright == IP_NULL);
2605
2606 return MACH_SEND_INVALID_REPLY;
2607
2608 invalid_dest:
2609 is_write_unlock(space);
2610
2611 if (release_port != IP_NULL)
2612 ip_release(release_port);
2613
2614 if (reply_soright != IP_NULL)
2615 ipc_notify_port_deleted(reply_soright, reply_name);
2616
2617 assert(voucher_port == IP_NULL);
2618 assert(voucher_soright == IP_NULL);
2619
2620 return MACH_SEND_INVALID_DEST;
2621 }
2622
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,
2626 ipc_space_t space,
2627 ipc_object_t dest,
2628 ipc_kmsg_t kmsg,
2629 mach_msg_return_t *mr);
2630
2631 void ipc_print_type_name(
2632 int 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,
2637 ipc_space_t space,
2638 ipc_object_t dest,
2639 ipc_kmsg_t kmsg,
2640 mach_msg_return_t *mr)
2641 {
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;
2647
2648 user_disp = user_dsc->disposition;
2649 result_disp = ipc_object_copyin_type(user_disp);
2650
2651 name = (mach_port_name_t)user_dsc->name;
2652 if (MACH_PORT_VALID(name)) {
2653
2654 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
2655 if (kr != KERN_SUCCESS) {
2656 *mr = MACH_SEND_INVALID_RIGHT;
2657 return NULL;
2658 }
2659
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;
2664 }
2665 dsc->name = (ipc_port_t) object;
2666 } else {
2667 dsc->name = CAST_MACH_NAME_TO_PORT(name);
2668 }
2669 dsc->disposition = result_disp;
2670 dsc->type = MACH_MSG_PORT_DESCRIPTOR;
2671
2672 dsc->pad_end = 0; // debug, unnecessary
2673
2674 return (mach_msg_descriptor_t *)(user_dsc_in+1);
2675 }
2676
2677 mach_msg_descriptor_t * ipc_kmsg_copyin_ool_descriptor(
2678 mach_msg_ool_descriptor_t *dsc,
2679 mach_msg_descriptor_t *user_dsc,
2680 int is_64bit,
2681 vm_offset_t *paddr,
2682 vm_map_copy_t *copy,
2683 vm_size_t *space_needed,
2684 vm_map_t map,
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,
2690 int is_64bit,
2691 vm_offset_t *paddr,
2692 vm_map_copy_t *copy,
2693 vm_size_t *space_needed,
2694 vm_map_t map,
2695 mach_msg_return_t *mr)
2696 {
2697 vm_size_t length;
2698 boolean_t dealloc;
2699 mach_msg_copy_options_t copy_options;
2700 mach_vm_offset_t addr;
2701 mach_msg_descriptor_type_t dsc_type;
2702
2703 if (is_64bit) {
2704 mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2705
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;
2711
2712 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2713 } else {
2714 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2715
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;
2721
2722 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2723 }
2724
2725 dsc->size = (mach_msg_size_t)length;
2726 dsc->deallocate = dealloc;
2727 dsc->copy = copy_options;
2728 dsc->type = dsc_type;
2729
2730 if (length == 0) {
2731 dsc->address = NULL;
2732 } else if ((length >= MSG_OOL_SIZE_SMALL) &&
2733 (copy_options == MACH_MSG_PHYSICAL_COPY) && !dealloc) {
2734
2735 /*
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.
2744 */
2745 if (copyin(addr, (char *)*paddr, length)) {
2746 *mr = MACH_SEND_INVALID_MEMORY;
2747 return NULL;
2748 }
2749
2750 /*
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.
2754 */
2755 if (!page_aligned(length)) {
2756 (void) memset((void *) (*paddr + length), 0,
2757 round_page(length) - length);
2758 }
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;
2762 return NULL;
2763 }
2764 dsc->address = (void *)*copy;
2765 *paddr += round_page(length);
2766 *space_needed -= round_page(length);
2767 } else {
2768
2769 /*
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.
2773 *
2774 * NOTE: A virtual copy is OK if the original is being
2775 * deallocted, even if a physical copy was requested.
2776 */
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;
2783 return NULL;
2784 }
2785 dsc->address = (void *)*copy;
2786 }
2787 return user_dsc;
2788 }
2789
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,
2793 int is_64bit,
2794 vm_map_t map,
2795 ipc_space_t space,
2796 ipc_object_t dest,
2797 ipc_kmsg_t kmsg,
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,
2803 int is_64bit,
2804 vm_map_t map,
2805 ipc_space_t space,
2806 ipc_object_t dest,
2807 ipc_kmsg_t kmsg,
2808 mach_msg_return_t *mr)
2809 {
2810 void *data;
2811 ipc_object_t *objects;
2812 unsigned int i;
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;
2821
2822 if (is_64bit) {
2823 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2824
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;
2831
2832 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2833 } else {
2834 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2835
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;
2842
2843 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2844 }
2845
2846 dsc->deallocate = deallocate;
2847 dsc->copy = copy_option;
2848 dsc->type = type;
2849 dsc->count = count;
2850 dsc->address = NULL; /* for now */
2851
2852 result_disp = ipc_object_copyin_type(user_disp);
2853 dsc->disposition = result_disp;
2854
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;
2859 return NULL;
2860 }
2861
2862 /* calculate length of data in bytes, rounding up */
2863
2864 if (os_mul_overflow(count, sizeof(mach_port_t), &ports_length)) {
2865 *mr = MACH_SEND_TOO_LARGE;
2866 return NULL;
2867 }
2868
2869 if (os_mul_overflow(count, sizeof(mach_port_name_t), &names_length)) {
2870 *mr = MACH_SEND_TOO_LARGE;
2871 return NULL;
2872 }
2873
2874 if (ports_length == 0) {
2875 return user_dsc;
2876 }
2877
2878 data = kalloc(ports_length);
2879
2880 if (data == NULL) {
2881 *mr = MACH_SEND_NO_BUFFER;
2882 return NULL;
2883 }
2884
2885 #ifdef __LP64__
2886 mach_port_name_t *names = &((mach_port_name_t *)data)[count];
2887 #else
2888 mach_port_name_t *names = ((mach_port_name_t *)data);
2889 #endif
2890
2891 if (copyinmap(map, addr, names, names_length) != KERN_SUCCESS) {
2892 kfree(data, ports_length);
2893 *mr = MACH_SEND_INVALID_MEMORY;
2894 return NULL;
2895 }
2896
2897 if (deallocate) {
2898 (void) mach_vm_deallocate(map, addr, (mach_vm_size_t)ports_length);
2899 }
2900
2901 objects = (ipc_object_t *) data;
2902 dsc->address = data;
2903
2904 for ( i = 0; i < count; i++) {
2905 mach_port_name_t name = names[i];
2906 ipc_object_t object;
2907
2908 if (!MACH_PORT_VALID(name)) {
2909 objects[i] = (ipc_object_t)CAST_MACH_NAME_TO_PORT(name);
2910 continue;
2911 }
2912
2913 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
2914
2915 if (kr != KERN_SUCCESS) {
2916 unsigned int j;
2917
2918 for(j = 0; j < i; j++) {
2919 object = objects[j];
2920 if (IPC_OBJECT_VALID(object))
2921 ipc_object_destroy(object, result_disp);
2922 }
2923 kfree(data, ports_length);
2924 dsc->address = NULL;
2925 *mr = MACH_SEND_INVALID_RIGHT;
2926 return NULL;
2927 }
2928
2929 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2930 ipc_port_check_circularity(
2931 (ipc_port_t) object,
2932 (ipc_port_t) dest))
2933 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2934
2935 objects[i] = object;
2936 }
2937
2938 return user_dsc;
2939 }
2940
2941 /*
2942 * Routine: ipc_kmsg_copyin_body
2943 * Purpose:
2944 * "Copy-in" port rights and out-of-line memory
2945 * in the message body.
2946 *
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.
2951 * Conditions:
2952 * Nothing locked.
2953 * Returns:
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
2961 */
2962
2963 mach_msg_return_t
2964 ipc_kmsg_copyin_body(
2965 ipc_kmsg_t kmsg,
2966 ipc_space_t space,
2967 vm_map_t map)
2968 {
2969 ipc_object_t dest;
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;
2981
2982 vm_size_t descriptor_size = 0;
2983
2984 mach_msg_type_number_t total_ool_port_count = 0;
2985
2986 /*
2987 * Determine if the target is a kernel port.
2988 */
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);
2992
2993 dsc_count = body->msgh_descriptor_count;
2994 if (dsc_count == 0)
2995 return MACH_MSG_SUCCESS;
2996
2997 /*
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.
3001 */
3002 daddr = NULL;
3003 for (i = 0; i < dsc_count; i++) {
3004 mach_msg_size_t size;
3005 mach_msg_type_number_t ool_port_count = 0;
3006
3007 daddr = naddr;
3008
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);
3017 break;
3018 default:
3019 descriptor_size += 12;
3020 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
3021 break;
3022 }
3023 } else {
3024 descriptor_size += 12;
3025 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
3026 }
3027
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;
3031 goto clean_message;
3032 }
3033
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;
3040
3041 if (daddr->out_of_line.copy != MACH_MSG_PHYSICAL_COPY &&
3042 daddr->out_of_line.copy != MACH_MSG_VIRTUAL_COPY) {
3043 /*
3044 * Invalid copy option
3045 */
3046 mr = MACH_SEND_INVALID_TYPE;
3047 goto clean_message;
3048 }
3049
3050 if ((size >= MSG_OOL_SIZE_SMALL) &&
3051 (daddr->out_of_line.copy == MACH_MSG_PHYSICAL_COPY) &&
3052 !(daddr->out_of_line.deallocate)) {
3053
3054 /*
3055 * Out-of-line memory descriptor, accumulate kernel
3056 * memory requirements
3057 */
3058 if (space_needed + round_page(size) <= space_needed) {
3059 /* Overflow dectected */
3060 mr = MACH_MSG_VM_KERNEL;
3061 goto clean_message;
3062 }
3063
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;
3068 goto clean_message;
3069 }
3070 }
3071 break;
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;
3076 goto clean_message;
3077 }
3078 break;
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;
3083
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;
3087 goto clean_message;
3088 }
3089
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;
3093 goto clean_message;
3094 }
3095 break;
3096 }
3097 }
3098
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;
3102 goto clean_message;
3103 }
3104
3105 /*
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
3108 * space.
3109 */
3110 if (space_needed) {
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;
3114 goto clean_message;
3115 }
3116 }
3117
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));
3120
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;
3124
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);
3127
3128 /* Update the message size for the larger in-kernel representation */
3129 kmsg->ikm_header->msgh_size += (mach_msg_size_t)dsc_adjust;
3130 }
3131
3132
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));
3135
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);
3142 kern_addr++;
3143 complex = TRUE;
3144 break;
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, &copy, &space_needed, map, &mr);
3149 kern_addr++;
3150 complex = TRUE;
3151 break;
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);
3155 kern_addr++;
3156 complex = TRUE;
3157 break;
3158 default:
3159 /* Invalid descriptor */
3160 mr = MACH_SEND_INVALID_TYPE;
3161 break;
3162 }
3163
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);
3169 goto out;
3170 }
3171 } /* End of loop */
3172
3173 if (!complex) {
3174 kmsg->ikm_header->msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
3175 }
3176 out:
3177 return mr;
3178
3179 clean_message:
3180 /* no descriptors have been copied in yet */
3181 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
3182 return mr;
3183 }
3184
3185
3186 /*
3187 * Routine: ipc_kmsg_copyin
3188 * Purpose:
3189 * "Copy-in" port rights and out-of-line memory
3190 * in the message.
3191 *
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.
3196 * Conditions:
3197 * Nothing locked.
3198 * Returns:
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.
3208 */
3209
3210 mach_msg_return_t
3211 ipc_kmsg_copyin(
3212 ipc_kmsg_t kmsg,
3213 ipc_space_t space,
3214 vm_map_t map,
3215 mach_msg_priority_t override,
3216 mach_msg_option_t *optionp)
3217 {
3218 mach_msg_return_t mr;
3219
3220 kmsg->ikm_header->msgh_bits &= MACH_MSGH_BITS_USER;
3221
3222 mr = ipc_kmsg_copyin_header(kmsg, space, override, optionp);
3223
3224 if (mr != MACH_MSG_SUCCESS)
3225 return mr;
3226
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)),
3232 0);
3233
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,
3239 kmsg->ikm_voucher,
3240 kmsg->ikm_header->msgh_id);
3241
3242 if ((kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0)
3243 return MACH_MSG_SUCCESS;
3244
3245 mr = ipc_kmsg_copyin_body( kmsg, space, map);
3246
3247 /* unreachable if !DEBUG */
3248 __unreachable_ok_push
3249 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
3250 {
3251 kprintf("body:\n");
3252 uint32_t i;
3253 for(i=0;i*4 < (kmsg->ikm_header->msgh_size - sizeof(mach_msg_header_t));i++)
3254 {
3255 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
3256 }
3257 }
3258 __unreachable_ok_pop
3259
3260 return mr;
3261 }
3262
3263 /*
3264 * Routine: ipc_kmsg_copyin_from_kernel
3265 * Purpose:
3266 * "Copy-in" port rights and out-of-line memory
3267 * in a message sent from the kernel.
3268 *
3269 * Because the message comes from the kernel,
3270 * the implementation assumes there are no errors
3271 * or peculiarities in the message.
3272 * Conditions:
3273 * Nothing locked.
3274 */
3275
3276 mach_msg_return_t
3277 ipc_kmsg_copyin_from_kernel(
3278 ipc_kmsg_t kmsg)
3279 {
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;
3285
3286 /* translate the destination and reply ports */
3287 if (!IO_VALID(remote))
3288 return MACH_SEND_INVALID_DEST;
3289
3290 ipc_object_copyin_from_kernel(remote, rname);
3291 if (IO_VALID(local))
3292 ipc_object_copyin_from_kernel(local, lname);
3293
3294 /*
3295 * The common case is a complex message with no reply port,
3296 * because that is what the memory_object interface uses.
3297 */
3298
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));
3303
3304 kmsg->ikm_header->msgh_bits = bits;
3305 } else {
3306 bits = (MACH_MSGH_BITS_OTHER(bits) |
3307 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
3308 ipc_object_copyin_type(lname)));
3309
3310 kmsg->ikm_header->msgh_bits = bits;
3311 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
3312 return MACH_MSG_SUCCESS;
3313 }
3314 {
3315 mach_msg_descriptor_t *saddr;
3316 mach_msg_body_t *body;
3317 mach_msg_type_number_t i, count;
3318
3319 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3320 saddr = (mach_msg_descriptor_t *) (body + 1);
3321 count = body->msgh_descriptor_count;
3322
3323 for (i = 0; i < count; i++, saddr++) {
3324
3325 switch (saddr->type.type) {
3326
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;
3331
3332 dsc = &saddr->port;
3333
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);
3338
3339 if (!IO_VALID(object)) {
3340 break;
3341 }
3342
3343 ipc_object_copyin_from_kernel(object, name);
3344
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 */
3349
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;
3356 }
3357 }
3358 break;
3359 }
3360 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3361 case MACH_MSG_OOL_DESCRIPTOR: {
3362 /*
3363 * The sender should supply ready-made memory, i.e.
3364 * a vm_map_copy_t, so we don't need to do anything.
3365 */
3366 break;
3367 }
3368 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
3369 ipc_object_t *objects;
3370 unsigned int j;
3371 mach_msg_type_name_t name;
3372 mach_msg_ool_ports_descriptor_t *dsc;
3373
3374 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
3375
3376 /* this is really the type SEND, SEND_ONCE, etc. */
3377 name = dsc->disposition;
3378 dsc->disposition = ipc_object_copyin_type(name);
3379
3380 objects = (ipc_object_t *) dsc->address;
3381
3382 for ( j = 0; j < dsc->count; j++) {
3383 ipc_object_t object = objects[j];
3384
3385 if (!IO_VALID(object))
3386 continue;
3387
3388 ipc_object_copyin_from_kernel(object, name);
3389
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;
3395 }
3396 break;
3397 }
3398 default: {
3399 #if MACH_ASSERT
3400 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3401 #endif /* MACH_ASSERT */
3402 }
3403 }
3404 }
3405 }
3406 return MACH_MSG_SUCCESS;
3407 }
3408
3409 #if IKM_SUPPORT_LEGACY
3410 mach_msg_return_t
3411 ipc_kmsg_copyin_from_kernel_legacy(
3412 ipc_kmsg_t kmsg)
3413 {
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;
3419
3420 /* translate the destination and reply ports */
3421 if (!IO_VALID(remote))
3422 return MACH_SEND_INVALID_DEST;
3423
3424 ipc_object_copyin_from_kernel(remote, rname);
3425 if (IO_VALID(local))
3426 ipc_object_copyin_from_kernel(local, lname);
3427
3428 /*
3429 * The common case is a complex message with no reply port,
3430 * because that is what the memory_object interface uses.
3431 */
3432
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));
3437
3438 kmsg->ikm_header->msgh_bits = bits;
3439 } else {
3440 bits = (MACH_MSGH_BITS_OTHER(bits) |
3441 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
3442 ipc_object_copyin_type(lname)));
3443
3444 kmsg->ikm_header->msgh_bits = bits;
3445 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
3446 return MACH_MSG_SUCCESS;
3447 }
3448 {
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;
3453
3454 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3455 saddr = (typeof(saddr)) (body + 1);
3456 count = body->msgh_descriptor_count;
3457
3458 if(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;
3464 }
3465 daddr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
3466
3467 for (i = 0; i < count; i++, saddr++, daddr++) {
3468 switch (saddr->type.type) {
3469
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;
3475
3476 dsc = (typeof(dsc))&saddr->port;
3477 dest_dsc = &daddr->port;
3478
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;
3485
3486 if (!IO_VALID(object)) {
3487 break;
3488 }
3489
3490 ipc_object_copyin_from_kernel(object, name);
3491
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 */
3496
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;
3503 }
3504 }
3505 break;
3506 }
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. */
3511
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;
3514
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;
3520
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;
3526 break;
3527 }
3528 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
3529 ipc_object_t *objects;
3530 unsigned int j;
3531 mach_msg_type_name_t name;
3532 mach_msg_ool_ports_descriptor_t *dest_dsc;
3533
3534 mach_msg_ool_ports_descriptor32_t *source_dsc = &saddr->ool_ports32;
3535 dest_dsc = (typeof(dest_dsc))&daddr->ool_ports;
3536
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;
3541
3542 /* this is really the type SEND, SEND_ONCE, etc. */
3543 name = disposition;
3544 disposition = ipc_object_copyin_type(name);
3545
3546 objects = (ipc_object_t *) (uintptr_t)source_dsc->address;
3547
3548 for ( j = 0; j < port_count; j++) {
3549 ipc_object_t object = objects[j];
3550
3551 if (!IO_VALID(object))
3552 continue;
3553
3554 ipc_object_copyin_from_kernel(object, name);
3555
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;
3561 }
3562
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;
3569 break;
3570 }
3571 default: {
3572 #if MACH_ASSERT
3573 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3574 #endif /* MACH_ASSERT */
3575 }
3576 }
3577 }
3578 }
3579 return MACH_MSG_SUCCESS;
3580 }
3581 #endif /* IKM_SUPPORT_LEGACY */
3582
3583 /*
3584 * Routine: ipc_kmsg_copyout_header
3585 * Purpose:
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.
3592 * Conditions:
3593 * Nothing locked.
3594 * Returns:
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.
3607 */
3608
3609 mach_msg_return_t
3610 ipc_kmsg_copyout_header(
3611 ipc_kmsg_t kmsg,
3612 ipc_space_t space,
3613 mach_msg_option_t option)
3614 {
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;
3618
3619 assert(IP_VALID(dest));
3620
3621 /*
3622 * While we still hold a reference on the received-from port,
3623 * process all send-possible notfications we received along with
3624 * the message.
3625 */
3626 ipc_port_spnotify(dest);
3627
3628 {
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;
3635
3636 ipc_port_t voucher = kmsg->ikm_voucher;
3637 ipc_port_t release_voucher_port = IP_NULL;
3638 mach_port_name_t voucher_name;
3639
3640 uint32_t entries_held = 0;
3641 boolean_t need_write_lock = FALSE;
3642 kern_return_t kr;
3643
3644 /*
3645 * Reserve any potentially needed entries in the target space.
3646 * We'll free any unused before unlocking the space.
3647 */
3648 if (IP_VALID(reply)) {
3649 entries_held++;
3650 need_write_lock = TRUE;
3651 }
3652 if (IP_VALID(voucher)) {
3653 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
3654
3655 if ((option & MACH_RCV_VOUCHER) != 0)
3656 entries_held++;
3657 need_write_lock = TRUE;
3658 }
3659
3660 if (need_write_lock) {
3661
3662 is_write_lock(space);
3663
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);
3669 }
3670
3671 kr = ipc_entries_hold(space, entries_held);
3672 if (KERN_SUCCESS == kr)
3673 break;
3674
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 */
3680 }
3681
3682 /* Handle reply port. */
3683 if (IP_VALID(reply)) {
3684 ipc_entry_t entry;
3685
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);
3691 } else {
3692 ip_lock(reply);
3693 if (!ip_active(reply)) {
3694 ip_unlock(reply);
3695
3696 release_reply_port = reply;
3697 reply = IP_DEAD;
3698 reply_name = MACH_PORT_DEAD;
3699 goto done_with_reply;
3700 }
3701
3702 /* claim a held entry for the reply port */
3703 assert(entries_held > 0);
3704 entries_held--;
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;
3709 }
3710
3711 /* space and reply port are locked and active */
3712 ip_reference(reply); /* hold onto the reply port */
3713
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 */
3718 } else
3719 reply_name = CAST_MACH_PORT_TO_NAME(reply);
3720
3721 done_with_reply:
3722
3723 /* Handle voucher port. */
3724 if (voucher_type != MACH_MSGH_BITS_ZERO) {
3725 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
3726
3727 if (!IP_VALID(voucher)) {
3728 if ((option & MACH_RCV_VOUCHER) == 0) {
3729 voucher_type = MACH_MSGH_BITS_ZERO;
3730 }
3731 voucher_name = MACH_PORT_NULL;
3732 goto done_with_voucher;
3733 }
3734
3735 /* clear voucher from its hiding place back in the kmsg */
3736 kmsg->ikm_voucher = IP_NULL;
3737
3738 if ((option & MACH_RCV_VOUCHER) != 0) {
3739 ipc_entry_t entry;
3740
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);
3745 } else {
3746 assert(entries_held > 0);
3747 entries_held--;
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;
3752 ip_lock(voucher);
3753 }
3754 /* space is locked and active */
3755
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 */
3762 } else {
3763 voucher_type = MACH_MSGH_BITS_ZERO;
3764 release_voucher_port = voucher;
3765 voucher_name = MACH_PORT_NULL;
3766 }
3767 } else {
3768 voucher_name = msg->msgh_voucher_port;
3769 }
3770
3771 done_with_voucher:
3772
3773 ip_lock(dest);
3774 is_write_unlock(space);
3775
3776 } else {
3777 /*
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.
3781 */
3782
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;
3787 }
3788
3789 ip_lock(dest);
3790 is_read_unlock(space);
3791
3792 reply_name = CAST_MACH_PORT_TO_NAME(reply);
3793
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;
3798 }
3799 voucher_name = MACH_PORT_NULL;
3800 } else {
3801 voucher_name = msg->msgh_voucher_port;
3802 }
3803 }
3804
3805 /*
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).
3810 *
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.
3818 *
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.
3835 *
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.
3844 *
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.
3850 */
3851
3852 if (ip_active(dest)) {
3853 ipc_object_copyout_dest(space, (ipc_object_t) dest,
3854 dest_type, &dest_name);
3855 /* dest is unlocked */
3856
3857 } else {
3858 ipc_port_timestamp_t timestamp;
3859
3860 timestamp = dest->ip_timestamp;
3861 ip_unlock(dest);
3862 ip_release(dest);
3863
3864 if (IP_VALID(reply)) {
3865 ip_lock(reply);
3866 if (ip_active(reply) ||
3867 IP_TIMESTAMP_ORDER(timestamp,
3868 reply->ip_timestamp))
3869 dest_name = MACH_PORT_DEAD;
3870 else
3871 dest_name = MACH_PORT_NULL;
3872 ip_unlock(reply);
3873 } else
3874 dest_name = MACH_PORT_DEAD;
3875 }
3876
3877 if (IP_VALID(reply))
3878 ip_release(reply);
3879
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);
3883 else
3884 ipc_port_release_send(release_reply_port);
3885 }
3886
3887 if (IP_VALID(release_voucher_port))
3888 ipc_port_release_send(release_voucher_port);
3889
3890
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)),
3897 0);
3898 } else {
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)),
3904 0);
3905 }
3906
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;
3912 }
3913
3914 return MACH_MSG_SUCCESS;
3915 }
3916
3917 /*
3918 * Routine: ipc_kmsg_copyout_object
3919 * Purpose:
3920 * Copy-out a port right. Always returns a name,
3921 * even for unsuccessful return codes. Always
3922 * consumes the supplied object.
3923 * Conditions:
3924 * Nothing locked.
3925 * Returns:
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.)
3932 */
3933
3934 mach_msg_return_t
3935 ipc_kmsg_copyout_object(
3936 ipc_space_t space,
3937 ipc_object_t object,
3938 mach_msg_type_name_t msgt_name,
3939 mach_port_name_t *namep)
3940 {
3941 kern_return_t kr;
3942
3943 if (!IO_VALID(object)) {
3944 *namep = CAST_MACH_PORT_TO_NAME(object);
3945 return MACH_MSG_SUCCESS;
3946 }
3947
3948 kr = ipc_object_copyout(space, object, msgt_name, TRUE, namep);
3949 if (kr != KERN_SUCCESS) {
3950 ipc_object_destroy(object, msgt_name);
3951
3952 if (kr == KERN_INVALID_CAPABILITY)
3953 *namep = MACH_PORT_DEAD;
3954 else {
3955 *namep = MACH_PORT_NULL;
3956
3957 if (kr == KERN_RESOURCE_SHORTAGE)
3958 return MACH_MSG_IPC_KERNEL;
3959 else
3960 return MACH_MSG_IPC_SPACE;
3961 }
3962 }
3963
3964 return MACH_MSG_SUCCESS;
3965 }
3966
3967 mach_msg_descriptor_t *
3968 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3969 mach_msg_descriptor_t *user_dsc,
3970 ipc_space_t space,
3971 kern_return_t *mr);
3972 mach_msg_descriptor_t *
3973 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3974 mach_msg_descriptor_t *dest_dsc,
3975 ipc_space_t space,
3976 kern_return_t *mr)
3977 {
3978 mach_port_t port;
3979 mach_port_name_t name;
3980 mach_msg_type_name_t disp;
3981
3982
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,
3987 (ipc_object_t)port,
3988 disp,
3989 &name);
3990
3991 if(current_task() == kernel_task)
3992 {
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;
4000 } else {
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;
4008 }
4009
4010 return (mach_msg_descriptor_t *)dest_dsc;
4011 }
4012
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)
4017 {
4018 vm_map_copy_t copy;
4019 vm_map_address_t rcv_addr;
4020 mach_msg_copy_options_t copy_options;
4021 vm_map_size_t size;
4022 mach_msg_descriptor_type_t dsc_type;
4023
4024 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4025
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;
4031
4032 if (copy != VM_MAP_COPY_NULL) {
4033 kern_return_t kr;
4034
4035 rcv_addr = 0;
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;
4043 else
4044 *mr |= MACH_MSG_VM_SPACE;
4045 vm_map_copy_discard(copy);
4046 rcv_addr = 0;
4047 size = 0;
4048 }
4049 } else {
4050 rcv_addr = 0;
4051 size = 0;
4052 }
4053
4054 /*
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.
4059 */
4060 if(current_task() == kernel_task)
4061 {
4062 mach_msg_ool_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4063 user_ool_dsc--;
4064 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
4065
4066 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
4067 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4068 TRUE : FALSE;
4069 user_ool_dsc->copy = copy_options;
4070 user_ool_dsc->type = dsc_type;
4071 user_ool_dsc->size = (mach_msg_size_t)size;
4072
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;
4076 user_ool_dsc--;
4077 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
4078
4079 user_ool_dsc->address = rcv_addr;
4080 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4081 TRUE : FALSE;
4082 user_ool_dsc->copy = copy_options;
4083 user_ool_dsc->type = dsc_type;
4084 user_ool_dsc->size = (mach_msg_size_t)size;
4085
4086 user_dsc = (typeof(user_dsc))user_ool_dsc;
4087 } else {
4088 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4089 user_ool_dsc--;
4090 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
4091
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) ?
4095 TRUE : FALSE;
4096 user_ool_dsc->copy = copy_options;
4097 user_ool_dsc->type = dsc_type;
4098
4099 user_dsc = (typeof(user_dsc))user_ool_dsc;
4100 }
4101 return user_dsc;
4102 }
4103
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,
4107 int is_64bit,
4108 vm_map_t map,
4109 ipc_space_t space,
4110 ipc_kmsg_t kmsg,
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,
4115 int is_64bit,
4116 vm_map_t map,
4117 ipc_space_t space,
4118 ipc_kmsg_t kmsg,
4119 mach_msg_return_t *mr)
4120 {
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;
4125
4126 mach_msg_copy_options_t copy_options = MACH_MSG_VIRTUAL_COPY;
4127
4128 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4129
4130 count = dsc->count;
4131 disp = dsc->disposition;
4132 ports_length = count * sizeof(mach_port_t);
4133 names_length = count * sizeof(mach_port_name_t);
4134
4135 if (ports_length != 0 && dsc->address != 0) {
4136
4137 /*
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.
4141 */
4142 #if 0
4143 if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
4144 if (differs) {
4145 OTHER_OOL_DESCRIPTOR *scatter_dsc;
4146
4147 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
4148 rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
4149 copy_options = scatter_dsc->copy;
4150 } else {
4151 mach_msg_ool_descriptor_t *scatter_dsc;
4152
4153 scatter_dsc = &saddr->out_of_line;
4154 rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
4155 copy_options = scatter_dsc->copy;
4156 }
4157 INCREMENT_SCATTER(saddr, sdsc_count, differs);
4158 }
4159 #endif
4160
4161 if (copy_options == MACH_MSG_VIRTUAL_COPY) {
4162 /*
4163 * Dynamically allocate the region
4164 */
4165 vm_tag_t tag;
4166 if (vm_kernel_map_is_kernel(map)) tag = VM_KERN_MEMORY_IPC;
4167 else tag = VM_MEMORY_MACH_MSG;
4168
4169 kern_return_t kr;
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);
4174 rcv_addr = 0;
4175
4176 if (kr == KERN_RESOURCE_SHORTAGE){
4177 *mr |= MACH_MSG_VM_KERNEL;
4178 } else {
4179 *mr |= MACH_MSG_VM_SPACE;
4180 }
4181 }
4182 }
4183
4184 /*
4185 * Handle the port rights and copy out the names
4186 * for those rights out to user-space.
4187 */
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;
4191
4192 /* copyout port rights carried in the message */
4193
4194 for ( i = 0; i < count ; i++) {
4195 ipc_object_t object = (ipc_object_t)objects[i];
4196
4197 *mr |= ipc_kmsg_copyout_object(space, object,
4198 disp, &names[i]);
4199 }
4200
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);
4206 }
4207 } else {
4208 rcv_addr = 0;
4209 }
4210
4211 /*
4212 * Now update the descriptor based on the information
4213 * calculated above.
4214 */
4215 if(current_task() == kernel_task) {
4216 mach_msg_ool_ports_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4217 user_ool_dsc--;
4218 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
4219
4220 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
4221 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4222 TRUE : FALSE;
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;
4227
4228 user_dsc = (typeof(user_dsc))user_ool_dsc;
4229 } if (is_64bit) {
4230 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4231 user_ool_dsc--;
4232 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
4233
4234 user_ool_dsc->address = rcv_addr;
4235 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4236 TRUE : FALSE;
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;
4241
4242 user_dsc = (typeof(user_dsc))user_ool_dsc;
4243 } else {
4244 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4245 user_ool_dsc--;
4246 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
4247
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) ?
4251 TRUE : FALSE;
4252 user_ool_dsc->copy = copy_options;
4253 user_ool_dsc->disposition = disp;
4254 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
4255
4256 user_dsc = (typeof(user_dsc))user_ool_dsc;
4257 }
4258 return user_dsc;
4259 }
4260
4261 /*
4262 * Routine: ipc_kmsg_copyout_body
4263 * Purpose:
4264 * "Copy-out" port rights and out-of-line memory
4265 * in the body of a message.
4266 *
4267 * The error codes are a combination of special bits.
4268 * The copyout proceeds despite errors.
4269 * Conditions:
4270 * Nothing locked.
4271 * Returns:
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
4278 */
4279
4280 mach_msg_return_t
4281 ipc_kmsg_copyout_body(
4282 ipc_kmsg_t kmsg,
4283 ipc_space_t space,
4284 vm_map_t map,
4285 mach_msg_body_t *slist)
4286 {
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;
4291 int i;
4292 mach_msg_return_t mr = MACH_MSG_SUCCESS;
4293 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
4294
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];
4300
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;
4306 }
4307 else {
4308 saddr = MACH_MSG_DESCRIPTOR_NULL;
4309 sdsc_count = 0;
4310 }
4311
4312 /* Now process the descriptors */
4313 for (i = dsc_count-1; i >= 0; i--) {
4314 switch (kern_dsc[i].type.type) {
4315
4316 case MACH_MSG_PORT_DESCRIPTOR:
4317 user_dsc = ipc_kmsg_copyout_port_descriptor(&kern_dsc[i], user_dsc, space, &mr);
4318 break;
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);
4323 break;
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);
4327 break;
4328 default : {
4329 panic("untyped IPC copyout body: invalid message descriptor");
4330 }
4331 }
4332 }
4333
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;
4340 }
4341
4342 return mr;
4343 }
4344
4345 /*
4346 * Routine: ipc_kmsg_copyout_size
4347 * Purpose:
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.
4352 * Conditions:
4353 * Nothing locked.
4354 * Returns:
4355 * size of the message as it would be received.
4356 */
4357
4358 mach_msg_size_t
4359 ipc_kmsg_copyout_size(
4360 ipc_kmsg_t kmsg,
4361 vm_map_t map)
4362 {
4363 mach_msg_size_t send_size;
4364
4365 send_size = kmsg->ikm_header->msgh_size;
4366
4367 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
4368
4369 #if defined(__LP64__)
4370 send_size -= LEGACY_HEADER_SIZE_DELTA;
4371 #endif
4372
4373 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
4374
4375 mach_msg_body_t *body;
4376 mach_msg_descriptor_t *saddr, *eaddr;
4377
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;
4381
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:
4387 if(!is_task_64bit)
4388 send_size -= DESC_SIZE_ADJUSTMENT;
4389 break;
4390 case MACH_MSG_PORT_DESCRIPTOR:
4391 send_size -= DESC_SIZE_ADJUSTMENT;
4392 break;
4393 default:
4394 break;
4395 }
4396 }
4397 }
4398 return send_size;
4399 }
4400
4401 /*
4402 * Routine: ipc_kmsg_copyout
4403 * Purpose:
4404 * "Copy-out" port rights and out-of-line memory
4405 * in the message.
4406 * Conditions:
4407 * Nothing locked.
4408 * Returns:
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.
4415 */
4416
4417 mach_msg_return_t
4418 ipc_kmsg_copyout(
4419 ipc_kmsg_t kmsg,
4420 ipc_space_t space,
4421 vm_map_t map,
4422 mach_msg_body_t *slist,
4423 mach_msg_option_t option)
4424 {
4425 mach_msg_return_t mr;
4426
4427 mr = ipc_kmsg_copyout_header(kmsg, space, option);
4428 if (mr != MACH_MSG_SUCCESS) {
4429 return mr;
4430 }
4431
4432 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
4433 mr = ipc_kmsg_copyout_body(kmsg, space, map, slist);
4434
4435 if (mr != MACH_MSG_SUCCESS)
4436 mr |= MACH_RCV_BODY_ERROR;
4437 }
4438
4439 return mr;
4440 }
4441
4442 /*
4443 * Routine: ipc_kmsg_copyout_pseudo
4444 * Purpose:
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.
4449 *
4450 * The error codes are a combination of special bits.
4451 * The copyout proceeds despite errors.
4452 * Conditions:
4453 * Nothing locked.
4454 * Returns:
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.
4460 */
4461
4462 mach_msg_return_t
4463 ipc_kmsg_copyout_pseudo(
4464 ipc_kmsg_t kmsg,
4465 ipc_space_t space,
4466 vm_map_t map,
4467 mach_msg_body_t *slist)
4468 {
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;
4479
4480 /* Set ith_knote to ITH_KNOTE_PSEUDO */
4481 current_thread()->ith_knote = ITH_KNOTE_PSEUDO;
4482
4483 assert(IO_VALID(dest));
4484
4485 #if 0
4486 /*
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.
4490 */
4491 ipc_importance_clean(kmsg);
4492 #else
4493 /* just assert it is already clean */
4494 ipc_importance_assert_clean(kmsg);
4495 #endif
4496
4497 mr = (ipc_kmsg_copyout_object(space, dest, dest_type, &dest_name) |
4498 ipc_kmsg_copyout_object(space, reply, reply_type, &reply_name));
4499
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);
4503
4504 if (IO_VALID(voucher)) {
4505 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
4506
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;
4510 }
4511
4512 if (mbits & MACH_MSGH_BITS_COMPLEX) {
4513 mr |= ipc_kmsg_copyout_body(kmsg, space, map, slist);
4514 }
4515
4516 return mr;
4517 }
4518
4519 /*
4520 * Routine: ipc_kmsg_copyout_dest
4521 * Purpose:
4522 * Copies out the destination port in the message.
4523 * Destroys all other rights and memory in the message.
4524 * Conditions:
4525 * Nothing locked.
4526 */
4527
4528 void
4529 ipc_kmsg_copyout_dest(
4530 ipc_kmsg_t kmsg,
4531 ipc_space_t space)
4532 {
4533 mach_msg_bits_t mbits;
4534 ipc_object_t dest;
4535 ipc_object_t reply;
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;
4541
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);
4550
4551 assert(IO_VALID(dest));
4552
4553 ipc_importance_assert_clean(kmsg);
4554
4555 io_lock(dest);
4556 if (io_active(dest)) {
4557 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4558 /* dest is unlocked */
4559 } else {
4560 io_unlock(dest);
4561 io_release(dest);
4562 dest_name = MACH_PORT_DEAD;
4563 }
4564
4565 if (IO_VALID(reply)) {
4566 ipc_object_destroy(reply, reply_type);
4567 reply_name = MACH_PORT_NULL;
4568 } else
4569 reply_name = CAST_MACH_PORT_TO_NAME(reply);
4570
4571 if (IO_VALID(voucher)) {
4572 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
4573
4574 kmsg->ikm_voucher = IP_NULL;
4575 ipc_object_destroy((ipc_object_t)voucher, voucher_type);
4576 voucher_name = MACH_PORT_NULL;
4577 }
4578
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;
4584
4585 if (mbits & MACH_MSGH_BITS_COMPLEX) {
4586 mach_msg_body_t *body;
4587
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));
4591 }
4592 }
4593
4594 /*
4595 * Routine: ipc_kmsg_copyout_to_kernel
4596 * Purpose:
4597 * Copies out the destination and reply ports in the message.
4598 * Leaves all other rights and memory in the message alone.
4599 * Conditions:
4600 * Nothing locked.
4601 *
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.
4605 */
4606
4607 void
4608 ipc_kmsg_copyout_to_kernel(
4609 ipc_kmsg_t kmsg,
4610 ipc_space_t space)
4611 {
4612 ipc_object_t dest;
4613 ipc_object_t reply;
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;
4617
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);
4622
4623 assert(IO_VALID(dest));
4624
4625 io_lock(dest);
4626 if (io_active(dest)) {
4627 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4628 /* dest is unlocked */
4629 } else {
4630 io_unlock(dest);
4631 io_release(dest);
4632 dest_name = MACH_PORT_DEAD;
4633 }
4634
4635 reply_name = CAST_MACH_PORT_TO_NAME(reply);
4636
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);
4642 }
4643
4644 #if IKM_SUPPORT_LEGACY
4645 void
4646 ipc_kmsg_copyout_to_kernel_legacy(
4647 ipc_kmsg_t kmsg,
4648 ipc_space_t space)
4649 {
4650 ipc_object_t dest;
4651 ipc_object_t reply;
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;
4655
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);
4660
4661 assert(IO_VALID(dest));
4662
4663 io_lock(dest);
4664 if (io_active(dest)) {
4665 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4666 /* dest is unlocked */
4667 } else {
4668 io_unlock(dest);
4669 io_release(dest);
4670 dest_name = MACH_PORT_DEAD;
4671 }
4672
4673 reply_name = CAST_MACH_PORT_TO_NAME(reply);
4674
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);
4680
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];
4687 daddr--;
4688
4689 vm_offset_t dsc_adjust = 0;
4690
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;
4696
4697 mach_port_t name = dsc->name;
4698 mach_msg_type_name_t disposition = dsc->disposition;
4699
4700 dest_dsc->name = CAST_MACH_PORT_TO_NAME(name);
4701 dest_dsc->disposition = disposition;
4702 dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
4703 break;
4704 }
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. */
4709
4710 mach_msg_ool_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->out_of_line;
4711
4712 mach_msg_ool_descriptor32_t *dest_dsc = &daddr->out_of_line32;
4713
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;
4719
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;
4725 break;
4726 }
4727 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
4728 mach_msg_ool_ports_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->ool_ports;
4729
4730 mach_msg_ool_ports_descriptor32_t *dest_dsc = &daddr->ool_ports32;
4731
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;
4737
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;
4743 break;
4744 }
4745 default: {
4746 #if MACH_ASSERT
4747 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
4748 #endif /* MACH_ASSERT */
4749 }
4750 }
4751 }
4752
4753 if(count) {
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;
4759 }
4760 }
4761 #endif /* IKM_SUPPORT_LEGACY */
4762
4763 #ifdef __arm64__
4764 /*
4765 * Just sets those parts of the trailer that aren't set up at allocation time.
4766 */
4767 static void
4768 ipc_kmsg_munge_trailer(mach_msg_max_trailer_t *in, void *_out, boolean_t is64bit)
4769 {
4770 if (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;
4776 } else {
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;
4782 }
4783 }
4784 #endif /* __arm64__ */
4785
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)
4791 {
4792 mach_msg_max_trailer_t *trailer;
4793
4794 #ifdef __arm64__
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));
4799
4800 /*
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.
4804 */
4805 bcopy(real_trailer_out, &tmp_trailer, MAX_TRAILER_SIZE);
4806 trailer = &tmp_trailer;
4807 #else /* __arm64__ */
4808 (void)thread;
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__ */
4813
4814 if (!(option & MACH_RCV_TRAILER_MASK)) {
4815 return trailer->msgh_trailer_size;
4816 }
4817
4818 trailer->msgh_seqno = seqno;
4819 trailer->msgh_context = context;
4820 trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit(thread), option);
4821
4822 if (minimal_trailer) {
4823 goto done;
4824 }
4825
4826 if (MACH_RCV_TRAILER_ELEMENTS(option) >=
4827 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV)){
4828 trailer->msgh_ad = 0;
4829 }
4830
4831 /*
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.
4835 */
4836
4837 if (option & MACH_RCV_TRAILER_ELEMENTS (MACH_RCV_TRAILER_LABELS)) {
4838 trailer->msgh_labels.sender = 0;
4839 }
4840
4841 done:
4842 #ifdef __arm64__
4843 ipc_kmsg_munge_trailer(trailer, real_trailer_out, thread_is_64bit(thread));
4844 #endif /* __arm64__ */
4845
4846 return trailer->msgh_trailer_size;
4847 }