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