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