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