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