]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/ipc_kmsg.c
xnu-1504.9.37.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_kmsg.c
1 /*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56 /*
57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
58 * support for mandatory and extensible security protections. This notice
59 * is included in support of clause 2.2 (b) of the Apple Public License,
60 * Version 2.0.
61 * Copyright (c) 2005 SPARTA, Inc.
62 */
63 /*
64 */
65 /*
66 * File: ipc/ipc_kmsg.c
67 * Author: Rich Draves
68 * Date: 1989
69 *
70 * Operations on kernel messages.
71 */
72
73 #include <norma_vm.h>
74
75 #include <mach/mach_types.h>
76 #include <mach/boolean.h>
77 #include <mach/kern_return.h>
78 #include <mach/message.h>
79 #include <mach/port.h>
80 #include <mach/vm_map.h>
81 #include <mach/mach_vm.h>
82 #include <mach/vm_statistics.h>
83
84 #include <kern/kern_types.h>
85 #include <kern/assert.h>
86 #include <kern/debug.h>
87 #include <kern/ipc_kobject.h>
88 #include <kern/kalloc.h>
89 #include <kern/zalloc.h>
90 #include <kern/processor.h>
91 #include <kern/thread.h>
92 #include <kern/sched_prim.h>
93 #include <kern/spl.h>
94 #include <kern/misc_protos.h>
95 #include <kern/counters.h>
96 #include <kern/cpu_data.h>
97
98 #include <machine/machlimits.h>
99
100 #include <vm/vm_map.h>
101 #include <vm/vm_object.h>
102 #include <vm/vm_kern.h>
103
104 #include <ipc/port.h>
105 #include <ipc/ipc_types.h>
106 #include <ipc/ipc_entry.h>
107 #include <ipc/ipc_kmsg.h>
108 #include <ipc/ipc_notify.h>
109 #include <ipc/ipc_object.h>
110 #include <ipc/ipc_space.h>
111 #include <ipc/ipc_port.h>
112 #include <ipc/ipc_right.h>
113 #include <ipc/ipc_hash.h>
114 #include <ipc/ipc_table.h>
115
116 #include <security/mac_mach_internal.h>
117
118 #include <string.h>
119
120 #ifdef ppc
121 #include <ppc/Firmware.h>
122 #include <ppc/low_trace.h>
123 #endif
124
125 #if DEBUG
126 #define DEBUG_MSGS_K64 1
127 #endif
128
129 #pragma pack(4)
130
131 typedef struct
132 {
133 mach_msg_bits_t msgh_bits;
134 mach_msg_size_t msgh_size;
135 uint32_t msgh_remote_port;
136 uint32_t msgh_local_port;
137 mach_msg_size_t msgh_reserved;
138 mach_msg_id_t msgh_id;
139 } mach_msg_legacy_header_t;
140
141 typedef struct
142 {
143 mach_msg_legacy_header_t header;
144 mach_msg_body_t body;
145 } mach_msg_legacy_base_t;
146
147 typedef struct
148 {
149 mach_port_name_t name;
150 mach_msg_size_t pad1;
151 uint32_t pad2 : 16;
152 mach_msg_type_name_t disposition : 8;
153 mach_msg_descriptor_type_t type : 8;
154 } mach_msg_legacy_port_descriptor_t;
155
156
157 typedef union
158 {
159 mach_msg_legacy_port_descriptor_t port;
160 mach_msg_ool_descriptor32_t out_of_line32;
161 mach_msg_ool_ports_descriptor32_t ool_ports32;
162 mach_msg_type_descriptor_t type;
163 } mach_msg_legacy_descriptor_t;
164
165 #pragma pack()
166
167 #define LEGACY_HEADER_SIZE_DELTA ((mach_msg_size_t)(sizeof(mach_msg_header_t) - sizeof(mach_msg_legacy_header_t)))
168 // END LP64 fixes
169
170
171 #if DEBUG_MSGS_K64
172 extern void ipc_pset_print64(
173 ipc_pset_t pset);
174
175 extern void ipc_kmsg_print64(
176 ipc_kmsg_t kmsg,
177 const char *str);
178
179 extern void ipc_msg_print64(
180 mach_msg_header_t *msgh);
181
182 extern ipc_port_t ipc_name_to_data64(
183 task_t task,
184 mach_port_name_t name);
185
186 /*
187 * Forward declarations
188 */
189 void ipc_msg_print_untyped64(
190 mach_msg_body_t *body);
191
192 const char * ipc_type_name64(
193 int type_name,
194 boolean_t received);
195
196 void ipc_print_type_name64(
197 int type_name);
198
199 const char *
200 msgh_bit_decode64(
201 mach_msg_bits_t bit);
202
203 const char *
204 mm_copy_options_string64(
205 mach_msg_copy_options_t option);
206
207 void db_print_msg_uid64(mach_msg_header_t *);
208
209 static void
210 ipc_msg_body_print64(void *body, int size)
211 {
212 uint32_t *word = (uint32_t *) body;
213 uint32_t *end = (uint32_t *)(((uintptr_t) body) + size
214 - sizeof(mach_msg_header_t));
215 int i;
216
217 kprintf(" body(%p-%p):\n %p: ", body, end, word);
218 for (;;) {
219 for (i = 0; i < 8; i++, word++) {
220 if (word >= end) {
221 kprintf("\n");
222 return;
223 }
224 kprintf("%08x ", *word);
225 }
226 kprintf("\n %p: ", word);
227 }
228 }
229
230
231 const char *
232 ipc_type_name64(
233 int type_name,
234 boolean_t received)
235 {
236 switch (type_name) {
237 case MACH_MSG_TYPE_PORT_NAME:
238 return "port_name";
239
240 case MACH_MSG_TYPE_MOVE_RECEIVE:
241 if (received) {
242 return "port_receive";
243 } else {
244 return "move_receive";
245 }
246
247 case MACH_MSG_TYPE_MOVE_SEND:
248 if (received) {
249 return "port_send";
250 } else {
251 return "move_send";
252 }
253
254 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
255 if (received) {
256 return "port_send_once";
257 } else {
258 return "move_send_once";
259 }
260
261 case MACH_MSG_TYPE_COPY_SEND:
262 return "copy_send";
263
264 case MACH_MSG_TYPE_MAKE_SEND:
265 return "make_send";
266
267 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
268 return "make_send_once";
269
270 default:
271 return (char *) 0;
272 }
273 }
274
275 void
276 ipc_print_type_name64(
277 int type_name)
278 {
279 const char *name = ipc_type_name64(type_name, TRUE);
280 if (name) {
281 kprintf("%s", name);
282 } else {
283 kprintf("type%d", type_name);
284 }
285 }
286
287 /*
288 * ipc_kmsg_print64 [ debug ]
289 */
290 void
291 ipc_kmsg_print64(
292 ipc_kmsg_t kmsg,
293 const char *str)
294 {
295 kprintf("%s kmsg=%p:\n", str, kmsg);
296 kprintf(" next=%p, prev=%p, size=%d",
297 kmsg->ikm_next,
298 kmsg->ikm_prev,
299 kmsg->ikm_size);
300 kprintf("\n");
301 ipc_msg_print64(kmsg->ikm_header);
302 }
303
304 const char *
305 msgh_bit_decode64(
306 mach_msg_bits_t bit)
307 {
308 switch (bit) {
309 case MACH_MSGH_BITS_COMPLEX: return "complex";
310 case MACH_MSGH_BITS_CIRCULAR: return "circular";
311 default: return (char *) 0;
312 }
313 }
314
315 /*
316 * ipc_msg_print64 [ debug ]
317 */
318 void
319 ipc_msg_print64(
320 mach_msg_header_t *msgh)
321 {
322 mach_msg_bits_t mbits;
323 unsigned int bit, i;
324 const char *bit_name;
325 int needs_comma;
326
327 mbits = msgh->msgh_bits;
328 kprintf(" msgh_bits=0x%x: l=0x%x,r=0x%x\n",
329 mbits,
330 MACH_MSGH_BITS_LOCAL(msgh->msgh_bits),
331 MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
332
333 mbits = MACH_MSGH_BITS_OTHER(mbits) & MACH_MSGH_BITS_USED;
334 kprintf(" decoded bits: ");
335 needs_comma = 0;
336 for (i = 0, bit = 1; i < sizeof(mbits) * 8; ++i, bit <<= 1) {
337 if ((mbits & bit) == 0)
338 continue;
339 bit_name = msgh_bit_decode64((mach_msg_bits_t)bit);
340 if (bit_name)
341 kprintf("%s%s", needs_comma ? "," : "", bit_name);
342 else
343 kprintf("%sunknown(0x%x),", needs_comma ? "," : "", bit);
344 ++needs_comma;
345 }
346 if (msgh->msgh_bits & ~MACH_MSGH_BITS_USED) {
347 kprintf("%sunused=0x%x,", needs_comma ? "," : "",
348 msgh->msgh_bits & ~MACH_MSGH_BITS_USED);
349 }
350 kprintf("\n");
351
352 needs_comma = 1;
353 if (msgh->msgh_remote_port) {
354 kprintf(" remote=%p(", msgh->msgh_remote_port);
355 ipc_print_type_name64(MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
356 kprintf(")");
357 } else {
358 kprintf(" remote=null");
359 }
360
361 if (msgh->msgh_local_port) {
362 kprintf("%slocal=%p(", needs_comma ? "," : "",
363 msgh->msgh_local_port);
364 ipc_print_type_name64(MACH_MSGH_BITS_LOCAL(msgh->msgh_bits));
365 kprintf(")\n");
366 } else {
367 kprintf("local=null\n");
368 }
369
370 kprintf(" msgh_id=%d, size=%d\n",
371 msgh->msgh_id,
372 msgh->msgh_size);
373
374 if (mbits & MACH_MSGH_BITS_COMPLEX) {
375 ipc_msg_print_untyped64((mach_msg_body_t *) (msgh + 1));
376 }
377
378 ipc_msg_body_print64((void *)(msgh + 1), msgh->msgh_size);
379 }
380
381
382 const char *
383 mm_copy_options_string64(
384 mach_msg_copy_options_t option)
385 {
386 const char *name;
387
388 switch (option) {
389 case MACH_MSG_PHYSICAL_COPY:
390 name = "PHYSICAL";
391 break;
392 case MACH_MSG_VIRTUAL_COPY:
393 name = "VIRTUAL";
394 break;
395 case MACH_MSG_OVERWRITE:
396 name = "OVERWRITE";
397 break;
398 case MACH_MSG_ALLOCATE:
399 name = "ALLOCATE";
400 break;
401 case MACH_MSG_KALLOC_COPY_T:
402 name = "KALLOC_COPY_T";
403 break;
404 default:
405 name = "unknown";
406 break;
407 }
408 return name;
409 }
410
411 void
412 ipc_msg_print_untyped64(
413 mach_msg_body_t *body)
414 {
415 mach_msg_descriptor_t *saddr, *send;
416 mach_msg_descriptor_type_t type;
417
418 kprintf(" %d descriptors: \n", body->msgh_descriptor_count);
419
420 saddr = (mach_msg_descriptor_t *) (body + 1);
421 send = saddr + body->msgh_descriptor_count;
422
423 for ( ; saddr < send; saddr++ ) {
424
425 type = saddr->type.type;
426
427 switch (type) {
428
429 case MACH_MSG_PORT_DESCRIPTOR: {
430 mach_msg_port_descriptor_t *dsc;
431
432 dsc = &saddr->port;
433 kprintf(" PORT name = %p disp = ", dsc->name);
434 ipc_print_type_name64(dsc->disposition);
435 kprintf("\n");
436 break;
437 }
438 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
439 case MACH_MSG_OOL_DESCRIPTOR: {
440 mach_msg_ool_descriptor_t *dsc;
441
442 dsc = (mach_msg_ool_descriptor_t *) &saddr->out_of_line;
443 kprintf(" OOL%s addr = %p size = 0x%x copy = %s %s\n",
444 type == MACH_MSG_OOL_DESCRIPTOR ? "" : " VOLATILE",
445 dsc->address, dsc->size,
446 mm_copy_options_string64(dsc->copy),
447 dsc->deallocate ? "DEALLOC" : "");
448 break;
449 }
450 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
451 mach_msg_ool_ports_descriptor_t *dsc;
452
453 dsc = (mach_msg_ool_ports_descriptor_t *) &saddr->ool_ports;
454
455 kprintf(" OOL_PORTS addr = %p count = 0x%x ",
456 dsc->address, dsc->count);
457 kprintf("disp = ");
458 ipc_print_type_name64(dsc->disposition);
459 kprintf(" copy = %s %s\n",
460 mm_copy_options_string64(dsc->copy),
461 dsc->deallocate ? "DEALLOC" : "");
462 break;
463 }
464
465 default: {
466 kprintf(" UNKNOWN DESCRIPTOR 0x%x\n", type);
467 break;
468 }
469 }
470 }
471 }
472
473 #define DEBUG_IPC_KMSG_PRINT(kmsg,string) \
474 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
475 ipc_kmsg_print64(kmsg, string); \
476 }
477 #define DEBUG_IPC_MSG_BODY_PRINT(body,size) \
478 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
479 ipc_msg_body_print64(body,size);\
480 }
481 #else /* !DEBUG_MSGS_K64 */
482 #define DEBUG_IPC_KMSG_PRINT(kmsg,string)
483 #define DEBUG_IPC_MSG_BODY_PRINT(body,size)
484 #endif /* !DEBUG_MSGS_K64 */
485
486 extern vm_map_t ipc_kernel_copy_map;
487 extern vm_size_t ipc_kmsg_max_vm_space;
488 extern vm_size_t msg_ool_size_small;
489
490 #define MSG_OOL_SIZE_SMALL msg_ool_size_small
491
492 #if defined(__LP64__)
493 #define MAP_SIZE_DIFFERS(map) (map->max_offset < MACH_VM_MAX_ADDRESS)
494 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor32_t
495 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor32_t
496 #else
497 #define MAP_SIZE_DIFFERS(map) (map->max_offset > VM_MAX_ADDRESS)
498 #define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor64_t
499 #define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor64_t
500 #endif
501
502 #define DESC_SIZE_ADJUSTMENT ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
503 sizeof(mach_msg_ool_descriptor32_t)))
504
505 /* scatter list macros */
506
507 #define SKIP_PORT_DESCRIPTORS(s, c) \
508 MACRO_BEGIN \
509 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
510 while ((c) > 0) { \
511 if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
512 break; \
513 (s)++; (c)--; \
514 } \
515 if (c == 0) \
516 (s) = MACH_MSG_DESCRIPTOR_NULL; \
517 } \
518 MACRO_END
519
520 #define INCREMENT_SCATTER(s, c, d) \
521 MACRO_BEGIN \
522 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
523 s = (d) ? (mach_msg_descriptor_t *) \
524 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) : \
525 (s + 1); \
526 (c)--; \
527 } \
528 MACRO_END
529
530 /* zone for cached ipc_kmsg_t structures */
531 zone_t ipc_kmsg_zone;
532
533 /*
534 * Forward declarations
535 */
536
537 void ipc_kmsg_clean(
538 ipc_kmsg_t kmsg);
539
540 void ipc_kmsg_clean_body(
541 ipc_kmsg_t kmsg,
542 mach_msg_type_number_t number,
543 mach_msg_descriptor_t *desc);
544
545 void ipc_kmsg_clean_partial(
546 ipc_kmsg_t kmsg,
547 mach_msg_type_number_t number,
548 mach_msg_descriptor_t *desc,
549 vm_offset_t paddr,
550 vm_size_t length);
551
552 mach_msg_return_t ipc_kmsg_copyin_body(
553 ipc_kmsg_t kmsg,
554 ipc_space_t space,
555 vm_map_t map);
556
557 /*
558 * We keep a per-processor cache of kernel message buffers.
559 * The cache saves the overhead/locking of using kalloc/kfree.
560 * The per-processor cache seems to miss less than a per-thread cache,
561 * and it also uses less memory. Access to the cache doesn't
562 * require locking.
563 */
564
565 /*
566 * Routine: ipc_kmsg_alloc
567 * Purpose:
568 * Allocate a kernel message structure. If we can get one from
569 * the cache, that is best. Otherwise, allocate a new one.
570 * Conditions:
571 * Nothing locked.
572 */
573 ipc_kmsg_t
574 ipc_kmsg_alloc(
575 mach_msg_size_t msg_and_trailer_size)
576 {
577 mach_msg_size_t max_expanded_size;
578 ipc_kmsg_t kmsg;
579
580 /*
581 * LP64support -
582 * Pad the allocation in case we need to expand the
583 * message descrptors for user spaces with pointers larger than
584 * the kernel's own, or vice versa. We don't know how many descriptors
585 * there are yet, so just assume the whole body could be
586 * descriptors (if there could be any at all).
587 *
588 * The expansion space is left in front of the header,
589 * because it is easier to pull the header and descriptors
590 * forward as we process them than it is to push all the
591 * data backwards.
592 */
593 mach_msg_size_t size = msg_and_trailer_size - MAX_TRAILER_SIZE;
594 if (size > sizeof(mach_msg_base_t)) {
595 mach_msg_size_t max_desc = (mach_msg_size_t)(((size - sizeof(mach_msg_base_t)) /
596 sizeof(mach_msg_ool_descriptor32_t)) *
597 DESC_SIZE_ADJUSTMENT);
598 if (msg_and_trailer_size > MACH_MSG_SIZE_MAX - max_desc)
599 return IKM_NULL;
600
601 max_expanded_size = msg_and_trailer_size + max_desc;
602 } else
603 max_expanded_size = msg_and_trailer_size;
604
605 if (max_expanded_size > ikm_less_overhead(MACH_MSG_SIZE_MAX))
606 return IKM_NULL;
607 else if (max_expanded_size < IKM_SAVED_MSG_SIZE)
608 max_expanded_size = IKM_SAVED_MSG_SIZE; /* round up for ikm_cache */
609
610 if (max_expanded_size == IKM_SAVED_MSG_SIZE) {
611 struct ikm_cache *cache;
612 unsigned int i;
613
614 disable_preemption();
615 cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
616 if ((i = cache->avail) > 0) {
617 assert(i <= IKM_STASH);
618 kmsg = cache->entries[--i];
619 cache->avail = i;
620 enable_preemption();
621 ikm_check_init(kmsg, max_expanded_size);
622 ikm_set_header(kmsg, msg_and_trailer_size);
623 return (kmsg);
624 }
625 enable_preemption();
626 kmsg = (ipc_kmsg_t)zalloc(ipc_kmsg_zone);
627 } else {
628 kmsg = (ipc_kmsg_t)kalloc(ikm_plus_overhead(max_expanded_size));
629 }
630
631 if (kmsg != IKM_NULL) {
632 ikm_init(kmsg, max_expanded_size);
633 ikm_set_header(kmsg, msg_and_trailer_size);
634 }
635
636 return(kmsg);
637 }
638
639 /*
640 * Routine: ipc_kmsg_free
641 * Purpose:
642 * Free a kernel message buffer. If the kms is preallocated
643 * to a port, just "put it back (marked unused)." We have to
644 * do this with the port locked. The port may have its hold
645 * on our message released. In that case, we have to just
646 * revert the message to a traditional one and free it normally.
647 * Conditions:
648 * Nothing locked.
649 */
650
651 void
652 ipc_kmsg_free(
653 ipc_kmsg_t kmsg)
654 {
655 mach_msg_size_t size = kmsg->ikm_size;
656 ipc_port_t port;
657
658 #if CONFIG_MACF_MACH
659 if (kmsg->ikm_sender != NULL) {
660 task_deallocate(kmsg->ikm_sender);
661 kmsg->ikm_sender = NULL;
662 }
663 #endif
664
665 /*
666 * Check to see if the message is bound to the port. If so,
667 * mark it not in use. If the port isn't already dead, then
668 * leave the message associated with it. Otherwise, free it.
669 */
670 port = ikm_prealloc_inuse_port(kmsg);
671 if (port != IP_NULL) {
672 ip_lock(port);
673 ikm_prealloc_clear_inuse(kmsg, port);
674 if (ip_active(port) && (port->ip_premsg == kmsg)) {
675 assert(IP_PREALLOC(port));
676 ip_unlock(port);
677 return;
678 }
679 ip_check_unlock(port); /* May be last reference */
680 }
681
682 /*
683 * Peek and see if it has to go back in the cache.
684 */
685 if (kmsg->ikm_size == IKM_SAVED_MSG_SIZE) {
686 struct ikm_cache *cache;
687 unsigned int i;
688
689 disable_preemption();
690 cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
691 if ((i = cache->avail) < IKM_STASH) {
692 cache->entries[i] = kmsg;
693 cache->avail = i + 1;
694 enable_preemption();
695 return;
696 }
697 enable_preemption();
698 zfree(ipc_kmsg_zone, kmsg);
699 return;
700 }
701 kfree(kmsg, ikm_plus_overhead(size));
702 }
703
704
705 /*
706 * Routine: ipc_kmsg_enqueue
707 * Purpose:
708 * Enqueue a kmsg.
709 */
710
711 void
712 ipc_kmsg_enqueue(
713 ipc_kmsg_queue_t queue,
714 ipc_kmsg_t kmsg)
715 {
716 ipc_kmsg_enqueue_macro(queue, kmsg);
717 }
718
719 /*
720 * Routine: ipc_kmsg_dequeue
721 * Purpose:
722 * Dequeue and return a kmsg.
723 */
724
725 ipc_kmsg_t
726 ipc_kmsg_dequeue(
727 ipc_kmsg_queue_t queue)
728 {
729 ipc_kmsg_t first;
730
731 first = ipc_kmsg_queue_first(queue);
732
733 if (first != IKM_NULL)
734 ipc_kmsg_rmqueue_first_macro(queue, first);
735
736 return first;
737 }
738
739 /*
740 * Routine: ipc_kmsg_rmqueue
741 * Purpose:
742 * Pull a kmsg out of a queue.
743 */
744
745 void
746 ipc_kmsg_rmqueue(
747 ipc_kmsg_queue_t queue,
748 ipc_kmsg_t kmsg)
749 {
750 ipc_kmsg_t next, prev;
751
752 assert(queue->ikmq_base != IKM_NULL);
753
754 next = kmsg->ikm_next;
755 prev = kmsg->ikm_prev;
756
757 if (next == kmsg) {
758 assert(prev == kmsg);
759 assert(queue->ikmq_base == kmsg);
760
761 queue->ikmq_base = IKM_NULL;
762 } else {
763 if (queue->ikmq_base == kmsg)
764 queue->ikmq_base = next;
765
766 next->ikm_prev = prev;
767 prev->ikm_next = next;
768 }
769 /* XXX Temporary debug logic */
770 assert((kmsg->ikm_next = IKM_BOGUS) == IKM_BOGUS);
771 assert((kmsg->ikm_prev = IKM_BOGUS) == IKM_BOGUS);
772 }
773
774 /*
775 * Routine: ipc_kmsg_queue_next
776 * Purpose:
777 * Return the kmsg following the given kmsg.
778 * (Or IKM_NULL if it is the last one in the queue.)
779 */
780
781 ipc_kmsg_t
782 ipc_kmsg_queue_next(
783 ipc_kmsg_queue_t queue,
784 ipc_kmsg_t kmsg)
785 {
786 ipc_kmsg_t next;
787
788 assert(queue->ikmq_base != IKM_NULL);
789
790 next = kmsg->ikm_next;
791 if (queue->ikmq_base == next)
792 next = IKM_NULL;
793
794 return next;
795 }
796
797 /*
798 * Routine: ipc_kmsg_destroy
799 * Purpose:
800 * Destroys a kernel message. Releases all rights,
801 * references, and memory held by the message.
802 * Frees the message.
803 * Conditions:
804 * No locks held.
805 */
806
807 void
808 ipc_kmsg_destroy(
809 ipc_kmsg_t kmsg)
810 {
811 ipc_kmsg_queue_t queue;
812 boolean_t empty;
813
814 /*
815 * ipc_kmsg_clean can cause more messages to be destroyed.
816 * Curtail recursion by queueing messages. If a message
817 * is already queued, then this is a recursive call.
818 */
819
820 queue = &(current_thread()->ith_messages);
821 empty = ipc_kmsg_queue_empty(queue);
822 ipc_kmsg_enqueue(queue, kmsg);
823
824 if (empty) {
825 /* must leave kmsg in queue while cleaning it */
826
827 while ((kmsg = ipc_kmsg_queue_first(queue)) != IKM_NULL) {
828 ipc_kmsg_clean(kmsg);
829 ipc_kmsg_rmqueue(queue, kmsg);
830 ipc_kmsg_free(kmsg);
831 }
832 }
833 }
834
835 /*
836 * Routine: ipc_kmsg_destroy_dest
837 * Purpose:
838 * Destroys a kernel message. Releases all rights,
839 * references, and memory held by the message (including
840 * the destination port reference.
841 * Frees the message.
842 * Conditions:
843 * No locks held.
844 */
845 void
846 ipc_kmsg_destroy_dest(
847 ipc_kmsg_t kmsg)
848 {
849 ipc_port_t port;
850
851 port = kmsg->ikm_header->msgh_remote_port;
852
853 ipc_port_release(port);
854 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
855 ipc_kmsg_destroy(kmsg);
856 }
857
858 /*
859 * Routine: ipc_kmsg_clean_body
860 * Purpose:
861 * Cleans the body of a kernel message.
862 * Releases all rights, references, and memory.
863 *
864 * Conditions:
865 * No locks held.
866 */
867
868 void
869 ipc_kmsg_clean_body(
870 __unused ipc_kmsg_t kmsg,
871 mach_msg_type_number_t number,
872 mach_msg_descriptor_t *saddr)
873 {
874 mach_msg_type_number_t i;
875
876 if ( number == 0 )
877 return;
878
879 for (i = 0 ; i < number; i++, saddr++ ) {
880
881 switch (saddr->type.type) {
882
883 case MACH_MSG_PORT_DESCRIPTOR: {
884 mach_msg_port_descriptor_t *dsc;
885
886 dsc = &saddr->port;
887
888 /*
889 * Destroy port rights carried in the message
890 */
891 if (!IO_VALID((ipc_object_t) dsc->name))
892 continue;
893 ipc_object_destroy((ipc_object_t) dsc->name, dsc->disposition);
894 break;
895 }
896 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
897 case MACH_MSG_OOL_DESCRIPTOR : {
898 mach_msg_ool_descriptor_t *dsc;
899
900 dsc = (mach_msg_ool_descriptor_t *)&saddr->out_of_line;
901
902 /*
903 * Destroy memory carried in the message
904 */
905 if (dsc->size == 0) {
906 assert(dsc->address == (void *) 0);
907 } else {
908 vm_map_copy_discard((vm_map_copy_t) dsc->address);
909 }
910 break;
911 }
912 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
913 ipc_object_t *objects;
914 mach_msg_type_number_t j;
915 mach_msg_ool_ports_descriptor_t *dsc;
916
917 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
918 objects = (ipc_object_t *) dsc->address;
919
920 if (dsc->count == 0) {
921 break;
922 }
923
924 assert(objects != (ipc_object_t *) 0);
925
926 /* destroy port rights carried in the message */
927
928 for (j = 0; j < dsc->count; j++) {
929 ipc_object_t object = objects[j];
930
931 if (!IO_VALID(object))
932 continue;
933
934 ipc_object_destroy(object, dsc->disposition);
935 }
936
937 /* destroy memory carried in the message */
938
939 assert(dsc->count != 0);
940
941 kfree(dsc->address,
942 (vm_size_t) dsc->count * sizeof(mach_port_t));
943 break;
944 }
945 default : {
946 printf("cleanup: don't understand this type of descriptor\n");
947 }
948 }
949 }
950 }
951
952 /*
953 * Routine: ipc_kmsg_clean_partial
954 * Purpose:
955 * Cleans a partially-acquired kernel message.
956 * number is the index of the type descriptor
957 * in the body of the message that contained the error.
958 * If dolast, the memory and port rights in this last
959 * type spec are also cleaned. In that case, number
960 * specifies the number of port rights to clean.
961 * Conditions:
962 * Nothing locked.
963 */
964
965 void
966 ipc_kmsg_clean_partial(
967 ipc_kmsg_t kmsg,
968 mach_msg_type_number_t number,
969 mach_msg_descriptor_t *desc,
970 vm_offset_t paddr,
971 vm_size_t length)
972 {
973 ipc_object_t object;
974 mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
975
976 object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
977 assert(IO_VALID(object));
978 ipc_object_destroy(object, MACH_MSGH_BITS_REMOTE(mbits));
979
980 object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
981 if (IO_VALID(object))
982 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
983
984 if (paddr) {
985 (void) vm_deallocate(ipc_kernel_copy_map, paddr, length);
986 }
987
988 ipc_kmsg_clean_body(kmsg, number, desc);
989 }
990
991 /*
992 * Routine: ipc_kmsg_clean
993 * Purpose:
994 * Cleans a kernel message. Releases all rights,
995 * references, and memory held by the message.
996 * Conditions:
997 * No locks held.
998 */
999
1000 void
1001 ipc_kmsg_clean(
1002 ipc_kmsg_t kmsg)
1003 {
1004 ipc_object_t object;
1005 mach_msg_bits_t mbits;
1006
1007 mbits = kmsg->ikm_header->msgh_bits;
1008 object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
1009 if (IO_VALID(object))
1010 ipc_object_destroy(object, MACH_MSGH_BITS_REMOTE(mbits));
1011
1012 object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1013 if (IO_VALID(object))
1014 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
1015
1016 if (mbits & MACH_MSGH_BITS_COMPLEX) {
1017 mach_msg_body_t *body;
1018
1019 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
1020 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count,
1021 (mach_msg_descriptor_t *)(body + 1));
1022 }
1023
1024 #if CONFIG_MACF_MACH
1025 if (kmsg->ikm_sender != NULL) {
1026 task_deallocate(kmsg->ikm_sender);
1027 kmsg->ikm_sender = NULL;
1028 }
1029 #endif
1030 }
1031
1032 /*
1033 * Routine: ipc_kmsg_set_prealloc
1034 * Purpose:
1035 * Assign a kmsg as a preallocated message buffer to a port.
1036 * Conditions:
1037 * port locked.
1038 */
1039
1040 void
1041 ipc_kmsg_set_prealloc(
1042 ipc_kmsg_t kmsg,
1043 ipc_port_t port)
1044 {
1045 assert(kmsg->ikm_prealloc == IP_NULL);
1046
1047 kmsg->ikm_prealloc = IP_NULL;
1048 IP_SET_PREALLOC(port, kmsg);
1049 }
1050
1051 /*
1052 * Routine: ipc_kmsg_clear_prealloc
1053 * Purpose:
1054 * Release the Assignment of a preallocated message buffer from a port.
1055 * Conditions:
1056 * port locked.
1057 */
1058 void
1059 ipc_kmsg_clear_prealloc(
1060 ipc_kmsg_t kmsg,
1061 ipc_port_t port)
1062 {
1063 assert(kmsg->ikm_prealloc == port);
1064
1065 kmsg->ikm_prealloc = IP_NULL;
1066 IP_CLEAR_PREALLOC(port, kmsg);
1067 }
1068
1069 /*
1070 * Routine: ipc_kmsg_prealloc
1071 * Purpose:
1072 * Wraper to ipc_kmsg_alloc() to account for
1073 * header expansion requirements.
1074 */
1075 ipc_kmsg_t
1076 ipc_kmsg_prealloc(mach_msg_size_t size)
1077 {
1078 #if defined(__LP64__)
1079 if (size > MACH_MSG_SIZE_MAX - LEGACY_HEADER_SIZE_DELTA)
1080 return IKM_NULL;
1081
1082 size += LEGACY_HEADER_SIZE_DELTA;
1083 #endif
1084 return ipc_kmsg_alloc(size);
1085 }
1086
1087
1088 /*
1089 * Routine: ipc_kmsg_get
1090 * Purpose:
1091 * Allocates a kernel message buffer.
1092 * Copies a user message to the message buffer.
1093 * Conditions:
1094 * Nothing locked.
1095 * Returns:
1096 * MACH_MSG_SUCCESS Acquired a message buffer.
1097 * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
1098 * MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
1099 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1100 * MACH_SEND_INVALID_DATA Couldn't copy message data.
1101 */
1102
1103 mach_msg_return_t
1104 ipc_kmsg_get(
1105 mach_vm_address_t msg_addr,
1106 mach_msg_size_t size,
1107 ipc_kmsg_t *kmsgp)
1108 {
1109 mach_msg_size_t msg_and_trailer_size;
1110 ipc_kmsg_t kmsg;
1111 mach_msg_max_trailer_t *trailer;
1112 mach_msg_legacy_base_t legacy_base;
1113 mach_msg_size_t len_copied;
1114 legacy_base.body.msgh_descriptor_count = 0;
1115
1116 if ((size < sizeof(mach_msg_legacy_header_t)) || (size & 3))
1117 return MACH_SEND_MSG_TOO_SMALL;
1118
1119 if (size > MACH_MSG_SIZE_MAX - MAX_TRAILER_SIZE)
1120 return MACH_SEND_TOO_LARGE;
1121
1122 if(size == sizeof(mach_msg_legacy_header_t))
1123 len_copied = sizeof(mach_msg_legacy_header_t);
1124 else
1125 len_copied = sizeof(mach_msg_legacy_base_t);
1126
1127 if (copyinmsg(msg_addr, (char *)&legacy_base, len_copied))
1128 return MACH_SEND_INVALID_DATA;
1129
1130 msg_addr += sizeof(legacy_base.header);
1131 #if defined(__LP64__)
1132 size += LEGACY_HEADER_SIZE_DELTA;
1133 #endif
1134 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
1135 unsigned int j;
1136 for (j=0; j<sizeof(legacy_base.header); j++) {
1137 kprintf("%02x\n", ((unsigned char*)&legacy_base.header)[j]);
1138 }
1139 }
1140
1141 msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1142 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1143 if (kmsg == IKM_NULL)
1144 return MACH_SEND_NO_BUFFER;
1145
1146 kmsg->ikm_header->msgh_size = size;
1147 kmsg->ikm_header->msgh_bits = legacy_base.header.msgh_bits;
1148 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_remote_port);
1149 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_local_port);
1150 kmsg->ikm_header->msgh_reserved = legacy_base.header.msgh_reserved;
1151 kmsg->ikm_header->msgh_id = legacy_base.header.msgh_id;
1152
1153 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
1154 " size: 0x%.8x\n"
1155 " bits: 0x%.8x\n"
1156 " remote_port: %p\n"
1157 " local_port: %p\n"
1158 " reserved: 0x%.8x\n"
1159 " id: %.8d\n",
1160 kmsg->ikm_header->msgh_size,
1161 kmsg->ikm_header->msgh_bits,
1162 kmsg->ikm_header->msgh_remote_port,
1163 kmsg->ikm_header->msgh_local_port,
1164 kmsg->ikm_header->msgh_reserved,
1165 kmsg->ikm_header->msgh_id);
1166
1167 if (copyinmsg(msg_addr, (char *)(kmsg->ikm_header + 1), size - (mach_msg_size_t)sizeof(mach_msg_header_t))) {
1168 ipc_kmsg_free(kmsg);
1169 return MACH_SEND_INVALID_DATA;
1170 }
1171
1172 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
1173 {
1174 kprintf("body: size: %lu\n", (size - sizeof(mach_msg_header_t)));
1175 uint32_t i;
1176 for(i=0;i*4 < (size - sizeof(mach_msg_header_t));i++)
1177 {
1178 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
1179 }
1180 }
1181 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_get()");
1182
1183 /*
1184 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1185 * However, the internal size field of the trailer (msgh_trailer_size)
1186 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
1187 * the cases where no implicit data is requested.
1188 */
1189 trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
1190 trailer->msgh_sender = current_thread()->task->sec_token;
1191 trailer->msgh_audit = current_thread()->task->audit_token;
1192 trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1193 trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
1194
1195 #ifdef ppc
1196 if(trcWork.traceMask) dbgTrace(0x1100, (unsigned int)kmsg->ikm_header->msgh_id,
1197 (unsigned int)kmsg->ikm_header->msgh_remote_port,
1198 (unsigned int)kmsg->ikm_header->msgh_local_port, 0);
1199 #endif
1200
1201 #if CONFIG_MACF_MACH
1202 /* XXX - why do we zero sender labels here instead of in mach_msg()? */
1203 task_t cur = current_task();
1204 if (cur) {
1205 task_reference(cur);
1206 kmsg->ikm_sender = cur;
1207 } else
1208 trailer->msgh_labels.sender = 0;
1209 #else
1210 trailer->msgh_labels.sender = 0;
1211 #endif
1212
1213 *kmsgp = kmsg;
1214 return MACH_MSG_SUCCESS;
1215 }
1216
1217 /*
1218 * Routine: ipc_kmsg_get_from_kernel
1219 * Purpose:
1220 * First checks for a preallocated message
1221 * reserved for kernel clients. If not found -
1222 * allocates a new kernel message buffer.
1223 * Copies a kernel message to the message buffer.
1224 * Only resource errors are allowed.
1225 * Conditions:
1226 * Nothing locked.
1227 * Ports in header are ipc_port_t.
1228 * Returns:
1229 * MACH_MSG_SUCCESS Acquired a message buffer.
1230 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1231 */
1232
1233 mach_msg_return_t
1234 ipc_kmsg_get_from_kernel(
1235 mach_msg_header_t *msg,
1236 mach_msg_size_t size,
1237 ipc_kmsg_t *kmsgp)
1238 {
1239 ipc_kmsg_t kmsg;
1240 mach_msg_size_t msg_and_trailer_size;
1241 mach_msg_max_trailer_t *trailer;
1242 ipc_port_t dest_port;
1243
1244 assert(size >= sizeof(mach_msg_header_t));
1245 // assert((size & 3) == 0);
1246
1247 assert(IP_VALID((ipc_port_t) msg->msgh_remote_port));
1248 dest_port = (ipc_port_t)msg->msgh_remote_port;
1249
1250 msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1251
1252 /*
1253 * See if the port has a pre-allocated kmsg for kernel
1254 * clients. These are set up for those kernel clients
1255 * which cannot afford to wait.
1256 */
1257 if (IP_PREALLOC(dest_port)) {
1258 mach_msg_size_t max_desc = 0;
1259
1260 ip_lock(dest_port);
1261 if (!ip_active(dest_port)) {
1262 ip_unlock(dest_port);
1263 return MACH_SEND_NO_BUFFER;
1264 }
1265 assert(IP_PREALLOC(dest_port));
1266 kmsg = dest_port->ip_premsg;
1267 if (ikm_prealloc_inuse(kmsg)) {
1268 ip_unlock(dest_port);
1269 return MACH_SEND_NO_BUFFER;
1270 }
1271 #if !defined(__LP64__)
1272 if (msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
1273 assert(size > sizeof(mach_msg_base_t));
1274 max_desc = ((mach_msg_base_t *)msg)->body.msgh_descriptor_count *
1275 DESC_SIZE_ADJUSTMENT;
1276 }
1277 #endif
1278 if (msg_and_trailer_size > kmsg->ikm_size - max_desc) {
1279 ip_unlock(dest_port);
1280 return MACH_SEND_TOO_LARGE;
1281 }
1282 ikm_prealloc_set_inuse(kmsg, dest_port);
1283 ikm_set_header(kmsg, msg_and_trailer_size);
1284 ip_unlock(dest_port);
1285 }
1286 else
1287 {
1288 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1289 if (kmsg == IKM_NULL)
1290 return MACH_SEND_NO_BUFFER;
1291 }
1292
1293 (void) memcpy((void *) kmsg->ikm_header, (const void *) msg, size);
1294
1295 kmsg->ikm_header->msgh_size = size;
1296
1297 /*
1298 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1299 * However, the internal size field of the trailer (msgh_trailer_size)
1300 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
1301 * optimize the cases where no implicit data is requested.
1302 */
1303 trailer = (mach_msg_max_trailer_t *)
1304 ((vm_offset_t)kmsg->ikm_header + size);
1305 trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
1306 trailer->msgh_audit = KERNEL_AUDIT_TOKEN;
1307 trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1308 trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
1309
1310 trailer->msgh_labels.sender = 0;
1311
1312 #if CONFIG_MACF_MACH
1313 kmsg->ikm_sender = NULL;
1314 #endif
1315 *kmsgp = kmsg;
1316 return MACH_MSG_SUCCESS;
1317 }
1318
1319 /*
1320 * Routine: ipc_kmsg_send
1321 * Purpose:
1322 * Send a message. The message holds a reference
1323 * for the destination port in the msgh_remote_port field.
1324 *
1325 * If unsuccessful, the caller still has possession of
1326 * the message and must do something with it. If successful,
1327 * the message is queued, given to a receiver, destroyed,
1328 * or handled directly by the kernel via mach_msg.
1329 * Conditions:
1330 * Nothing locked.
1331 * Returns:
1332 * MACH_MSG_SUCCESS The message was accepted.
1333 * MACH_SEND_TIMED_OUT Caller still has message.
1334 * MACH_SEND_INTERRUPTED Caller still has message.
1335 */
1336 mach_msg_return_t
1337 ipc_kmsg_send(
1338 ipc_kmsg_t kmsg,
1339 mach_msg_option_t option,
1340 mach_msg_timeout_t send_timeout)
1341 {
1342 ipc_port_t port;
1343 mach_msg_return_t error = MACH_MSG_SUCCESS;
1344 spl_t s;
1345
1346 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1347 assert(IP_VALID(port));
1348
1349 if ((option & ~(MACH_SEND_TIMEOUT|MACH_SEND_ALWAYS)) != 0)
1350 printf("ipc_kmsg_send: bad option 0x%x\n", option);
1351
1352 ip_lock(port);
1353
1354 if (port->ip_receiver == ipc_space_kernel) {
1355
1356 /*
1357 * We can check ip_receiver == ipc_space_kernel
1358 * before checking that the port is active because
1359 * ipc_port_dealloc_kernel clears ip_receiver
1360 * before destroying a kernel port.
1361 */
1362 assert(ip_active(port));
1363 port->ip_messages.imq_seqno++;
1364 ip_unlock(port);
1365
1366 current_task()->messages_sent++;
1367
1368 /*
1369 * Call the server routine, and get the reply message to send.
1370 */
1371 kmsg = ipc_kobject_server(kmsg);
1372 if (kmsg == IKM_NULL)
1373 return MACH_MSG_SUCCESS;
1374
1375 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1376 assert(IP_VALID(port));
1377 ip_lock(port);
1378 /* fall thru with reply - same options */
1379 }
1380
1381 /*
1382 * Can't deliver to a dead port.
1383 * However, we can pretend it got sent
1384 * and was then immediately destroyed.
1385 */
1386 if (!ip_active(port)) {
1387 /*
1388 * We can't let ipc_kmsg_destroy deallocate
1389 * the port right, because we might end up
1390 * in an infinite loop trying to deliver
1391 * a send-once notification.
1392 */
1393
1394 ip_release(port);
1395 ip_check_unlock(port);
1396 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1397 ipc_kmsg_destroy(kmsg);
1398 return MACH_MSG_SUCCESS;
1399 }
1400
1401 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_CIRCULAR) {
1402 ip_unlock(port);
1403
1404 /* don't allow the creation of a circular loop */
1405
1406 ipc_kmsg_destroy(kmsg);
1407 return MACH_MSG_SUCCESS;
1408 }
1409
1410 /*
1411 * We have a valid message and a valid reference on the port.
1412 * we can unlock the port and call mqueue_send() on its message
1413 * queue. Lock message queue while port is locked.
1414 */
1415 s = splsched();
1416 imq_lock(&port->ip_messages);
1417 ip_unlock(port);
1418 error = ipc_mqueue_send(&port->ip_messages, kmsg, option,
1419 send_timeout, s);
1420
1421 /*
1422 * If the port has been destroyed while we wait, treat the message
1423 * as a successful delivery (like we do for an inactive port).
1424 */
1425 if (error == MACH_SEND_INVALID_DEST) {
1426 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1427 ipc_kmsg_destroy(kmsg);
1428 return MACH_MSG_SUCCESS;
1429 }
1430 return error;
1431 }
1432
1433 /*
1434 * Routine: ipc_kmsg_put
1435 * Purpose:
1436 * Copies a message buffer to a user message.
1437 * Copies only the specified number of bytes.
1438 * Frees the message buffer.
1439 * Conditions:
1440 * Nothing locked. The message buffer must have clean
1441 * header fields.
1442 * Returns:
1443 * MACH_MSG_SUCCESS Copied data out of message buffer.
1444 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
1445 */
1446
1447 mach_msg_return_t
1448 ipc_kmsg_put(
1449 mach_vm_address_t msg_addr,
1450 ipc_kmsg_t kmsg,
1451 mach_msg_size_t size)
1452 {
1453 mach_msg_return_t mr;
1454
1455 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_put()");
1456
1457
1458 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
1459 " size: 0x%.8x\n"
1460 " bits: 0x%.8x\n"
1461 " remote_port: %p\n"
1462 " local_port: %p\n"
1463 " reserved: 0x%.8x\n"
1464 " id: %.8d\n",
1465 kmsg->ikm_header->msgh_size,
1466 kmsg->ikm_header->msgh_bits,
1467 kmsg->ikm_header->msgh_remote_port,
1468 kmsg->ikm_header->msgh_local_port,
1469 kmsg->ikm_header->msgh_reserved,
1470 kmsg->ikm_header->msgh_id);
1471
1472 #if defined(__LP64__)
1473 if (current_task() != kernel_task) { /* don't if receiver expects fully-cooked in-kernel msg; ux_exception */
1474 mach_msg_legacy_header_t *legacy_header =
1475 (mach_msg_legacy_header_t *)((vm_offset_t)(kmsg->ikm_header) + LEGACY_HEADER_SIZE_DELTA);
1476
1477 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
1478 mach_msg_size_t msg_size = kmsg->ikm_header->msgh_size;
1479 mach_port_name_t remote_port = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_remote_port);
1480 mach_port_name_t local_port = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_local_port);
1481 mach_msg_size_t reserved = kmsg->ikm_header->msgh_reserved;
1482 mach_msg_id_t id = kmsg->ikm_header->msgh_id;
1483
1484 legacy_header->msgh_id = id;
1485 legacy_header->msgh_reserved = reserved;
1486 legacy_header->msgh_local_port = local_port;
1487 legacy_header->msgh_remote_port = remote_port;
1488 legacy_header->msgh_size = msg_size - LEGACY_HEADER_SIZE_DELTA;
1489 legacy_header->msgh_bits = bits;
1490
1491 size -= LEGACY_HEADER_SIZE_DELTA;
1492 kmsg->ikm_header = (mach_msg_header_t *)legacy_header;
1493 }
1494 #endif
1495
1496 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
1497 kprintf("ipc_kmsg_put header+body: %d\n", (size));
1498 uint32_t i;
1499 for(i=0;i*4 < size;i++)
1500 {
1501 kprintf("%.4x\n",((uint32_t *)kmsg->ikm_header)[i]);
1502 }
1503 kprintf("type: %d\n", ((mach_msg_type_descriptor_t *)(((mach_msg_base_t *)kmsg->ikm_header)+1))->type);
1504 }
1505 if (copyoutmsg((const char *) kmsg->ikm_header, msg_addr, size))
1506 mr = MACH_RCV_INVALID_DATA;
1507 else
1508 mr = MACH_MSG_SUCCESS;
1509
1510 ipc_kmsg_free(kmsg);
1511 return mr;
1512 }
1513
1514 /*
1515 * Routine: ipc_kmsg_put_to_kernel
1516 * Purpose:
1517 * Copies a message buffer to a kernel message.
1518 * Frees the message buffer.
1519 * No errors allowed.
1520 * Conditions:
1521 * Nothing locked.
1522 */
1523
1524 void
1525 ipc_kmsg_put_to_kernel(
1526 mach_msg_header_t *msg,
1527 ipc_kmsg_t kmsg,
1528 mach_msg_size_t size)
1529 {
1530 (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, size);
1531
1532 ipc_kmsg_free(kmsg);
1533 }
1534
1535 /*
1536 * Routine: ipc_kmsg_copyin_header
1537 * Purpose:
1538 * "Copy-in" port rights in the header of a message.
1539 * Operates atomically; if it doesn't succeed the
1540 * message header and the space are left untouched.
1541 * If it does succeed the remote/local port fields
1542 * contain object pointers instead of port names,
1543 * and the bits field is updated. The destination port
1544 * will be a valid port pointer.
1545 *
1546 * The notify argument implements the MACH_SEND_CANCEL option.
1547 * If it is not MACH_PORT_NULL, it should name a receive right.
1548 * If the processing of the destination port would generate
1549 * a port-deleted notification (because the right for the
1550 * destination port is destroyed and it had a request for
1551 * a dead-name notification registered), and the port-deleted
1552 * notification would be sent to the named receive right,
1553 * then it isn't sent and the send-once right for the notify
1554 * port is quietly destroyed.
1555 *
1556 * Conditions:
1557 * Nothing locked.
1558 * Returns:
1559 * MACH_MSG_SUCCESS Successful copyin.
1560 * MACH_SEND_INVALID_HEADER
1561 * Illegal value in the message header bits.
1562 * MACH_SEND_INVALID_DEST The space is dead.
1563 * MACH_SEND_INVALID_NOTIFY
1564 * Notify is non-null and doesn't name a receive right.
1565 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1566 * MACH_SEND_INVALID_DEST Can't copyin destination port.
1567 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1568 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
1569 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1570 */
1571
1572 mach_msg_return_t
1573 ipc_kmsg_copyin_header(
1574 mach_msg_header_t *msg,
1575 ipc_space_t space,
1576 mach_port_name_t notify)
1577 {
1578 mach_msg_bits_t mbits = msg->msgh_bits & MACH_MSGH_BITS_USER;
1579 mach_port_name_t dest_name = CAST_MACH_PORT_TO_NAME(msg->msgh_remote_port);
1580 mach_port_name_t reply_name = CAST_MACH_PORT_TO_NAME(msg->msgh_local_port);
1581 kern_return_t kr;
1582
1583 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
1584 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
1585 ipc_object_t dest_port, reply_port;
1586 ipc_port_t dest_soright, reply_soright;
1587 ipc_port_t notify_port;
1588 ipc_entry_t entry;
1589
1590 if ((mbits != msg->msgh_bits) ||
1591 (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type)) ||
1592 ((reply_type == 0) ?
1593 (reply_name != MACH_PORT_NULL) :
1594 !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type)))
1595 return MACH_SEND_INVALID_HEADER;
1596
1597 reply_soright = IP_NULL; /* in case we go to invalid dest early */
1598
1599 is_write_lock(space);
1600 if (!space->is_active)
1601 goto invalid_dest;
1602
1603 if (!MACH_PORT_VALID(dest_name))
1604 goto invalid_dest;
1605
1606 #if CONFIG_MACF_MACH
1607 /*
1608 * We do the port send check here instead of in ipc_kmsg_send()
1609 * because copying the header involves copying the port rights too
1610 * and we need to do the send check before anything is actually copied.
1611 */
1612 entry = ipc_entry_lookup(space, dest_name);
1613 if (entry != IE_NULL) {
1614 int error = 0;
1615 ipc_port_t port = (ipc_port_t) entry->ie_object;
1616 if (port == IP_NULL)
1617 goto invalid_dest;
1618 ip_lock(port);
1619 if (ip_active(port)) {
1620 task_t self = current_task();
1621 tasklabel_lock(self);
1622 error = mac_port_check_send(&self->maclabel,
1623 &port->ip_label);
1624 tasklabel_unlock(self);
1625 }
1626 ip_unlock(port);
1627 if (error != 0)
1628 goto invalid_dest;
1629 }
1630 #endif
1631
1632 if (notify != MACH_PORT_NULL) {
1633 if ((entry = ipc_entry_lookup(space, notify)) == IE_NULL) {
1634 is_write_unlock(space);
1635 return MACH_SEND_INVALID_NOTIFY;
1636 }
1637 if((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1638 is_write_unlock(space);
1639 return MACH_SEND_INVALID_NOTIFY;
1640 }
1641
1642 notify_port = (ipc_port_t) entry->ie_object;
1643 } else
1644 notify_port = IP_NULL;
1645
1646 if (dest_name == reply_name) {
1647 mach_port_name_t name = dest_name;
1648
1649 /*
1650 * Destination and reply ports are the same!
1651 * This is a little tedious to make atomic, because
1652 * there are 25 combinations of dest_type/reply_type.
1653 * However, most are easy. If either is move-sonce,
1654 * then there must be an error. If either are
1655 * make-send or make-sonce, then we must be looking
1656 * at a receive right so the port can't die.
1657 * The hard cases are the combinations of
1658 * copy-send and make-send.
1659 */
1660
1661 entry = ipc_entry_lookup(space, name);
1662 if (entry == IE_NULL)
1663 goto invalid_dest;
1664
1665 assert(reply_type != 0); /* because name not null */
1666
1667 if (!ipc_right_copyin_check(space, name, entry, reply_type))
1668 goto invalid_reply;
1669
1670 if ((dest_type == MACH_MSG_TYPE_MOVE_SEND_ONCE) ||
1671 (reply_type == MACH_MSG_TYPE_MOVE_SEND_ONCE)) {
1672 /*
1673 * Why must there be an error? To get a valid
1674 * destination, this entry must name a live
1675 * port (not a dead name or dead port). However
1676 * a successful move-sonce will destroy a
1677 * live entry. Therefore the other copyin,
1678 * whatever it is, would fail. We've already
1679 * checked for reply port errors above,
1680 * so report a destination error.
1681 */
1682
1683 goto invalid_dest;
1684 } else if ((dest_type == MACH_MSG_TYPE_MAKE_SEND) ||
1685 (dest_type == MACH_MSG_TYPE_MAKE_SEND_ONCE) ||
1686 (reply_type == MACH_MSG_TYPE_MAKE_SEND) ||
1687 (reply_type == MACH_MSG_TYPE_MAKE_SEND_ONCE)) {
1688 kr = ipc_right_copyin(space, name, entry,
1689 dest_type, FALSE,
1690 &dest_port, &dest_soright);
1691 if (kr != KERN_SUCCESS)
1692 goto invalid_dest;
1693
1694 /*
1695 * Either dest or reply needs a receive right.
1696 * We know the receive right is there, because
1697 * of the copyin_check and copyin calls. Hence
1698 * the port is not in danger of dying. If dest
1699 * used the receive right, then the right needed
1700 * by reply (and verified by copyin_check) will
1701 * still be there.
1702 */
1703
1704 assert(IO_VALID(dest_port));
1705 assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
1706 assert(dest_soright == IP_NULL);
1707
1708 kr = ipc_right_copyin(space, name, entry,
1709 reply_type, TRUE,
1710 &reply_port, &reply_soright);
1711
1712 assert(kr == KERN_SUCCESS);
1713 assert(reply_port == dest_port);
1714 assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
1715 assert(reply_soright == IP_NULL);
1716 } else if ((dest_type == MACH_MSG_TYPE_COPY_SEND) &&
1717 (reply_type == MACH_MSG_TYPE_COPY_SEND)) {
1718 /*
1719 * To make this atomic, just do one copy-send,
1720 * and dup the send right we get out.
1721 */
1722
1723 kr = ipc_right_copyin(space, name, entry,
1724 dest_type, FALSE,
1725 &dest_port, &dest_soright);
1726 if (kr != KERN_SUCCESS)
1727 goto invalid_dest;
1728
1729 assert(entry->ie_bits & MACH_PORT_TYPE_SEND);
1730 assert(dest_soright == IP_NULL);
1731
1732 /*
1733 * It's OK if the port we got is dead now,
1734 * so reply_port is IP_DEAD, because the msg
1735 * won't go anywhere anyway.
1736 */
1737
1738 reply_port = (ipc_object_t)
1739 ipc_port_copy_send((ipc_port_t) dest_port);
1740 reply_soright = IP_NULL;
1741 } else if ((dest_type == MACH_MSG_TYPE_MOVE_SEND) &&
1742 (reply_type == MACH_MSG_TYPE_MOVE_SEND)) {
1743 /*
1744 * This is an easy case. Just use our
1745 * handy-dandy special-purpose copyin call
1746 * to get two send rights for the price of one.
1747 */
1748
1749 kr = ipc_right_copyin_two(space, name, entry,
1750 &dest_port, &dest_soright);
1751 if (kr != KERN_SUCCESS)
1752 goto invalid_dest;
1753
1754 /* the entry might need to be deallocated */
1755 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
1756 ipc_entry_dealloc(space, name, entry);
1757
1758 reply_port = dest_port;
1759 reply_soright = IP_NULL;
1760 } else {
1761 ipc_port_t soright;
1762
1763 assert(((dest_type == MACH_MSG_TYPE_COPY_SEND) &&
1764 (reply_type == MACH_MSG_TYPE_MOVE_SEND)) ||
1765 ((dest_type == MACH_MSG_TYPE_MOVE_SEND) &&
1766 (reply_type == MACH_MSG_TYPE_COPY_SEND)));
1767
1768 /*
1769 * To make this atomic, just do a move-send,
1770 * and dup the send right we get out.
1771 */
1772
1773 kr = ipc_right_copyin(space, name, entry,
1774 MACH_MSG_TYPE_MOVE_SEND, FALSE,
1775 &dest_port, &soright);
1776 if (kr != KERN_SUCCESS)
1777 goto invalid_dest;
1778
1779 /* the entry might need to be deallocated */
1780
1781 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
1782 ipc_entry_dealloc(space, name, entry);
1783
1784 /*
1785 * It's OK if the port we got is dead now,
1786 * so reply_port is IP_DEAD, because the msg
1787 * won't go anywhere anyway.
1788 */
1789
1790 reply_port = (ipc_object_t)
1791 ipc_port_copy_send((ipc_port_t) dest_port);
1792
1793 if (dest_type == MACH_MSG_TYPE_MOVE_SEND) {
1794 dest_soright = soright;
1795 reply_soright = IP_NULL;
1796 } else {
1797 dest_soright = IP_NULL;
1798 reply_soright = soright;
1799 }
1800 }
1801 } else if (!MACH_PORT_VALID(reply_name)) {
1802 /*
1803 * No reply port! This is an easy case
1804 * to make atomic. Just copyin the destination.
1805 */
1806
1807 entry = ipc_entry_lookup(space, dest_name);
1808 if (entry == IE_NULL)
1809 goto invalid_dest;
1810
1811 kr = ipc_right_copyin(space, dest_name, entry,
1812 dest_type, FALSE,
1813 &dest_port, &dest_soright);
1814 if (kr != KERN_SUCCESS)
1815 goto invalid_dest;
1816
1817 /* the entry might need to be deallocated */
1818
1819 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
1820 ipc_entry_dealloc(space, dest_name, entry);
1821
1822 reply_port = (ipc_object_t)CAST_MACH_NAME_TO_PORT(reply_name);
1823 reply_soright = IP_NULL;
1824 } else {
1825 ipc_entry_t dest_entry, reply_entry;
1826
1827 /*
1828 * This is the tough case to make atomic.
1829 * The difficult problem is serializing with port death.
1830 * At the time we copyin dest_port, it must be alive.
1831 * If reply_port is alive when we copyin it, then
1832 * we are OK, because we serialize before the death
1833 * of both ports. Assume reply_port is dead at copyin.
1834 * Then if dest_port dies/died after reply_port died,
1835 * we are OK, because we serialize between the death
1836 * of the two ports. So the bad case is when dest_port
1837 * dies after its copyin, reply_port dies before its
1838 * copyin, and dest_port dies before reply_port. Then
1839 * the copyins operated as if dest_port was alive
1840 * and reply_port was dead, which shouldn't have happened
1841 * because they died in the other order.
1842 *
1843 * Note that it is easy for a user task to tell if
1844 * a copyin happened before or after a port died.
1845 * For example, suppose both dest and reply are
1846 * send-once rights (types are both move-sonce) and
1847 * both rights have dead-name requests registered.
1848 * If a port dies before copyin, a dead-name notification
1849 * is generated and the dead name's urefs are incremented,
1850 * and if the copyin happens first, a port-deleted
1851 * notification is generated.
1852 *
1853 * Note that although the entries are different,
1854 * dest_port and reply_port might still be the same.
1855 *
1856 * JMM - The code to handle this was too expensive and, anyway,
1857 * we intend to separate the dest lookup from the reply copyin
1858 * by a wide margin, so the user will have to learn to deal!
1859 * I will be making the change soon!
1860 */
1861
1862 dest_entry = ipc_entry_lookup(space, dest_name);
1863 if (dest_entry == IE_NULL)
1864 goto invalid_dest;
1865
1866 reply_entry = ipc_entry_lookup(space, reply_name);
1867 if (reply_entry == IE_NULL)
1868 goto invalid_reply;
1869
1870 assert(dest_entry != reply_entry); /* names are not equal */
1871 assert(reply_type != 0); /* because reply_name not null */
1872
1873 if (!ipc_right_copyin_check(space, reply_name, reply_entry,
1874 reply_type))
1875 goto invalid_reply;
1876
1877 kr = ipc_right_copyin(space, dest_name, dest_entry,
1878 dest_type, FALSE,
1879 &dest_port, &dest_soright);
1880 if (kr != KERN_SUCCESS)
1881 goto invalid_dest;
1882
1883 assert(IO_VALID(dest_port));
1884
1885 kr = ipc_right_copyin(space, reply_name, reply_entry,
1886 reply_type, TRUE,
1887 &reply_port, &reply_soright);
1888
1889 assert(kr == KERN_SUCCESS);
1890
1891 /* the entries might need to be deallocated */
1892
1893 if (IE_BITS_TYPE(reply_entry->ie_bits) == MACH_PORT_TYPE_NONE)
1894 ipc_entry_dealloc(space, reply_name, reply_entry);
1895
1896 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE)
1897 ipc_entry_dealloc(space, dest_name, dest_entry);
1898 }
1899
1900 /*
1901 * At this point, dest_port, reply_port,
1902 * dest_soright, reply_soright are all initialized.
1903 * Any defunct entries have been deallocated.
1904 * The space is still write-locked, and we need to
1905 * make the MACH_SEND_CANCEL check. The notify_port pointer
1906 * is still usable, because the copyin code above won't ever
1907 * deallocate a receive right, so its entry still exists
1908 * and holds a ref. Note notify_port might even equal
1909 * dest_port or reply_port.
1910 */
1911
1912 if ((notify != MACH_PORT_NULL) &&
1913 (dest_soright == notify_port)) {
1914 ipc_port_release_sonce(dest_soright);
1915 dest_soright = IP_NULL;
1916 }
1917
1918 is_write_unlock(space);
1919
1920 if (dest_soright != IP_NULL)
1921 ipc_notify_port_deleted(dest_soright, dest_name);
1922
1923 if (reply_soright != IP_NULL)
1924 ipc_notify_port_deleted(reply_soright, reply_name);
1925
1926 dest_type = ipc_object_copyin_type(dest_type);
1927 reply_type = ipc_object_copyin_type(reply_type);
1928
1929 msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
1930 MACH_MSGH_BITS(dest_type, reply_type));
1931 msg->msgh_remote_port = (ipc_port_t)dest_port;
1932 msg->msgh_local_port = (ipc_port_t)reply_port;
1933
1934 return MACH_MSG_SUCCESS;
1935
1936 invalid_reply:
1937 is_write_unlock(space);
1938 return MACH_SEND_INVALID_REPLY;
1939
1940 invalid_dest:
1941 is_write_unlock(space);
1942 if (reply_soright != IP_NULL)
1943 ipc_notify_port_deleted(reply_soright, reply_name);
1944 return MACH_SEND_INVALID_DEST;
1945 }
1946
1947 mach_msg_descriptor_t *ipc_kmsg_copyin_port_descriptor(
1948 volatile mach_msg_port_descriptor_t *dsc,
1949 mach_msg_legacy_port_descriptor_t *user_dsc,
1950 ipc_space_t space,
1951 ipc_object_t dest,
1952 ipc_kmsg_t kmsg,
1953 mach_msg_return_t *mr);
1954
1955 void ipc_print_type_name(
1956 int type_name);
1957 mach_msg_descriptor_t *
1958 ipc_kmsg_copyin_port_descriptor(
1959 volatile mach_msg_port_descriptor_t *dsc,
1960 mach_msg_legacy_port_descriptor_t *user_dsc_in,
1961 ipc_space_t space,
1962 ipc_object_t dest,
1963 ipc_kmsg_t kmsg,
1964 mach_msg_return_t *mr)
1965 {
1966 volatile mach_msg_legacy_port_descriptor_t *user_dsc = user_dsc_in;
1967 mach_msg_type_name_t user_disp;
1968 mach_msg_type_name_t result_disp;
1969 mach_port_name_t name;
1970 ipc_object_t object;
1971
1972 user_disp = user_dsc->disposition;
1973 result_disp = ipc_object_copyin_type(user_disp);
1974
1975 name = (mach_port_name_t)user_dsc->name;
1976 if (MACH_PORT_VALID(name)) {
1977
1978 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
1979 if (kr != KERN_SUCCESS) {
1980 *mr = MACH_SEND_INVALID_RIGHT;
1981 return NULL;
1982 }
1983
1984 if ((result_disp == MACH_MSG_TYPE_PORT_RECEIVE) &&
1985 ipc_port_check_circularity((ipc_port_t) object,
1986 (ipc_port_t) dest)) {
1987 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
1988 }
1989 dsc->name = (ipc_port_t) object;
1990 } else {
1991 dsc->name = CAST_MACH_NAME_TO_PORT(name);
1992 }
1993 dsc->disposition = result_disp;
1994 dsc->type = MACH_MSG_PORT_DESCRIPTOR;
1995
1996 dsc->pad_end = 0; // debug, unnecessary
1997
1998 return (mach_msg_descriptor_t *)(user_dsc_in+1);
1999 }
2000
2001 mach_msg_descriptor_t * ipc_kmsg_copyin_ool_descriptor(
2002 mach_msg_ool_descriptor_t *dsc,
2003 mach_msg_descriptor_t *user_dsc,
2004 int is_64bit,
2005 vm_offset_t *paddr,
2006 vm_map_copy_t *copy,
2007 vm_size_t *space_needed,
2008 vm_map_t map,
2009 mach_msg_return_t *mr);
2010 mach_msg_descriptor_t *
2011 ipc_kmsg_copyin_ool_descriptor(
2012 mach_msg_ool_descriptor_t *dsc,
2013 mach_msg_descriptor_t *user_dsc,
2014 int is_64bit,
2015 vm_offset_t *paddr,
2016 vm_map_copy_t *copy,
2017 vm_size_t *space_needed,
2018 vm_map_t map,
2019 mach_msg_return_t *mr)
2020 {
2021 vm_size_t length;
2022 boolean_t dealloc;
2023 mach_msg_copy_options_t copy_options;
2024 mach_vm_offset_t addr;
2025 mach_msg_descriptor_type_t dsc_type;
2026
2027 if (is_64bit) {
2028 mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2029
2030 addr = (mach_vm_offset_t) user_ool_dsc->address;
2031 length = user_ool_dsc->size;
2032 dealloc = user_ool_dsc->deallocate;
2033 copy_options = user_ool_dsc->copy;
2034 dsc_type = user_ool_dsc->type;
2035
2036 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2037 } else {
2038 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2039
2040 addr = CAST_USER_ADDR_T(user_ool_dsc->address);
2041 dealloc = user_ool_dsc->deallocate;
2042 copy_options = user_ool_dsc->copy;
2043 dsc_type = user_ool_dsc->type;
2044 length = user_ool_dsc->size;
2045
2046 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2047 }
2048
2049 dsc->size = (mach_msg_size_t)length;
2050 dsc->deallocate = dealloc;
2051 dsc->copy = copy_options;
2052 dsc->type = dsc_type;
2053
2054 if (length == 0) {
2055 dsc->address = NULL;
2056 } else if ((length >= MSG_OOL_SIZE_SMALL) &&
2057 (copy_options == MACH_MSG_PHYSICAL_COPY) && !dealloc) {
2058
2059 /*
2060 * If the request is a physical copy and the source
2061 * is not being deallocated, then allocate space
2062 * in the kernel's pageable ipc copy map and copy
2063 * the data in. The semantics guarantee that the
2064 * data will have been physically copied before
2065 * the send operation terminates. Thus if the data
2066 * is not being deallocated, we must be prepared
2067 * to page if the region is sufficiently large.
2068 */
2069 if (copyin(addr, (char *)*paddr, length)) {
2070 *mr = MACH_SEND_INVALID_MEMORY;
2071 return NULL;
2072 }
2073
2074 /*
2075 * The kernel ipc copy map is marked no_zero_fill.
2076 * If the transfer is not a page multiple, we need
2077 * to zero fill the balance.
2078 */
2079 if (!page_aligned(length)) {
2080 (void) memset((void *) (*paddr + length), 0,
2081 round_page(length) - length);
2082 }
2083 if (vm_map_copyin(ipc_kernel_copy_map, (vm_map_address_t)*paddr,
2084 (vm_map_size_t)length, TRUE, copy) != KERN_SUCCESS) {
2085 *mr = MACH_MSG_VM_KERNEL;
2086 return NULL;
2087 }
2088 dsc->address = (void *)*copy;
2089 *paddr += round_page(length);
2090 *space_needed -= round_page(length);
2091 } else {
2092
2093 /*
2094 * Make a vm_map_copy_t of the of the data. If the
2095 * data is small, this will do an optimized physical
2096 * copy. Otherwise, it will do a virtual copy.
2097 *
2098 * NOTE: A virtual copy is OK if the original is being
2099 * deallocted, even if a physical copy was requested.
2100 */
2101 kern_return_t kr = vm_map_copyin(map, addr,
2102 (vm_map_size_t)length, dealloc, copy);
2103 if (kr != KERN_SUCCESS) {
2104 *mr = (kr == KERN_RESOURCE_SHORTAGE) ?
2105 MACH_MSG_VM_KERNEL :
2106 MACH_SEND_INVALID_MEMORY;
2107 return NULL;
2108 }
2109 dsc->address = (void *)*copy;
2110 }
2111 return user_dsc;
2112 }
2113
2114 mach_msg_descriptor_t * ipc_kmsg_copyin_ool_ports_descriptor(
2115 mach_msg_ool_ports_descriptor_t *dsc,
2116 mach_msg_descriptor_t *user_dsc,
2117 int is_64bit,
2118 vm_map_t map,
2119 ipc_space_t space,
2120 ipc_object_t dest,
2121 ipc_kmsg_t kmsg,
2122 mach_msg_return_t *mr);
2123 mach_msg_descriptor_t *
2124 ipc_kmsg_copyin_ool_ports_descriptor(
2125 mach_msg_ool_ports_descriptor_t *dsc,
2126 mach_msg_descriptor_t *user_dsc,
2127 int is_64bit,
2128 vm_map_t map,
2129 ipc_space_t space,
2130 ipc_object_t dest,
2131 ipc_kmsg_t kmsg,
2132 mach_msg_return_t *mr)
2133 {
2134 void *data;
2135 ipc_object_t *objects;
2136 unsigned int i;
2137 mach_vm_offset_t addr;
2138 mach_msg_type_name_t user_disp;
2139 mach_msg_type_name_t result_disp;
2140 mach_msg_type_number_t count;
2141 mach_msg_copy_options_t copy_option;
2142 boolean_t deallocate;
2143 mach_msg_descriptor_type_t type;
2144 vm_size_t ports_length, names_length;
2145
2146 if (is_64bit) {
2147 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2148
2149 addr = (mach_vm_offset_t)user_ool_dsc->address;
2150 count = user_ool_dsc->count;
2151 deallocate = user_ool_dsc->deallocate;
2152 copy_option = user_ool_dsc->copy;
2153 user_disp = user_ool_dsc->disposition;
2154 type = user_ool_dsc->type;
2155
2156 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2157 } else {
2158 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2159
2160 addr = CAST_USER_ADDR_T(user_ool_dsc->address);
2161 count = user_ool_dsc->count;
2162 deallocate = user_ool_dsc->deallocate;
2163 copy_option = user_ool_dsc->copy;
2164 user_disp = user_ool_dsc->disposition;
2165 type = user_ool_dsc->type;
2166
2167 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2168 }
2169
2170 dsc->deallocate = deallocate;
2171 dsc->copy = copy_option;
2172 dsc->type = type;
2173 dsc->count = count;
2174 dsc->address = NULL; /* for now */
2175
2176 result_disp = ipc_object_copyin_type(user_disp);
2177 dsc->disposition = result_disp;
2178
2179 if (count > (INT_MAX / sizeof(mach_port_t))) {
2180 *mr = MACH_SEND_TOO_LARGE;
2181 return NULL;
2182 }
2183
2184 /* calculate length of data in bytes, rounding up */
2185 ports_length = count * sizeof(mach_port_t);
2186 names_length = count * sizeof(mach_port_name_t);
2187
2188 if (ports_length == 0) {
2189 return user_dsc;
2190 }
2191
2192 data = kalloc(ports_length);
2193
2194 if (data == NULL) {
2195 *mr = MACH_SEND_NO_BUFFER;
2196 return NULL;
2197 }
2198
2199 #ifdef __LP64__
2200 mach_port_name_t *names = &((mach_port_name_t *)data)[count];
2201 #else
2202 mach_port_name_t *names = ((mach_port_name_t *)data);
2203 #endif
2204
2205 if (copyinmap(map, addr, names, names_length) != KERN_SUCCESS) {
2206 kfree(data, ports_length);
2207 *mr = MACH_SEND_INVALID_MEMORY;
2208 return NULL;
2209 }
2210
2211 if (deallocate) {
2212 (void) mach_vm_deallocate(map, addr, (mach_vm_size_t)ports_length);
2213 }
2214
2215 objects = (ipc_object_t *) data;
2216 dsc->address = data;
2217
2218 for ( i = 0; i < count; i++) {
2219 mach_port_name_t name = names[i];
2220 ipc_object_t object;
2221
2222 if (!MACH_PORT_VALID(name)) {
2223 objects[i] = (ipc_object_t)CAST_MACH_NAME_TO_PORT(name);
2224 continue;
2225 }
2226
2227 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
2228
2229 if (kr != KERN_SUCCESS) {
2230 unsigned int j;
2231
2232 for(j = 0; j < i; j++) {
2233 object = objects[j];
2234 if (IPC_OBJECT_VALID(object))
2235 ipc_object_destroy(object, result_disp);
2236 }
2237 kfree(data, ports_length);
2238 dsc->address = NULL;
2239 *mr = MACH_SEND_INVALID_RIGHT;
2240 return NULL;
2241 }
2242
2243 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2244 ipc_port_check_circularity(
2245 (ipc_port_t) object,
2246 (ipc_port_t) dest))
2247 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2248
2249 objects[i] = object;
2250 }
2251
2252 return user_dsc;
2253 }
2254
2255 /*
2256 * Routine: ipc_kmsg_copyin_body
2257 * Purpose:
2258 * "Copy-in" port rights and out-of-line memory
2259 * in the message body.
2260 *
2261 * In all failure cases, the message is left holding
2262 * no rights or memory. However, the message buffer
2263 * is not deallocated. If successful, the message
2264 * contains a valid destination port.
2265 * Conditions:
2266 * Nothing locked.
2267 * Returns:
2268 * MACH_MSG_SUCCESS Successful copyin.
2269 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2270 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2271 * MACH_SEND_INVALID_TYPE Bad type specification.
2272 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2273 * MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
2274 * MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
2275 */
2276
2277 mach_msg_return_t
2278 ipc_kmsg_copyin_body(
2279 ipc_kmsg_t kmsg,
2280 ipc_space_t space,
2281 vm_map_t map)
2282 {
2283 ipc_object_t dest;
2284 mach_msg_body_t *body;
2285 mach_msg_descriptor_t *daddr, *naddr;
2286 mach_msg_descriptor_t *user_addr, *kern_addr;
2287 mach_msg_type_number_t dsc_count;
2288 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
2289 boolean_t complex = FALSE;
2290 vm_size_t space_needed = 0;
2291 vm_offset_t paddr = 0;
2292 vm_map_copy_t copy = VM_MAP_COPY_NULL;
2293 mach_msg_type_number_t i;
2294 mach_msg_return_t mr = MACH_MSG_SUCCESS;
2295
2296 vm_size_t descriptor_size = 0;
2297
2298 /*
2299 * Determine if the target is a kernel port.
2300 */
2301 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
2302 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
2303 naddr = (mach_msg_descriptor_t *) (body + 1);
2304
2305 dsc_count = body->msgh_descriptor_count;
2306 if (dsc_count == 0)
2307 return MACH_MSG_SUCCESS;
2308
2309 /*
2310 * Make an initial pass to determine kernal VM space requirements for
2311 * physical copies and possible contraction of the descriptors from
2312 * processes with pointers larger than the kernel's.
2313 */
2314 daddr = NULL;
2315 for (i = 0; i < dsc_count; i++) {
2316 daddr = naddr;
2317
2318 /* make sure the descriptor fits in the message */
2319 if (is_task_64bit) {
2320 switch (daddr->type.type) {
2321 case MACH_MSG_OOL_DESCRIPTOR:
2322 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2323 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2324 descriptor_size += 16;
2325 naddr = (typeof(naddr))((vm_offset_t)daddr + 16);
2326 break;
2327 default:
2328 descriptor_size += 12;
2329 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
2330 break;
2331 }
2332 } else {
2333 descriptor_size += 12;
2334 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
2335 }
2336
2337 if (naddr > (mach_msg_descriptor_t *)
2338 ((vm_offset_t)kmsg->ikm_header + kmsg->ikm_header->msgh_size)) {
2339 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2340 mr = MACH_SEND_MSG_TOO_SMALL;
2341 goto out;
2342 }
2343
2344 switch (daddr->type.type) {
2345 mach_msg_size_t size;
2346
2347 case MACH_MSG_OOL_DESCRIPTOR:
2348 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2349 size = (is_task_64bit) ?
2350 ((mach_msg_ool_descriptor64_t *)daddr)->size :
2351 daddr->out_of_line.size;
2352
2353 if (daddr->out_of_line.copy != MACH_MSG_PHYSICAL_COPY &&
2354 daddr->out_of_line.copy != MACH_MSG_VIRTUAL_COPY) {
2355 /*
2356 * Invalid copy option
2357 */
2358 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2359 mr = MACH_SEND_INVALID_TYPE;
2360 goto out;
2361 }
2362
2363 if ((size >= MSG_OOL_SIZE_SMALL) &&
2364 (daddr->out_of_line.copy == MACH_MSG_PHYSICAL_COPY) &&
2365 !(daddr->out_of_line.deallocate)) {
2366
2367 /*
2368 * Out-of-line memory descriptor, accumulate kernel
2369 * memory requirements
2370 */
2371 space_needed += round_page(size);
2372 if (space_needed > ipc_kmsg_max_vm_space) {
2373
2374 /*
2375 * Per message kernel memory limit exceeded
2376 */
2377 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2378 mr = MACH_MSG_VM_KERNEL;
2379 goto out;
2380 }
2381 }
2382 }
2383 }
2384
2385 /*
2386 * Allocate space in the pageable kernel ipc copy map for all the
2387 * ool data that is to be physically copied. Map is marked wait for
2388 * space.
2389 */
2390 if (space_needed) {
2391 if (vm_allocate(ipc_kernel_copy_map, &paddr, space_needed,
2392 VM_FLAGS_ANYWHERE) != KERN_SUCCESS) {
2393 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2394 mr = MACH_MSG_VM_KERNEL;
2395 goto out;
2396 }
2397 }
2398
2399 /* user_addr = just after base as it was copied in */
2400 user_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
2401 /* Shift the mach_msg_base_t down to make for dsc_count*16bytes of descriptors */
2402 if(descriptor_size != 16*dsc_count) {
2403 vm_offset_t dsc_adjust = 16*dsc_count - descriptor_size;
2404 memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
2405 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
2406 /* Update the message size for the larger in-kernel representation */
2407 kmsg->ikm_header->msgh_size += (mach_msg_size_t)dsc_adjust;
2408 }
2409
2410
2411 /* kern_addr = just after base after it has been (conditionally) moved */
2412 kern_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
2413
2414 /* handle the OOL regions and port descriptors. */
2415 for(i=0;i<dsc_count;i++) {
2416 switch (user_addr->type.type) {
2417 case MACH_MSG_PORT_DESCRIPTOR:
2418 user_addr = ipc_kmsg_copyin_port_descriptor((mach_msg_port_descriptor_t *)kern_addr,
2419 (mach_msg_legacy_port_descriptor_t *)user_addr, space, dest, kmsg, &mr);
2420 kern_addr++;
2421 complex = TRUE;
2422 break;
2423 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2424 case MACH_MSG_OOL_DESCRIPTOR:
2425 user_addr = ipc_kmsg_copyin_ool_descriptor((mach_msg_ool_descriptor_t *)kern_addr,
2426 user_addr, is_task_64bit, &paddr, &copy, &space_needed, map, &mr);
2427 kern_addr++;
2428 complex = TRUE;
2429 break;
2430 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2431 user_addr = ipc_kmsg_copyin_ool_ports_descriptor((mach_msg_ool_ports_descriptor_t *)kern_addr,
2432 user_addr, is_task_64bit, map, space, dest, kmsg, &mr);
2433 kern_addr++;
2434 complex = TRUE;
2435 break;
2436 default:
2437 /* Invalid descriptor */
2438 mr = MACH_SEND_INVALID_TYPE;
2439 break;
2440 }
2441
2442 if (MACH_MSG_SUCCESS != mr) {
2443 /* clean from start of message descriptors to i */
2444 ipc_kmsg_clean_partial(kmsg, i,
2445 (mach_msg_descriptor_t *)((mach_msg_base_t *)kmsg->ikm_header + 1),
2446 paddr, space_needed);
2447 goto out;
2448 }
2449 } /* End of loop */
2450
2451 if (!complex) {
2452 kmsg->ikm_header->msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
2453 }
2454 out:
2455 return mr;
2456 }
2457
2458
2459 /*
2460 * Routine: ipc_kmsg_copyin
2461 * Purpose:
2462 * "Copy-in" port rights and out-of-line memory
2463 * in the message.
2464 *
2465 * In all failure cases, the message is left holding
2466 * no rights or memory. However, the message buffer
2467 * is not deallocated. If successful, the message
2468 * contains a valid destination port.
2469 * Conditions:
2470 * Nothing locked.
2471 * Returns:
2472 * MACH_MSG_SUCCESS Successful copyin.
2473 * MACH_SEND_INVALID_HEADER
2474 * Illegal value in the message header bits.
2475 * MACH_SEND_INVALID_NOTIFY Bad notify port.
2476 * MACH_SEND_INVALID_DEST Can't copyin destination port.
2477 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
2478 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2479 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2480 * MACH_SEND_INVALID_TYPE Bad type specification.
2481 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2482 */
2483
2484 mach_msg_return_t
2485 ipc_kmsg_copyin(
2486 ipc_kmsg_t kmsg,
2487 ipc_space_t space,
2488 vm_map_t map,
2489 mach_port_name_t notify)
2490 {
2491 mach_msg_return_t mr;
2492
2493 mr = ipc_kmsg_copyin_header(kmsg->ikm_header, space, notify);
2494 if (mr != MACH_MSG_SUCCESS)
2495 return mr;
2496
2497 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_copyin header:\n%.8x\n%.8x\n%p\n%p\n%.8x\n%.8x\n",
2498 kmsg->ikm_header->msgh_size,
2499 kmsg->ikm_header->msgh_bits,
2500 kmsg->ikm_header->msgh_remote_port,
2501 kmsg->ikm_header->msgh_local_port,
2502 kmsg->ikm_header->msgh_reserved,
2503 kmsg->ikm_header->msgh_id);
2504
2505 if ((kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0)
2506 return MACH_MSG_SUCCESS;
2507
2508 mr = ipc_kmsg_copyin_body( kmsg, space, map);
2509
2510 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
2511 {
2512 kprintf("body:\n");
2513 uint32_t i;
2514 for(i=0;i*4 < (kmsg->ikm_header->msgh_size - sizeof(mach_msg_header_t));i++)
2515 {
2516 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
2517 }
2518 }
2519 return mr;
2520 }
2521
2522 /*
2523 * Routine: ipc_kmsg_copyin_from_kernel
2524 * Purpose:
2525 * "Copy-in" port rights and out-of-line memory
2526 * in a message sent from the kernel.
2527 *
2528 * Because the message comes from the kernel,
2529 * the implementation assumes there are no errors
2530 * or peculiarities in the message.
2531 *
2532 * Returns TRUE if queueing the message
2533 * would result in a circularity.
2534 * Conditions:
2535 * Nothing locked.
2536 */
2537
2538 void
2539 ipc_kmsg_copyin_from_kernel(
2540 ipc_kmsg_t kmsg)
2541 {
2542 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
2543 mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
2544 mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
2545 ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
2546 ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
2547
2548 /* translate the destination and reply ports */
2549
2550 ipc_object_copyin_from_kernel(remote, rname);
2551 if (IO_VALID(local))
2552 ipc_object_copyin_from_kernel(local, lname);
2553
2554 /*
2555 * The common case is a complex message with no reply port,
2556 * because that is what the memory_object interface uses.
2557 */
2558
2559 if (bits == (MACH_MSGH_BITS_COMPLEX |
2560 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
2561 bits = (MACH_MSGH_BITS_COMPLEX |
2562 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
2563
2564 kmsg->ikm_header->msgh_bits = bits;
2565 } else {
2566 bits = (MACH_MSGH_BITS_OTHER(bits) |
2567 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
2568 ipc_object_copyin_type(lname)));
2569
2570 kmsg->ikm_header->msgh_bits = bits;
2571 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
2572 return;
2573 }
2574 {
2575 mach_msg_descriptor_t *saddr;
2576 mach_msg_body_t *body;
2577 mach_msg_type_number_t i, count;
2578
2579 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
2580 saddr = (mach_msg_descriptor_t *) (body + 1);
2581 count = body->msgh_descriptor_count;
2582
2583 for (i = 0; i < count; i++, saddr++) {
2584
2585 switch (saddr->type.type) {
2586
2587 case MACH_MSG_PORT_DESCRIPTOR: {
2588 mach_msg_type_name_t name;
2589 ipc_object_t object;
2590 mach_msg_port_descriptor_t *dsc;
2591
2592 dsc = &saddr->port;
2593
2594 /* this is really the type SEND, SEND_ONCE, etc. */
2595 name = dsc->disposition;
2596 object = (ipc_object_t) dsc->name;
2597 dsc->disposition = ipc_object_copyin_type(name);
2598
2599 if (!IO_VALID(object)) {
2600 break;
2601 }
2602
2603 ipc_object_copyin_from_kernel(object, name);
2604
2605 /* CDY avoid circularity when the destination is also */
2606 /* the kernel. This check should be changed into an */
2607 /* assert when the new kobject model is in place since*/
2608 /* ports will not be used in kernel to kernel chats */
2609
2610 if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
2611 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2612 ipc_port_check_circularity((ipc_port_t) object,
2613 (ipc_port_t) remote)) {
2614 kmsg->ikm_header->msgh_bits |=
2615 MACH_MSGH_BITS_CIRCULAR;
2616 }
2617 }
2618 break;
2619 }
2620 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2621 case MACH_MSG_OOL_DESCRIPTOR: {
2622 /*
2623 * The sender should supply ready-made memory, i.e.
2624 * a vm_map_copy_t, so we don't need to do anything.
2625 */
2626 break;
2627 }
2628 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
2629 ipc_object_t *objects;
2630 unsigned int j;
2631 mach_msg_type_name_t name;
2632 mach_msg_ool_ports_descriptor_t *dsc;
2633
2634 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
2635
2636 /* this is really the type SEND, SEND_ONCE, etc. */
2637 name = dsc->disposition;
2638 dsc->disposition = ipc_object_copyin_type(name);
2639
2640 objects = (ipc_object_t *) dsc->address;
2641
2642 for ( j = 0; j < dsc->count; j++) {
2643 ipc_object_t object = objects[j];
2644
2645 if (!IO_VALID(object))
2646 continue;
2647
2648 ipc_object_copyin_from_kernel(object, name);
2649
2650 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2651 ipc_port_check_circularity(
2652 (ipc_port_t) object,
2653 (ipc_port_t) remote))
2654 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2655 }
2656 break;
2657 }
2658 default: {
2659 #if MACH_ASSERT
2660 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
2661 #endif /* MACH_ASSERT */
2662 }
2663 }
2664 }
2665 }
2666 }
2667
2668 #if IKM_SUPPORT_LEGACY
2669 void
2670 ipc_kmsg_copyin_from_kernel_legacy(
2671 ipc_kmsg_t kmsg)
2672 {
2673 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
2674 mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
2675 mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
2676 ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
2677 ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
2678
2679 /* translate the destination and reply ports */
2680
2681 ipc_object_copyin_from_kernel(remote, rname);
2682 if (IO_VALID(local))
2683 ipc_object_copyin_from_kernel(local, lname);
2684
2685 /*
2686 * The common case is a complex message with no reply port,
2687 * because that is what the memory_object interface uses.
2688 */
2689
2690 if (bits == (MACH_MSGH_BITS_COMPLEX |
2691 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
2692 bits = (MACH_MSGH_BITS_COMPLEX |
2693 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
2694
2695 kmsg->ikm_header->msgh_bits = bits;
2696 } else {
2697 bits = (MACH_MSGH_BITS_OTHER(bits) |
2698 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
2699 ipc_object_copyin_type(lname)));
2700
2701 kmsg->ikm_header->msgh_bits = bits;
2702 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
2703 return;
2704 }
2705 {
2706 mach_msg_legacy_descriptor_t *saddr;
2707 mach_msg_descriptor_t *daddr;
2708 mach_msg_body_t *body;
2709 mach_msg_type_number_t i, count;
2710
2711 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
2712 saddr = (typeof(saddr)) (body + 1);
2713 count = body->msgh_descriptor_count;
2714
2715 if(count) {
2716 vm_offset_t dsc_adjust = 4*count;
2717 memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
2718 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
2719 /* Update the message size for the larger in-kernel representation */
2720 kmsg->ikm_header->msgh_size += dsc_adjust;
2721 }
2722 daddr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
2723
2724 for (i = 0; i < count; i++, saddr++, daddr++) {
2725 switch (saddr->type.type) {
2726
2727 case MACH_MSG_PORT_DESCRIPTOR: {
2728 mach_msg_type_name_t name;
2729 ipc_object_t object;
2730 mach_msg_legacy_port_descriptor_t *dsc;
2731 mach_msg_port_descriptor_t *dest_dsc;
2732
2733 dsc = (typeof(dsc))&saddr->port;
2734 dest_dsc = &daddr->port;
2735
2736 /* this is really the type SEND, SEND_ONCE, etc. */
2737 name = dsc->disposition;
2738 object = (ipc_object_t) CAST_MACH_NAME_TO_PORT(dsc->name);
2739 dest_dsc->disposition = ipc_object_copyin_type(name);
2740 dest_dsc->name = (mach_port_t)object;
2741 dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
2742
2743 if (!IO_VALID(object)) {
2744 break;
2745 }
2746
2747 ipc_object_copyin_from_kernel(object, name);
2748
2749 /* CDY avoid circularity when the destination is also */
2750 /* the kernel. This check should be changed into an */
2751 /* assert when the new kobject model is in place since*/
2752 /* ports will not be used in kernel to kernel chats */
2753
2754 if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
2755 if ((dest_dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2756 ipc_port_check_circularity((ipc_port_t) object,
2757 (ipc_port_t) remote)) {
2758 kmsg->ikm_header->msgh_bits |=
2759 MACH_MSGH_BITS_CIRCULAR;
2760 }
2761 }
2762 break;
2763 }
2764 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2765 case MACH_MSG_OOL_DESCRIPTOR: {
2766 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
2767 * so we don't need to do anything special. */
2768
2769 mach_msg_ool_descriptor32_t *source_dsc = &saddr->out_of_line32;
2770 mach_msg_ool_descriptor_t *dest_dsc = (typeof(dest_dsc))&daddr->out_of_line;
2771
2772 vm_offset_t address = source_dsc->address;
2773 vm_size_t size = source_dsc->size;
2774 boolean_t deallocate = source_dsc->deallocate;
2775 mach_msg_copy_options_t copy = source_dsc->copy;
2776 mach_msg_descriptor_type_t type = source_dsc->type;
2777
2778 dest_dsc->address = (void *)address;
2779 dest_dsc->size = size;
2780 dest_dsc->deallocate = deallocate;
2781 dest_dsc->copy = copy;
2782 dest_dsc->type = type;
2783 break;
2784 }
2785 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
2786 ipc_object_t *objects;
2787 unsigned int j;
2788 mach_msg_type_name_t name;
2789 mach_msg_ool_ports_descriptor_t *dest_dsc;
2790
2791 mach_msg_ool_ports_descriptor32_t *source_dsc = &saddr->ool_ports32;
2792 dest_dsc = (typeof(dest_dsc))&daddr->ool_ports;
2793
2794 boolean_t deallocate = source_dsc->deallocate;
2795 mach_msg_copy_options_t copy = source_dsc->copy;
2796 mach_msg_size_t port_count = source_dsc->count;
2797 mach_msg_type_name_t disposition = source_dsc->disposition;
2798
2799 /* this is really the type SEND, SEND_ONCE, etc. */
2800 name = disposition;
2801 disposition = ipc_object_copyin_type(name);
2802
2803 objects = (ipc_object_t *) (uintptr_t)source_dsc->address;
2804
2805 for ( j = 0; j < port_count; j++) {
2806 ipc_object_t object = objects[j];
2807
2808 if (!IO_VALID(object))
2809 continue;
2810
2811 ipc_object_copyin_from_kernel(object, name);
2812
2813 if ((disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2814 ipc_port_check_circularity(
2815 (ipc_port_t) object,
2816 (ipc_port_t) remote))
2817 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2818 }
2819
2820 dest_dsc->address = objects;
2821 dest_dsc->deallocate = deallocate;
2822 dest_dsc->copy = copy;
2823 dest_dsc->disposition = disposition;
2824 dest_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
2825 dest_dsc->count = port_count;
2826 break;
2827 }
2828 default: {
2829 #if MACH_ASSERT
2830 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
2831 #endif /* MACH_ASSERT */
2832 }
2833 }
2834 }
2835 }
2836 }
2837 #endif /* IKM_SUPPORT_LEGACY */
2838
2839 /*
2840 * Routine: ipc_kmsg_copyout_header
2841 * Purpose:
2842 * "Copy-out" port rights in the header of a message.
2843 * Operates atomically; if it doesn't succeed the
2844 * message header and the space are left untouched.
2845 * If it does succeed the remote/local port fields
2846 * contain port names instead of object pointers,
2847 * and the bits field is updated.
2848 *
2849 * The notify argument implements the MACH_RCV_NOTIFY option.
2850 * If it is not MACH_PORT_NULL, it should name a receive right.
2851 * If the process of receiving the reply port creates a
2852 * new right in the receiving task, then the new right is
2853 * automatically registered for a dead-name notification,
2854 * with the notify port supplying the send-once right.
2855 * Conditions:
2856 * Nothing locked.
2857 * Returns:
2858 * MACH_MSG_SUCCESS Copied out port rights.
2859 * MACH_RCV_INVALID_NOTIFY
2860 * Notify is non-null and doesn't name a receive right.
2861 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
2862 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
2863 * The space is dead.
2864 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
2865 * No room in space for another name.
2866 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
2867 * Couldn't allocate memory for the reply port.
2868 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
2869 * Couldn't allocate memory for the dead-name request.
2870 */
2871
2872 mach_msg_return_t
2873 ipc_kmsg_copyout_header(
2874 mach_msg_header_t *msg,
2875 ipc_space_t space,
2876 mach_port_name_t notify)
2877 {
2878 mach_msg_bits_t mbits = msg->msgh_bits;
2879 ipc_port_t dest = (ipc_port_t) msg->msgh_remote_port;
2880
2881 assert(IP_VALID(dest));
2882
2883 {
2884 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
2885 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
2886 ipc_port_t reply = (ipc_port_t) msg->msgh_local_port;
2887 mach_port_name_t dest_name, reply_name;
2888
2889 if (IP_VALID(reply)) {
2890 ipc_port_t notify_port;
2891 ipc_entry_t entry;
2892 kern_return_t kr;
2893
2894 /*
2895 * Handling notify (for MACH_RCV_NOTIFY) is tricky.
2896 * The problem is atomically making a send-once right
2897 * from the notify port and installing it for a
2898 * dead-name request in the new entry, because this
2899 * requires two port locks (on the notify port and
2900 * the reply port). However, we can safely make
2901 * and consume send-once rights for the notify port
2902 * as long as we hold the space locked. This isn't
2903 * an atomicity problem, because the only way
2904 * to detect that a send-once right has been created
2905 * and then consumed if it wasn't needed is by getting
2906 * at the receive right to look at ip_sorights, and
2907 * because the space is write-locked status calls can't
2908 * lookup the notify port receive right. When we make
2909 * the send-once right, we lock the notify port,
2910 * so any status calls in progress will be done.
2911 */
2912
2913 is_write_lock(space);
2914
2915 for (;;) {
2916 ipc_port_request_index_t request;
2917
2918 if (!space->is_active) {
2919 is_write_unlock(space);
2920 return (MACH_RCV_HEADER_ERROR|
2921 MACH_MSG_IPC_SPACE);
2922 }
2923
2924 if (notify != MACH_PORT_NULL) {
2925 notify_port = ipc_port_lookup_notify(space,
2926 notify);
2927 if (notify_port == IP_NULL) {
2928 printf("ipc_kmsg_copyout_header: no notify port\n");
2929 is_write_unlock(space);
2930 return MACH_RCV_INVALID_NOTIFY;
2931 }
2932 } else
2933 notify_port = IP_NULL;
2934
2935 if ((reply_type != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
2936 ipc_right_reverse(space, (ipc_object_t) reply,
2937 &reply_name, &entry)) {
2938 /* reply port is locked and active */
2939
2940 /*
2941 * We don't need the notify_port
2942 * send-once right, but we can't release
2943 * it here because reply port is locked.
2944 * Wait until after the copyout to
2945 * release the notify port right.
2946 */
2947
2948 assert(entry->ie_bits &
2949 MACH_PORT_TYPE_SEND_RECEIVE);
2950 break;
2951 }
2952
2953 ip_lock(reply);
2954 if (!ip_active(reply)) {
2955 ip_release(reply);
2956 ip_check_unlock(reply);
2957
2958 if (notify_port != IP_NULL)
2959 ipc_port_release_sonce(notify_port);
2960
2961 ip_lock(dest);
2962 is_write_unlock(space);
2963
2964 reply = IP_DEAD;
2965 reply_name = MACH_PORT_DEAD;
2966 goto copyout_dest;
2967 }
2968
2969 reply_name = CAST_MACH_PORT_TO_NAME(reply);
2970 kr = ipc_entry_get(space, &reply_name, &entry);
2971 if (kr != KERN_SUCCESS) {
2972 ip_unlock(reply);
2973
2974 if (notify_port != IP_NULL)
2975 ipc_port_release_sonce(notify_port);
2976
2977 /* space is locked */
2978 kr = ipc_entry_grow_table(space,
2979 ITS_SIZE_NONE);
2980 if (kr != KERN_SUCCESS) {
2981 /* space is unlocked */
2982
2983 if (kr == KERN_RESOURCE_SHORTAGE) {
2984 printf("ipc_kmsg_copyout_header: can't grow kernel ipc space\n");
2985 return (MACH_RCV_HEADER_ERROR|
2986 MACH_MSG_IPC_KERNEL);
2987 } else {
2988 printf("ipc_kmsg_copyout_header: can't grow user ipc space\n");
2989 return (MACH_RCV_HEADER_ERROR|
2990 MACH_MSG_IPC_SPACE);
2991 }
2992 }
2993 /* space is locked again; start over */
2994
2995 continue;
2996 }
2997 assert(IE_BITS_TYPE(entry->ie_bits) ==
2998 MACH_PORT_TYPE_NONE);
2999 assert(entry->ie_object == IO_NULL);
3000
3001 if (notify_port == IP_NULL) {
3002 /* not making a dead-name request */
3003
3004 entry->ie_object = (ipc_object_t) reply;
3005 break;
3006 }
3007
3008 kr = ipc_port_dnrequest(reply, reply_name,
3009 notify_port, &request);
3010 if (kr != KERN_SUCCESS) {
3011 ip_unlock(reply);
3012
3013 ipc_port_release_sonce(notify_port);
3014
3015 ipc_entry_dealloc(space, reply_name, entry);
3016 is_write_unlock(space);
3017
3018 ip_lock(reply);
3019 if (!ip_active(reply)) {
3020 /* will fail next time around loop */
3021
3022 ip_unlock(reply);
3023 is_write_lock(space);
3024 continue;
3025 }
3026
3027 kr = ipc_port_dngrow(reply, ITS_SIZE_NONE);
3028 /* port is unlocked */
3029 if (kr != KERN_SUCCESS) {
3030 printf("ipc_kmsg_copyout_header: can't grow kernel ipc space2\n");
3031 return (MACH_RCV_HEADER_ERROR|
3032 MACH_MSG_IPC_KERNEL);
3033 }
3034
3035 is_write_lock(space);
3036 continue;
3037 }
3038
3039 notify_port = IP_NULL; /* don't release right below */
3040
3041 entry->ie_object = (ipc_object_t) reply;
3042 entry->ie_request = request;
3043 break;
3044 }
3045
3046 /* space and reply port are locked and active */
3047
3048 ip_reference(reply); /* hold onto the reply port */
3049
3050 kr = ipc_right_copyout(space, reply_name, entry,
3051 reply_type, TRUE, (ipc_object_t) reply);
3052 /* reply port is unlocked */
3053 assert(kr == KERN_SUCCESS);
3054
3055 if (notify_port != IP_NULL)
3056 ipc_port_release_sonce(notify_port);
3057
3058 ip_lock(dest);
3059 is_write_unlock(space);
3060 } else {
3061 /*
3062 * No reply port! This is an easy case.
3063 * We only need to have the space locked
3064 * when checking notify and when locking
3065 * the destination (to ensure atomicity).
3066 */
3067
3068 is_read_lock(space);
3069 if (!space->is_active) {
3070 is_read_unlock(space);
3071 return MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE;
3072 }
3073
3074 if (notify != MACH_PORT_NULL) {
3075 ipc_entry_t entry;
3076
3077 /* must check notify even though it won't be used */
3078
3079 if ((entry = ipc_entry_lookup(space, notify)) == IE_NULL) {
3080 printf("ipc_kmsg_copyout_header: ipc_entry_lookup failed\n");
3081 is_read_unlock(space);
3082 return MACH_RCV_INVALID_NOTIFY;
3083 }
3084
3085 if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
3086 printf("ipc_kmsg_copyout_header: MACH_PORT_TYPE_RECEIVE not set!\n");
3087 is_read_unlock(space);
3088 return MACH_RCV_INVALID_NOTIFY;
3089 }
3090 }
3091
3092 ip_lock(dest);
3093 is_read_unlock(space);
3094
3095 reply_name = CAST_MACH_PORT_TO_NAME(reply);
3096 }
3097
3098 /*
3099 * At this point, the space is unlocked and the destination
3100 * port is locked. (Lock taken while space was locked.)
3101 * reply_name is taken care of; we still need dest_name.
3102 * We still hold a ref for reply (if it is valid).
3103 *
3104 * If the space holds receive rights for the destination,
3105 * we return its name for the right. Otherwise the task
3106 * managed to destroy or give away the receive right between
3107 * receiving the message and this copyout. If the destination
3108 * is dead, return MACH_PORT_DEAD, and if the receive right
3109 * exists somewhere else (another space, in transit)
3110 * return MACH_PORT_NULL.
3111 *
3112 * Making this copyout operation atomic with the previous
3113 * copyout of the reply port is a bit tricky. If there was
3114 * no real reply port (it wasn't IP_VALID) then this isn't
3115 * an issue. If the reply port was dead at copyout time,
3116 * then we are OK, because if dest is dead we serialize
3117 * after the death of both ports and if dest is alive
3118 * we serialize after reply died but before dest's (later) death.
3119 * So assume reply was alive when we copied it out. If dest
3120 * is alive, then we are OK because we serialize before
3121 * the ports' deaths. So assume dest is dead when we look at it.
3122 * If reply dies/died after dest, then we are OK because
3123 * we serialize after dest died but before reply dies.
3124 * So the hard case is when reply is alive at copyout,
3125 * dest is dead at copyout, and reply died before dest died.
3126 * In this case pretend that dest is still alive, so
3127 * we serialize while both ports are alive.
3128 *
3129 * Because the space lock is held across the copyout of reply
3130 * and locking dest, the receive right for dest can't move
3131 * in or out of the space while the copyouts happen, so
3132 * that isn't an atomicity problem. In the last hard case
3133 * above, this implies that when dest is dead that the
3134 * space couldn't have had receive rights for dest at
3135 * the time reply was copied-out, so when we pretend
3136 * that dest is still alive, we can return MACH_PORT_NULL.
3137 *
3138 * If dest == reply, then we have to make it look like
3139 * either both copyouts happened before the port died,
3140 * or both happened after the port died. This special
3141 * case works naturally if the timestamp comparison
3142 * is done correctly.
3143 */
3144
3145 copyout_dest:
3146
3147 if (ip_active(dest)) {
3148 ipc_object_copyout_dest(space, (ipc_object_t) dest,
3149 dest_type, &dest_name);
3150 /* dest is unlocked */
3151 } else {
3152 ipc_port_timestamp_t timestamp;
3153
3154 timestamp = dest->ip_timestamp;
3155 ip_release(dest);
3156 ip_check_unlock(dest);
3157
3158 if (IP_VALID(reply)) {
3159 ip_lock(reply);
3160 if (ip_active(reply) ||
3161 IP_TIMESTAMP_ORDER(timestamp,
3162 reply->ip_timestamp))
3163 dest_name = MACH_PORT_DEAD;
3164 else
3165 dest_name = MACH_PORT_NULL;
3166 ip_unlock(reply);
3167 } else
3168 dest_name = MACH_PORT_DEAD;
3169 }
3170
3171 if (IP_VALID(reply))
3172 ipc_port_release(reply);
3173
3174 msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
3175 MACH_MSGH_BITS(reply_type, dest_type));
3176 msg->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
3177 msg->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
3178 }
3179
3180 return MACH_MSG_SUCCESS;
3181 }
3182
3183 /*
3184 * Routine: ipc_kmsg_copyout_object
3185 * Purpose:
3186 * Copy-out a port right. Always returns a name,
3187 * even for unsuccessful return codes. Always
3188 * consumes the supplied object.
3189 * Conditions:
3190 * Nothing locked.
3191 * Returns:
3192 * MACH_MSG_SUCCESS The space acquired the right
3193 * (name is valid) or the object is dead (MACH_PORT_DEAD).
3194 * MACH_MSG_IPC_SPACE No room in space for the right,
3195 * or the space is dead. (Name is MACH_PORT_NULL.)
3196 * MACH_MSG_IPC_KERNEL Kernel resource shortage.
3197 * (Name is MACH_PORT_NULL.)
3198 */
3199
3200 mach_msg_return_t
3201 ipc_kmsg_copyout_object(
3202 ipc_space_t space,
3203 ipc_object_t object,
3204 mach_msg_type_name_t msgt_name,
3205 mach_port_name_t *namep)
3206 {
3207 kern_return_t kr;
3208
3209 if (!IO_VALID(object)) {
3210 *namep = CAST_MACH_PORT_TO_NAME(object);
3211 return MACH_MSG_SUCCESS;
3212 }
3213
3214 kr = ipc_object_copyout(space, object, msgt_name, TRUE, namep);
3215 if (kr != KERN_SUCCESS) {
3216 ipc_object_destroy(object, msgt_name);
3217
3218 if (kr == KERN_INVALID_CAPABILITY)
3219 *namep = MACH_PORT_DEAD;
3220 else {
3221 *namep = MACH_PORT_NULL;
3222
3223 if (kr == KERN_RESOURCE_SHORTAGE)
3224 return MACH_MSG_IPC_KERNEL;
3225 else
3226 return MACH_MSG_IPC_SPACE;
3227 }
3228 }
3229
3230 return MACH_MSG_SUCCESS;
3231 }
3232
3233 mach_msg_descriptor_t *
3234 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3235 mach_msg_descriptor_t *user_dsc,
3236 ipc_space_t space,
3237 kern_return_t *mr);
3238 mach_msg_descriptor_t *
3239 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3240 mach_msg_descriptor_t *dest_dsc,
3241 ipc_space_t space,
3242 kern_return_t *mr)
3243 {
3244 mach_port_t port;
3245 mach_port_name_t name;
3246 mach_msg_type_name_t disp;
3247
3248
3249 /* Copyout port right carried in the message */
3250 port = dsc->port.name;
3251 disp = dsc->port.disposition;
3252 *mr |= ipc_kmsg_copyout_object(space,
3253 (ipc_object_t)port,
3254 disp,
3255 &name);
3256
3257 if(current_task() == kernel_task)
3258 {
3259 mach_msg_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
3260 user_dsc--; // point to the start of this port descriptor
3261 user_dsc->name = CAST_MACH_NAME_TO_PORT(name);
3262 user_dsc->disposition = disp;
3263 user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
3264 dest_dsc = (typeof(dest_dsc))user_dsc;
3265 } else {
3266 mach_msg_legacy_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
3267 user_dsc--; // point to the start of this port descriptor
3268 user_dsc->name = CAST_MACH_PORT_TO_NAME(name);
3269 user_dsc->disposition = disp;
3270 user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
3271 dest_dsc = (typeof(dest_dsc))user_dsc;
3272 }
3273
3274 return (mach_msg_descriptor_t *)dest_dsc;
3275 }
3276
3277 mach_msg_descriptor_t *
3278 ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descriptor_t *user_dsc, int is_64bit, vm_map_t map, mach_msg_return_t *mr);
3279 mach_msg_descriptor_t *
3280 ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descriptor_t *user_dsc, int is_64bit, vm_map_t map, mach_msg_return_t *mr)
3281 {
3282 vm_map_copy_t copy;
3283 mach_vm_offset_t rcv_addr;
3284 mach_msg_copy_options_t copy_options;
3285 mach_msg_size_t size;
3286 mach_msg_descriptor_type_t dsc_type;
3287
3288 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
3289
3290 copy = (vm_map_copy_t) dsc->address;
3291 size = dsc->size;
3292 copy_options = dsc->copy;
3293 assert(copy_options != MACH_MSG_KALLOC_COPY_T);
3294 dsc_type = dsc->type;
3295 rcv_addr = 0;
3296
3297 if (copy != VM_MAP_COPY_NULL) {
3298 /*
3299 * Check to see if there is an overwrite descriptor
3300 * specified in the scatter list for this ool data.
3301 * The descriptor has already been verified.
3302 */
3303 #if 0
3304 if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
3305 if (differs) {
3306 OTHER_OOL_DESCRIPTOR *scatter_dsc;
3307
3308 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
3309 if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
3310 rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
3311 copy_options = MACH_MSG_OVERWRITE;
3312 } else {
3313 copy_options = MACH_MSG_VIRTUAL_COPY;
3314 }
3315 } else {
3316 mach_msg_ool_descriptor_t *scatter_dsc;
3317
3318 scatter_dsc = &saddr->out_of_line;
3319 if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
3320 rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
3321 copy_options = MACH_MSG_OVERWRITE;
3322 } else {
3323 copy_options = MACH_MSG_VIRTUAL_COPY;
3324 }
3325 }
3326 INCREMENT_SCATTER(saddr, sdsc_count, differs);
3327 }
3328 #endif
3329
3330
3331 /*
3332 * Whether the data was virtually or physically
3333 * copied we have a vm_map_copy_t for it.
3334 * If there's an overwrite region specified
3335 * overwrite it, otherwise do a virtual copy out.
3336 */
3337 kern_return_t kr;
3338 if (copy_options == MACH_MSG_OVERWRITE && rcv_addr != 0) {
3339 kr = vm_map_copy_overwrite(map, rcv_addr,
3340 copy, TRUE);
3341 } else {
3342 kr = vm_map_copyout(map, &rcv_addr, copy);
3343 }
3344 if (kr != KERN_SUCCESS) {
3345 if (kr == KERN_RESOURCE_SHORTAGE)
3346 *mr |= MACH_MSG_VM_KERNEL;
3347 else
3348 *mr |= MACH_MSG_VM_SPACE;
3349 vm_map_copy_discard(copy);
3350 rcv_addr = 0;
3351 size = 0;
3352 }
3353 } else {
3354 rcv_addr = 0;
3355 size = 0;
3356 }
3357
3358 /*
3359 * Now update the descriptor as the user would see it.
3360 * This may require expanding the descriptor to the user
3361 * visible size. There is already space allocated for
3362 * this in what naddr points to.
3363 */
3364 if(current_task() == kernel_task)
3365 {
3366 mach_msg_ool_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3367 user_ool_dsc--;
3368
3369 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
3370 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3371 TRUE : FALSE;
3372 user_ool_dsc->copy = copy_options;
3373 user_ool_dsc->type = dsc_type;
3374 user_ool_dsc->size = size;
3375
3376 user_dsc = (typeof(user_dsc))user_ool_dsc;
3377 } else if (is_64bit) {
3378 mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3379 user_ool_dsc--;
3380
3381 user_ool_dsc->address = rcv_addr;
3382 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3383 TRUE : FALSE;
3384 user_ool_dsc->copy = copy_options;
3385 user_ool_dsc->type = dsc_type;
3386 user_ool_dsc->size = size;
3387
3388 user_dsc = (typeof(user_dsc))user_ool_dsc;
3389 } else {
3390 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3391 user_ool_dsc--;
3392
3393 user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
3394 user_ool_dsc->size = size;
3395 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3396 TRUE : FALSE;
3397 user_ool_dsc->copy = copy_options;
3398 user_ool_dsc->type = dsc_type;
3399
3400 user_dsc = (typeof(user_dsc))user_ool_dsc;
3401 }
3402 return user_dsc;
3403 }
3404
3405 mach_msg_descriptor_t *
3406 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
3407 mach_msg_descriptor_t *user_dsc,
3408 int is_64bit,
3409 vm_map_t map,
3410 ipc_space_t space,
3411 ipc_kmsg_t kmsg,
3412 mach_msg_return_t *mr);
3413 mach_msg_descriptor_t *
3414 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
3415 mach_msg_descriptor_t *user_dsc,
3416 int is_64bit,
3417 vm_map_t map,
3418 ipc_space_t space,
3419 ipc_kmsg_t kmsg,
3420 mach_msg_return_t *mr)
3421 {
3422 mach_vm_offset_t rcv_addr;
3423 mach_msg_type_name_t disp;
3424 mach_msg_type_number_t count, i;
3425 vm_size_t ports_length, names_length;
3426
3427 mach_msg_copy_options_t copy_options = MACH_MSG_VIRTUAL_COPY;
3428
3429 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
3430
3431 count = dsc->count;
3432 disp = dsc->disposition;
3433 ports_length = count * sizeof(mach_port_t);
3434 names_length = count * sizeof(mach_port_name_t);
3435
3436 if (ports_length != 0 && dsc->address != 0) {
3437
3438 /*
3439 * Check to see if there is an overwrite descriptor
3440 * specified in the scatter list for this ool data.
3441 * The descriptor has already been verified.
3442 */
3443 #if 0
3444 if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
3445 if (differs) {
3446 OTHER_OOL_DESCRIPTOR *scatter_dsc;
3447
3448 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
3449 rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
3450 copy_options = scatter_dsc->copy;
3451 } else {
3452 mach_msg_ool_descriptor_t *scatter_dsc;
3453
3454 scatter_dsc = &saddr->out_of_line;
3455 rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
3456 copy_options = scatter_dsc->copy;
3457 }
3458 INCREMENT_SCATTER(saddr, sdsc_count, differs);
3459 }
3460 #endif
3461
3462 if (copy_options == MACH_MSG_VIRTUAL_COPY) {
3463 /*
3464 * Dynamically allocate the region
3465 */
3466 int anywhere = VM_MAKE_TAG(VM_MEMORY_MACH_MSG)|
3467 VM_FLAGS_ANYWHERE;
3468
3469 kern_return_t kr;
3470 if ((kr = mach_vm_allocate(map, &rcv_addr,
3471 (mach_vm_size_t)names_length,
3472 anywhere)) != KERN_SUCCESS) {
3473 ipc_kmsg_clean_body(kmsg, 1, (mach_msg_descriptor_t *)dsc);
3474 rcv_addr = 0;
3475
3476 if (kr == KERN_RESOURCE_SHORTAGE){
3477 *mr |= MACH_MSG_VM_KERNEL;
3478 } else {
3479 *mr |= MACH_MSG_VM_SPACE;
3480 }
3481 }
3482 }
3483
3484 /*
3485 * Handle the port rights and copy out the names
3486 * for those rights out to user-space.
3487 */
3488 if (rcv_addr != 0) {
3489 mach_port_t *objects = (mach_port_t *) dsc->address;
3490 mach_port_name_t *names = (mach_port_name_t *) dsc->address;
3491
3492 /* copyout port rights carried in the message */
3493
3494 for ( i = 0; i < count ; i++) {
3495 ipc_object_t object = (ipc_object_t)objects[i];
3496
3497 *mr |= ipc_kmsg_copyout_object(space, object,
3498 disp, &names[i]);
3499 }
3500
3501 /* copyout to memory allocated above */
3502 void *data = dsc->address;
3503 if (copyoutmap(map, data, rcv_addr, names_length) != KERN_SUCCESS)
3504 *mr |= MACH_MSG_VM_SPACE;
3505 kfree(data, ports_length);
3506 }
3507 } else {
3508 rcv_addr = 0;
3509 }
3510
3511 /*
3512 * Now update the descriptor based on the information
3513 * calculated above.
3514 */
3515 if(current_task() == kernel_task) {
3516 mach_msg_ool_ports_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3517 user_ool_dsc--;
3518
3519 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
3520 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3521 TRUE : FALSE;
3522 user_ool_dsc->copy = copy_options;
3523 user_ool_dsc->disposition = disp;
3524 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3525 user_ool_dsc->count = count;
3526
3527 user_dsc = (typeof(user_dsc))user_ool_dsc;
3528 } if (is_64bit) {
3529 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3530 user_ool_dsc--;
3531
3532 user_ool_dsc->address = rcv_addr;
3533 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3534 TRUE : FALSE;
3535 user_ool_dsc->copy = copy_options;
3536 user_ool_dsc->disposition = disp;
3537 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3538 user_ool_dsc->count = count;
3539
3540 user_dsc = (typeof(user_dsc))user_ool_dsc;
3541 } else {
3542 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3543 user_ool_dsc--;
3544
3545 user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
3546 user_ool_dsc->count = count;
3547 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3548 TRUE : FALSE;
3549 user_ool_dsc->copy = copy_options;
3550 user_ool_dsc->disposition = disp;
3551 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3552
3553 user_dsc = (typeof(user_dsc))user_ool_dsc;
3554 }
3555 return user_dsc;
3556 }
3557
3558 /*
3559 * Routine: ipc_kmsg_copyout_body
3560 * Purpose:
3561 * "Copy-out" port rights and out-of-line memory
3562 * in the body of a message.
3563 *
3564 * The error codes are a combination of special bits.
3565 * The copyout proceeds despite errors.
3566 * Conditions:
3567 * Nothing locked.
3568 * Returns:
3569 * MACH_MSG_SUCCESS Successful copyout.
3570 * MACH_MSG_IPC_SPACE No room for port right in name space.
3571 * MACH_MSG_VM_SPACE No room for memory in address space.
3572 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
3573 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
3574 * MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
3575 */
3576
3577 mach_msg_return_t
3578 ipc_kmsg_copyout_body(
3579 ipc_kmsg_t kmsg,
3580 ipc_space_t space,
3581 vm_map_t map,
3582 mach_msg_body_t *slist)
3583 {
3584 mach_msg_body_t *body;
3585 mach_msg_descriptor_t *kern_dsc, *user_dsc;
3586 mach_msg_descriptor_t *saddr;
3587 mach_msg_type_number_t dsc_count, sdsc_count;
3588 int i;
3589 mach_msg_return_t mr = MACH_MSG_SUCCESS;
3590 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
3591
3592 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3593 dsc_count = body->msgh_descriptor_count;
3594 kern_dsc = (mach_msg_descriptor_t *) (body + 1);
3595 /* Point user_dsc just after the end of all the descriptors */
3596 user_dsc = &kern_dsc[dsc_count];
3597
3598 /* Do scatter list setup */
3599 if (slist != MACH_MSG_BODY_NULL) {
3600 panic("Scatter lists disabled");
3601 saddr = (mach_msg_descriptor_t *) (slist + 1);
3602 sdsc_count = slist->msgh_descriptor_count;
3603 }
3604 else {
3605 saddr = MACH_MSG_DESCRIPTOR_NULL;
3606 sdsc_count = 0;
3607 }
3608
3609 /* Now process the descriptors */
3610 for (i = dsc_count-1; i >= 0; i--) {
3611 switch (kern_dsc[i].type.type) {
3612
3613 case MACH_MSG_PORT_DESCRIPTOR:
3614 user_dsc = ipc_kmsg_copyout_port_descriptor(&kern_dsc[i], user_dsc, space, &mr);
3615 break;
3616 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3617 case MACH_MSG_OOL_DESCRIPTOR :
3618 user_dsc = ipc_kmsg_copyout_ool_descriptor(
3619 (mach_msg_ool_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, &mr);
3620 break;
3621 case MACH_MSG_OOL_PORTS_DESCRIPTOR :
3622 user_dsc = ipc_kmsg_copyout_ool_ports_descriptor(
3623 (mach_msg_ool_ports_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, space, kmsg, &mr);
3624 break;
3625 default : {
3626 panic("untyped IPC copyout body: invalid message descriptor");
3627 }
3628 }
3629 }
3630
3631 if(user_dsc != kern_dsc) {
3632 vm_offset_t dsc_adjust = (vm_offset_t)user_dsc - (vm_offset_t)kern_dsc;
3633 memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
3634 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
3635 /* Update the message size for the smaller user representation */
3636 kmsg->ikm_header->msgh_size -= (mach_msg_size_t)dsc_adjust;
3637 }
3638
3639 return mr;
3640 }
3641
3642 /*
3643 * Routine: ipc_kmsg_copyout_size
3644 * Purpose:
3645 * Compute the size of the message as copied out to the given
3646 * map. If the destination map's pointers are a different size
3647 * than the kernel's, we have to allow for expansion/
3648 * contraction of the descriptors as appropriate.
3649 * Conditions:
3650 * Nothing locked.
3651 * Returns:
3652 * size of the message as it would be received.
3653 */
3654
3655 mach_msg_size_t
3656 ipc_kmsg_copyout_size(
3657 ipc_kmsg_t kmsg,
3658 vm_map_t map)
3659 {
3660 mach_msg_size_t send_size;
3661
3662 send_size = kmsg->ikm_header->msgh_size;
3663
3664 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
3665
3666 #if defined(__LP64__)
3667 send_size -= LEGACY_HEADER_SIZE_DELTA;
3668 #endif
3669
3670 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
3671
3672 mach_msg_body_t *body;
3673 mach_msg_descriptor_t *saddr, *eaddr;
3674
3675 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3676 saddr = (mach_msg_descriptor_t *) (body + 1);
3677 eaddr = saddr + body->msgh_descriptor_count;
3678
3679 for ( ; saddr < eaddr; saddr++ ) {
3680 switch (saddr->type.type) {
3681 case MACH_MSG_OOL_DESCRIPTOR:
3682 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3683 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3684 if(!is_task_64bit)
3685 send_size -= DESC_SIZE_ADJUSTMENT;
3686 break;
3687 case MACH_MSG_PORT_DESCRIPTOR:
3688 send_size -= DESC_SIZE_ADJUSTMENT;
3689 break;
3690 default:
3691 break;
3692 }
3693 }
3694 }
3695 return send_size;
3696 }
3697
3698 /*
3699 * Routine: ipc_kmsg_copyout
3700 * Purpose:
3701 * "Copy-out" port rights and out-of-line memory
3702 * in the message.
3703 * Conditions:
3704 * Nothing locked.
3705 * Returns:
3706 * MACH_MSG_SUCCESS Copied out all rights and memory.
3707 * MACH_RCV_INVALID_NOTIFY Bad notify port.
3708 * Rights and memory in the message are intact.
3709 * MACH_RCV_HEADER_ERROR + special bits
3710 * Rights and memory in the message are intact.
3711 * MACH_RCV_BODY_ERROR + special bits
3712 * The message header was successfully copied out.
3713 * As much of the body was handled as possible.
3714 */
3715
3716 mach_msg_return_t
3717 ipc_kmsg_copyout(
3718 ipc_kmsg_t kmsg,
3719 ipc_space_t space,
3720 vm_map_t map,
3721 mach_port_name_t notify,
3722 mach_msg_body_t *slist)
3723 {
3724 mach_msg_return_t mr;
3725
3726 mr = ipc_kmsg_copyout_header(kmsg->ikm_header, space, notify);
3727 if (mr != MACH_MSG_SUCCESS) {
3728 return mr;
3729 }
3730
3731 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
3732 mr = ipc_kmsg_copyout_body(kmsg, space, map, slist);
3733
3734 if (mr != MACH_MSG_SUCCESS)
3735 mr |= MACH_RCV_BODY_ERROR;
3736 }
3737
3738 return mr;
3739 }
3740
3741 /*
3742 * Routine: ipc_kmsg_copyout_pseudo
3743 * Purpose:
3744 * Does a pseudo-copyout of the message.
3745 * This is like a regular copyout, except
3746 * that the ports in the header are handled
3747 * as if they are in the body. They aren't reversed.
3748 *
3749 * The error codes are a combination of special bits.
3750 * The copyout proceeds despite errors.
3751 * Conditions:
3752 * Nothing locked.
3753 * Returns:
3754 * MACH_MSG_SUCCESS Successful copyout.
3755 * MACH_MSG_IPC_SPACE No room for port right in name space.
3756 * MACH_MSG_VM_SPACE No room for memory in address space.
3757 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
3758 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
3759 */
3760
3761 mach_msg_return_t
3762 ipc_kmsg_copyout_pseudo(
3763 ipc_kmsg_t kmsg,
3764 ipc_space_t space,
3765 vm_map_t map,
3766 mach_msg_body_t *slist)
3767 {
3768 mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
3769 ipc_object_t dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
3770 ipc_object_t reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
3771 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
3772 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
3773 mach_port_name_t dest_name, reply_name;
3774 mach_msg_return_t mr;
3775
3776 assert(IO_VALID(dest));
3777
3778 mr = (ipc_kmsg_copyout_object(space, dest, dest_type, &dest_name) |
3779 ipc_kmsg_copyout_object(space, reply, reply_type, &reply_name));
3780
3781 kmsg->ikm_header->msgh_bits = mbits &~ MACH_MSGH_BITS_CIRCULAR;
3782 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(dest_name);
3783 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(reply_name);
3784
3785 if (mbits & MACH_MSGH_BITS_COMPLEX) {
3786 mr |= ipc_kmsg_copyout_body(kmsg, space, map, slist);
3787 }
3788
3789 return mr;
3790 }
3791
3792 /*
3793 * Routine: ipc_kmsg_copyout_dest
3794 * Purpose:
3795 * Copies out the destination port in the message.
3796 * Destroys all other rights and memory in the message.
3797 * Conditions:
3798 * Nothing locked.
3799 */
3800
3801 void
3802 ipc_kmsg_copyout_dest(
3803 ipc_kmsg_t kmsg,
3804 ipc_space_t space)
3805 {
3806 mach_msg_bits_t mbits;
3807 ipc_object_t dest;
3808 ipc_object_t reply;
3809 mach_msg_type_name_t dest_type;
3810 mach_msg_type_name_t reply_type;
3811 mach_port_name_t dest_name, reply_name;
3812
3813 mbits = kmsg->ikm_header->msgh_bits;
3814 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
3815 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
3816 dest_type = MACH_MSGH_BITS_REMOTE(mbits);
3817 reply_type = MACH_MSGH_BITS_LOCAL(mbits);
3818
3819 assert(IO_VALID(dest));
3820
3821 io_lock(dest);
3822 if (io_active(dest)) {
3823 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
3824 /* dest is unlocked */
3825 } else {
3826 io_release(dest);
3827 io_check_unlock(dest);
3828 dest_name = MACH_PORT_DEAD;
3829 }
3830
3831 if (IO_VALID(reply)) {
3832 ipc_object_destroy(reply, reply_type);
3833 reply_name = MACH_PORT_NULL;
3834 } else
3835 reply_name = CAST_MACH_PORT_TO_NAME(reply);
3836
3837 kmsg->ikm_header->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
3838 MACH_MSGH_BITS(reply_type, dest_type));
3839 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
3840 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
3841
3842 if (mbits & MACH_MSGH_BITS_COMPLEX) {
3843 mach_msg_body_t *body;
3844
3845 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3846 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count,
3847 (mach_msg_descriptor_t *)(body + 1));
3848 }
3849 }
3850
3851 /*
3852 * Routine: ipc_kmsg_copyin_scatter
3853 * Purpose:
3854 * allocate and copyin a scatter list
3855 * Algorithm:
3856 * The gather (kmsg) is valid since it has been copied in.
3857 * Gather list descriptors are sequentially paired with scatter
3858 * list descriptors, with port descriptors in either list ignored.
3859 * Descriptors are consistent if the type fileds match and size
3860 * of the scatter descriptor is less than or equal to the
3861 * size of the gather descriptor. A MACH_MSG_ALLOCATE copy
3862 * strategy in a scatter descriptor matches any size in the
3863 * corresponding gather descriptor assuming they are the same type.
3864 * Either list may be larger than the other. During the
3865 * subsequent copy out, excess scatter descriptors are ignored
3866 * and excess gather descriptors default to dynamic allocation.
3867 *
3868 * In the case of a size error, the scatter list is released.
3869 * Conditions:
3870 * Nothing locked.
3871 * Returns:
3872 * the allocated message body containing the scatter list.
3873 */
3874
3875 mach_msg_body_t *
3876 ipc_kmsg_get_scatter(
3877 mach_vm_address_t msg_addr,
3878 mach_msg_size_t slist_size,
3879 ipc_kmsg_t kmsg)
3880 {
3881 mach_msg_body_t *slist;
3882 mach_msg_body_t *body;
3883 mach_msg_descriptor_t *gstart, *gend;
3884 mach_msg_descriptor_t *sstart, *send;
3885
3886 #if defined(__LP64__)
3887 panic("ipc_kmsg_get_scatter called!");
3888 #endif
3889
3890 if (slist_size < sizeof(mach_msg_base_t))
3891 return MACH_MSG_BODY_NULL;
3892
3893 slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
3894 slist = (mach_msg_body_t *)kalloc(slist_size);
3895 if (slist == MACH_MSG_BODY_NULL)
3896 return slist;
3897
3898 if (copyin(msg_addr + sizeof(mach_msg_header_t), (char *)slist, slist_size)) {
3899 kfree(slist, slist_size);
3900 return MACH_MSG_BODY_NULL;
3901 }
3902
3903 if ((slist->msgh_descriptor_count* sizeof(mach_msg_descriptor_t)
3904 + sizeof(mach_msg_size_t)) > slist_size) {
3905 kfree(slist, slist_size);
3906 return MACH_MSG_BODY_NULL;
3907 }
3908
3909 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3910 gstart = (mach_msg_descriptor_t *) (body + 1);
3911 gend = gstart + body->msgh_descriptor_count;
3912
3913 sstart = (mach_msg_descriptor_t *) (slist + 1);
3914 send = sstart + slist->msgh_descriptor_count;
3915
3916 while (gstart < gend) {
3917 mach_msg_descriptor_type_t g_type;
3918
3919 /*
3920 * Skip port descriptors in gather list.
3921 */
3922 g_type = gstart->type.type;
3923
3924 if (g_type != MACH_MSG_PORT_DESCRIPTOR) {
3925
3926 /*
3927 * A scatter list with a 0 descriptor count is treated as an
3928 * automatic size mismatch.
3929 */
3930 if (slist->msgh_descriptor_count == 0) {
3931 kfree(slist, slist_size);
3932 return MACH_MSG_BODY_NULL;
3933 }
3934
3935 /*
3936 * Skip port descriptors in scatter list.
3937 */
3938 while (sstart < send) {
3939 if (sstart->type.type != MACH_MSG_PORT_DESCRIPTOR)
3940 break;
3941 sstart++;
3942 }
3943
3944 /*
3945 * No more scatter descriptors, we're done
3946 */
3947 if (sstart >= send) {
3948 break;
3949 }
3950
3951 /*
3952 * Check type, copy and size fields
3953 */
3954 if (g_type == MACH_MSG_OOL_DESCRIPTOR ||
3955 g_type == MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
3956 if (sstart->type.type != MACH_MSG_OOL_DESCRIPTOR &&
3957 sstart->type.type != MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
3958 kfree(slist, slist_size);
3959 return MACH_MSG_BODY_NULL;
3960 }
3961 if (sstart->out_of_line.copy == MACH_MSG_OVERWRITE &&
3962 gstart->out_of_line.size > sstart->out_of_line.size) {
3963 kfree(slist, slist_size);
3964 return MACH_MSG_BODY_NULL;
3965 }
3966 }
3967 else {
3968 if (sstart->type.type != MACH_MSG_OOL_PORTS_DESCRIPTOR) {
3969 kfree(slist, slist_size);
3970 return MACH_MSG_BODY_NULL;
3971 }
3972 if (sstart->ool_ports.copy == MACH_MSG_OVERWRITE &&
3973 gstart->ool_ports.count > sstart->ool_ports.count) {
3974 kfree(slist, slist_size);
3975 return MACH_MSG_BODY_NULL;
3976 }
3977 }
3978 sstart++;
3979 }
3980 gstart++;
3981 }
3982 return slist;
3983 }
3984
3985
3986 /*
3987 * Routine: ipc_kmsg_free_scatter
3988 * Purpose:
3989 * Deallocate a scatter list. Since we actually allocated
3990 * a body without a header, and since the header was originally
3991 * accounted for in slist_size, we have to ajust it down
3992 * before freeing the scatter list.
3993 */
3994 void
3995 ipc_kmsg_free_scatter(
3996 mach_msg_body_t *slist,
3997 mach_msg_size_t slist_size)
3998 {
3999 #if defined(__LP64__)
4000 panic("%s called; halting!", __func__);
4001 #endif
4002
4003 slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
4004 kfree(slist, slist_size);
4005 }
4006
4007
4008 /*
4009 * Routine: ipc_kmsg_copyout_to_kernel
4010 * Purpose:
4011 * Copies out the destination and reply ports in the message.
4012 * Leaves all other rights and memory in the message alone.
4013 * Conditions:
4014 * Nothing locked.
4015 *
4016 * Derived from ipc_kmsg_copyout_dest.
4017 * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
4018 * We really do want to save rights and memory.
4019 */
4020
4021 void
4022 ipc_kmsg_copyout_to_kernel(
4023 ipc_kmsg_t kmsg,
4024 ipc_space_t space)
4025 {
4026 ipc_object_t dest;
4027 ipc_object_t reply;
4028 mach_msg_type_name_t dest_type;
4029 mach_msg_type_name_t reply_type;
4030 mach_port_name_t dest_name, reply_name;
4031
4032 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4033 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
4034 dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
4035 reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
4036
4037 assert(IO_VALID(dest));
4038
4039 io_lock(dest);
4040 if (io_active(dest)) {
4041 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4042 /* dest is unlocked */
4043 } else {
4044 io_release(dest);
4045 io_check_unlock(dest);
4046 dest_name = MACH_PORT_DEAD;
4047 }
4048
4049 reply_name = CAST_MACH_PORT_TO_NAME(reply);
4050
4051 kmsg->ikm_header->msgh_bits =
4052 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
4053 MACH_MSGH_BITS(reply_type, dest_type));
4054 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
4055 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
4056 }
4057
4058 #if IKM_SUPPORT_LEGACY
4059 void
4060 ipc_kmsg_copyout_to_kernel_legacy(
4061 ipc_kmsg_t kmsg,
4062 ipc_space_t space)
4063 {
4064 ipc_object_t dest;
4065 ipc_object_t reply;
4066 mach_msg_type_name_t dest_type;
4067 mach_msg_type_name_t reply_type;
4068 mach_port_name_t dest_name, reply_name;
4069
4070 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4071 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
4072 dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
4073 reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
4074
4075 assert(IO_VALID(dest));
4076
4077 io_lock(dest);
4078 if (io_active(dest)) {
4079 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4080 /* dest is unlocked */
4081 } else {
4082 io_release(dest);
4083 io_check_unlock(dest);
4084 dest_name = MACH_PORT_DEAD;
4085 }
4086
4087 reply_name = CAST_MACH_PORT_TO_NAME(reply);
4088
4089 kmsg->ikm_header->msgh_bits =
4090 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
4091 MACH_MSGH_BITS(reply_type, dest_type));
4092 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
4093 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
4094
4095 mach_msg_descriptor_t *saddr;
4096 mach_msg_legacy_descriptor_t *daddr;
4097 mach_msg_type_number_t i, count = ((mach_msg_base_t *)kmsg->ikm_header)->body.msgh_descriptor_count;
4098 saddr = (mach_msg_descriptor_t *) (((mach_msg_base_t *)kmsg->ikm_header) + 1);
4099 saddr = &saddr[count-1];
4100 daddr = (mach_msg_legacy_descriptor_t *)&saddr[count];
4101 daddr--;
4102
4103 vm_offset_t dsc_adjust = 0;
4104
4105 for (i = 0; i < count; i++, saddr--, daddr--) {
4106 switch (saddr->type.type) {
4107 case MACH_MSG_PORT_DESCRIPTOR: {
4108 mach_msg_port_descriptor_t *dsc = &saddr->port;
4109 mach_msg_legacy_port_descriptor_t *dest_dsc = &daddr->port;
4110
4111 mach_port_t name = dsc->name;
4112 mach_msg_type_name_t disposition = dsc->disposition;
4113
4114 dest_dsc->name = CAST_MACH_PORT_TO_NAME(name);
4115 dest_dsc->disposition = disposition;
4116 dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
4117 break;
4118 }
4119 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4120 case MACH_MSG_OOL_DESCRIPTOR: {
4121 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
4122 * so we don't need to do anything special. */
4123
4124 mach_msg_ool_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->out_of_line;
4125
4126 mach_msg_ool_descriptor32_t *dest_dsc = &daddr->out_of_line32;
4127
4128 vm_offset_t address = (vm_offset_t)source_dsc->address;
4129 vm_size_t size = source_dsc->size;
4130 boolean_t deallocate = source_dsc->deallocate;
4131 mach_msg_copy_options_t copy = source_dsc->copy;
4132 mach_msg_descriptor_type_t type = source_dsc->type;
4133
4134 dest_dsc->address = address;
4135 dest_dsc->size = size;
4136 dest_dsc->deallocate = deallocate;
4137 dest_dsc->copy = copy;
4138 dest_dsc->type = type;
4139 break;
4140 }
4141 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
4142 mach_msg_ool_ports_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->ool_ports;
4143
4144 mach_msg_ool_ports_descriptor32_t *dest_dsc = &daddr->ool_ports32;
4145
4146 vm_offset_t address = (vm_offset_t)source_dsc->address;
4147 vm_size_t port_count = source_dsc->count;
4148 boolean_t deallocate = source_dsc->deallocate;
4149 mach_msg_copy_options_t copy = source_dsc->copy;
4150 mach_msg_descriptor_type_t type = source_dsc->type;
4151
4152 dest_dsc->address = address;
4153 dest_dsc->count = port_count;
4154 dest_dsc->deallocate = deallocate;
4155 dest_dsc->copy = copy;
4156 dest_dsc->type = type;
4157 break;
4158 }
4159 default: {
4160 #if MACH_ASSERT
4161 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
4162 #endif /* MACH_ASSERT */
4163 }
4164 }
4165 }
4166
4167 if(count) {
4168 dsc_adjust = 4*count;
4169 memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
4170 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
4171 /* Update the message size for the smaller user representation */
4172 kmsg->ikm_header->msgh_size -= dsc_adjust;
4173 }
4174 }
4175 #endif /* IKM_SUPPORT_LEGACY */
4176
4177
4178 #include <mach_kdb.h>
4179 #if MACH_KDB
4180
4181 #include <ddb/db_output.h>
4182 #include <ipc/ipc_print.h>
4183 /*
4184 * Forward declarations
4185 */
4186 void ipc_msg_print_untyped(
4187 mach_msg_body_t *body);
4188
4189 const char * ipc_type_name(
4190 int type_name,
4191 boolean_t received);
4192
4193 const char *
4194 msgh_bit_decode(
4195 mach_msg_bits_t bit);
4196
4197 const char *
4198 mm_copy_options_string(
4199 mach_msg_copy_options_t option);
4200
4201 void db_print_msg_uid(mach_msg_header_t *);
4202
4203
4204 const char *
4205 ipc_type_name(
4206 int type_name,
4207 boolean_t received)
4208 {
4209 switch (type_name) {
4210 case MACH_MSG_TYPE_PORT_NAME:
4211 return "port_name";
4212
4213 case MACH_MSG_TYPE_MOVE_RECEIVE:
4214 if (received) {
4215 return "port_receive";
4216 } else {
4217 return "move_receive";
4218 }
4219
4220 case MACH_MSG_TYPE_MOVE_SEND:
4221 if (received) {
4222 return "port_send";
4223 } else {
4224 return "move_send";
4225 }
4226
4227 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
4228 if (received) {
4229 return "port_send_once";
4230 } else {
4231 return "move_send_once";
4232 }
4233
4234 case MACH_MSG_TYPE_COPY_SEND:
4235 return "copy_send";
4236
4237 case MACH_MSG_TYPE_MAKE_SEND:
4238 return "make_send";
4239
4240 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
4241 return "make_send_once";
4242
4243 default:
4244 return (char *) 0;
4245 }
4246 }
4247
4248 void
4249 ipc_print_type_name(
4250 int type_name)
4251 {
4252 const char *name = ipc_type_name(type_name, TRUE);
4253 if (name) {
4254 printf("%s", name);
4255 } else {
4256 printf("type%d", type_name);
4257 }
4258 }
4259
4260 /*
4261 * ipc_kmsg_print [ debug ]
4262 */
4263 void
4264 ipc_kmsg_print(
4265 ipc_kmsg_t kmsg)
4266 {
4267 iprintf("kmsg=0x%x\n", kmsg);
4268 iprintf("ikm_next=0x%x, prev=0x%x, size=%d",
4269 kmsg->ikm_next,
4270 kmsg->ikm_prev,
4271 kmsg->ikm_size);
4272 printf("\n");
4273 ipc_msg_print(kmsg->ikm_header);
4274 }
4275
4276 const char *
4277 msgh_bit_decode(
4278 mach_msg_bits_t bit)
4279 {
4280 switch (bit) {
4281 case MACH_MSGH_BITS_COMPLEX: return "complex";
4282 case MACH_MSGH_BITS_CIRCULAR: return "circular";
4283 default: return (char *) 0;
4284 }
4285 }
4286
4287 /*
4288 * ipc_msg_print [ debug ]
4289 */
4290 void
4291 ipc_msg_print(
4292 mach_msg_header_t *msgh)
4293 {
4294 mach_msg_bits_t mbits;
4295 unsigned int bit, i;
4296 const char *bit_name;
4297 int needs_comma;
4298
4299 mbits = msgh->msgh_bits;
4300 iprintf("msgh_bits=0x%x: l=0x%x,r=0x%x\n",
4301 mbits,
4302 MACH_MSGH_BITS_LOCAL(msgh->msgh_bits),
4303 MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
4304
4305 mbits = MACH_MSGH_BITS_OTHER(mbits) & MACH_MSGH_BITS_USED;
4306 db_indent += 2;
4307 if (mbits)
4308 iprintf("decoded bits: ");
4309 needs_comma = 0;
4310 for (i = 0, bit = 1; i < sizeof(mbits) * 8; ++i, bit <<= 1) {
4311 if ((mbits & bit) == 0)
4312 continue;
4313 bit_name = msgh_bit_decode((mach_msg_bits_t)bit);
4314 if (bit_name)
4315 printf("%s%s", needs_comma ? "," : "", bit_name);
4316 else
4317 printf("%sunknown(0x%x),", needs_comma ? "," : "", bit);
4318 ++needs_comma;
4319 }
4320 if (msgh->msgh_bits & ~MACH_MSGH_BITS_USED) {
4321 printf("%sunused=0x%x,", needs_comma ? "," : "",
4322 msgh->msgh_bits & ~MACH_MSGH_BITS_USED);
4323 }
4324 printf("\n");
4325 db_indent -= 2;
4326
4327 needs_comma = 1;
4328 if (msgh->msgh_remote_port) {
4329 iprintf("remote=0x%x(", msgh->msgh_remote_port);
4330 ipc_print_type_name(MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
4331 printf(")");
4332 } else {
4333 iprintf("remote=null");
4334 }
4335
4336 if (msgh->msgh_local_port) {
4337 printf("%slocal=%p(", needs_comma ? "," : "",
4338 msgh->msgh_local_port);
4339 ipc_print_type_name(MACH_MSGH_BITS_LOCAL(msgh->msgh_bits));
4340 printf(")\n");
4341 } else {
4342 printf("local=null\n");
4343 }
4344
4345 iprintf("msgh_id=%d, size=%d\n",
4346 msgh->msgh_id,
4347 msgh->msgh_size);
4348
4349 if (mbits & MACH_MSGH_BITS_COMPLEX) {
4350 ipc_msg_print_untyped((mach_msg_body_t *) (msgh + 1));
4351 }
4352 }
4353
4354
4355 const char *
4356 mm_copy_options_string(
4357 mach_msg_copy_options_t option)
4358 {
4359 const char *name;
4360
4361 switch (option) {
4362 case MACH_MSG_PHYSICAL_COPY:
4363 name = "PHYSICAL";
4364 break;
4365 case MACH_MSG_VIRTUAL_COPY:
4366 name = "VIRTUAL";
4367 break;
4368 case MACH_MSG_OVERWRITE:
4369 name = "OVERWRITE";
4370 break;
4371 case MACH_MSG_ALLOCATE:
4372 name = "ALLOCATE";
4373 break;
4374 case MACH_MSG_KALLOC_COPY_T:
4375 name = "KALLOC_COPY_T";
4376 break;
4377 default:
4378 name = "unknown";
4379 break;
4380 }
4381 return name;
4382 }
4383
4384 void
4385 ipc_msg_print_untyped(
4386 mach_msg_body_t *body)
4387 {
4388 mach_msg_descriptor_t *saddr, *send;
4389 mach_msg_descriptor_type_t type;
4390
4391 iprintf("%d descriptors %d: \n", body->msgh_descriptor_count);
4392
4393 saddr = (mach_msg_descriptor_t *) (body + 1);
4394 send = saddr + body->msgh_descriptor_count;
4395
4396 for ( ; saddr < send; saddr++ ) {
4397
4398 type = saddr->type.type;
4399
4400 switch (type) {
4401
4402 case MACH_MSG_PORT_DESCRIPTOR: {
4403 mach_msg_port_descriptor_t *dsc;
4404
4405 dsc = &saddr->port;
4406 iprintf("-- PORT name = 0x%x disp = ", dsc->name);
4407 ipc_print_type_name(dsc->disposition);
4408 printf("\n");
4409 break;
4410 }
4411 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4412 case MACH_MSG_OOL_DESCRIPTOR: {
4413 mach_msg_ool_descriptor_t *dsc;
4414
4415 dsc = &saddr->out_of_line;
4416 iprintf("-- OOL%s addr = 0x%x size = 0x%x copy = %s %s\n",
4417 type == MACH_MSG_OOL_DESCRIPTOR ? "" : " VOLATILE",
4418 dsc->address, dsc->size,
4419 mm_copy_options_string(dsc->copy),
4420 dsc->deallocate ? "DEALLOC" : "");
4421 break;
4422 }
4423 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
4424 mach_msg_ool_ports_descriptor_t *dsc;
4425
4426 dsc = &saddr->ool_ports;
4427
4428 iprintf("-- OOL_PORTS addr = 0x%x count = 0x%x ",
4429 dsc->address, dsc->count);
4430 printf("disp = ");
4431 ipc_print_type_name(dsc->disposition);
4432 printf(" copy = %s %s\n",
4433 mm_copy_options_string(dsc->copy),
4434 dsc->deallocate ? "DEALLOC" : "");
4435 break;
4436 }
4437
4438 default: {
4439 iprintf("-- UNKNOWN DESCRIPTOR 0x%x\n", type);
4440 break;
4441 }
4442 }
4443 }
4444 }
4445 #endif /* MACH_KDB */