]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ipc/ipc_kmsg.c
xnu-4570.41.2.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_kmsg.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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 */
2d21ac55
A
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 */
1c79356b
A
63/*
64 */
65/*
66 * File: ipc/ipc_kmsg.c
67 * Author: Rich Draves
68 * Date: 1989
69 *
70 * Operations on kernel messages.
71 */
72
1c79356b 73
91447636 74#include <mach/mach_types.h>
1c79356b
A
75#include <mach/boolean.h>
76#include <mach/kern_return.h>
77#include <mach/message.h>
78#include <mach/port.h>
91447636
A
79#include <mach/vm_map.h>
80#include <mach/mach_vm.h>
1c79356b 81#include <mach/vm_statistics.h>
91447636
A
82
83#include <kern/kern_types.h>
1c79356b 84#include <kern/assert.h>
b0d623f7 85#include <kern/debug.h>
91447636 86#include <kern/ipc_kobject.h>
1c79356b 87#include <kern/kalloc.h>
91447636
A
88#include <kern/zalloc.h>
89#include <kern/processor.h>
1c79356b
A
90#include <kern/thread.h>
91#include <kern/sched_prim.h>
1c79356b
A
92#include <kern/misc_protos.h>
93#include <kern/counters.h>
91447636 94#include <kern/cpu_data.h>
39037602 95#include <kern/policy_internal.h>
91447636 96
b0d623f7
A
97#include <machine/machlimits.h>
98
1c79356b
A
99#include <vm/vm_map.h>
100#include <vm/vm_object.h>
101#include <vm/vm_kern.h>
91447636 102
1c79356b 103#include <ipc/port.h>
91447636 104#include <ipc/ipc_types.h>
1c79356b
A
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>
fe8ab488 114#include <ipc/ipc_importance.h>
39037602
A
115#if MACH_FLIPC
116#include <kern/mach_node.h>
117#include <ipc/flipc.h>
118#endif
1c79356b 119
d190cdc3
A
120#include <os/overflow.h>
121
2d21ac55
A
122#include <security/mac_mach_internal.h>
123
39037602
A
124#include <device/device_server.h>
125
1c79356b
A
126#include <string.h>
127
55e303ae
A
128#ifdef ppc
129#include <ppc/Firmware.h>
130#include <ppc/low_trace.h>
131#endif
132
b0d623f7
A
133#if DEBUG
134#define DEBUG_MSGS_K64 1
135#endif
136
39236c6e
A
137#include <sys/kdebug.h>
138#include <libkern/OSAtomic.h>
139
b0d623f7
A
140#pragma pack(4)
141
142typedef struct
143{
144 mach_msg_bits_t msgh_bits;
145 mach_msg_size_t msgh_size;
fe8ab488
A
146 mach_port_name_t msgh_remote_port;
147 mach_port_name_t msgh_local_port;
148 mach_port_name_t msgh_voucher_port;
b0d623f7
A
149 mach_msg_id_t msgh_id;
150} mach_msg_legacy_header_t;
151
152typedef struct
153{
154 mach_msg_legacy_header_t header;
155 mach_msg_body_t body;
156} mach_msg_legacy_base_t;
157
158typedef 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
168typedef 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)))
fe8ab488 179
b0d623f7
A
180// END LP64 fixes
181
182
183#if DEBUG_MSGS_K64
184extern void ipc_pset_print64(
185 ipc_pset_t pset);
186
187extern void ipc_kmsg_print64(
188 ipc_kmsg_t kmsg,
189 const char *str);
190
191extern void ipc_msg_print64(
192 mach_msg_header_t *msgh);
193
194extern ipc_port_t ipc_name_to_data64(
195 task_t task,
196 mach_port_name_t name);
197
198/*
199 * Forward declarations
200 */
201void ipc_msg_print_untyped64(
202 mach_msg_body_t *body);
203
204const char * ipc_type_name64(
205 int type_name,
206 boolean_t received);
207
208void ipc_print_type_name64(
209 int type_name);
210
211const char *
212msgh_bit_decode64(
213 mach_msg_bits_t bit);
214
215const char *
216mm_copy_options_string64(
217 mach_msg_copy_options_t option);
218
219void db_print_msg_uid64(mach_msg_header_t *);
220
221static void
222ipc_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
243const char *
244ipc_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
287void
288ipc_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 */
302void
303ipc_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
316const char *
317msgh_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 */
330void
331ipc_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
394const char *
395mm_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:
3e170ce0 408 name = "OVERWRITE(DEPRECATED)";
b0d623f7
A
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
423void
424ipc_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) \
fe8ab488 486 __unreachable_ok_push \
b0d623f7
A
487 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
488 ipc_kmsg_print64(kmsg, string); \
fe8ab488
A
489 } \
490 __unreachable_ok_pop
491
b0d623f7 492#define DEBUG_IPC_MSG_BODY_PRINT(body,size) \
fe8ab488 493 __unreachable_ok_push \
b0d623f7
A
494 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
495 ipc_msg_body_print64(body,size);\
fe8ab488
A
496 } \
497 __unreachable_ok_pop
b0d623f7
A
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 */
55e303ae 502
1c79356b 503extern vm_map_t ipc_kernel_copy_map;
316670eb 504extern vm_size_t ipc_kmsg_max_space;
1c79356b 505extern vm_size_t ipc_kmsg_max_vm_space;
316670eb 506extern vm_size_t ipc_kmsg_max_body_space;
1c79356b
A
507extern vm_size_t msg_ool_size_small;
508
509#define MSG_OOL_SIZE_SMALL msg_ool_size_small
510
91447636
A
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
b0d623f7
A
521#define DESC_SIZE_ADJUSTMENT ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
522 sizeof(mach_msg_ool_descriptor32_t)))
91447636
A
523
524/* scatter list macros */
525
526#define SKIP_PORT_DESCRIPTORS(s, c) \
527MACRO_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 } \
537MACRO_END
538
539#define INCREMENT_SCATTER(s, c, d) \
540MACRO_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 } \
547MACRO_END
548
39037602
A
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)
5ba3f43e 581#include <stdint.h>
39037602
A
582extern boolean_t kdebug_debugid_enabled(uint32_t debugid);
583
584void 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
91447636
A
829/* zone for cached ipc_kmsg_t structures */
830zone_t ipc_kmsg_zone;
1c79356b
A
831
832/*
833 * Forward declarations
834 */
835
836void ipc_kmsg_clean(
837 ipc_kmsg_t kmsg);
838
839void ipc_kmsg_clean_body(
840 ipc_kmsg_t kmsg,
91447636
A
841 mach_msg_type_number_t number,
842 mach_msg_descriptor_t *desc);
1c79356b
A
843
844void ipc_kmsg_clean_partial(
845 ipc_kmsg_t kmsg,
846 mach_msg_type_number_t number,
91447636 847 mach_msg_descriptor_t *desc,
1c79356b
A
848 vm_offset_t paddr,
849 vm_size_t length);
850
1c79356b
A
851mach_msg_return_t ipc_kmsg_copyin_body(
852 ipc_kmsg_t kmsg,
853 ipc_space_t space,
854 vm_map_t map);
855
5ba3f43e
A
856extern int thread_qos_from_pthread_priority(unsigned long, unsigned long *);
857
1c79356b
A
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 */
1c79356b
A
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 */
874ipc_kmsg_t
875ipc_kmsg_alloc(
876 mach_msg_size_t msg_and_trailer_size)
877{
91447636 878 mach_msg_size_t max_expanded_size;
1c79356b
A
879 ipc_kmsg_t kmsg;
880
91447636
A
881 /*
882 * LP64support -
883 * Pad the allocation in case we need to expand the
884 * message descrptors for user spaces with pointers larger than
b0d623f7 885 * the kernel's own, or vice versa. We don't know how many descriptors
91447636
A
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 */
8ad349bb 894 mach_msg_size_t size = msg_and_trailer_size - MAX_TRAILER_SIZE;
316670eb
A
895
896 /* compare against implementation upper limit for the body */
897 if (size > ipc_kmsg_max_body_space)
898 return IKM_NULL;
899
8ad349bb 900 if (size > sizeof(mach_msg_base_t)) {
b0d623f7
A
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);
316670eb
A
904
905 /* make sure expansion won't cause wrap */
b7266188 906 if (msg_and_trailer_size > MACH_MSG_SIZE_MAX - max_desc)
8ad349bb 907 return IKM_NULL;
b0d623f7 908
8ad349bb
A
909 max_expanded_size = msg_and_trailer_size + max_desc;
910 } else
fe8ab488 911 max_expanded_size = msg_and_trailer_size;
91447636 912
316670eb 913 if (max_expanded_size < IKM_SAVED_MSG_SIZE)
8ad349bb 914 max_expanded_size = IKM_SAVED_MSG_SIZE; /* round up for ikm_cache */
91447636
A
915
916 if (max_expanded_size == IKM_SAVED_MSG_SIZE) {
917 struct ikm_cache *cache;
918 unsigned int i;
1c79356b
A
919
920 disable_preemption();
91447636
A
921 cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
922 if ((i = cache->avail) > 0) {
1c79356b 923 assert(i <= IKM_STASH);
91447636
A
924 kmsg = cache->entries[--i];
925 cache->avail = i;
1c79356b 926 enable_preemption();
b7266188
A
927 ikm_check_init(kmsg, max_expanded_size);
928 ikm_set_header(kmsg, msg_and_trailer_size);
1c79356b
A
929 return (kmsg);
930 }
931 enable_preemption();
91447636
A
932 kmsg = (ipc_kmsg_t)zalloc(ipc_kmsg_zone);
933 } else {
934 kmsg = (ipc_kmsg_t)kalloc(ikm_plus_overhead(max_expanded_size));
1c79356b
A
935 }
936
1c79356b 937 if (kmsg != IKM_NULL) {
91447636 938 ikm_init(kmsg, max_expanded_size);
b7266188 939 ikm_set_header(kmsg, msg_and_trailer_size);
1c79356b 940 }
2d21ac55 941
1c79356b
A
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
957void
958ipc_kmsg_free(
959 ipc_kmsg_t kmsg)
960{
961 mach_msg_size_t size = kmsg->ikm_size;
962 ipc_port_t port;
963
fe8ab488
A
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);
2d21ac55 969
1c79356b
A
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
91447636 973 * leave the message associated with it. Otherwise, free it.
1c79356b
A
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);
316670eb 982 ip_release(port);
1c79356b
A
983 return;
984 }
316670eb
A
985 ip_unlock(port);
986 ip_release(port); /* May be last reference */
1c79356b
A
987 }
988
989 /*
990 * Peek and see if it has to go back in the cache.
991 */
91447636
A
992 if (kmsg->ikm_size == IKM_SAVED_MSG_SIZE) {
993 struct ikm_cache *cache;
994 unsigned int i;
1c79356b
A
995
996 disable_preemption();
91447636
A
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;
1c79356b
A
1001 enable_preemption();
1002 return;
1003 }
1004 enable_preemption();
91447636
A
1005 zfree(ipc_kmsg_zone, kmsg);
1006 return;
1c79356b 1007 }
91447636 1008 kfree(kmsg, ikm_plus_overhead(size));
1c79356b
A
1009}
1010
1011
1012/*
1013 * Routine: ipc_kmsg_enqueue
1014 * Purpose:
1015 * Enqueue a kmsg.
1016 */
1017
1018void
1019ipc_kmsg_enqueue(
1020 ipc_kmsg_queue_t queue,
1021 ipc_kmsg_t kmsg)
1022{
39037602
A
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
1051boolean_t
1052ipc_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
1100boolean_t
1101ipc_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;
5ba3f43e 1114 cur = cur->ikm_prev;
39037602
A
1115 }
1116 return FALSE;
1c79356b
A
1117}
1118
1119/*
1120 * Routine: ipc_kmsg_dequeue
1121 * Purpose:
1122 * Dequeue and return a kmsg.
1123 */
1124
1125ipc_kmsg_t
1126ipc_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)
39037602 1134 ipc_kmsg_rmqueue(queue, first);
1c79356b
A
1135
1136 return first;
1137}
1138
1139/*
1140 * Routine: ipc_kmsg_rmqueue
1141 * Purpose:
1142 * Pull a kmsg out of a queue.
1143 */
1144
1145void
1146ipc_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 {
5c9f4661
A
1163 if (__improbable(next->ikm_prev != kmsg || prev->ikm_next != kmsg)) {
1164 panic("ipc_kmsg_rmqueue: inconsistent prev/next pointers. "
1165 "(prev->next: %p, next->prev: %p, kmsg: %p)",
1166 prev->ikm_next, next->ikm_prev, kmsg);
1167 }
1168
1c79356b
A
1169 if (queue->ikmq_base == kmsg)
1170 queue->ikmq_base = next;
1171
1172 next->ikm_prev = prev;
1173 prev->ikm_next = next;
1174 }
1175 /* XXX Temporary debug logic */
2d21ac55
A
1176 assert((kmsg->ikm_next = IKM_BOGUS) == IKM_BOGUS);
1177 assert((kmsg->ikm_prev = IKM_BOGUS) == IKM_BOGUS);
1c79356b
A
1178}
1179
1180/*
1181 * Routine: ipc_kmsg_queue_next
1182 * Purpose:
1183 * Return the kmsg following the given kmsg.
1184 * (Or IKM_NULL if it is the last one in the queue.)
1185 */
1186
1187ipc_kmsg_t
1188ipc_kmsg_queue_next(
1189 ipc_kmsg_queue_t queue,
1190 ipc_kmsg_t kmsg)
1191{
1192 ipc_kmsg_t next;
1193
1194 assert(queue->ikmq_base != IKM_NULL);
1195
1196 next = kmsg->ikm_next;
1197 if (queue->ikmq_base == next)
1198 next = IKM_NULL;
1199
1200 return next;
1201}
1202
1203/*
1204 * Routine: ipc_kmsg_destroy
1205 * Purpose:
1206 * Destroys a kernel message. Releases all rights,
1207 * references, and memory held by the message.
1208 * Frees the message.
1209 * Conditions:
1210 * No locks held.
1211 */
1212
1213void
1214ipc_kmsg_destroy(
1215 ipc_kmsg_t kmsg)
1216{
1c79356b 1217 /*
6d2010ae
A
1218 * Destroying a message can cause more messages to be destroyed.
1219 * Curtail recursion by putting messages on the deferred
1220 * destruction queue. If this was the first message on the
1221 * queue, this instance must process the full queue.
1c79356b 1222 */
6d2010ae
A
1223 if (ipc_kmsg_delayed_destroy(kmsg))
1224 ipc_kmsg_reap_delayed();
1225}
1c79356b 1226
6d2010ae
A
1227/*
1228 * Routine: ipc_kmsg_delayed_destroy
1229 * Purpose:
1230 * Enqueues a kernel message for deferred destruction.
1231 * Returns:
1232 * Boolean indicator that the caller is responsible to reap
1233 * deferred messages.
1234 */
1c79356b 1235
6d2010ae
A
1236boolean_t ipc_kmsg_delayed_destroy(
1237 ipc_kmsg_t kmsg)
1238{
1239 ipc_kmsg_queue_t queue = &(current_thread()->ith_messages);
1240 boolean_t first = ipc_kmsg_queue_empty(queue);
1c79356b 1241
6d2010ae
A
1242 ipc_kmsg_enqueue(queue, kmsg);
1243 return first;
1c79356b
A
1244}
1245
1246/*
6d2010ae 1247 * Routine: ipc_kmsg_destroy_queue
1c79356b 1248 * Purpose:
6d2010ae
A
1249 * Destroys messages from the per-thread
1250 * deferred reaping queue.
1c79356b
A
1251 * Conditions:
1252 * No locks held.
1253 */
6d2010ae 1254
91447636 1255void
6d2010ae 1256ipc_kmsg_reap_delayed(void)
1c79356b 1257{
6d2010ae
A
1258 ipc_kmsg_queue_t queue = &(current_thread()->ith_messages);
1259 ipc_kmsg_t kmsg;
1c79356b 1260
6d2010ae
A
1261 /*
1262 * must leave kmsg in queue while cleaning it to assure
1263 * no nested calls recurse into here.
1264 */
1265 while ((kmsg = ipc_kmsg_queue_first(queue)) != IKM_NULL) {
1266 ipc_kmsg_clean(kmsg);
1267 ipc_kmsg_rmqueue(queue, kmsg);
1268 ipc_kmsg_free(kmsg);
1269 }
1c79356b
A
1270}
1271
1272/*
1273 * Routine: ipc_kmsg_clean_body
1274 * Purpose:
1275 * Cleans the body of a kernel message.
1276 * Releases all rights, references, and memory.
1277 *
1278 * Conditions:
1279 * No locks held.
1280 */
6d2010ae 1281static unsigned int _ipc_kmsg_clean_invalid_desc = 0;
1c79356b
A
1282void
1283ipc_kmsg_clean_body(
91447636
A
1284 __unused ipc_kmsg_t kmsg,
1285 mach_msg_type_number_t number,
1286 mach_msg_descriptor_t *saddr)
1c79356b 1287{
b0d623f7 1288 mach_msg_type_number_t i;
1c79356b
A
1289
1290 if ( number == 0 )
1291 return;
1292
b0d623f7 1293 for (i = 0 ; i < number; i++, saddr++ ) {
1c79356b
A
1294
1295 switch (saddr->type.type) {
1296
1297 case MACH_MSG_PORT_DESCRIPTOR: {
1298 mach_msg_port_descriptor_t *dsc;
1299
1300 dsc = &saddr->port;
1301
1302 /*
1303 * Destroy port rights carried in the message
1304 */
1305 if (!IO_VALID((ipc_object_t) dsc->name))
1306 continue;
1307 ipc_object_destroy((ipc_object_t) dsc->name, dsc->disposition);
1308 break;
1309 }
1310 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
1311 case MACH_MSG_OOL_DESCRIPTOR : {
1312 mach_msg_ool_descriptor_t *dsc;
1313
b0d623f7 1314 dsc = (mach_msg_ool_descriptor_t *)&saddr->out_of_line;
1c79356b
A
1315
1316 /*
1317 * Destroy memory carried in the message
1318 */
1319 if (dsc->size == 0) {
1320 assert(dsc->address == (void *) 0);
1321 } else {
1322 vm_map_copy_discard((vm_map_copy_t) dsc->address);
1323 }
1324 break;
1325 }
1326 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
1327 ipc_object_t *objects;
1328 mach_msg_type_number_t j;
1329 mach_msg_ool_ports_descriptor_t *dsc;
1330
b0d623f7 1331 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
1c79356b
A
1332 objects = (ipc_object_t *) dsc->address;
1333
1334 if (dsc->count == 0) {
1335 break;
1336 }
1337
1338 assert(objects != (ipc_object_t *) 0);
1339
1340 /* destroy port rights carried in the message */
1341
1342 for (j = 0; j < dsc->count; j++) {
1343 ipc_object_t object = objects[j];
1344
1345 if (!IO_VALID(object))
1346 continue;
1347
1348 ipc_object_destroy(object, dsc->disposition);
1349 }
1350
1351 /* destroy memory carried in the message */
1352
1353 assert(dsc->count != 0);
1354
91447636 1355 kfree(dsc->address,
b0d623f7 1356 (vm_size_t) dsc->count * sizeof(mach_port_t));
1c79356b
A
1357 break;
1358 }
1359 default : {
6d2010ae 1360 _ipc_kmsg_clean_invalid_desc++; /* don't understand this type of descriptor */
1c79356b
A
1361 }
1362 }
1363 }
1364}
1365
1366/*
1367 * Routine: ipc_kmsg_clean_partial
1368 * Purpose:
1369 * Cleans a partially-acquired kernel message.
1370 * number is the index of the type descriptor
1371 * in the body of the message that contained the error.
1372 * If dolast, the memory and port rights in this last
1373 * type spec are also cleaned. In that case, number
1374 * specifies the number of port rights to clean.
1375 * Conditions:
1376 * Nothing locked.
1377 */
1378
1379void
1380ipc_kmsg_clean_partial(
1381 ipc_kmsg_t kmsg,
1382 mach_msg_type_number_t number,
91447636 1383 mach_msg_descriptor_t *desc,
1c79356b
A
1384 vm_offset_t paddr,
1385 vm_size_t length)
1386{
1387 ipc_object_t object;
91447636 1388 mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
1c79356b 1389
fe8ab488
A
1390 /* deal with importance chain while we still have dest and voucher references */
1391 ipc_importance_clean(kmsg);
1392
91447636 1393 object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
1c79356b 1394 assert(IO_VALID(object));
6d2010ae 1395 ipc_object_destroy_dest(object, MACH_MSGH_BITS_REMOTE(mbits));
1c79356b 1396
91447636 1397 object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
1398 if (IO_VALID(object))
1399 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
1400
fe8ab488
A
1401 object = (ipc_object_t) kmsg->ikm_voucher;
1402 if (IO_VALID(object)) {
1403 assert(MACH_MSGH_BITS_VOUCHER(mbits) == MACH_MSG_TYPE_MOVE_SEND);
1404 ipc_object_destroy(object, MACH_MSG_TYPE_PORT_SEND);
1405 kmsg->ikm_voucher = IP_NULL;
1406 }
1407
1c79356b
A
1408 if (paddr) {
1409 (void) vm_deallocate(ipc_kernel_copy_map, paddr, length);
1410 }
1411
91447636 1412 ipc_kmsg_clean_body(kmsg, number, desc);
1c79356b
A
1413}
1414
1415/*
1416 * Routine: ipc_kmsg_clean
1417 * Purpose:
1418 * Cleans a kernel message. Releases all rights,
1419 * references, and memory held by the message.
1420 * Conditions:
1421 * No locks held.
1422 */
1423
1424void
1425ipc_kmsg_clean(
1426 ipc_kmsg_t kmsg)
1427{
1428 ipc_object_t object;
1429 mach_msg_bits_t mbits;
1430
fe8ab488
A
1431 /* deal with importance chain while we still have dest and voucher references */
1432 ipc_importance_clean(kmsg);
1433
91447636
A
1434 mbits = kmsg->ikm_header->msgh_bits;
1435 object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
1c79356b 1436 if (IO_VALID(object))
6d2010ae 1437 ipc_object_destroy_dest(object, MACH_MSGH_BITS_REMOTE(mbits));
1c79356b 1438
91447636 1439 object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
1440 if (IO_VALID(object))
1441 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
1442
fe8ab488
A
1443 object = (ipc_object_t) kmsg->ikm_voucher;
1444 if (IO_VALID(object)) {
1445 assert(MACH_MSGH_BITS_VOUCHER(mbits) == MACH_MSG_TYPE_MOVE_SEND);
1446 ipc_object_destroy(object, MACH_MSG_TYPE_PORT_SEND);
1447 kmsg->ikm_voucher = IP_NULL;
1448 }
1449
1c79356b
A
1450 if (mbits & MACH_MSGH_BITS_COMPLEX) {
1451 mach_msg_body_t *body;
1452
91447636
A
1453 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
1454 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count,
1455 (mach_msg_descriptor_t *)(body + 1));
1c79356b
A
1456 }
1457}
1458
1459/*
1460 * Routine: ipc_kmsg_set_prealloc
1461 * Purpose:
1462 * Assign a kmsg as a preallocated message buffer to a port.
1463 * Conditions:
1464 * port locked.
1465 */
1466
1467void
1468ipc_kmsg_set_prealloc(
1469 ipc_kmsg_t kmsg,
1470 ipc_port_t port)
1471{
1472 assert(kmsg->ikm_prealloc == IP_NULL);
1473
1474 kmsg->ikm_prealloc = IP_NULL;
5ba3f43e
A
1475 /* take the mqueue lock since the sync qos is protected under it */
1476 imq_lock(&port->ip_messages);
1477
1478 /* copy the sync qos values to kmsg */
1479 for (int i = 0; i < THREAD_QOS_LAST; i++) {
1480 kmsg->sync_qos[i] = port_sync_qos(port, i);
1481 }
1482 kmsg->special_port_qos = port_special_qos(port);
1c79356b 1483 IP_SET_PREALLOC(port, kmsg);
5ba3f43e 1484 imq_unlock(&port->ip_messages);
1c79356b
A
1485}
1486
1487/*
1488 * Routine: ipc_kmsg_clear_prealloc
1489 * Purpose:
1490 * Release the Assignment of a preallocated message buffer from a port.
1491 * Conditions:
1492 * port locked.
1493 */
1494void
1495ipc_kmsg_clear_prealloc(
1496 ipc_kmsg_t kmsg,
1497 ipc_port_t port)
1498{
1499 assert(kmsg->ikm_prealloc == port);
1500
1501 kmsg->ikm_prealloc = IP_NULL;
5ba3f43e
A
1502
1503 /* take the mqueue lock since the sync qos is protected under it */
1504 imq_lock(&port->ip_messages);
1505
1c79356b 1506 IP_CLEAR_PREALLOC(port, kmsg);
5ba3f43e
A
1507
1508 /* copy the sync qos values from kmsg to port */
1509 for (int i = 0; i < THREAD_QOS_LAST; i++) {
1510 set_port_sync_qos(port, i, kmsg->sync_qos[i]);
1511 }
1512 set_port_special_qos(port, kmsg->special_port_qos);
1513 imq_unlock(&port->ip_messages);
1c79356b
A
1514}
1515
b7266188
A
1516/*
1517 * Routine: ipc_kmsg_prealloc
1518 * Purpose:
1519 * Wraper to ipc_kmsg_alloc() to account for
1520 * header expansion requirements.
1521 */
1522ipc_kmsg_t
1523ipc_kmsg_prealloc(mach_msg_size_t size)
1524{
1525#if defined(__LP64__)
1526 if (size > MACH_MSG_SIZE_MAX - LEGACY_HEADER_SIZE_DELTA)
1527 return IKM_NULL;
1528
1529 size += LEGACY_HEADER_SIZE_DELTA;
1530#endif
1531 return ipc_kmsg_alloc(size);
1532}
91447636
A
1533
1534
1c79356b
A
1535/*
1536 * Routine: ipc_kmsg_get
1537 * Purpose:
1538 * Allocates a kernel message buffer.
1539 * Copies a user message to the message buffer.
1540 * Conditions:
1541 * Nothing locked.
1542 * Returns:
1543 * MACH_MSG_SUCCESS Acquired a message buffer.
1544 * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
1545 * MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
316670eb 1546 * MACH_SEND_TOO_LARGE Message too large to ever be sent.
1c79356b
A
1547 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1548 * MACH_SEND_INVALID_DATA Couldn't copy message data.
1549 */
1550
1551mach_msg_return_t
1552ipc_kmsg_get(
91447636
A
1553 mach_vm_address_t msg_addr,
1554 mach_msg_size_t size,
1c79356b
A
1555 ipc_kmsg_t *kmsgp)
1556{
1557 mach_msg_size_t msg_and_trailer_size;
1558 ipc_kmsg_t kmsg;
55e303ae 1559 mach_msg_max_trailer_t *trailer;
b0d623f7
A
1560 mach_msg_legacy_base_t legacy_base;
1561 mach_msg_size_t len_copied;
1562 legacy_base.body.msgh_descriptor_count = 0;
1c79356b 1563
b0d623f7 1564 if ((size < sizeof(mach_msg_legacy_header_t)) || (size & 3))
1c79356b
A
1565 return MACH_SEND_MSG_TOO_SMALL;
1566
316670eb 1567 if (size > ipc_kmsg_max_body_space)
8ad349bb
A
1568 return MACH_SEND_TOO_LARGE;
1569
b0d623f7
A
1570 if(size == sizeof(mach_msg_legacy_header_t))
1571 len_copied = sizeof(mach_msg_legacy_header_t);
1572 else
1573 len_copied = sizeof(mach_msg_legacy_base_t);
1c79356b 1574
b0d623f7
A
1575 if (copyinmsg(msg_addr, (char *)&legacy_base, len_copied))
1576 return MACH_SEND_INVALID_DATA;
1577
5ba3f43e
A
1578 /*
1579 * If the message claims to be complex, it must at least
1580 * have the length of a "base" message (header + dsc_count).
1581 */
1582 if (len_copied < sizeof(mach_msg_legacy_base_t) &&
1583 (legacy_base.header.msgh_bits & MACH_MSGH_BITS_COMPLEX))
1584 return MACH_SEND_MSG_TOO_SMALL;
1585
b0d623f7
A
1586 msg_addr += sizeof(legacy_base.header);
1587#if defined(__LP64__)
1588 size += LEGACY_HEADER_SIZE_DELTA;
1589#endif
fe8ab488
A
1590 /* unreachable if !DEBUG */
1591 __unreachable_ok_push
b0d623f7
A
1592 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
1593 unsigned int j;
1594 for (j=0; j<sizeof(legacy_base.header); j++) {
1595 kprintf("%02x\n", ((unsigned char*)&legacy_base.header)[j]);
1596 }
1597 }
fe8ab488 1598 __unreachable_ok_pop
1c79356b 1599
b0d623f7
A
1600 msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1601 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1c79356b
A
1602 if (kmsg == IKM_NULL)
1603 return MACH_SEND_NO_BUFFER;
1604
b0d623f7
A
1605 kmsg->ikm_header->msgh_size = size;
1606 kmsg->ikm_header->msgh_bits = legacy_base.header.msgh_bits;
1607 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_remote_port);
1608 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_local_port);
fe8ab488 1609 kmsg->ikm_header->msgh_voucher_port = legacy_base.header.msgh_voucher_port;
b0d623f7
A
1610 kmsg->ikm_header->msgh_id = legacy_base.header.msgh_id;
1611
1612 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
1613 " size: 0x%.8x\n"
1614 " bits: 0x%.8x\n"
1615 " remote_port: %p\n"
1616 " local_port: %p\n"
fe8ab488 1617 " voucher_port: 0x%.8x\n"
b0d623f7
A
1618 " id: %.8d\n",
1619 kmsg->ikm_header->msgh_size,
1620 kmsg->ikm_header->msgh_bits,
1621 kmsg->ikm_header->msgh_remote_port,
1622 kmsg->ikm_header->msgh_local_port,
fe8ab488 1623 kmsg->ikm_header->msgh_voucher_port,
b0d623f7
A
1624 kmsg->ikm_header->msgh_id);
1625
1626 if (copyinmsg(msg_addr, (char *)(kmsg->ikm_header + 1), size - (mach_msg_size_t)sizeof(mach_msg_header_t))) {
1c79356b
A
1627 ipc_kmsg_free(kmsg);
1628 return MACH_SEND_INVALID_DATA;
1629 }
1630
fe8ab488
A
1631 /* unreachable if !DEBUG */
1632 __unreachable_ok_push
b0d623f7
A
1633 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
1634 {
1635 kprintf("body: size: %lu\n", (size - sizeof(mach_msg_header_t)));
1636 uint32_t i;
1637 for(i=0;i*4 < (size - sizeof(mach_msg_header_t));i++)
1638 {
1639 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
1640 }
1641 }
fe8ab488 1642 __unreachable_ok_pop
b0d623f7 1643 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_get()");
1c79356b
A
1644
1645 /*
1646 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1647 * However, the internal size field of the trailer (msgh_trailer_size)
1648 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
1649 * the cases where no implicit data is requested.
1650 */
91447636
A
1651 trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
1652 trailer->msgh_sender = current_thread()->task->sec_token;
1653 trailer->msgh_audit = current_thread()->task->audit_token;
1c79356b
A
1654 trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1655 trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
b0d623f7 1656
55e303ae 1657#ifdef ppc
b36670ce 1658 if(trcWork.traceMask) dbgTrace(0x1100, (unsigned int)kmsg->ikm_header->msgh_id,
91447636
A
1659 (unsigned int)kmsg->ikm_header->msgh_remote_port,
1660 (unsigned int)kmsg->ikm_header->msgh_local_port, 0);
55e303ae 1661#endif
2d21ac55 1662
b0d623f7 1663 trailer->msgh_labels.sender = 0;
1c79356b
A
1664 *kmsgp = kmsg;
1665 return MACH_MSG_SUCCESS;
1666}
1667
1668/*
1669 * Routine: ipc_kmsg_get_from_kernel
1670 * Purpose:
91447636
A
1671 * First checks for a preallocated message
1672 * reserved for kernel clients. If not found -
1673 * allocates a new kernel message buffer.
1c79356b
A
1674 * Copies a kernel message to the message buffer.
1675 * Only resource errors are allowed.
1676 * Conditions:
1677 * Nothing locked.
1678 * Ports in header are ipc_port_t.
1679 * Returns:
1680 * MACH_MSG_SUCCESS Acquired a message buffer.
1681 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1682 */
1683
1684mach_msg_return_t
1685ipc_kmsg_get_from_kernel(
1686 mach_msg_header_t *msg,
91447636 1687 mach_msg_size_t size,
1c79356b
A
1688 ipc_kmsg_t *kmsgp)
1689{
1690 ipc_kmsg_t kmsg;
1691 mach_msg_size_t msg_and_trailer_size;
55e303ae 1692 mach_msg_max_trailer_t *trailer;
1c79356b
A
1693 ipc_port_t dest_port;
1694
1695 assert(size >= sizeof(mach_msg_header_t));
316670eb 1696 assert((size & 3) == 0);
1c79356b 1697
1c79356b
A
1698 dest_port = (ipc_port_t)msg->msgh_remote_port;
1699
1700 msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1701
1702 /*
1703 * See if the port has a pre-allocated kmsg for kernel
1704 * clients. These are set up for those kernel clients
1705 * which cannot afford to wait.
1706 */
6d2010ae 1707 if (IP_VALID(dest_port) && IP_PREALLOC(dest_port)) {
b7266188
A
1708 mach_msg_size_t max_desc = 0;
1709
1c79356b
A
1710 ip_lock(dest_port);
1711 if (!ip_active(dest_port)) {
1712 ip_unlock(dest_port);
1713 return MACH_SEND_NO_BUFFER;
1714 }
1715 assert(IP_PREALLOC(dest_port));
1716 kmsg = dest_port->ip_premsg;
1c79356b
A
1717 if (ikm_prealloc_inuse(kmsg)) {
1718 ip_unlock(dest_port);
1719 return MACH_SEND_NO_BUFFER;
1720 }
b7266188
A
1721#if !defined(__LP64__)
1722 if (msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
1723 assert(size > sizeof(mach_msg_base_t));
1724 max_desc = ((mach_msg_base_t *)msg)->body.msgh_descriptor_count *
1725 DESC_SIZE_ADJUSTMENT;
1726 }
1727#endif
1728 if (msg_and_trailer_size > kmsg->ikm_size - max_desc) {
1729 ip_unlock(dest_port);
1730 return MACH_SEND_TOO_LARGE;
1731 }
1c79356b 1732 ikm_prealloc_set_inuse(kmsg, dest_port);
b7266188 1733 ikm_set_header(kmsg, msg_and_trailer_size);
1c79356b 1734 ip_unlock(dest_port);
b0d623f7
A
1735 }
1736 else
b0d623f7 1737 {
1c79356b
A
1738 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1739 if (kmsg == IKM_NULL)
1740 return MACH_SEND_NO_BUFFER;
1741 }
1742
91447636 1743 (void) memcpy((void *) kmsg->ikm_header, (const void *) msg, size);
1c79356b 1744
5ba3f43e
A
1745 ikm_qos_init(kmsg);
1746
91447636 1747 kmsg->ikm_header->msgh_size = size;
1c79356b
A
1748
1749 /*
1750 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1751 * However, the internal size field of the trailer (msgh_trailer_size)
1752 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
1753 * optimize the cases where no implicit data is requested.
1754 */
55e303ae 1755 trailer = (mach_msg_max_trailer_t *)
91447636 1756 ((vm_offset_t)kmsg->ikm_header + size);
1c79356b 1757 trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
55e303ae 1758 trailer->msgh_audit = KERNEL_AUDIT_TOKEN;
1c79356b
A
1759 trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1760 trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
1761
2d21ac55
A
1762 trailer->msgh_labels.sender = 0;
1763
1c79356b
A
1764 *kmsgp = kmsg;
1765 return MACH_MSG_SUCCESS;
1766}
1767
1768/*
1769 * Routine: ipc_kmsg_send
1770 * Purpose:
1771 * Send a message. The message holds a reference
1772 * for the destination port in the msgh_remote_port field.
1773 *
1774 * If unsuccessful, the caller still has possession of
1775 * the message and must do something with it. If successful,
1776 * the message is queued, given to a receiver, destroyed,
1777 * or handled directly by the kernel via mach_msg.
1778 * Conditions:
1779 * Nothing locked.
1780 * Returns:
1781 * MACH_MSG_SUCCESS The message was accepted.
1782 * MACH_SEND_TIMED_OUT Caller still has message.
1783 * MACH_SEND_INTERRUPTED Caller still has message.
6d2010ae 1784 * MACH_SEND_INVALID_DEST Caller still has message.
1c79356b 1785 */
39236c6e
A
1786
1787
1c79356b
A
1788mach_msg_return_t
1789ipc_kmsg_send(
1790 ipc_kmsg_t kmsg,
1791 mach_msg_option_t option,
91447636 1792 mach_msg_timeout_t send_timeout)
1c79356b 1793{
1c79356b 1794 ipc_port_t port;
3e170ce0 1795 thread_t th = current_thread();
b0d623f7 1796 mach_msg_return_t error = MACH_MSG_SUCCESS;
4bd07ac2 1797 boolean_t kernel_reply = FALSE;
91447636 1798
3e170ce0
A
1799 /* Check if honor qlimit flag is set on thread. */
1800 if ((th->options & TH_OPT_HONOR_QLIMIT) == TH_OPT_HONOR_QLIMIT) {
1801 /* Remove the MACH_SEND_ALWAYS flag to honor queue limit. */
1802 option &= (~MACH_SEND_ALWAYS);
1803 /* Add the timeout flag since the message queue might be full. */
1804 option |= MACH_SEND_TIMEOUT;
1805 th->options &= (~TH_OPT_HONOR_QLIMIT);
1806 }
1807
39236c6e
A
1808#if IMPORTANCE_INHERITANCE
1809 boolean_t did_importance = FALSE;
5ba3f43e 1810#if IMPORTANCE_TRACE
39236c6e
A
1811 mach_msg_id_t imp_msgh_id = -1;
1812 int sender_pid = -1;
5ba3f43e 1813#endif /* IMPORTANCE_TRACE */
39236c6e
A
1814#endif /* IMPORTANCE_INHERITANCE */
1815
1816 /* don't allow the creation of a circular loop */
1817 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_CIRCULAR) {
1818 ipc_kmsg_destroy(kmsg);
39037602 1819 KDBG(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_INFO) | DBG_FUNC_END, MACH_MSGH_BITS_CIRCULAR);
39236c6e
A
1820 return MACH_MSG_SUCCESS;
1821 }
1822
490019cf
A
1823 ipc_voucher_send_preprocessing(kmsg);
1824
91447636 1825 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1c79356b 1826 assert(IP_VALID(port));
1c79356b
A
1827 ip_lock(port);
1828
fe8ab488
A
1829#if IMPORTANCE_INHERITANCE
1830retry:
1831#endif /* IMPORTANCE_INHERITANCE */
1832 /*
1833 * Can't deliver to a dead port.
1834 * However, we can pretend it got sent
1835 * and was then immediately destroyed.
1836 */
1837 if (!ip_active(port)) {
1838 ip_unlock(port);
39037602
A
1839#if MACH_FLIPC
1840 if (MACH_NODE_VALID(kmsg->ikm_node) && FPORT_VALID(port->ip_messages.imq_fport))
1841 flipc_msg_ack(kmsg->ikm_node, &port->ip_messages, FALSE);
1842#endif
fe8ab488
A
1843 ip_release(port); /* JMM - Future: release right, not just ref */
1844 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1845 ipc_kmsg_destroy(kmsg);
39037602 1846 KDBG(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_INFO) | DBG_FUNC_END, MACH_SEND_INVALID_DEST);
fe8ab488
A
1847 return MACH_MSG_SUCCESS;
1848 }
1849
1c79356b
A
1850 if (port->ip_receiver == ipc_space_kernel) {
1851
1852 /*
1853 * We can check ip_receiver == ipc_space_kernel
1854 * before checking that the port is active because
1855 * ipc_port_dealloc_kernel clears ip_receiver
1856 * before destroying a kernel port.
1857 */
1858 assert(ip_active(port));
1859 port->ip_messages.imq_seqno++;
1860 ip_unlock(port);
1861
1862 current_task()->messages_sent++;
1863
1864 /*
1865 * Call the server routine, and get the reply message to send.
1866 */
39037602 1867 kmsg = ipc_kobject_server(kmsg, option);
1c79356b
A
1868 if (kmsg == IKM_NULL)
1869 return MACH_MSG_SUCCESS;
1870
39037602
A
1871 /* restart the KMSG_INFO tracing for the reply message */
1872 KDBG(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_INFO) | DBG_FUNC_START);
91447636 1873 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1c79356b
A
1874 assert(IP_VALID(port));
1875 ip_lock(port);
1876 /* fall thru with reply - same options */
4bd07ac2 1877 kernel_reply = TRUE;
39037602
A
1878 if (!ip_active(port))
1879 error = MACH_SEND_INVALID_DEST;
1c79356b
A
1880 }
1881
39236c6e
A
1882#if IMPORTANCE_INHERITANCE
1883 /*
1884 * Need to see if this message needs importance donation and/or
fe8ab488
A
1885 * propagation. That routine can drop the port lock temporarily.
1886 * If it does we'll have to revalidate the destination.
39236c6e 1887 */
fe8ab488 1888 if (did_importance == FALSE) {
39236c6e 1889 did_importance = TRUE;
fe8ab488
A
1890 if (ipc_importance_send(kmsg, option))
1891 goto retry;
1c79356b 1892 }
39236c6e 1893#endif /* IMPORTANCE_INHERITANCE */
1c79356b 1894
39037602
A
1895 if (error != MACH_MSG_SUCCESS) {
1896 ip_unlock(port);
1897 } else {
1898 /*
1899 * We have a valid message and a valid reference on the port.
1900 * we can unlock the port and call mqueue_send() on its message
1901 * queue. Lock message queue while port is locked.
1902 */
1903 imq_lock(&port->ip_messages);
1904 ip_unlock(port);
39236c6e 1905
39037602
A
1906 error = ipc_mqueue_send(&port->ip_messages, kmsg, option,
1907 send_timeout);
1908 }
b0d623f7 1909
39236c6e
A
1910#if IMPORTANCE_INHERITANCE
1911 if (did_importance == TRUE) {
1912 __unused int importance_cleared = 0;
1913 switch (error) {
1914 case MACH_SEND_TIMED_OUT:
1915 case MACH_SEND_NO_BUFFER:
1916 case MACH_SEND_INTERRUPTED:
fe8ab488 1917 case MACH_SEND_INVALID_DEST:
39236c6e
A
1918 /*
1919 * We still have the kmsg and its
1920 * reference on the port. But we
1921 * have to back out the importance
1922 * boost.
1923 *
1924 * The port could have changed hands,
1925 * be inflight to another destination,
1926 * etc... But in those cases our
1927 * back-out will find the new owner
1928 * (and all the operations that
1929 * transferred the right should have
1930 * applied their own boost adjustments
1931 * to the old owner(s)).
1932 */
1933 importance_cleared = 1;
fe8ab488 1934 ipc_importance_clean(kmsg);
39236c6e
A
1935 break;
1936
39236c6e
A
1937 case MACH_MSG_SUCCESS:
1938 default:
1939 break;
1940 }
5ba3f43e 1941#if IMPORTANCE_TRACE
39236c6e 1942 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_MSG, IMP_MSG_SEND)) | DBG_FUNC_END,
3e170ce0 1943 task_pid(current_task()), sender_pid, imp_msgh_id, importance_cleared, 0);
5ba3f43e 1944#endif /* IMPORTANCE_TRACE */
39236c6e
A
1945 }
1946#endif /* IMPORTANCE_INHERITANCE */
1947
b0d623f7
A
1948 /*
1949 * If the port has been destroyed while we wait, treat the message
1950 * as a successful delivery (like we do for an inactive port).
1951 */
1952 if (error == MACH_SEND_INVALID_DEST) {
39037602
A
1953#if MACH_FLIPC
1954 if (MACH_NODE_VALID(kmsg->ikm_node) && FPORT_VALID(port->ip_messages.imq_fport))
1955 flipc_msg_ack(kmsg->ikm_node, &port->ip_messages, FALSE);
1956#endif
fe8ab488 1957 ip_release(port); /* JMM - Future: release right, not just ref */
b0d623f7
A
1958 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1959 ipc_kmsg_destroy(kmsg);
39037602 1960 KDBG(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_INFO) | DBG_FUNC_END, MACH_SEND_INVALID_DEST);
b0d623f7
A
1961 return MACH_MSG_SUCCESS;
1962 }
4bd07ac2
A
1963
1964 if (error != MACH_MSG_SUCCESS && kernel_reply) {
1965 /*
1966 * Kernel reply messages that fail can't be allowed to
1967 * pseudo-receive on error conditions. We need to just treat
1968 * the message as a successful delivery.
1969 */
39037602
A
1970#if MACH_FLIPC
1971 if (MACH_NODE_VALID(kmsg->ikm_node) && FPORT_VALID(port->ip_messages.imq_fport))
1972 flipc_msg_ack(kmsg->ikm_node, &port->ip_messages, FALSE);
1973#endif
4bd07ac2
A
1974 ip_release(port); /* JMM - Future: release right, not just ref */
1975 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1976 ipc_kmsg_destroy(kmsg);
39037602 1977 KDBG(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_INFO) | DBG_FUNC_END, error);
4bd07ac2
A
1978 return MACH_MSG_SUCCESS;
1979 }
b0d623f7 1980 return error;
1c79356b
A
1981}
1982
1983/*
1984 * Routine: ipc_kmsg_put
1985 * Purpose:
1986 * Copies a message buffer to a user message.
1987 * Copies only the specified number of bytes.
1988 * Frees the message buffer.
1989 * Conditions:
1990 * Nothing locked. The message buffer must have clean
1991 * header fields.
1992 * Returns:
1993 * MACH_MSG_SUCCESS Copied data out of message buffer.
1994 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
1995 */
1996
1997mach_msg_return_t
1998ipc_kmsg_put(
1c79356b 1999 ipc_kmsg_t kmsg,
39037602
A
2000 mach_msg_option_t option,
2001 mach_vm_address_t rcv_addr,
2002 mach_msg_size_t rcv_size,
2003 mach_msg_size_t trailer_size,
2004 mach_msg_size_t *sizep)
1c79356b 2005{
39037602 2006 mach_msg_size_t size = kmsg->ikm_header->msgh_size + trailer_size;
1c79356b
A
2007 mach_msg_return_t mr;
2008
b0d623f7
A
2009 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_put()");
2010
2011
2012 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
2013 " size: 0x%.8x\n"
2014 " bits: 0x%.8x\n"
2015 " remote_port: %p\n"
2016 " local_port: %p\n"
fe8ab488 2017 " voucher_port: 0x%.8x\n"
b0d623f7
A
2018 " id: %.8d\n",
2019 kmsg->ikm_header->msgh_size,
2020 kmsg->ikm_header->msgh_bits,
2021 kmsg->ikm_header->msgh_remote_port,
2022 kmsg->ikm_header->msgh_local_port,
fe8ab488 2023 kmsg->ikm_header->msgh_voucher_port,
b0d623f7
A
2024 kmsg->ikm_header->msgh_id);
2025
2026#if defined(__LP64__)
2027 if (current_task() != kernel_task) { /* don't if receiver expects fully-cooked in-kernel msg; ux_exception */
2028 mach_msg_legacy_header_t *legacy_header =
2029 (mach_msg_legacy_header_t *)((vm_offset_t)(kmsg->ikm_header) + LEGACY_HEADER_SIZE_DELTA);
2030
2031 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
2032 mach_msg_size_t msg_size = kmsg->ikm_header->msgh_size;
2033 mach_port_name_t remote_port = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_remote_port);
2034 mach_port_name_t local_port = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_local_port);
fe8ab488 2035 mach_port_name_t voucher_port = kmsg->ikm_header->msgh_voucher_port;
b0d623f7
A
2036 mach_msg_id_t id = kmsg->ikm_header->msgh_id;
2037
2038 legacy_header->msgh_id = id;
fe8ab488
A
2039 legacy_header->msgh_local_port = local_port;
2040 legacy_header->msgh_remote_port = remote_port;
2041 legacy_header->msgh_voucher_port = voucher_port;
b0d623f7
A
2042 legacy_header->msgh_size = msg_size - LEGACY_HEADER_SIZE_DELTA;
2043 legacy_header->msgh_bits = bits;
2044
2045 size -= LEGACY_HEADER_SIZE_DELTA;
2046 kmsg->ikm_header = (mach_msg_header_t *)legacy_header;
2047 }
2048#endif
2049
fe8ab488
A
2050 /* unreachable if !DEBUG */
2051 __unreachable_ok_push
b0d623f7
A
2052 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
2053 kprintf("ipc_kmsg_put header+body: %d\n", (size));
2054 uint32_t i;
2055 for(i=0;i*4 < size;i++)
2056 {
2057 kprintf("%.4x\n",((uint32_t *)kmsg->ikm_header)[i]);
2058 }
2059 kprintf("type: %d\n", ((mach_msg_type_descriptor_t *)(((mach_msg_base_t *)kmsg->ikm_header)+1))->type);
2060 }
fe8ab488 2061 __unreachable_ok_pop
39037602
A
2062
2063 /* Re-Compute target address if using stack-style delivery */
2064 if (option & MACH_RCV_STACK) {
2065 rcv_addr += rcv_size - size;
2066 }
2067
2068 if (copyoutmsg((const char *) kmsg->ikm_header, rcv_addr, size)) {
1c79356b 2069 mr = MACH_RCV_INVALID_DATA;
39037602
A
2070 size = 0;
2071 } else
1c79356b
A
2072 mr = MACH_MSG_SUCCESS;
2073
39037602
A
2074 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_KMSG_LINK) | DBG_FUNC_NONE,
2075 (rcv_addr >= VM_MIN_KERNEL_AND_KEXT_ADDRESS ||
2076 rcv_addr + size >= VM_MIN_KERNEL_AND_KEXT_ADDRESS) ? (uintptr_t)0 : (uintptr_t)rcv_addr,
2077 VM_KERNEL_ADDRPERM((uintptr_t)kmsg),
2078 1 /* this is on the receive/copyout path */,
2079 0,
2080 0);
1c79356b 2081 ipc_kmsg_free(kmsg);
39037602
A
2082
2083 if (sizep)
2084 *sizep = size;
1c79356b
A
2085 return mr;
2086}
2087
2088/*
2089 * Routine: ipc_kmsg_put_to_kernel
2090 * Purpose:
2091 * Copies a message buffer to a kernel message.
2092 * Frees the message buffer.
2093 * No errors allowed.
2094 * Conditions:
2095 * Nothing locked.
2096 */
2097
2098void
2099ipc_kmsg_put_to_kernel(
2100 mach_msg_header_t *msg,
2101 ipc_kmsg_t kmsg,
2102 mach_msg_size_t size)
2103{
91447636 2104 (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, size);
1c79356b
A
2105
2106 ipc_kmsg_free(kmsg);
2107}
2108
39037602
A
2109unsigned long pthread_priority_canonicalize(unsigned long priority, boolean_t propagation);
2110
5ba3f43e 2111static kern_return_t
39037602
A
2112ipc_kmsg_set_qos(
2113 ipc_kmsg_t kmsg,
2114 mach_msg_option_t options,
2115 mach_msg_priority_t override)
2116{
2117 kern_return_t kr;
5ba3f43e
A
2118 unsigned long flags = 0;
2119 ipc_port_t special_reply_port = kmsg->ikm_header->msgh_local_port;
2120 ipc_port_t dest_port = kmsg->ikm_header->msgh_remote_port;
39037602
A
2121
2122 kr = ipc_get_pthpriority_from_kmsg_voucher(kmsg, &kmsg->ikm_qos);
2123 if (kr != KERN_SUCCESS) {
2124 kmsg->ikm_qos = MACH_MSG_PRIORITY_UNSPECIFIED;
2125 }
2126 kmsg->ikm_qos_override = kmsg->ikm_qos;
2127
2128 if (options & MACH_SEND_OVERRIDE) {
2129 unsigned long canonical;
2130 mach_msg_priority_t canon;
2131
2132 canonical = pthread_priority_canonicalize(override, TRUE);
2133 canon = (mach_msg_priority_t)canonical;
2134 if (canon > kmsg->ikm_qos)
2135 kmsg->ikm_qos_override = canon;
2136 }
5ba3f43e
A
2137
2138 kr = KERN_SUCCESS;
2139 if ((options & MACH_SEND_SYNC_OVERRIDE)) {
2140 if (IP_VALID(special_reply_port) &&
2141 MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits) == MACH_MSG_TYPE_PORT_SEND_ONCE) {
2142 /*
2143 * Update the sync override count if the reply port is a special reply port,
2144 * link the destination port to special reply port and update the qos count
2145 * of destination port.
2146 *
2147 * Use the qos value passed by voucher and not the one passed by notify field.
2148 */
2149 kr = ipc_port_link_special_reply_port_with_qos(special_reply_port, dest_port,
2150 thread_qos_from_pthread_priority(kmsg->ikm_qos, &flags));
2151 } else {
2152 kr = KERN_FAILURE;
2153 }
2154 }
2155 return kr;
39037602
A
2156}
2157
1c79356b
A
2158/*
2159 * Routine: ipc_kmsg_copyin_header
2160 * Purpose:
2161 * "Copy-in" port rights in the header of a message.
2162 * Operates atomically; if it doesn't succeed the
2163 * message header and the space are left untouched.
2164 * If it does succeed the remote/local port fields
2165 * contain object pointers instead of port names,
2166 * and the bits field is updated. The destination port
2167 * will be a valid port pointer.
2168 *
1c79356b
A
2169 * Conditions:
2170 * Nothing locked.
2171 * Returns:
2172 * MACH_MSG_SUCCESS Successful copyin.
2173 * MACH_SEND_INVALID_HEADER
2174 * Illegal value in the message header bits.
2175 * MACH_SEND_INVALID_DEST The space is dead.
1c79356b
A
2176 * MACH_SEND_INVALID_DEST Can't copyin destination port.
2177 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2178 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
2179 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2180 */
2181
2182mach_msg_return_t
2183ipc_kmsg_copyin_header(
fe8ab488 2184 ipc_kmsg_t kmsg,
1c79356b 2185 ipc_space_t space,
39037602 2186 mach_msg_priority_t override,
39236c6e 2187 mach_msg_option_t *optionp)
1c79356b 2188{
fe8ab488 2189 mach_msg_header_t *msg = kmsg->ikm_header;
1c79356b 2190 mach_msg_bits_t mbits = msg->msgh_bits & MACH_MSGH_BITS_USER;
b0d623f7
A
2191 mach_port_name_t dest_name = CAST_MACH_PORT_TO_NAME(msg->msgh_remote_port);
2192 mach_port_name_t reply_name = CAST_MACH_PORT_TO_NAME(msg->msgh_local_port);
fe8ab488 2193 mach_port_name_t voucher_name = MACH_PORT_NULL;
1c79356b
A
2194 kern_return_t kr;
2195
2196 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
2197 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
fe8ab488
A
2198 mach_msg_type_name_t voucher_type = MACH_MSGH_BITS_VOUCHER(mbits);
2199 ipc_object_t dest_port = IO_NULL;
2200 ipc_object_t reply_port = IO_NULL;
2201 ipc_port_t dest_soright = IP_NULL;
2202 ipc_port_t reply_soright = IP_NULL;
2203 ipc_port_t voucher_soright = IP_NULL;
316670eb 2204 ipc_port_t release_port = IP_NULL;
fe8ab488
A
2205 ipc_port_t voucher_port = IP_NULL;
2206 ipc_port_t voucher_release_port = IP_NULL;
2207 ipc_entry_t dest_entry = IE_NULL;
2208 ipc_entry_t reply_entry = IE_NULL;
2209 ipc_entry_t voucher_entry = IE_NULL;
316670eb 2210
39236c6e 2211 int assertcnt = 0;
3e170ce0 2212#if IMPORTANCE_INHERITANCE
39236c6e
A
2213 boolean_t needboost = FALSE;
2214#endif /* IMPORTANCE_INHERITANCE */
2215
1c79356b
A
2216 if ((mbits != msg->msgh_bits) ||
2217 (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type)) ||
2218 ((reply_type == 0) ?
2219 (reply_name != MACH_PORT_NULL) :
2220 !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type)))
2221 return MACH_SEND_INVALID_HEADER;
2222
fe8ab488
A
2223 if (!MACH_PORT_VALID(dest_name))
2224 return MACH_SEND_INVALID_DEST;
1c79356b
A
2225
2226 is_write_lock(space);
fe8ab488
A
2227 if (!is_active(space)) {
2228 is_write_unlock(space);
2229 return MACH_SEND_INVALID_DEST;
2230 }
2231 /* space locked and active */
1c79356b 2232
2d21ac55 2233 /*
fe8ab488
A
2234 * If there is a voucher specified, make sure the disposition is
2235 * valid and the entry actually refers to a voucher port. Don't
2236 * actually copy in until we validate destination and reply.
2d21ac55 2237 */
fe8ab488
A
2238 if (voucher_type != MACH_MSGH_BITS_ZERO) {
2239
2240 voucher_name = msg->msgh_voucher_port;
2241
2242 if (voucher_name == MACH_PORT_DEAD ||
2243 (voucher_type != MACH_MSG_TYPE_MOVE_SEND &&
2244 voucher_type != MACH_MSG_TYPE_COPY_SEND)) {
2245 is_write_unlock(space);
2246 return MACH_SEND_INVALID_VOUCHER;
2247 }
2248
2249 if (voucher_name != MACH_PORT_NULL) {
2250 voucher_entry = ipc_entry_lookup(space, voucher_name);
2251 if (voucher_entry == IE_NULL ||
2252 (voucher_entry->ie_bits & MACH_PORT_TYPE_SEND) == 0 ||
2253 io_kotype(voucher_entry->ie_object) != IKOT_VOUCHER) {
2254 is_write_unlock(space);
2255 return MACH_SEND_INVALID_VOUCHER;
2256 }
2257 } else {
2258 voucher_type = MACH_MSG_TYPE_MOVE_SEND;
2d21ac55 2259 }
2d21ac55 2260 }
1c79356b 2261
fe8ab488
A
2262 /*
2263 * Handle combinations of validating destination and reply; along
2264 * with copying in destination, reply, and voucher in an atomic way.
2265 */
2266
2267 if (dest_name == voucher_name) {
1c79356b
A
2268
2269 /*
fe8ab488
A
2270 * If the destination name is the same as the voucher name,
2271 * the voucher_entry must already be known. Either that or
2272 * the destination name is MACH_PORT_NULL (i.e. invalid).
1c79356b 2273 */
fe8ab488
A
2274 dest_entry = voucher_entry;
2275 if (dest_entry == IE_NULL) {
1c79356b 2276 goto invalid_dest;
fe8ab488 2277 }
1c79356b 2278
fe8ab488
A
2279 /*
2280 * Make sure a future copyin of the reply port will succeed.
2281 * Once we start copying in the dest/voucher pair, we can't
2282 * back out.
2283 */
2284 if (MACH_PORT_VALID(reply_name)) {
2285 assert(reply_type != 0); /* because reply_name not null */
1c79356b 2286
fe8ab488
A
2287 /* It is just WRONG if dest, voucher, and reply are all the same. */
2288 if (voucher_name == reply_name) {
2289 goto invalid_reply;
2290 }
2291 reply_entry = ipc_entry_lookup(space, reply_name);
2292 if (reply_entry == IE_NULL) {
2293 goto invalid_reply;
2294 }
2295 assert(dest_entry != reply_entry); /* names are not equal */
2296 if (!ipc_right_copyin_check(space, reply_name, reply_entry, reply_type)) {
2297 goto invalid_reply;
2298 }
2299 }
1c79356b 2300
fe8ab488
A
2301 /*
2302 * Do the joint copyin of the dest disposition and
2303 * voucher disposition from the one entry/port. We
2304 * already validated that the voucher copyin would
2305 * succeed (above). So, any failure in combining
2306 * the copyins can be blamed on the destination.
2307 */
2308 kr = ipc_right_copyin_two(space, dest_name, dest_entry,
2309 dest_type, voucher_type,
2310 &dest_port, &dest_soright,
2311 &release_port);
2312 if (kr != KERN_SUCCESS) {
2313 assert(kr != KERN_INVALID_CAPABILITY);
1c79356b 2314 goto invalid_dest;
fe8ab488
A
2315 }
2316 voucher_port = (ipc_port_t)dest_port;
1c79356b 2317
fe8ab488
A
2318 /*
2319 * could not have been one of these dispositions,
2320 * validated the port was a true kernel voucher port above,
2321 * AND was successfully able to copyin both dest and voucher.
2322 */
2323 assert(dest_type != MACH_MSG_TYPE_MAKE_SEND);
2324 assert(dest_type != MACH_MSG_TYPE_MAKE_SEND_ONCE);
2325 assert(dest_type != MACH_MSG_TYPE_MOVE_SEND_ONCE);
2326
2327 /*
2328 * Perform the delayed reply right copyin (guaranteed success).
2329 */
2330 if (reply_entry != IE_NULL) {
fe8ab488 2331 kr = ipc_right_copyin(space, reply_name, reply_entry,
39236c6e
A
2332 reply_type, TRUE,
2333 &reply_port, &reply_soright,
3e170ce0 2334 &release_port, &assertcnt);
39236c6e 2335 assert(assertcnt == 0);
1c79356b 2336 assert(kr == KERN_SUCCESS);
fe8ab488 2337 }
1c79356b 2338
fe8ab488
A
2339 } else {
2340 if (dest_name == reply_name) {
1c79356b 2341 /*
fe8ab488
A
2342 * Destination and reply ports are the same!
2343 * This is very similar to the case where the
2344 * destination and voucher ports were the same
2345 * (except the reply port disposition is not
2346 * previously validated).
1c79356b 2347 */
fe8ab488
A
2348 dest_entry = ipc_entry_lookup(space, dest_name);
2349 if (dest_entry == IE_NULL) {
2350 goto invalid_dest;
2351 }
2352 reply_entry = dest_entry;
2353 assert(reply_type != 0); /* because name not null */
1c79356b 2354
fe8ab488
A
2355 /*
2356 * Do the joint copyin of the dest disposition and
2357 * reply disposition from the one entry/port.
1c79356b 2358 */
fe8ab488
A
2359 kr = ipc_right_copyin_two(space, dest_name, dest_entry,
2360 dest_type, reply_type,
316670eb
A
2361 &dest_port, &dest_soright,
2362 &release_port);
fe8ab488
A
2363 if (kr == KERN_INVALID_CAPABILITY) {
2364 goto invalid_reply;
2365 } else if (kr != KERN_SUCCESS) {
1c79356b 2366 goto invalid_dest;
6d2010ae 2367 }
1c79356b 2368 reply_port = dest_port;
fe8ab488
A
2369
2370
1c79356b 2371 } else {
fe8ab488
A
2372 /*
2373 * Handle destination and reply independently, as
2374 * they are independent entries (even if the entries
2375 * refer to the same port).
2376 *
2377 * This can be the tough case to make atomic.
2378 *
2379 * The difficult problem is serializing with port death.
2380 * The bad case is when dest_port dies after its copyin,
2381 * reply_port dies before its copyin, and dest_port dies before
2382 * reply_port. Then the copyins operated as if dest_port was
2383 * alive and reply_port was dead, which shouldn't have happened
2384 * because they died in the other order.
2385 *
2386 * Note that it is easy for a user task to tell if
2387 * a copyin happened before or after a port died.
2388 * If a port dies before copyin, a dead-name notification
2389 * is generated and the dead name's urefs are incremented,
2390 * and if the copyin happens first, a port-deleted
2391 * notification is generated.
2392 *
2393 * Even so, avoiding that potentially detectable race is too
2394 * expensive - and no known code cares about it. So, we just
2395 * do the expedient thing and copy them in one after the other.
2396 */
1c79356b 2397
fe8ab488
A
2398 dest_entry = ipc_entry_lookup(space, dest_name);
2399 if (dest_entry == IE_NULL) {
2400 goto invalid_dest;
2401 }
2402 assert(dest_entry != voucher_entry);
1c79356b
A
2403
2404 /*
fe8ab488 2405 * Make sure reply port entry is valid before dest copyin.
1c79356b 2406 */
fe8ab488
A
2407 if (MACH_PORT_VALID(reply_name)) {
2408 if (reply_name == voucher_name) {
2409 goto invalid_reply;
2410 }
2411 reply_entry = ipc_entry_lookup(space, reply_name);
2412 if (reply_entry == IE_NULL) {
2413 goto invalid_reply;
2414 }
2415 assert(dest_entry != reply_entry); /* names are not equal */
2416 assert(reply_type != 0); /* because reply_name not null */
2417
2418 if (!ipc_right_copyin_check(space, reply_name, reply_entry, reply_type)) {
2419 goto invalid_reply;
2420 }
2421 }
1c79356b 2422
fe8ab488
A
2423 /*
2424 * copyin the destination.
2425 */
fe8ab488
A
2426 kr = ipc_right_copyin(space, dest_name, dest_entry,
2427 dest_type, FALSE,
2428 &dest_port, &dest_soright,
3e170ce0 2429 &release_port, &assertcnt);
39236c6e 2430 assert(assertcnt == 0);
fe8ab488 2431 if (kr != KERN_SUCCESS) {
1c79356b 2432 goto invalid_dest;
6d2010ae 2433 }
fe8ab488
A
2434 assert(IO_VALID(dest_port));
2435 assert(!IP_VALID(release_port));
1c79356b
A
2436
2437 /*
fe8ab488
A
2438 * Copyin the pre-validated reply right.
2439 * It's OK if the reply right has gone dead in the meantime.
1c79356b 2440 */
fe8ab488 2441 if (MACH_PORT_VALID(reply_name)) {
fe8ab488
A
2442 kr = ipc_right_copyin(space, reply_name, reply_entry,
2443 reply_type, TRUE,
2444 &reply_port, &reply_soright,
3e170ce0 2445 &release_port, &assertcnt);
fe8ab488 2446 assert(assertcnt == 0);
fe8ab488
A
2447 assert(kr == KERN_SUCCESS);
2448 } else {
2449 /* convert invalid name to equivalent ipc_object type */
2450 reply_port = (ipc_object_t)CAST_MACH_NAME_TO_PORT(reply_name);
2451 }
6d2010ae 2452 }
1c79356b 2453
1c79356b 2454 /*
fe8ab488
A
2455 * Finally can copyin the voucher right now that dest and reply
2456 * are fully copied in (guaranteed success).
1c79356b 2457 */
fe8ab488 2458 if (IE_NULL != voucher_entry) {
fe8ab488
A
2459 kr = ipc_right_copyin(space, voucher_name, voucher_entry,
2460 voucher_type, FALSE,
2461 (ipc_object_t *)&voucher_port,
2462 &voucher_soright,
2463 &voucher_release_port,
3e170ce0 2464 &assertcnt);
fe8ab488 2465 assert(assertcnt == 0);
fe8ab488
A
2466 assert(KERN_SUCCESS == kr);
2467 assert(IP_VALID(voucher_port));
2468 assert(ip_active(voucher_port));
6d2010ae 2469 }
fe8ab488 2470 }
1c79356b 2471
d190cdc3
A
2472 /*
2473 * The entries might need to be deallocated.
2474 *
2475 * Each entry should be deallocated only once,
2476 * even if it was specified in more than one slot in the header.
2477 * Note that dest can be the same entry as reply or voucher,
2478 * but reply and voucher must be distinct entries.
2479 */
fe8ab488 2480 assert(IE_NULL != dest_entry);
d190cdc3
A
2481 if (IE_NULL != reply_entry)
2482 assert(reply_entry != voucher_entry);
2483
fe8ab488
A
2484 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
2485 ipc_entry_dealloc(space, dest_name, dest_entry);
d190cdc3
A
2486
2487 if (dest_entry == reply_entry) {
2488 reply_entry = IE_NULL;
2489 }
2490
2491 if (dest_entry == voucher_entry) {
2492 voucher_entry = IE_NULL;
2493 }
2494
fe8ab488
A
2495 dest_entry = IE_NULL;
2496 }
d190cdc3 2497 if (IE_NULL != reply_entry &&
fe8ab488
A
2498 IE_BITS_TYPE(reply_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
2499 ipc_entry_dealloc(space, reply_name, reply_entry);
2500 reply_entry = IE_NULL;
2501 }
d190cdc3 2502 if (IE_NULL != voucher_entry &&
fe8ab488
A
2503 IE_BITS_TYPE(voucher_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
2504 ipc_entry_dealloc(space, voucher_name, voucher_entry);
2505 voucher_entry = IE_NULL;
2506 }
2507
6d2010ae
A
2508 dest_type = ipc_object_copyin_type(dest_type);
2509 reply_type = ipc_object_copyin_type(reply_type);
2510
1c79356b 2511 /*
6d2010ae
A
2512 * JMM - Without rdar://problem/6275821, this is the last place we can
2513 * re-arm the send-possible notifications. It may trigger unexpectedly
39236c6e
A
2514 * early (send may NOT have failed), but better than missing. We assure
2515 * we won't miss by forcing MACH_SEND_ALWAYS if we got past arming.
1c79356b 2516 */
39236c6e
A
2517 if (((*optionp & MACH_SEND_NOTIFY) != 0) &&
2518 dest_type != MACH_MSG_TYPE_PORT_SEND_ONCE &&
6d2010ae
A
2519 dest_entry != IE_NULL && dest_entry->ie_request != IE_REQ_NONE) {
2520 ipc_port_t dport = (ipc_port_t)dest_port;
2521
2522 assert(dport != IP_NULL);
2523 ip_lock(dport);
39236c6e
A
2524 if (ip_active(dport) && dport->ip_receiver != ipc_space_kernel) {
2525 if (ip_full(dport)) {
2526#if IMPORTANCE_INHERITANCE
2527 needboost = ipc_port_request_sparm(dport, dest_name,
39037602
A
2528 dest_entry->ie_request,
2529 *optionp,
2530 override);
39236c6e
A
2531 if (needboost == FALSE)
2532 ip_unlock(dport);
2533#else
39037602
A
2534 ipc_port_request_sparm(dport, dest_name,
2535 dest_entry->ie_request,
2536 *optionp,
2537 override);
39236c6e
A
2538 ip_unlock(dport);
2539#endif /* IMPORTANCE_INHERITANCE */
2540 } else {
2541 *optionp |= MACH_SEND_ALWAYS;
2542 ip_unlock(dport);
2543 }
2544 } else {
2545 ip_unlock(dport);
6d2010ae 2546 }
1c79356b
A
2547 }
2548
2549 is_write_unlock(space);
2550
39236c6e
A
2551#if IMPORTANCE_INHERITANCE
2552 /*
2553 * If our request is the first boosting send-possible
2554 * notification this cycle, push the boost down the
2555 * destination port.
2556 */
2557 if (needboost == TRUE) {
2558 ipc_port_t dport = (ipc_port_t)dest_port;
2559
2560 /* dport still locked from above */
4bd07ac2 2561 if (ipc_port_importance_delta(dport, IPID_OPTION_SENDPOSSIBLE, 1) == FALSE) {
39236c6e 2562 ip_unlock(dport);
fe8ab488 2563 }
39236c6e
A
2564 }
2565#endif /* IMPORTANCE_INHERITANCE */
2566
fe8ab488 2567 if (dest_soright != IP_NULL) {
1c79356b 2568 ipc_notify_port_deleted(dest_soright, dest_name);
fe8ab488
A
2569 }
2570 if (reply_soright != IP_NULL) {
1c79356b 2571 ipc_notify_port_deleted(reply_soright, reply_name);
fe8ab488
A
2572 }
2573 if (voucher_soright != IP_NULL) {
2574 ipc_notify_port_deleted(voucher_soright, voucher_name);
2575 }
39037602
A
2576
2577 /*
2578 * No room to store voucher port in in-kernel msg header,
2579 * so we store it back in the kmsg itself. Extract the
2580 * qos, and apply any override before we enqueue the kmsg.
2581 */
2582 if (IP_VALID(voucher_port)) {
2583
2584 kmsg->ikm_voucher = voucher_port;
2585 voucher_type = MACH_MSG_TYPE_MOVE_SEND;
2586 }
2587
fe8ab488 2588 msg->msgh_bits = MACH_MSGH_BITS_SET(dest_type, reply_type, voucher_type, mbits);
1c79356b
A
2589 msg->msgh_remote_port = (ipc_port_t)dest_port;
2590 msg->msgh_local_port = (ipc_port_t)reply_port;
2591
5ba3f43e
A
2592 /* capture the qos value(s) for the kmsg */
2593 ipc_kmsg_set_qos(kmsg, *optionp, override);
2594
316670eb
A
2595 if (release_port != IP_NULL)
2596 ip_release(release_port);
2597
fe8ab488
A
2598 if (voucher_release_port != IP_NULL)
2599 ip_release(voucher_release_port);
39236c6e 2600
1c79356b
A
2601 return MACH_MSG_SUCCESS;
2602
2603invalid_reply:
2604 is_write_unlock(space);
316670eb 2605
316670eb
A
2606 if (release_port != IP_NULL)
2607 ip_release(release_port);
2608
fe8ab488
A
2609 assert(voucher_port == IP_NULL);
2610 assert(voucher_soright == IP_NULL);
2611
1c79356b
A
2612 return MACH_SEND_INVALID_REPLY;
2613
2614invalid_dest:
2615 is_write_unlock(space);
316670eb 2616
316670eb
A
2617 if (release_port != IP_NULL)
2618 ip_release(release_port);
2619
1c79356b
A
2620 if (reply_soright != IP_NULL)
2621 ipc_notify_port_deleted(reply_soright, reply_name);
316670eb 2622
fe8ab488
A
2623 assert(voucher_port == IP_NULL);
2624 assert(voucher_soright == IP_NULL);
2625
1c79356b
A
2626 return MACH_SEND_INVALID_DEST;
2627}
2628
b0d623f7
A
2629mach_msg_descriptor_t *ipc_kmsg_copyin_port_descriptor(
2630 volatile mach_msg_port_descriptor_t *dsc,
2631 mach_msg_legacy_port_descriptor_t *user_dsc,
2632 ipc_space_t space,
2633 ipc_object_t dest,
2634 ipc_kmsg_t kmsg,
2635 mach_msg_return_t *mr);
2636
2637void ipc_print_type_name(
2638 int type_name);
2639mach_msg_descriptor_t *
2640ipc_kmsg_copyin_port_descriptor(
2641 volatile mach_msg_port_descriptor_t *dsc,
2642 mach_msg_legacy_port_descriptor_t *user_dsc_in,
2643 ipc_space_t space,
2644 ipc_object_t dest,
2645 ipc_kmsg_t kmsg,
2646 mach_msg_return_t *mr)
2647{
2648 volatile mach_msg_legacy_port_descriptor_t *user_dsc = user_dsc_in;
2649 mach_msg_type_name_t user_disp;
2650 mach_msg_type_name_t result_disp;
2651 mach_port_name_t name;
2652 ipc_object_t object;
2653
2654 user_disp = user_dsc->disposition;
2655 result_disp = ipc_object_copyin_type(user_disp);
2656
2657 name = (mach_port_name_t)user_dsc->name;
2658 if (MACH_PORT_VALID(name)) {
2659
2660 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
2661 if (kr != KERN_SUCCESS) {
2662 *mr = MACH_SEND_INVALID_RIGHT;
2663 return NULL;
2664 }
2665
2666 if ((result_disp == MACH_MSG_TYPE_PORT_RECEIVE) &&
2667 ipc_port_check_circularity((ipc_port_t) object,
2668 (ipc_port_t) dest)) {
2669 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2670 }
2671 dsc->name = (ipc_port_t) object;
2672 } else {
2673 dsc->name = CAST_MACH_NAME_TO_PORT(name);
2674 }
2675 dsc->disposition = result_disp;
2676 dsc->type = MACH_MSG_PORT_DESCRIPTOR;
2677
2678 dsc->pad_end = 0; // debug, unnecessary
2679
2680 return (mach_msg_descriptor_t *)(user_dsc_in+1);
2681}
2682
2683mach_msg_descriptor_t * ipc_kmsg_copyin_ool_descriptor(
2684 mach_msg_ool_descriptor_t *dsc,
2685 mach_msg_descriptor_t *user_dsc,
2686 int is_64bit,
2687 vm_offset_t *paddr,
2688 vm_map_copy_t *copy,
2689 vm_size_t *space_needed,
2690 vm_map_t map,
2691 mach_msg_return_t *mr);
2692mach_msg_descriptor_t *
2693ipc_kmsg_copyin_ool_descriptor(
2694 mach_msg_ool_descriptor_t *dsc,
2695 mach_msg_descriptor_t *user_dsc,
2696 int is_64bit,
2697 vm_offset_t *paddr,
2698 vm_map_copy_t *copy,
2699 vm_size_t *space_needed,
2700 vm_map_t map,
2701 mach_msg_return_t *mr)
2702{
2703 vm_size_t length;
2704 boolean_t dealloc;
2705 mach_msg_copy_options_t copy_options;
2706 mach_vm_offset_t addr;
2707 mach_msg_descriptor_type_t dsc_type;
2708
2709 if (is_64bit) {
2710 mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2711
2712 addr = (mach_vm_offset_t) user_ool_dsc->address;
2713 length = user_ool_dsc->size;
2714 dealloc = user_ool_dsc->deallocate;
2715 copy_options = user_ool_dsc->copy;
2716 dsc_type = user_ool_dsc->type;
2717
2718 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2719 } else {
2720 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2721
2722 addr = CAST_USER_ADDR_T(user_ool_dsc->address);
2723 dealloc = user_ool_dsc->deallocate;
2724 copy_options = user_ool_dsc->copy;
2725 dsc_type = user_ool_dsc->type;
2726 length = user_ool_dsc->size;
2727
2728 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2729 }
2730
2731 dsc->size = (mach_msg_size_t)length;
2732 dsc->deallocate = dealloc;
2733 dsc->copy = copy_options;
2734 dsc->type = dsc_type;
2735
2736 if (length == 0) {
2737 dsc->address = NULL;
2738 } else if ((length >= MSG_OOL_SIZE_SMALL) &&
2739 (copy_options == MACH_MSG_PHYSICAL_COPY) && !dealloc) {
2740
2741 /*
2742 * If the request is a physical copy and the source
2743 * is not being deallocated, then allocate space
2744 * in the kernel's pageable ipc copy map and copy
2745 * the data in. The semantics guarantee that the
2746 * data will have been physically copied before
2747 * the send operation terminates. Thus if the data
2748 * is not being deallocated, we must be prepared
2749 * to page if the region is sufficiently large.
2750 */
2751 if (copyin(addr, (char *)*paddr, length)) {
2752 *mr = MACH_SEND_INVALID_MEMORY;
2753 return NULL;
2754 }
2755
2756 /*
2757 * The kernel ipc copy map is marked no_zero_fill.
2758 * If the transfer is not a page multiple, we need
2759 * to zero fill the balance.
2760 */
2761 if (!page_aligned(length)) {
2762 (void) memset((void *) (*paddr + length), 0,
2763 round_page(length) - length);
2764 }
2765 if (vm_map_copyin(ipc_kernel_copy_map, (vm_map_address_t)*paddr,
2766 (vm_map_size_t)length, TRUE, copy) != KERN_SUCCESS) {
2767 *mr = MACH_MSG_VM_KERNEL;
2768 return NULL;
2769 }
2770 dsc->address = (void *)*copy;
2771 *paddr += round_page(length);
2772 *space_needed -= round_page(length);
2773 } else {
2774
2775 /*
2776 * Make a vm_map_copy_t of the of the data. If the
2777 * data is small, this will do an optimized physical
2778 * copy. Otherwise, it will do a virtual copy.
2779 *
2780 * NOTE: A virtual copy is OK if the original is being
2781 * deallocted, even if a physical copy was requested.
2782 */
2783 kern_return_t kr = vm_map_copyin(map, addr,
2784 (vm_map_size_t)length, dealloc, copy);
2785 if (kr != KERN_SUCCESS) {
2786 *mr = (kr == KERN_RESOURCE_SHORTAGE) ?
2787 MACH_MSG_VM_KERNEL :
2788 MACH_SEND_INVALID_MEMORY;
2789 return NULL;
2790 }
2791 dsc->address = (void *)*copy;
2792 }
2793 return user_dsc;
2794}
2795
2796mach_msg_descriptor_t * ipc_kmsg_copyin_ool_ports_descriptor(
2797 mach_msg_ool_ports_descriptor_t *dsc,
2798 mach_msg_descriptor_t *user_dsc,
2799 int is_64bit,
2800 vm_map_t map,
2801 ipc_space_t space,
2802 ipc_object_t dest,
2803 ipc_kmsg_t kmsg,
2804 mach_msg_return_t *mr);
2805mach_msg_descriptor_t *
2806ipc_kmsg_copyin_ool_ports_descriptor(
2807 mach_msg_ool_ports_descriptor_t *dsc,
2808 mach_msg_descriptor_t *user_dsc,
2809 int is_64bit,
2810 vm_map_t map,
2811 ipc_space_t space,
2812 ipc_object_t dest,
2813 ipc_kmsg_t kmsg,
2814 mach_msg_return_t *mr)
2815{
2816 void *data;
2817 ipc_object_t *objects;
2818 unsigned int i;
2819 mach_vm_offset_t addr;
2820 mach_msg_type_name_t user_disp;
2821 mach_msg_type_name_t result_disp;
2822 mach_msg_type_number_t count;
2823 mach_msg_copy_options_t copy_option;
2824 boolean_t deallocate;
2825 mach_msg_descriptor_type_t type;
2826 vm_size_t ports_length, names_length;
2827
2828 if (is_64bit) {
2829 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2830
2831 addr = (mach_vm_offset_t)user_ool_dsc->address;
2832 count = user_ool_dsc->count;
2833 deallocate = user_ool_dsc->deallocate;
2834 copy_option = user_ool_dsc->copy;
2835 user_disp = user_ool_dsc->disposition;
2836 type = user_ool_dsc->type;
2837
2838 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2839 } else {
2840 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2841
2842 addr = CAST_USER_ADDR_T(user_ool_dsc->address);
2843 count = user_ool_dsc->count;
2844 deallocate = user_ool_dsc->deallocate;
2845 copy_option = user_ool_dsc->copy;
2846 user_disp = user_ool_dsc->disposition;
2847 type = user_ool_dsc->type;
2848
2849 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2850 }
2851
2852 dsc->deallocate = deallocate;
2853 dsc->copy = copy_option;
2854 dsc->type = type;
2855 dsc->count = count;
2856 dsc->address = NULL; /* for now */
2857
2858 result_disp = ipc_object_copyin_type(user_disp);
2859 dsc->disposition = result_disp;
2860
d190cdc3
A
2861 /* We always do a 'physical copy', but you have to specify something valid */
2862 if (copy_option != MACH_MSG_PHYSICAL_COPY &&
2863 copy_option != MACH_MSG_VIRTUAL_COPY) {
2864 *mr = MACH_SEND_INVALID_TYPE;
b0d623f7
A
2865 return NULL;
2866 }
2867
2868 /* calculate length of data in bytes, rounding up */
d190cdc3
A
2869
2870 if (os_mul_overflow(count, sizeof(mach_port_t), &ports_length)) {
2871 *mr = MACH_SEND_TOO_LARGE;
2872 return NULL;
2873 }
2874
2875 if (os_mul_overflow(count, sizeof(mach_port_name_t), &names_length)) {
2876 *mr = MACH_SEND_TOO_LARGE;
2877 return NULL;
2878 }
b0d623f7
A
2879
2880 if (ports_length == 0) {
2881 return user_dsc;
2882 }
2883
2884 data = kalloc(ports_length);
2885
2886 if (data == NULL) {
2887 *mr = MACH_SEND_NO_BUFFER;
2888 return NULL;
2889 }
2890
2891#ifdef __LP64__
2892 mach_port_name_t *names = &((mach_port_name_t *)data)[count];
2893#else
2894 mach_port_name_t *names = ((mach_port_name_t *)data);
2895#endif
2896
2897 if (copyinmap(map, addr, names, names_length) != KERN_SUCCESS) {
2898 kfree(data, ports_length);
2899 *mr = MACH_SEND_INVALID_MEMORY;
2900 return NULL;
2901 }
2902
2903 if (deallocate) {
2904 (void) mach_vm_deallocate(map, addr, (mach_vm_size_t)ports_length);
2905 }
2906
2907 objects = (ipc_object_t *) data;
2908 dsc->address = data;
2909
2910 for ( i = 0; i < count; i++) {
2911 mach_port_name_t name = names[i];
2912 ipc_object_t object;
2913
2914 if (!MACH_PORT_VALID(name)) {
2915 objects[i] = (ipc_object_t)CAST_MACH_NAME_TO_PORT(name);
2916 continue;
2917 }
2918
2919 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
2920
2921 if (kr != KERN_SUCCESS) {
2922 unsigned int j;
2923
2924 for(j = 0; j < i; j++) {
2925 object = objects[j];
2926 if (IPC_OBJECT_VALID(object))
2927 ipc_object_destroy(object, result_disp);
2928 }
2929 kfree(data, ports_length);
2930 dsc->address = NULL;
2931 *mr = MACH_SEND_INVALID_RIGHT;
2932 return NULL;
2933 }
2934
2935 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2936 ipc_port_check_circularity(
2937 (ipc_port_t) object,
2938 (ipc_port_t) dest))
2939 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2940
2941 objects[i] = object;
2942 }
2943
2944 return user_dsc;
2945}
2946
1c79356b
A
2947/*
2948 * Routine: ipc_kmsg_copyin_body
2949 * Purpose:
2950 * "Copy-in" port rights and out-of-line memory
2951 * in the message body.
2952 *
2953 * In all failure cases, the message is left holding
2954 * no rights or memory. However, the message buffer
2955 * is not deallocated. If successful, the message
2956 * contains a valid destination port.
2957 * Conditions:
2958 * Nothing locked.
2959 * Returns:
2960 * MACH_MSG_SUCCESS Successful copyin.
2961 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2962 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2963 * MACH_SEND_INVALID_TYPE Bad type specification.
2964 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2965 * MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
2966 * MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
2967 */
2968
2969mach_msg_return_t
2970ipc_kmsg_copyin_body(
2971 ipc_kmsg_t kmsg,
2972 ipc_space_t space,
2973 vm_map_t map)
2974{
2975 ipc_object_t dest;
2976 mach_msg_body_t *body;
91447636 2977 mach_msg_descriptor_t *daddr, *naddr;
b0d623f7 2978 mach_msg_descriptor_t *user_addr, *kern_addr;
91447636 2979 mach_msg_type_number_t dsc_count;
b0d623f7 2980 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
91447636 2981 boolean_t complex = FALSE;
1c79356b
A
2982 vm_size_t space_needed = 0;
2983 vm_offset_t paddr = 0;
1c79356b 2984 vm_map_copy_t copy = VM_MAP_COPY_NULL;
91447636
A
2985 mach_msg_type_number_t i;
2986 mach_msg_return_t mr = MACH_MSG_SUCCESS;
b0d623f7
A
2987
2988 vm_size_t descriptor_size = 0;
2989
d190cdc3
A
2990 mach_msg_type_number_t total_ool_port_count = 0;
2991
1c79356b
A
2992 /*
2993 * Determine if the target is a kernel port.
2994 */
91447636
A
2995 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
2996 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
2997 naddr = (mach_msg_descriptor_t *) (body + 1);
1c79356b 2998
91447636
A
2999 dsc_count = body->msgh_descriptor_count;
3000 if (dsc_count == 0)
3001 return MACH_MSG_SUCCESS;
3002
1c79356b
A
3003 /*
3004 * Make an initial pass to determine kernal VM space requirements for
91447636
A
3005 * physical copies and possible contraction of the descriptors from
3006 * processes with pointers larger than the kernel's.
1c79356b 3007 */
2d21ac55 3008 daddr = NULL;
91447636 3009 for (i = 0; i < dsc_count; i++) {
fe8ab488 3010 mach_msg_size_t size;
d190cdc3 3011 mach_msg_type_number_t ool_port_count = 0;
fe8ab488 3012
91447636
A
3013 daddr = naddr;
3014
3015 /* make sure the descriptor fits in the message */
b0d623f7 3016 if (is_task_64bit) {
91447636
A
3017 switch (daddr->type.type) {
3018 case MACH_MSG_OOL_DESCRIPTOR:
3019 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3020 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
b0d623f7
A
3021 descriptor_size += 16;
3022 naddr = (typeof(naddr))((vm_offset_t)daddr + 16);
3023 break;
91447636 3024 default:
b0d623f7
A
3025 descriptor_size += 12;
3026 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
3027 break;
91447636 3028 }
91447636 3029 } else {
b0d623f7
A
3030 descriptor_size += 12;
3031 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
91447636
A
3032 }
3033
3034 if (naddr > (mach_msg_descriptor_t *)
3035 ((vm_offset_t)kmsg->ikm_header + kmsg->ikm_header->msgh_size)) {
d190cdc3
A
3036 mr = MACH_SEND_MSG_TOO_SMALL;
3037 goto clean_message;
91447636 3038 }
1c79356b 3039
91447636 3040 switch (daddr->type.type) {
91447636
A
3041 case MACH_MSG_OOL_DESCRIPTOR:
3042 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
b0d623f7
A
3043 size = (is_task_64bit) ?
3044 ((mach_msg_ool_descriptor64_t *)daddr)->size :
91447636
A
3045 daddr->out_of_line.size;
3046
3047 if (daddr->out_of_line.copy != MACH_MSG_PHYSICAL_COPY &&
3048 daddr->out_of_line.copy != MACH_MSG_VIRTUAL_COPY) {
3049 /*
3050 * Invalid copy option
3051 */
91447636 3052 mr = MACH_SEND_INVALID_TYPE;
d190cdc3 3053 goto clean_message;
91447636 3054 }
d190cdc3 3055
91447636
A
3056 if ((size >= MSG_OOL_SIZE_SMALL) &&
3057 (daddr->out_of_line.copy == MACH_MSG_PHYSICAL_COPY) &&
3058 !(daddr->out_of_line.deallocate)) {
3059
3060 /*
3061 * Out-of-line memory descriptor, accumulate kernel
3062 * memory requirements
3063 */
39236c6e 3064 if (space_needed + round_page(size) <= space_needed) {
d190cdc3
A
3065 /* Overflow dectected */
3066 mr = MACH_MSG_VM_KERNEL;
3067 goto clean_message;
3068 }
3069
91447636
A
3070 space_needed += round_page(size);
3071 if (space_needed > ipc_kmsg_max_vm_space) {
d190cdc3 3072 /* Per message kernel memory limit exceeded */
91447636 3073 mr = MACH_MSG_VM_KERNEL;
d190cdc3 3074 goto clean_message;
1c79356b 3075 }
91447636 3076 }
d190cdc3
A
3077 break;
3078 case MACH_MSG_PORT_DESCRIPTOR:
3079 if (os_add_overflow(total_ool_port_count, 1, &total_ool_port_count)) {
3080 /* Overflow detected */
3081 mr = MACH_SEND_TOO_LARGE;
3082 goto clean_message;
3083 }
3084 break;
3085 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3086 ool_port_count = (is_task_64bit) ?
3087 ((mach_msg_ool_ports_descriptor64_t *)daddr)->count :
3088 daddr->ool_ports.count;
3089
3090 if (os_add_overflow(total_ool_port_count, ool_port_count, &total_ool_port_count)) {
3091 /* Overflow detected */
3092 mr = MACH_SEND_TOO_LARGE;
3093 goto clean_message;
3094 }
3095
3096 if (ool_port_count > (ipc_kmsg_max_vm_space/sizeof(mach_port_t))) {
3097 /* Per message kernel memory limit exceeded */
3098 mr = MACH_SEND_TOO_LARGE;
3099 goto clean_message;
3100 }
3101 break;
1c79356b
A
3102 }
3103 }
3104
d190cdc3
A
3105 /* Sending more than 16383 rights in one message seems crazy */
3106 if (total_ool_port_count >= (MACH_PORT_UREFS_MAX / 4)) {
3107 mr = MACH_SEND_TOO_LARGE;
3108 goto clean_message;
3109 }
3110
1c79356b
A
3111 /*
3112 * Allocate space in the pageable kernel ipc copy map for all the
3113 * ool data that is to be physically copied. Map is marked wait for
3114 * space.
3115 */
3116 if (space_needed) {
5ba3f43e
A
3117 if (vm_allocate_kernel(ipc_kernel_copy_map, &paddr, space_needed,
3118 VM_FLAGS_ANYWHERE, VM_KERN_MEMORY_IPC) != KERN_SUCCESS) {
b0d623f7 3119 mr = MACH_MSG_VM_KERNEL;
d190cdc3 3120 goto clean_message;
b0d623f7 3121 }
1c79356b
A
3122 }
3123
b0d623f7
A
3124 /* user_addr = just after base as it was copied in */
3125 user_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
fe8ab488
A
3126
3127 /* Shift the mach_msg_base_t down to make room for dsc_count*16bytes of descriptors */
b0d623f7
A
3128 if(descriptor_size != 16*dsc_count) {
3129 vm_offset_t dsc_adjust = 16*dsc_count - descriptor_size;
fe8ab488 3130
b0d623f7
A
3131 memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
3132 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
fe8ab488 3133
b0d623f7
A
3134 /* Update the message size for the larger in-kernel representation */
3135 kmsg->ikm_header->msgh_size += (mach_msg_size_t)dsc_adjust;
3136 }
1c79356b 3137
1c79356b 3138
b0d623f7
A
3139 /* kern_addr = just after base after it has been (conditionally) moved */
3140 kern_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
3141
3142 /* handle the OOL regions and port descriptors. */
3143 for(i=0;i<dsc_count;i++) {
3144 switch (user_addr->type.type) {
3145 case MACH_MSG_PORT_DESCRIPTOR:
3146 user_addr = ipc_kmsg_copyin_port_descriptor((mach_msg_port_descriptor_t *)kern_addr,
3147 (mach_msg_legacy_port_descriptor_t *)user_addr, space, dest, kmsg, &mr);
3148 kern_addr++;
3149 complex = TRUE;
3150 break;
3151 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3152 case MACH_MSG_OOL_DESCRIPTOR:
3153 user_addr = ipc_kmsg_copyin_ool_descriptor((mach_msg_ool_descriptor_t *)kern_addr,
3154 user_addr, is_task_64bit, &paddr, &copy, &space_needed, map, &mr);
3155 kern_addr++;
3156 complex = TRUE;
3157 break;
3158 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3159 user_addr = ipc_kmsg_copyin_ool_ports_descriptor((mach_msg_ool_ports_descriptor_t *)kern_addr,
3160 user_addr, is_task_64bit, map, space, dest, kmsg, &mr);
3161 kern_addr++;
3162 complex = TRUE;
3163 break;
3164 default:
3165 /* Invalid descriptor */
3166 mr = MACH_SEND_INVALID_TYPE;
3167 break;
3168 }
91447636 3169
b0d623f7
A
3170 if (MACH_MSG_SUCCESS != mr) {
3171 /* clean from start of message descriptors to i */
3172 ipc_kmsg_clean_partial(kmsg, i,
3173 (mach_msg_descriptor_t *)((mach_msg_base_t *)kmsg->ikm_header + 1),
3174 paddr, space_needed);
3175 goto out;
3176 }
3177 } /* End of loop */
1c79356b 3178
91447636
A
3179 if (!complex) {
3180 kmsg->ikm_header->msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
3181 }
91447636 3182 out:
91447636 3183 return mr;
d190cdc3
A
3184
3185clean_message:
3186 /* no descriptors have been copied in yet */
3187 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
3188 return mr;
1c79356b
A
3189}
3190
3191
3192/*
3193 * Routine: ipc_kmsg_copyin
3194 * Purpose:
3195 * "Copy-in" port rights and out-of-line memory
3196 * in the message.
3197 *
3198 * In all failure cases, the message is left holding
3199 * no rights or memory. However, the message buffer
3200 * is not deallocated. If successful, the message
3201 * contains a valid destination port.
3202 * Conditions:
3203 * Nothing locked.
3204 * Returns:
3205 * MACH_MSG_SUCCESS Successful copyin.
3206 * MACH_SEND_INVALID_HEADER
3207 * Illegal value in the message header bits.
1c79356b
A
3208 * MACH_SEND_INVALID_DEST Can't copyin destination port.
3209 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
3210 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
3211 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
3212 * MACH_SEND_INVALID_TYPE Bad type specification.
3213 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
3214 */
3215
3216mach_msg_return_t
3217ipc_kmsg_copyin(
3218 ipc_kmsg_t kmsg,
3219 ipc_space_t space,
3220 vm_map_t map,
39037602 3221 mach_msg_priority_t override,
39236c6e 3222 mach_msg_option_t *optionp)
1c79356b
A
3223{
3224 mach_msg_return_t mr;
39236c6e
A
3225
3226 kmsg->ikm_header->msgh_bits &= MACH_MSGH_BITS_USER;
3227
39037602 3228 mr = ipc_kmsg_copyin_header(kmsg, space, override, optionp);
39236c6e 3229
1c79356b
A
3230 if (mr != MACH_MSG_SUCCESS)
3231 return mr;
fe8ab488
A
3232
3233 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_MSG_SEND) | DBG_FUNC_NONE,
3234 VM_KERNEL_ADDRPERM((uintptr_t)kmsg),
3235 (uintptr_t)kmsg->ikm_header->msgh_bits,
3236 (uintptr_t)kmsg->ikm_header->msgh_id,
3237 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(kmsg->ikm_voucher)),
3238 0);
3239
3240 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_copyin header:\n%.8x\n%.8x\n%p\n%p\n%p\n%.8x\n",
3241 kmsg->ikm_header->msgh_size,
3242 kmsg->ikm_header->msgh_bits,
3243 kmsg->ikm_header->msgh_remote_port,
3244 kmsg->ikm_header->msgh_local_port,
3245 kmsg->ikm_voucher,
3246 kmsg->ikm_header->msgh_id);
b0d623f7 3247
91447636 3248 if ((kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0)
1c79356b
A
3249 return MACH_MSG_SUCCESS;
3250
b0d623f7
A
3251 mr = ipc_kmsg_copyin_body( kmsg, space, map);
3252
fe8ab488
A
3253 /* unreachable if !DEBUG */
3254 __unreachable_ok_push
b0d623f7
A
3255 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
3256 {
3257 kprintf("body:\n");
3258 uint32_t i;
3259 for(i=0;i*4 < (kmsg->ikm_header->msgh_size - sizeof(mach_msg_header_t));i++)
3260 {
3261 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
3262 }
3263 }
fe8ab488 3264 __unreachable_ok_pop
39236c6e 3265
b0d623f7 3266 return mr;
1c79356b
A
3267}
3268
3269/*
3270 * Routine: ipc_kmsg_copyin_from_kernel
3271 * Purpose:
3272 * "Copy-in" port rights and out-of-line memory
3273 * in a message sent from the kernel.
3274 *
3275 * Because the message comes from the kernel,
3276 * the implementation assumes there are no errors
3277 * or peculiarities in the message.
1c79356b
A
3278 * Conditions:
3279 * Nothing locked.
3280 */
3281
6d2010ae 3282mach_msg_return_t
1c79356b
A
3283ipc_kmsg_copyin_from_kernel(
3284 ipc_kmsg_t kmsg)
3285{
91447636 3286 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
1c79356b
A
3287 mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
3288 mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
91447636
A
3289 ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
3290 ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
3291
3292 /* translate the destination and reply ports */
6d2010ae
A
3293 if (!IO_VALID(remote))
3294 return MACH_SEND_INVALID_DEST;
1c79356b
A
3295
3296 ipc_object_copyin_from_kernel(remote, rname);
3297 if (IO_VALID(local))
3298 ipc_object_copyin_from_kernel(local, lname);
3299
3300 /*
3301 * The common case is a complex message with no reply port,
3302 * because that is what the memory_object interface uses.
3303 */
3304
3305 if (bits == (MACH_MSGH_BITS_COMPLEX |
3306 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
3307 bits = (MACH_MSGH_BITS_COMPLEX |
3308 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
3309
91447636 3310 kmsg->ikm_header->msgh_bits = bits;
1c79356b
A
3311 } else {
3312 bits = (MACH_MSGH_BITS_OTHER(bits) |
3313 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
3314 ipc_object_copyin_type(lname)));
3315
91447636 3316 kmsg->ikm_header->msgh_bits = bits;
1c79356b 3317 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
6d2010ae 3318 return MACH_MSG_SUCCESS;
1c79356b
A
3319 }
3320 {
b0d623f7 3321 mach_msg_descriptor_t *saddr;
1c79356b 3322 mach_msg_body_t *body;
b0d623f7 3323 mach_msg_type_number_t i, count;
1c79356b 3324
91447636 3325 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
1c79356b 3326 saddr = (mach_msg_descriptor_t *) (body + 1);
b0d623f7 3327 count = body->msgh_descriptor_count;
1c79356b 3328
b0d623f7 3329 for (i = 0; i < count; i++, saddr++) {
1c79356b
A
3330
3331 switch (saddr->type.type) {
3332
3333 case MACH_MSG_PORT_DESCRIPTOR: {
3334 mach_msg_type_name_t name;
3335 ipc_object_t object;
3336 mach_msg_port_descriptor_t *dsc;
3337
3338 dsc = &saddr->port;
3339
3340 /* this is really the type SEND, SEND_ONCE, etc. */
3341 name = dsc->disposition;
3342 object = (ipc_object_t) dsc->name;
3343 dsc->disposition = ipc_object_copyin_type(name);
3344
3345 if (!IO_VALID(object)) {
3346 break;
3347 }
3348
3349 ipc_object_copyin_from_kernel(object, name);
3350
3351 /* CDY avoid circularity when the destination is also */
3352 /* the kernel. This check should be changed into an */
3353 /* assert when the new kobject model is in place since*/
3354 /* ports will not be used in kernel to kernel chats */
3355
3356 if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
3357 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
3358 ipc_port_check_circularity((ipc_port_t) object,
3359 (ipc_port_t) remote)) {
91447636 3360 kmsg->ikm_header->msgh_bits |=
1c79356b
A
3361 MACH_MSGH_BITS_CIRCULAR;
3362 }
3363 }
3364 break;
3365 }
3366 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3367 case MACH_MSG_OOL_DESCRIPTOR: {
3368 /*
3369 * The sender should supply ready-made memory, i.e.
3370 * a vm_map_copy_t, so we don't need to do anything.
3371 */
3372 break;
3373 }
3374 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
3375 ipc_object_t *objects;
91447636 3376 unsigned int j;
1c79356b
A
3377 mach_msg_type_name_t name;
3378 mach_msg_ool_ports_descriptor_t *dsc;
3379
b0d623f7 3380 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
1c79356b
A
3381
3382 /* this is really the type SEND, SEND_ONCE, etc. */
3383 name = dsc->disposition;
3384 dsc->disposition = ipc_object_copyin_type(name);
3385
3386 objects = (ipc_object_t *) dsc->address;
3387
3388 for ( j = 0; j < dsc->count; j++) {
3389 ipc_object_t object = objects[j];
3390
3391 if (!IO_VALID(object))
3392 continue;
3393
3394 ipc_object_copyin_from_kernel(object, name);
3395
3396 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
3397 ipc_port_check_circularity(
3398 (ipc_port_t) object,
3399 (ipc_port_t) remote))
91447636 3400 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
1c79356b
A
3401 }
3402 break;
3403 }
3404 default: {
3405#if MACH_ASSERT
3406 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3407#endif /* MACH_ASSERT */
3408 }
3409 }
3410 }
3411 }
6d2010ae 3412 return MACH_MSG_SUCCESS;
1c79356b
A
3413}
3414
b0d623f7 3415#if IKM_SUPPORT_LEGACY
6d2010ae 3416mach_msg_return_t
b0d623f7
A
3417ipc_kmsg_copyin_from_kernel_legacy(
3418 ipc_kmsg_t kmsg)
3419{
3420 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
3421 mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
3422 mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
3423 ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
3424 ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
3425
3426 /* translate the destination and reply ports */
6d2010ae
A
3427 if (!IO_VALID(remote))
3428 return MACH_SEND_INVALID_DEST;
b0d623f7
A
3429
3430 ipc_object_copyin_from_kernel(remote, rname);
3431 if (IO_VALID(local))
3432 ipc_object_copyin_from_kernel(local, lname);
3433
3434 /*
3435 * The common case is a complex message with no reply port,
3436 * because that is what the memory_object interface uses.
3437 */
3438
3439 if (bits == (MACH_MSGH_BITS_COMPLEX |
3440 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
3441 bits = (MACH_MSGH_BITS_COMPLEX |
3442 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
3443
3444 kmsg->ikm_header->msgh_bits = bits;
3445 } else {
3446 bits = (MACH_MSGH_BITS_OTHER(bits) |
3447 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
3448 ipc_object_copyin_type(lname)));
3449
3450 kmsg->ikm_header->msgh_bits = bits;
3451 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
6d2010ae 3452 return MACH_MSG_SUCCESS;
b0d623f7
A
3453 }
3454 {
3455 mach_msg_legacy_descriptor_t *saddr;
3456 mach_msg_descriptor_t *daddr;
3457 mach_msg_body_t *body;
3458 mach_msg_type_number_t i, count;
3459
3460 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3461 saddr = (typeof(saddr)) (body + 1);
3462 count = body->msgh_descriptor_count;
3463
3464 if(count) {
3465 vm_offset_t dsc_adjust = 4*count;
3466 memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
3467 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
3468 /* Update the message size for the larger in-kernel representation */
3469 kmsg->ikm_header->msgh_size += dsc_adjust;
3470 }
3471 daddr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
3472
3473 for (i = 0; i < count; i++, saddr++, daddr++) {
3474 switch (saddr->type.type) {
3475
3476 case MACH_MSG_PORT_DESCRIPTOR: {
3477 mach_msg_type_name_t name;
3478 ipc_object_t object;
3479 mach_msg_legacy_port_descriptor_t *dsc;
3480 mach_msg_port_descriptor_t *dest_dsc;
3481
3482 dsc = (typeof(dsc))&saddr->port;
3483 dest_dsc = &daddr->port;
3484
3485 /* this is really the type SEND, SEND_ONCE, etc. */
3486 name = dsc->disposition;
3487 object = (ipc_object_t) CAST_MACH_NAME_TO_PORT(dsc->name);
3488 dest_dsc->disposition = ipc_object_copyin_type(name);
3489 dest_dsc->name = (mach_port_t)object;
3490 dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
3491
3492 if (!IO_VALID(object)) {
3493 break;
3494 }
3495
3496 ipc_object_copyin_from_kernel(object, name);
3497
3498 /* CDY avoid circularity when the destination is also */
3499 /* the kernel. This check should be changed into an */
3500 /* assert when the new kobject model is in place since*/
3501 /* ports will not be used in kernel to kernel chats */
3502
3503 if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
3504 if ((dest_dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
3505 ipc_port_check_circularity((ipc_port_t) object,
3506 (ipc_port_t) remote)) {
3507 kmsg->ikm_header->msgh_bits |=
3508 MACH_MSGH_BITS_CIRCULAR;
3509 }
3510 }
3511 break;
3512 }
3513 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3514 case MACH_MSG_OOL_DESCRIPTOR: {
3515 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
3516 * so we don't need to do anything special. */
3517
3518 mach_msg_ool_descriptor32_t *source_dsc = &saddr->out_of_line32;
3519 mach_msg_ool_descriptor_t *dest_dsc = (typeof(dest_dsc))&daddr->out_of_line;
3520
3521 vm_offset_t address = source_dsc->address;
3522 vm_size_t size = source_dsc->size;
3523 boolean_t deallocate = source_dsc->deallocate;
3524 mach_msg_copy_options_t copy = source_dsc->copy;
3525 mach_msg_descriptor_type_t type = source_dsc->type;
3526
3527 dest_dsc->address = (void *)address;
3528 dest_dsc->size = size;
3529 dest_dsc->deallocate = deallocate;
3530 dest_dsc->copy = copy;
3531 dest_dsc->type = type;
3532 break;
3533 }
3534 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
3535 ipc_object_t *objects;
3536 unsigned int j;
3537 mach_msg_type_name_t name;
3538 mach_msg_ool_ports_descriptor_t *dest_dsc;
3539
3540 mach_msg_ool_ports_descriptor32_t *source_dsc = &saddr->ool_ports32;
3541 dest_dsc = (typeof(dest_dsc))&daddr->ool_ports;
3542
3543 boolean_t deallocate = source_dsc->deallocate;
3544 mach_msg_copy_options_t copy = source_dsc->copy;
3545 mach_msg_size_t port_count = source_dsc->count;
3546 mach_msg_type_name_t disposition = source_dsc->disposition;
3547
3548 /* this is really the type SEND, SEND_ONCE, etc. */
3549 name = disposition;
3550 disposition = ipc_object_copyin_type(name);
3551
3552 objects = (ipc_object_t *) (uintptr_t)source_dsc->address;
3553
3554 for ( j = 0; j < port_count; j++) {
3555 ipc_object_t object = objects[j];
3556
3557 if (!IO_VALID(object))
3558 continue;
3559
3560 ipc_object_copyin_from_kernel(object, name);
3561
3562 if ((disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
3563 ipc_port_check_circularity(
3564 (ipc_port_t) object,
3565 (ipc_port_t) remote))
3566 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
3567 }
3568
3569 dest_dsc->address = objects;
3570 dest_dsc->deallocate = deallocate;
3571 dest_dsc->copy = copy;
3572 dest_dsc->disposition = disposition;
3573 dest_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3574 dest_dsc->count = port_count;
3575 break;
3576 }
3577 default: {
3578#if MACH_ASSERT
3579 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3580#endif /* MACH_ASSERT */
3581 }
3582 }
3583 }
3584 }
6d2010ae 3585 return MACH_MSG_SUCCESS;
b0d623f7
A
3586}
3587#endif /* IKM_SUPPORT_LEGACY */
3588
1c79356b
A
3589/*
3590 * Routine: ipc_kmsg_copyout_header
3591 * Purpose:
3592 * "Copy-out" port rights in the header of a message.
3593 * Operates atomically; if it doesn't succeed the
3594 * message header and the space are left untouched.
3595 * If it does succeed the remote/local port fields
3596 * contain port names instead of object pointers,
3597 * and the bits field is updated.
1c79356b
A
3598 * Conditions:
3599 * Nothing locked.
3600 * Returns:
3601 * MACH_MSG_SUCCESS Copied out port rights.
3602 * MACH_RCV_INVALID_NOTIFY
3603 * Notify is non-null and doesn't name a receive right.
3604 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
3605 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
3606 * The space is dead.
3607 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
3608 * No room in space for another name.
3609 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
3610 * Couldn't allocate memory for the reply port.
3611 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
3612 * Couldn't allocate memory for the dead-name request.
3613 */
3614
3615mach_msg_return_t
3616ipc_kmsg_copyout_header(
fe8ab488
A
3617 ipc_kmsg_t kmsg,
3618 ipc_space_t space,
3619 mach_msg_option_t option)
1c79356b 3620{
fe8ab488 3621 mach_msg_header_t *msg = kmsg->ikm_header;
1c79356b
A
3622 mach_msg_bits_t mbits = msg->msgh_bits;
3623 ipc_port_t dest = (ipc_port_t) msg->msgh_remote_port;
3624
3625 assert(IP_VALID(dest));
3626
6d2010ae
A
3627 /*
3628 * While we still hold a reference on the received-from port,
3629 * process all send-possible notfications we received along with
3630 * the message.
3631 */
3632 ipc_port_spnotify(dest);
3633
1c79356b
A
3634 {
3635 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
3636 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
fe8ab488
A
3637 mach_msg_type_name_t voucher_type = MACH_MSGH_BITS_VOUCHER(mbits);
3638 ipc_port_t reply = msg->msgh_local_port;
3639 ipc_port_t release_reply_port = IP_NULL;
1c79356b
A
3640 mach_port_name_t dest_name, reply_name;
3641
fe8ab488
A
3642 ipc_port_t voucher = kmsg->ikm_voucher;
3643 ipc_port_t release_voucher_port = IP_NULL;
3644 mach_port_name_t voucher_name;
3645
3646 uint32_t entries_held = 0;
3647 boolean_t need_write_lock = FALSE;
3648 kern_return_t kr;
3649
3650 /*
3651 * Reserve any potentially needed entries in the target space.
3652 * We'll free any unused before unlocking the space.
3653 */
1c79356b 3654 if (IP_VALID(reply)) {
fe8ab488
A
3655 entries_held++;
3656 need_write_lock = TRUE;
3657 }
3658 if (IP_VALID(voucher)) {
3659 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
1c79356b 3660
fe8ab488
A
3661 if ((option & MACH_RCV_VOUCHER) != 0)
3662 entries_held++;
3663 need_write_lock = TRUE;
3664 }
3665
3666 if (need_write_lock) {
1c79356b
A
3667
3668 is_write_lock(space);
3669
fe8ab488 3670 while(entries_held) {
316670eb 3671 if (!is_active(space)) {
1c79356b
A
3672 is_write_unlock(space);
3673 return (MACH_RCV_HEADER_ERROR|
3674 MACH_MSG_IPC_SPACE);
3675 }
fe8ab488
A
3676
3677 kr = ipc_entries_hold(space, entries_held);
3678 if (KERN_SUCCESS == kr)
1c79356b 3679 break;
1c79356b 3680
fe8ab488
A
3681 kr = ipc_entry_grow_table(space, ITS_SIZE_NONE);
3682 if (KERN_SUCCESS != kr)
3683 return(MACH_RCV_HEADER_ERROR|
3684 MACH_MSG_IPC_SPACE);
3685 /* space was unlocked and relocked - retry */
3686 }
1c79356b 3687
fe8ab488
A
3688 /* Handle reply port. */
3689 if (IP_VALID(reply)) {
3690 ipc_entry_t entry;
1c79356b 3691
fe8ab488
A
3692 /* Is there already an entry we can use? */
3693 if ((reply_type != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
3694 ipc_right_reverse(space, (ipc_object_t) reply, &reply_name, &entry)) {
3695 /* reply port is locked and active */
3696 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
3697 } else {
3698 ip_lock(reply);
3699 if (!ip_active(reply)) {
3700 ip_unlock(reply);
3701
3702 release_reply_port = reply;
3703 reply = IP_DEAD;
3704 reply_name = MACH_PORT_DEAD;
3705 goto done_with_reply;
1c79356b 3706 }
fe8ab488
A
3707
3708 /* claim a held entry for the reply port */
3709 assert(entries_held > 0);
3710 entries_held--;
3711 ipc_entry_claim(space, &reply_name, &entry);
3712 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
3713 assert(entry->ie_object == IO_NULL);
3714 entry->ie_object = (ipc_object_t) reply;
1c79356b 3715 }
1c79356b 3716
fe8ab488
A
3717 /* space and reply port are locked and active */
3718 ip_reference(reply); /* hold onto the reply port */
3719
3720 kr = ipc_right_copyout(space, reply_name, entry,
3721 reply_type, TRUE, (ipc_object_t) reply);
3722 assert(kr == KERN_SUCCESS);
3723 /* reply port is unlocked */
3724 } else
3725 reply_name = CAST_MACH_PORT_TO_NAME(reply);
1c79356b 3726
fe8ab488 3727 done_with_reply:
1c79356b 3728
fe8ab488
A
3729 /* Handle voucher port. */
3730 if (voucher_type != MACH_MSGH_BITS_ZERO) {
3731 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
1c79356b 3732
fe8ab488
A
3733 if (!IP_VALID(voucher)) {
3734 if ((option & MACH_RCV_VOUCHER) == 0) {
3735 voucher_type = MACH_MSGH_BITS_ZERO;
3736 }
3737 voucher_name = MACH_PORT_NULL;
3738 goto done_with_voucher;
3739 }
3740
3741 /* clear voucher from its hiding place back in the kmsg */
3742 kmsg->ikm_voucher = IP_NULL;
3743
3744 if ((option & MACH_RCV_VOUCHER) != 0) {
3745 ipc_entry_t entry;
3746
3747 if (ipc_right_reverse(space, (ipc_object_t) voucher,
3748 &voucher_name, &entry)) {
3749 /* voucher port locked */
3750 assert(entry->ie_bits & MACH_PORT_TYPE_SEND);
3751 } else {
3752 assert(entries_held > 0);
3753 entries_held--;
3754 ipc_entry_claim(space, &voucher_name, &entry);
3755 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
3756 assert(entry->ie_object == IO_NULL);
3757 entry->ie_object = (ipc_object_t) voucher;
3758 ip_lock(voucher);
3759 }
3760 /* space is locked and active */
3761
3762 assert(ip_active(voucher));
3763 assert(ip_kotype(voucher) == IKOT_VOUCHER);
3764 kr = ipc_right_copyout(space, voucher_name, entry,
3765 MACH_MSG_TYPE_MOVE_SEND, TRUE,
3766 (ipc_object_t) voucher);
3767 /* voucher port is unlocked */
3768 } else {
3769 voucher_type = MACH_MSGH_BITS_ZERO;
3770 release_voucher_port = voucher;
3771 voucher_name = MACH_PORT_NULL;
3772 }
3773 } else {
3774 voucher_name = msg->msgh_voucher_port;
3775 }
39236c6e 3776
fe8ab488 3777 done_with_voucher:
1c79356b 3778
1c79356b
A
3779 ip_lock(dest);
3780 is_write_unlock(space);
39236c6e 3781
1c79356b
A
3782 } else {
3783 /*
fe8ab488 3784 * No reply or voucher port! This is an easy case.
1c79356b 3785 * We only need to have the space locked
6d2010ae 3786 * when locking the destination.
1c79356b
A
3787 */
3788
3789 is_read_lock(space);
316670eb 3790 if (!is_active(space)) {
1c79356b
A
3791 is_read_unlock(space);
3792 return MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE;
3793 }
3794
1c79356b
A
3795 ip_lock(dest);
3796 is_read_unlock(space);
3797
b0d623f7 3798 reply_name = CAST_MACH_PORT_TO_NAME(reply);
fe8ab488
A
3799
3800 if (voucher_type != MACH_MSGH_BITS_ZERO) {
3801 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
3802 if ((option & MACH_RCV_VOUCHER) == 0) {
3803 voucher_type = MACH_MSGH_BITS_ZERO;
3804 }
3805 voucher_name = MACH_PORT_NULL;
3806 } else {
3807 voucher_name = msg->msgh_voucher_port;
3808 }
1c79356b
A
3809 }
3810
3811 /*
3812 * At this point, the space is unlocked and the destination
3813 * port is locked. (Lock taken while space was locked.)
3814 * reply_name is taken care of; we still need dest_name.
3815 * We still hold a ref for reply (if it is valid).
3816 *
3817 * If the space holds receive rights for the destination,
3818 * we return its name for the right. Otherwise the task
3819 * managed to destroy or give away the receive right between
3820 * receiving the message and this copyout. If the destination
3821 * is dead, return MACH_PORT_DEAD, and if the receive right
3822 * exists somewhere else (another space, in transit)
3823 * return MACH_PORT_NULL.
3824 *
3825 * Making this copyout operation atomic with the previous
3826 * copyout of the reply port is a bit tricky. If there was
3827 * no real reply port (it wasn't IP_VALID) then this isn't
3828 * an issue. If the reply port was dead at copyout time,
3829 * then we are OK, because if dest is dead we serialize
3830 * after the death of both ports and if dest is alive
3831 * we serialize after reply died but before dest's (later) death.
3832 * So assume reply was alive when we copied it out. If dest
3833 * is alive, then we are OK because we serialize before
3834 * the ports' deaths. So assume dest is dead when we look at it.
3835 * If reply dies/died after dest, then we are OK because
3836 * we serialize after dest died but before reply dies.
3837 * So the hard case is when reply is alive at copyout,
3838 * dest is dead at copyout, and reply died before dest died.
3839 * In this case pretend that dest is still alive, so
3840 * we serialize while both ports are alive.
3841 *
3842 * Because the space lock is held across the copyout of reply
3843 * and locking dest, the receive right for dest can't move
3844 * in or out of the space while the copyouts happen, so
3845 * that isn't an atomicity problem. In the last hard case
3846 * above, this implies that when dest is dead that the
3847 * space couldn't have had receive rights for dest at
3848 * the time reply was copied-out, so when we pretend
3849 * that dest is still alive, we can return MACH_PORT_NULL.
3850 *
3851 * If dest == reply, then we have to make it look like
3852 * either both copyouts happened before the port died,
3853 * or both happened after the port died. This special
3854 * case works naturally if the timestamp comparison
3855 * is done correctly.
3856 */
3857
1c79356b
A
3858 if (ip_active(dest)) {
3859 ipc_object_copyout_dest(space, (ipc_object_t) dest,
3860 dest_type, &dest_name);
3861 /* dest is unlocked */
39236c6e 3862
1c79356b
A
3863 } else {
3864 ipc_port_timestamp_t timestamp;
3865
3866 timestamp = dest->ip_timestamp;
316670eb 3867 ip_unlock(dest);
1c79356b 3868 ip_release(dest);
1c79356b
A
3869
3870 if (IP_VALID(reply)) {
3871 ip_lock(reply);
3872 if (ip_active(reply) ||
3873 IP_TIMESTAMP_ORDER(timestamp,
3874 reply->ip_timestamp))
3875 dest_name = MACH_PORT_DEAD;
3876 else
3877 dest_name = MACH_PORT_NULL;
3878 ip_unlock(reply);
3879 } else
3880 dest_name = MACH_PORT_DEAD;
3881 }
3882
3883 if (IP_VALID(reply))
316670eb
A
3884 ip_release(reply);
3885
fe8ab488
A
3886 if (IP_VALID(release_reply_port)) {
3887 if (reply_type == MACH_MSG_TYPE_PORT_SEND_ONCE)
3888 ipc_port_release_sonce(release_reply_port);
3889 else
3890 ipc_port_release_send(release_reply_port);
3891 }
3892
3893 if (IP_VALID(release_voucher_port))
3894 ipc_port_release_send(release_voucher_port);
3895
1c79356b 3896
fe8ab488
A
3897 if ((option & MACH_RCV_VOUCHER) != 0) {
3898 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_RECV) | DBG_FUNC_NONE,
3899 VM_KERNEL_ADDRPERM((uintptr_t)kmsg),
3900 (uintptr_t)kmsg->ikm_header->msgh_bits,
3901 (uintptr_t)kmsg->ikm_header->msgh_id,
3902 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(voucher)),
3903 0);
3904 } else {
3905 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_MSG_RECV_VOUCHER_REFUSED) | DBG_FUNC_NONE,
3906 VM_KERNEL_ADDRPERM((uintptr_t)kmsg),
3907 (uintptr_t)kmsg->ikm_header->msgh_bits,
3908 (uintptr_t)kmsg->ikm_header->msgh_id,
3909 VM_KERNEL_ADDRPERM((uintptr_t)unsafe_convert_port_to_voucher(voucher)),
3910 0);
3911 }
3912
3913 msg->msgh_bits = MACH_MSGH_BITS_SET(reply_type, dest_type,
3914 voucher_type, mbits);
b0d623f7
A
3915 msg->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
3916 msg->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
fe8ab488 3917 msg->msgh_voucher_port = voucher_name;
1c79356b
A
3918 }
3919
fe8ab488 3920 return MACH_MSG_SUCCESS;
1c79356b
A
3921}
3922
3923/*
3924 * Routine: ipc_kmsg_copyout_object
3925 * Purpose:
3926 * Copy-out a port right. Always returns a name,
3927 * even for unsuccessful return codes. Always
3928 * consumes the supplied object.
3929 * Conditions:
3930 * Nothing locked.
3931 * Returns:
3932 * MACH_MSG_SUCCESS The space acquired the right
3933 * (name is valid) or the object is dead (MACH_PORT_DEAD).
3934 * MACH_MSG_IPC_SPACE No room in space for the right,
3935 * or the space is dead. (Name is MACH_PORT_NULL.)
3936 * MACH_MSG_IPC_KERNEL Kernel resource shortage.
3937 * (Name is MACH_PORT_NULL.)
3938 */
3939
3940mach_msg_return_t
3941ipc_kmsg_copyout_object(
3942 ipc_space_t space,
3943 ipc_object_t object,
3944 mach_msg_type_name_t msgt_name,
3945 mach_port_name_t *namep)
3946{
3947 kern_return_t kr;
3948
3949 if (!IO_VALID(object)) {
b0d623f7 3950 *namep = CAST_MACH_PORT_TO_NAME(object);
1c79356b
A
3951 return MACH_MSG_SUCCESS;
3952 }
3953
3954 kr = ipc_object_copyout(space, object, msgt_name, TRUE, namep);
3955 if (kr != KERN_SUCCESS) {
3956 ipc_object_destroy(object, msgt_name);
3957
3958 if (kr == KERN_INVALID_CAPABILITY)
3959 *namep = MACH_PORT_DEAD;
3960 else {
3961 *namep = MACH_PORT_NULL;
3962
3963 if (kr == KERN_RESOURCE_SHORTAGE)
3964 return MACH_MSG_IPC_KERNEL;
3965 else
3966 return MACH_MSG_IPC_SPACE;
3967 }
3968 }
3969
3970 return MACH_MSG_SUCCESS;
3971}
3972
b0d623f7
A
3973mach_msg_descriptor_t *
3974ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3975 mach_msg_descriptor_t *user_dsc,
3976 ipc_space_t space,
3977 kern_return_t *mr);
3978mach_msg_descriptor_t *
3979ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3980 mach_msg_descriptor_t *dest_dsc,
3981 ipc_space_t space,
3982 kern_return_t *mr)
3983{
3984 mach_port_t port;
3985 mach_port_name_t name;
3986 mach_msg_type_name_t disp;
3987
3988
3989 /* Copyout port right carried in the message */
3990 port = dsc->port.name;
3991 disp = dsc->port.disposition;
3992 *mr |= ipc_kmsg_copyout_object(space,
3993 (ipc_object_t)port,
3994 disp,
3995 &name);
3996
3997 if(current_task() == kernel_task)
3998 {
3999 mach_msg_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
4000 user_dsc--; // point to the start of this port descriptor
00867663 4001 bzero((void *)user_dsc, sizeof(*user_dsc));
b0d623f7
A
4002 user_dsc->name = CAST_MACH_NAME_TO_PORT(name);
4003 user_dsc->disposition = disp;
4004 user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
4005 dest_dsc = (typeof(dest_dsc))user_dsc;
4006 } else {
4007 mach_msg_legacy_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
4008 user_dsc--; // point to the start of this port descriptor
00867663 4009 bzero((void *)user_dsc, sizeof(*user_dsc));
b0d623f7
A
4010 user_dsc->name = CAST_MACH_PORT_TO_NAME(name);
4011 user_dsc->disposition = disp;
4012 user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
4013 dest_dsc = (typeof(dest_dsc))user_dsc;
4014 }
4015
4016 return (mach_msg_descriptor_t *)dest_dsc;
4017}
4018
4019mach_msg_descriptor_t *
4020ipc_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);
4021mach_msg_descriptor_t *
4022ipc_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)
4023{
4024 vm_map_copy_t copy;
316670eb 4025 vm_map_address_t rcv_addr;
b0d623f7 4026 mach_msg_copy_options_t copy_options;
39037602 4027 vm_map_size_t size;
b0d623f7
A
4028 mach_msg_descriptor_type_t dsc_type;
4029
4030 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4031
39037602
A
4032 copy = (vm_map_copy_t)dsc->address;
4033 size = (vm_map_size_t)dsc->size;
b0d623f7
A
4034 copy_options = dsc->copy;
4035 assert(copy_options != MACH_MSG_KALLOC_COPY_T);
4036 dsc_type = dsc->type;
b0d623f7
A
4037
4038 if (copy != VM_MAP_COPY_NULL) {
3e170ce0 4039 kern_return_t kr;
b0d623f7 4040
3e170ce0 4041 rcv_addr = 0;
39037602 4042 if (vm_map_copy_validate_size(map, copy, &size) == FALSE)
2dced7af 4043 panic("Inconsistent OOL/copyout size on %p: expected %d, got %lld @%p",
39037602
A
4044 dsc, dsc->size, (unsigned long long)copy->size, copy);
4045 kr = vm_map_copyout_size(map, &rcv_addr, copy, size);
b0d623f7
A
4046 if (kr != KERN_SUCCESS) {
4047 if (kr == KERN_RESOURCE_SHORTAGE)
4048 *mr |= MACH_MSG_VM_KERNEL;
4049 else
4050 *mr |= MACH_MSG_VM_SPACE;
4051 vm_map_copy_discard(copy);
4052 rcv_addr = 0;
4053 size = 0;
4054 }
4055 } else {
4056 rcv_addr = 0;
4057 size = 0;
4058 }
4059
4060 /*
4061 * Now update the descriptor as the user would see it.
4062 * This may require expanding the descriptor to the user
4063 * visible size. There is already space allocated for
4064 * this in what naddr points to.
4065 */
4066 if(current_task() == kernel_task)
4067 {
4068 mach_msg_ool_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4069 user_ool_dsc--;
00867663 4070 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
b0d623f7
A
4071
4072 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
4073 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4074 TRUE : FALSE;
4075 user_ool_dsc->copy = copy_options;
4076 user_ool_dsc->type = dsc_type;
39037602 4077 user_ool_dsc->size = (mach_msg_size_t)size;
b0d623f7
A
4078
4079 user_dsc = (typeof(user_dsc))user_ool_dsc;
4080 } else if (is_64bit) {
4081 mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4082 user_ool_dsc--;
00867663 4083 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
b0d623f7
A
4084
4085 user_ool_dsc->address = rcv_addr;
4086 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4087 TRUE : FALSE;
4088 user_ool_dsc->copy = copy_options;
4089 user_ool_dsc->type = dsc_type;
39037602 4090 user_ool_dsc->size = (mach_msg_size_t)size;
b0d623f7
A
4091
4092 user_dsc = (typeof(user_dsc))user_ool_dsc;
4093 } else {
4094 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4095 user_ool_dsc--;
00867663 4096 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
b0d623f7
A
4097
4098 user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
39037602 4099 user_ool_dsc->size = (mach_msg_size_t)size;
b0d623f7
A
4100 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4101 TRUE : FALSE;
4102 user_ool_dsc->copy = copy_options;
4103 user_ool_dsc->type = dsc_type;
4104
4105 user_dsc = (typeof(user_dsc))user_ool_dsc;
4106 }
4107 return user_dsc;
4108}
4109
4110mach_msg_descriptor_t *
4111ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
4112 mach_msg_descriptor_t *user_dsc,
4113 int is_64bit,
4114 vm_map_t map,
4115 ipc_space_t space,
4116 ipc_kmsg_t kmsg,
4117 mach_msg_return_t *mr);
4118mach_msg_descriptor_t *
4119ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
4120 mach_msg_descriptor_t *user_dsc,
4121 int is_64bit,
4122 vm_map_t map,
4123 ipc_space_t space,
4124 ipc_kmsg_t kmsg,
4125 mach_msg_return_t *mr)
4126{
39236c6e 4127 mach_vm_offset_t rcv_addr = 0;
b0d623f7
A
4128 mach_msg_type_name_t disp;
4129 mach_msg_type_number_t count, i;
4130 vm_size_t ports_length, names_length;
4131
4132 mach_msg_copy_options_t copy_options = MACH_MSG_VIRTUAL_COPY;
4133
4134 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
4135
4136 count = dsc->count;
4137 disp = dsc->disposition;
4138 ports_length = count * sizeof(mach_port_t);
4139 names_length = count * sizeof(mach_port_name_t);
4140
4141 if (ports_length != 0 && dsc->address != 0) {
4142
4143 /*
4144 * Check to see if there is an overwrite descriptor
4145 * specified in the scatter list for this ool data.
4146 * The descriptor has already been verified.
4147 */
4148#if 0
4149 if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
4150 if (differs) {
4151 OTHER_OOL_DESCRIPTOR *scatter_dsc;
4152
4153 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
4154 rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
4155 copy_options = scatter_dsc->copy;
4156 } else {
4157 mach_msg_ool_descriptor_t *scatter_dsc;
4158
4159 scatter_dsc = &saddr->out_of_line;
4160 rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
4161 copy_options = scatter_dsc->copy;
4162 }
4163 INCREMENT_SCATTER(saddr, sdsc_count, differs);
4164 }
4165#endif
4166
4167 if (copy_options == MACH_MSG_VIRTUAL_COPY) {
4168 /*
4169 * Dynamically allocate the region
4170 */
5ba3f43e
A
4171 vm_tag_t tag;
4172 if (vm_kernel_map_is_kernel(map)) tag = VM_KERN_MEMORY_IPC;
4173 else tag = VM_MEMORY_MACH_MSG;
b0d623f7
A
4174
4175 kern_return_t kr;
5ba3f43e 4176 if ((kr = mach_vm_allocate_kernel(map, &rcv_addr,
b0d623f7 4177 (mach_vm_size_t)names_length,
5ba3f43e 4178 VM_FLAGS_ANYWHERE, tag)) != KERN_SUCCESS) {
b0d623f7
A
4179 ipc_kmsg_clean_body(kmsg, 1, (mach_msg_descriptor_t *)dsc);
4180 rcv_addr = 0;
4181
4182 if (kr == KERN_RESOURCE_SHORTAGE){
4183 *mr |= MACH_MSG_VM_KERNEL;
4184 } else {
4185 *mr |= MACH_MSG_VM_SPACE;
4186 }
4187 }
4188 }
4189
4190 /*
4191 * Handle the port rights and copy out the names
4192 * for those rights out to user-space.
4193 */
4194 if (rcv_addr != 0) {
4195 mach_port_t *objects = (mach_port_t *) dsc->address;
4196 mach_port_name_t *names = (mach_port_name_t *) dsc->address;
4197
4198 /* copyout port rights carried in the message */
4199
4200 for ( i = 0; i < count ; i++) {
4201 ipc_object_t object = (ipc_object_t)objects[i];
4202
4203 *mr |= ipc_kmsg_copyout_object(space, object,
4204 disp, &names[i]);
4205 }
4206
4207 /* copyout to memory allocated above */
4208 void *data = dsc->address;
4209 if (copyoutmap(map, data, rcv_addr, names_length) != KERN_SUCCESS)
4210 *mr |= MACH_MSG_VM_SPACE;
4211 kfree(data, ports_length);
4212 }
4213 } else {
4214 rcv_addr = 0;
4215 }
4216
4217 /*
4218 * Now update the descriptor based on the information
4219 * calculated above.
4220 */
4221 if(current_task() == kernel_task) {
4222 mach_msg_ool_ports_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4223 user_ool_dsc--;
00867663 4224 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
b0d623f7
A
4225
4226 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
4227 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4228 TRUE : FALSE;
4229 user_ool_dsc->copy = copy_options;
4230 user_ool_dsc->disposition = disp;
4231 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
4232 user_ool_dsc->count = count;
4233
4234 user_dsc = (typeof(user_dsc))user_ool_dsc;
4235 } if (is_64bit) {
4236 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4237 user_ool_dsc--;
00867663 4238 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
b0d623f7
A
4239
4240 user_ool_dsc->address = rcv_addr;
4241 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4242 TRUE : FALSE;
4243 user_ool_dsc->copy = copy_options;
4244 user_ool_dsc->disposition = disp;
4245 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
4246 user_ool_dsc->count = count;
4247
4248 user_dsc = (typeof(user_dsc))user_ool_dsc;
4249 } else {
4250 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
4251 user_ool_dsc--;
00867663 4252 bzero((void *)user_ool_dsc, sizeof(*user_ool_dsc));
b0d623f7
A
4253
4254 user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
4255 user_ool_dsc->count = count;
4256 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
4257 TRUE : FALSE;
4258 user_ool_dsc->copy = copy_options;
4259 user_ool_dsc->disposition = disp;
4260 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
4261
4262 user_dsc = (typeof(user_dsc))user_ool_dsc;
4263 }
4264 return user_dsc;
4265}
4266
1c79356b
A
4267/*
4268 * Routine: ipc_kmsg_copyout_body
4269 * Purpose:
4270 * "Copy-out" port rights and out-of-line memory
4271 * in the body of a message.
4272 *
4273 * The error codes are a combination of special bits.
4274 * The copyout proceeds despite errors.
4275 * Conditions:
4276 * Nothing locked.
4277 * Returns:
4278 * MACH_MSG_SUCCESS Successful copyout.
4279 * MACH_MSG_IPC_SPACE No room for port right in name space.
4280 * MACH_MSG_VM_SPACE No room for memory in address space.
4281 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
4282 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
4283 * MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
4284 */
4285
4286mach_msg_return_t
4287ipc_kmsg_copyout_body(
4288 ipc_kmsg_t kmsg,
4289 ipc_space_t space,
4290 vm_map_t map,
4291 mach_msg_body_t *slist)
4292{
4293 mach_msg_body_t *body;
b0d623f7 4294 mach_msg_descriptor_t *kern_dsc, *user_dsc;
91447636 4295 mach_msg_descriptor_t *saddr;
b0d623f7
A
4296 mach_msg_type_number_t dsc_count, sdsc_count;
4297 int i;
1c79356b 4298 mach_msg_return_t mr = MACH_MSG_SUCCESS;
b0d623f7 4299 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
1c79356b 4300
91447636
A
4301 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
4302 dsc_count = body->msgh_descriptor_count;
b0d623f7
A
4303 kern_dsc = (mach_msg_descriptor_t *) (body + 1);
4304 /* Point user_dsc just after the end of all the descriptors */
4305 user_dsc = &kern_dsc[dsc_count];
1c79356b 4306
b0d623f7 4307 /* Do scatter list setup */
1c79356b 4308 if (slist != MACH_MSG_BODY_NULL) {
b0d623f7 4309 panic("Scatter lists disabled");
91447636
A
4310 saddr = (mach_msg_descriptor_t *) (slist + 1);
4311 sdsc_count = slist->msgh_descriptor_count;
1c79356b
A
4312 }
4313 else {
91447636
A
4314 saddr = MACH_MSG_DESCRIPTOR_NULL;
4315 sdsc_count = 0;
1c79356b
A
4316 }
4317
b0d623f7
A
4318 /* Now process the descriptors */
4319 for (i = dsc_count-1; i >= 0; i--) {
4320 switch (kern_dsc[i].type.type) {
4321
4322 case MACH_MSG_PORT_DESCRIPTOR:
4323 user_dsc = ipc_kmsg_copyout_port_descriptor(&kern_dsc[i], user_dsc, space, &mr);
4324 break;
4325 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4326 case MACH_MSG_OOL_DESCRIPTOR :
4327 user_dsc = ipc_kmsg_copyout_ool_descriptor(
4328 (mach_msg_ool_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, &mr);
4329 break;
4330 case MACH_MSG_OOL_PORTS_DESCRIPTOR :
4331 user_dsc = ipc_kmsg_copyout_ool_ports_descriptor(
4332 (mach_msg_ool_ports_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, space, kmsg, &mr);
4333 break;
4334 default : {
4335 panic("untyped IPC copyout body: invalid message descriptor");
4336 }
4337 }
91447636
A
4338 }
4339
b0d623f7
A
4340 if(user_dsc != kern_dsc) {
4341 vm_offset_t dsc_adjust = (vm_offset_t)user_dsc - (vm_offset_t)kern_dsc;
4342 memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
4343 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
4344 /* Update the message size for the smaller user representation */
4345 kmsg->ikm_header->msgh_size -= (mach_msg_size_t)dsc_adjust;
1c79356b 4346 }
b0d623f7 4347
1c79356b
A
4348 return mr;
4349}
4350
91447636
A
4351/*
4352 * Routine: ipc_kmsg_copyout_size
4353 * Purpose:
4354 * Compute the size of the message as copied out to the given
4355 * map. If the destination map's pointers are a different size
4356 * than the kernel's, we have to allow for expansion/
4357 * contraction of the descriptors as appropriate.
4358 * Conditions:
4359 * Nothing locked.
4360 * Returns:
4361 * size of the message as it would be received.
4362 */
4363
4364mach_msg_size_t
4365ipc_kmsg_copyout_size(
4366 ipc_kmsg_t kmsg,
4367 vm_map_t map)
4368{
b0d623f7 4369 mach_msg_size_t send_size;
91447636 4370
b0d623f7 4371 send_size = kmsg->ikm_header->msgh_size;
91447636 4372
b0d623f7 4373 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
91447636 4374
b0d623f7
A
4375#if defined(__LP64__)
4376 send_size -= LEGACY_HEADER_SIZE_DELTA;
4377#endif
91447636 4378
b0d623f7 4379 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
91447636 4380
b0d623f7
A
4381 mach_msg_body_t *body;
4382 mach_msg_descriptor_t *saddr, *eaddr;
91447636 4383
b0d623f7
A
4384 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
4385 saddr = (mach_msg_descriptor_t *) (body + 1);
4386 eaddr = saddr + body->msgh_descriptor_count;
4387
4388 for ( ; saddr < eaddr; saddr++ ) {
4389 switch (saddr->type.type) {
4390 case MACH_MSG_OOL_DESCRIPTOR:
4391 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4392 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4393 if(!is_task_64bit)
4394 send_size -= DESC_SIZE_ADJUSTMENT;
4395 break;
4396 case MACH_MSG_PORT_DESCRIPTOR:
4397 send_size -= DESC_SIZE_ADJUSTMENT;
4398 break;
4399 default:
4400 break;
4401 }
4402 }
4403 }
4404 return send_size;
91447636
A
4405}
4406
1c79356b
A
4407/*
4408 * Routine: ipc_kmsg_copyout
4409 * Purpose:
4410 * "Copy-out" port rights and out-of-line memory
4411 * in the message.
4412 * Conditions:
4413 * Nothing locked.
4414 * Returns:
4415 * MACH_MSG_SUCCESS Copied out all rights and memory.
1c79356b
A
4416 * MACH_RCV_HEADER_ERROR + special bits
4417 * Rights and memory in the message are intact.
4418 * MACH_RCV_BODY_ERROR + special bits
4419 * The message header was successfully copied out.
4420 * As much of the body was handled as possible.
4421 */
4422
4423mach_msg_return_t
4424ipc_kmsg_copyout(
4425 ipc_kmsg_t kmsg,
4426 ipc_space_t space,
4427 vm_map_t map,
fe8ab488
A
4428 mach_msg_body_t *slist,
4429 mach_msg_option_t option)
1c79356b
A
4430{
4431 mach_msg_return_t mr;
4432
fe8ab488 4433 mr = ipc_kmsg_copyout_header(kmsg, space, option);
2d21ac55 4434 if (mr != MACH_MSG_SUCCESS) {
1c79356b 4435 return mr;
2d21ac55 4436 }
1c79356b 4437
91447636 4438 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
1c79356b
A
4439 mr = ipc_kmsg_copyout_body(kmsg, space, map, slist);
4440
4441 if (mr != MACH_MSG_SUCCESS)
4442 mr |= MACH_RCV_BODY_ERROR;
4443 }
4444
4445 return mr;
4446}
4447
4448/*
4449 * Routine: ipc_kmsg_copyout_pseudo
4450 * Purpose:
4451 * Does a pseudo-copyout of the message.
4452 * This is like a regular copyout, except
4453 * that the ports in the header are handled
4454 * as if they are in the body. They aren't reversed.
4455 *
4456 * The error codes are a combination of special bits.
4457 * The copyout proceeds despite errors.
4458 * Conditions:
4459 * Nothing locked.
4460 * Returns:
4461 * MACH_MSG_SUCCESS Successful copyout.
4462 * MACH_MSG_IPC_SPACE No room for port right in name space.
4463 * MACH_MSG_VM_SPACE No room for memory in address space.
4464 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
4465 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
4466 */
4467
4468mach_msg_return_t
4469ipc_kmsg_copyout_pseudo(
4470 ipc_kmsg_t kmsg,
4471 ipc_space_t space,
4472 vm_map_t map,
4473 mach_msg_body_t *slist)
4474{
91447636
A
4475 mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
4476 ipc_object_t dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4477 ipc_object_t reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
fe8ab488 4478 ipc_object_t voucher = (ipc_object_t) kmsg->ikm_voucher;
1c79356b
A
4479 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
4480 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
fe8ab488
A
4481 mach_msg_type_name_t voucher_type = MACH_MSGH_BITS_VOUCHER(mbits);
4482 mach_port_name_t voucher_name = kmsg->ikm_header->msgh_voucher_port;
1c79356b
A
4483 mach_port_name_t dest_name, reply_name;
4484 mach_msg_return_t mr;
4485
5ba3f43e
A
4486 /* Set ith_knote to ITH_KNOTE_PSEUDO */
4487 current_thread()->ith_knote = ITH_KNOTE_PSEUDO;
4488
1c79356b
A
4489 assert(IO_VALID(dest));
4490
fe8ab488
A
4491#if 0
4492 /*
4493 * If we did this here, it looks like we wouldn't need the undo logic
4494 * at the end of ipc_kmsg_send() in the error cases. Not sure which
4495 * would be more elegant to keep.
4496 */
4497 ipc_importance_clean(kmsg);
4498#else
4499 /* just assert it is already clean */
4500 ipc_importance_assert_clean(kmsg);
4501#endif
4502
1c79356b
A
4503 mr = (ipc_kmsg_copyout_object(space, dest, dest_type, &dest_name) |
4504 ipc_kmsg_copyout_object(space, reply, reply_type, &reply_name));
4505
39236c6e 4506 kmsg->ikm_header->msgh_bits = mbits & MACH_MSGH_BITS_USER;
b0d623f7
A
4507 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(dest_name);
4508 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(reply_name);
1c79356b 4509
fe8ab488
A
4510 if (IO_VALID(voucher)) {
4511 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
4512
4513 kmsg->ikm_voucher = IP_NULL;
4514 mr |= ipc_kmsg_copyout_object(space, voucher, voucher_type, &voucher_name);
4515 kmsg->ikm_header->msgh_voucher_port = voucher_name;
4516 }
4517
1c79356b
A
4518 if (mbits & MACH_MSGH_BITS_COMPLEX) {
4519 mr |= ipc_kmsg_copyout_body(kmsg, space, map, slist);
4520 }
4521
4522 return mr;
4523}
4524
4525/*
4526 * Routine: ipc_kmsg_copyout_dest
4527 * Purpose:
4528 * Copies out the destination port in the message.
4529 * Destroys all other rights and memory in the message.
4530 * Conditions:
4531 * Nothing locked.
4532 */
4533
4534void
4535ipc_kmsg_copyout_dest(
4536 ipc_kmsg_t kmsg,
4537 ipc_space_t space)
4538{
4539 mach_msg_bits_t mbits;
4540 ipc_object_t dest;
4541 ipc_object_t reply;
fe8ab488 4542 ipc_object_t voucher;
1c79356b
A
4543 mach_msg_type_name_t dest_type;
4544 mach_msg_type_name_t reply_type;
fe8ab488
A
4545 mach_msg_type_name_t voucher_type;
4546 mach_port_name_t dest_name, reply_name, voucher_name;
1c79356b 4547
91447636
A
4548 mbits = kmsg->ikm_header->msgh_bits;
4549 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4550 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
fe8ab488
A
4551 voucher = (ipc_object_t) kmsg->ikm_voucher;
4552 voucher_name = kmsg->ikm_header->msgh_voucher_port;
1c79356b
A
4553 dest_type = MACH_MSGH_BITS_REMOTE(mbits);
4554 reply_type = MACH_MSGH_BITS_LOCAL(mbits);
fe8ab488 4555 voucher_type = MACH_MSGH_BITS_VOUCHER(mbits);
1c79356b
A
4556
4557 assert(IO_VALID(dest));
4558
fe8ab488
A
4559 ipc_importance_assert_clean(kmsg);
4560
1c79356b
A
4561 io_lock(dest);
4562 if (io_active(dest)) {
4563 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4564 /* dest is unlocked */
4565 } else {
316670eb 4566 io_unlock(dest);
1c79356b 4567 io_release(dest);
1c79356b
A
4568 dest_name = MACH_PORT_DEAD;
4569 }
4570
4571 if (IO_VALID(reply)) {
4572 ipc_object_destroy(reply, reply_type);
4573 reply_name = MACH_PORT_NULL;
4574 } else
b0d623f7 4575 reply_name = CAST_MACH_PORT_TO_NAME(reply);
1c79356b 4576
fe8ab488
A
4577 if (IO_VALID(voucher)) {
4578 assert(voucher_type == MACH_MSG_TYPE_MOVE_SEND);
4579
4580 kmsg->ikm_voucher = IP_NULL;
4581 ipc_object_destroy((ipc_object_t)voucher, voucher_type);
4582 voucher_name = MACH_PORT_NULL;
4583 }
4584
4585 kmsg->ikm_header->msgh_bits = MACH_MSGH_BITS_SET(reply_type, dest_type,
4586 voucher_type, mbits);
b0d623f7
A
4587 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
4588 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
fe8ab488 4589 kmsg->ikm_header->msgh_voucher_port = voucher_name;
1c79356b
A
4590
4591 if (mbits & MACH_MSGH_BITS_COMPLEX) {
4592 mach_msg_body_t *body;
4593
91447636
A
4594 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
4595 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count,
4596 (mach_msg_descriptor_t *)(body + 1));
1c79356b
A
4597 }
4598}
91447636 4599
1c79356b
A
4600/*
4601 * Routine: ipc_kmsg_copyout_to_kernel
4602 * Purpose:
4603 * Copies out the destination and reply ports in the message.
4604 * Leaves all other rights and memory in the message alone.
4605 * Conditions:
4606 * Nothing locked.
4607 *
4608 * Derived from ipc_kmsg_copyout_dest.
4609 * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
4610 * We really do want to save rights and memory.
4611 */
4612
4613void
4614ipc_kmsg_copyout_to_kernel(
4615 ipc_kmsg_t kmsg,
4616 ipc_space_t space)
4617{
4618 ipc_object_t dest;
4619 ipc_object_t reply;
4620 mach_msg_type_name_t dest_type;
4621 mach_msg_type_name_t reply_type;
4622 mach_port_name_t dest_name, reply_name;
4623
91447636
A
4624 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4625 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
4626 dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
4627 reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
1c79356b
A
4628
4629 assert(IO_VALID(dest));
4630
4631 io_lock(dest);
4632 if (io_active(dest)) {
4633 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4634 /* dest is unlocked */
4635 } else {
316670eb 4636 io_unlock(dest);
1c79356b 4637 io_release(dest);
1c79356b
A
4638 dest_name = MACH_PORT_DEAD;
4639 }
4640
b0d623f7 4641 reply_name = CAST_MACH_PORT_TO_NAME(reply);
1c79356b 4642
91447636
A
4643 kmsg->ikm_header->msgh_bits =
4644 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
1c79356b 4645 MACH_MSGH_BITS(reply_type, dest_type));
b0d623f7
A
4646 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
4647 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
1c79356b
A
4648}
4649
b0d623f7
A
4650#if IKM_SUPPORT_LEGACY
4651void
4652ipc_kmsg_copyout_to_kernel_legacy(
4653 ipc_kmsg_t kmsg,
4654 ipc_space_t space)
4655{
4656 ipc_object_t dest;
4657 ipc_object_t reply;
4658 mach_msg_type_name_t dest_type;
4659 mach_msg_type_name_t reply_type;
4660 mach_port_name_t dest_name, reply_name;
4661
4662 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4663 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
4664 dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
4665 reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
4666
4667 assert(IO_VALID(dest));
4668
4669 io_lock(dest);
4670 if (io_active(dest)) {
4671 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4672 /* dest is unlocked */
4673 } else {
316670eb 4674 io_unlock(dest);
b0d623f7 4675 io_release(dest);
b0d623f7
A
4676 dest_name = MACH_PORT_DEAD;
4677 }
4678
4679 reply_name = CAST_MACH_PORT_TO_NAME(reply);
4680
4681 kmsg->ikm_header->msgh_bits =
4682 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
4683 MACH_MSGH_BITS(reply_type, dest_type));
4684 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
4685 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
4686
4687 mach_msg_descriptor_t *saddr;
4688 mach_msg_legacy_descriptor_t *daddr;
4689 mach_msg_type_number_t i, count = ((mach_msg_base_t *)kmsg->ikm_header)->body.msgh_descriptor_count;
4690 saddr = (mach_msg_descriptor_t *) (((mach_msg_base_t *)kmsg->ikm_header) + 1);
4691 saddr = &saddr[count-1];
4692 daddr = (mach_msg_legacy_descriptor_t *)&saddr[count];
4693 daddr--;
4694
4695 vm_offset_t dsc_adjust = 0;
4696
4697 for (i = 0; i < count; i++, saddr--, daddr--) {
4698 switch (saddr->type.type) {
4699 case MACH_MSG_PORT_DESCRIPTOR: {
4700 mach_msg_port_descriptor_t *dsc = &saddr->port;
4701 mach_msg_legacy_port_descriptor_t *dest_dsc = &daddr->port;
4702
4703 mach_port_t name = dsc->name;
4704 mach_msg_type_name_t disposition = dsc->disposition;
4705
4706 dest_dsc->name = CAST_MACH_PORT_TO_NAME(name);
4707 dest_dsc->disposition = disposition;
4708 dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
4709 break;
4710 }
4711 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4712 case MACH_MSG_OOL_DESCRIPTOR: {
4713 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
4714 * so we don't need to do anything special. */
4715
4716 mach_msg_ool_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->out_of_line;
4717
4718 mach_msg_ool_descriptor32_t *dest_dsc = &daddr->out_of_line32;
4719
4720 vm_offset_t address = (vm_offset_t)source_dsc->address;
4721 vm_size_t size = source_dsc->size;
4722 boolean_t deallocate = source_dsc->deallocate;
4723 mach_msg_copy_options_t copy = source_dsc->copy;
4724 mach_msg_descriptor_type_t type = source_dsc->type;
4725
4726 dest_dsc->address = address;
4727 dest_dsc->size = size;
4728 dest_dsc->deallocate = deallocate;
4729 dest_dsc->copy = copy;
4730 dest_dsc->type = type;
4731 break;
4732 }
4733 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
4734 mach_msg_ool_ports_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->ool_ports;
4735
4736 mach_msg_ool_ports_descriptor32_t *dest_dsc = &daddr->ool_ports32;
4737
4738 vm_offset_t address = (vm_offset_t)source_dsc->address;
4739 vm_size_t port_count = source_dsc->count;
4740 boolean_t deallocate = source_dsc->deallocate;
4741 mach_msg_copy_options_t copy = source_dsc->copy;
4742 mach_msg_descriptor_type_t type = source_dsc->type;
4743
4744 dest_dsc->address = address;
4745 dest_dsc->count = port_count;
4746 dest_dsc->deallocate = deallocate;
4747 dest_dsc->copy = copy;
4748 dest_dsc->type = type;
4749 break;
4750 }
4751 default: {
4752#if MACH_ASSERT
4753 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
4754#endif /* MACH_ASSERT */
4755 }
4756 }
4757 }
4758
4759 if(count) {
4760 dsc_adjust = 4*count;
4761 memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
4762 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
4763 /* Update the message size for the smaller user representation */
4764 kmsg->ikm_header->msgh_size -= dsc_adjust;
4765 }
4766}
4767#endif /* IKM_SUPPORT_LEGACY */
4768
5ba3f43e
A
4769#ifdef __arm64__
4770/*
4771 * Just sets those parts of the trailer that aren't set up at allocation time.
4772 */
4773static void
4774ipc_kmsg_munge_trailer(mach_msg_max_trailer_t *in, void *_out, boolean_t is64bit)
4775{
4776 if (is64bit) {
4777 mach_msg_max_trailer64_t *out = (mach_msg_max_trailer64_t*)_out;
4778 out->msgh_seqno = in->msgh_seqno;
4779 out->msgh_context = in->msgh_context;
4780 out->msgh_trailer_size = in->msgh_trailer_size;
4781 out->msgh_ad = in->msgh_ad;
4782 } else {
4783 mach_msg_max_trailer32_t *out = (mach_msg_max_trailer32_t*)_out;
4784 out->msgh_seqno = in->msgh_seqno;
4785 out->msgh_context = (mach_port_context32_t)in->msgh_context;
4786 out->msgh_trailer_size = in->msgh_trailer_size;
4787 out->msgh_ad = in->msgh_ad;
4788 }
4789}
4790#endif /* __arm64__ */
fe8ab488 4791
316670eb 4792mach_msg_trailer_size_t
fe8ab488 4793ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space __unused,
316670eb
A
4794 mach_msg_option_t option, thread_t thread,
4795 mach_port_seqno_t seqno, boolean_t minimal_trailer,
4796 mach_vm_offset_t context)
1c79356b 4797{
316670eb 4798 mach_msg_max_trailer_t *trailer;
1c79356b 4799
5ba3f43e
A
4800#ifdef __arm64__
4801 mach_msg_max_trailer_t tmp_trailer; /* This accommodates U64, and we'll munge */
4802 void *real_trailer_out = (void*)(mach_msg_max_trailer_t *)
4803 ((vm_offset_t)kmsg->ikm_header +
4804 round_msg(kmsg->ikm_header->msgh_size));
4805
4806 /*
4807 * Populate scratch with initial values set up at message allocation time.
4808 * After, we reinterpret the space in the message as the right type
4809 * of trailer for the address space in question.
4810 */
4811 bcopy(real_trailer_out, &tmp_trailer, MAX_TRAILER_SIZE);
4812 trailer = &tmp_trailer;
4813#else /* __arm64__ */
316670eb
A
4814 (void)thread;
4815 trailer = (mach_msg_max_trailer_t *)
4816 ((vm_offset_t)kmsg->ikm_header +
4817 round_msg(kmsg->ikm_header->msgh_size));
5ba3f43e 4818#endif /* __arm64__ */
1c79356b 4819
316670eb
A
4820 if (!(option & MACH_RCV_TRAILER_MASK)) {
4821 return trailer->msgh_trailer_size;
1c79356b 4822 }
1c79356b 4823
316670eb
A
4824 trailer->msgh_seqno = seqno;
4825 trailer->msgh_context = context;
4826 trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit(thread), option);
1c79356b 4827
316670eb
A
4828 if (minimal_trailer) {
4829 goto done;
1c79356b
A
4830 }
4831
316670eb
A
4832 if (MACH_RCV_TRAILER_ELEMENTS(option) >=
4833 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV)){
fe8ab488 4834 trailer->msgh_ad = 0;
1c79356b 4835 }
1c79356b 4836
316670eb
A
4837 /*
4838 * The ipc_kmsg_t holds a reference to the label of a label
4839 * handle, not the port. We must get a reference to the port
4840 * and a send right to copyout to the receiver.
4841 */
1c79356b 4842
316670eb 4843 if (option & MACH_RCV_TRAILER_ELEMENTS (MACH_RCV_TRAILER_LABELS)) {
316670eb 4844 trailer->msgh_labels.sender = 0;
1c79356b 4845 }
1c79356b 4846
316670eb 4847done:
5ba3f43e
A
4848#ifdef __arm64__
4849 ipc_kmsg_munge_trailer(trailer, real_trailer_out, thread_is_64bit(thread));
4850#endif /* __arm64__ */
39236c6e 4851
316670eb 4852 return trailer->msgh_trailer_size;
1c79356b 4853}