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