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