]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ipc/ipc_kmsg.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_kmsg.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
2d21ac55
A
56/*
57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
58 * support for mandatory and extensible security protections. This notice
59 * is included in support of clause 2.2 (b) of the Apple Public License,
60 * Version 2.0.
61 * Copyright (c) 2005 SPARTA, Inc.
62 */
1c79356b
A
63/*
64 */
65/*
66 * File: ipc/ipc_kmsg.c
67 * Author: Rich Draves
68 * Date: 1989
69 *
70 * Operations on kernel messages.
71 */
72
1c79356b 73
91447636 74#include <mach/mach_types.h>
1c79356b
A
75#include <mach/boolean.h>
76#include <mach/kern_return.h>
77#include <mach/message.h>
78#include <mach/port.h>
91447636
A
79#include <mach/vm_map.h>
80#include <mach/mach_vm.h>
1c79356b 81#include <mach/vm_statistics.h>
91447636
A
82
83#include <kern/kern_types.h>
1c79356b 84#include <kern/assert.h>
b0d623f7 85#include <kern/debug.h>
91447636 86#include <kern/ipc_kobject.h>
1c79356b 87#include <kern/kalloc.h>
91447636
A
88#include <kern/zalloc.h>
89#include <kern/processor.h>
1c79356b
A
90#include <kern/thread.h>
91#include <kern/sched_prim.h>
92#include <kern/spl.h>
93#include <kern/misc_protos.h>
94#include <kern/counters.h>
91447636
A
95#include <kern/cpu_data.h>
96
b0d623f7
A
97#include <machine/machlimits.h>
98
1c79356b
A
99#include <vm/vm_map.h>
100#include <vm/vm_object.h>
101#include <vm/vm_kern.h>
91447636 102
1c79356b 103#include <ipc/port.h>
91447636 104#include <ipc/ipc_types.h>
1c79356b
A
105#include <ipc/ipc_entry.h>
106#include <ipc/ipc_kmsg.h>
107#include <ipc/ipc_notify.h>
108#include <ipc/ipc_object.h>
109#include <ipc/ipc_space.h>
110#include <ipc/ipc_port.h>
111#include <ipc/ipc_right.h>
112#include <ipc/ipc_hash.h>
113#include <ipc/ipc_table.h>
114
2d21ac55
A
115#include <security/mac_mach_internal.h>
116
1c79356b
A
117#include <string.h>
118
55e303ae
A
119#ifdef ppc
120#include <ppc/Firmware.h>
121#include <ppc/low_trace.h>
122#endif
123
b0d623f7
A
124#if DEBUG
125#define DEBUG_MSGS_K64 1
126#endif
127
39236c6e
A
128#include <sys/kdebug.h>
129#include <libkern/OSAtomic.h>
130
b0d623f7
A
131#pragma pack(4)
132
133typedef struct
134{
135 mach_msg_bits_t msgh_bits;
136 mach_msg_size_t msgh_size;
137 uint32_t msgh_remote_port;
138 uint32_t msgh_local_port;
139 mach_msg_size_t msgh_reserved;
140 mach_msg_id_t msgh_id;
141} mach_msg_legacy_header_t;
142
143typedef struct
144{
145 mach_msg_legacy_header_t header;
146 mach_msg_body_t body;
147} mach_msg_legacy_base_t;
148
149typedef struct
150{
151 mach_port_name_t name;
152 mach_msg_size_t pad1;
153 uint32_t pad2 : 16;
154 mach_msg_type_name_t disposition : 8;
155 mach_msg_descriptor_type_t type : 8;
156} mach_msg_legacy_port_descriptor_t;
157
158
159typedef union
160{
161 mach_msg_legacy_port_descriptor_t port;
162 mach_msg_ool_descriptor32_t out_of_line32;
163 mach_msg_ool_ports_descriptor32_t ool_ports32;
164 mach_msg_type_descriptor_t type;
165} mach_msg_legacy_descriptor_t;
166
167#pragma pack()
168
169#define LEGACY_HEADER_SIZE_DELTA ((mach_msg_size_t)(sizeof(mach_msg_header_t) - sizeof(mach_msg_legacy_header_t)))
170// END LP64 fixes
171
172
173#if DEBUG_MSGS_K64
174extern void ipc_pset_print64(
175 ipc_pset_t pset);
176
177extern void ipc_kmsg_print64(
178 ipc_kmsg_t kmsg,
179 const char *str);
180
181extern void ipc_msg_print64(
182 mach_msg_header_t *msgh);
183
184extern ipc_port_t ipc_name_to_data64(
185 task_t task,
186 mach_port_name_t name);
187
188/*
189 * Forward declarations
190 */
191void ipc_msg_print_untyped64(
192 mach_msg_body_t *body);
193
194const char * ipc_type_name64(
195 int type_name,
196 boolean_t received);
197
198void ipc_print_type_name64(
199 int type_name);
200
201const char *
202msgh_bit_decode64(
203 mach_msg_bits_t bit);
204
205const char *
206mm_copy_options_string64(
207 mach_msg_copy_options_t option);
208
209void db_print_msg_uid64(mach_msg_header_t *);
210
211static void
212ipc_msg_body_print64(void *body, int size)
213{
214 uint32_t *word = (uint32_t *) body;
215 uint32_t *end = (uint32_t *)(((uintptr_t) body) + size
216 - sizeof(mach_msg_header_t));
217 int i;
218
219 kprintf(" body(%p-%p):\n %p: ", body, end, word);
220 for (;;) {
221 for (i = 0; i < 8; i++, word++) {
222 if (word >= end) {
223 kprintf("\n");
224 return;
225 }
226 kprintf("%08x ", *word);
227 }
228 kprintf("\n %p: ", word);
229 }
230}
231
232
233const char *
234ipc_type_name64(
235 int type_name,
236 boolean_t received)
237{
238 switch (type_name) {
239 case MACH_MSG_TYPE_PORT_NAME:
240 return "port_name";
241
242 case MACH_MSG_TYPE_MOVE_RECEIVE:
243 if (received) {
244 return "port_receive";
245 } else {
246 return "move_receive";
247 }
248
249 case MACH_MSG_TYPE_MOVE_SEND:
250 if (received) {
251 return "port_send";
252 } else {
253 return "move_send";
254 }
255
256 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
257 if (received) {
258 return "port_send_once";
259 } else {
260 return "move_send_once";
261 }
262
263 case MACH_MSG_TYPE_COPY_SEND:
264 return "copy_send";
265
266 case MACH_MSG_TYPE_MAKE_SEND:
267 return "make_send";
268
269 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
270 return "make_send_once";
271
272 default:
273 return (char *) 0;
274 }
275}
276
277void
278ipc_print_type_name64(
279 int type_name)
280{
281 const char *name = ipc_type_name64(type_name, TRUE);
282 if (name) {
283 kprintf("%s", name);
284 } else {
285 kprintf("type%d", type_name);
286 }
287}
288
289/*
290 * ipc_kmsg_print64 [ debug ]
291 */
292void
293ipc_kmsg_print64(
294 ipc_kmsg_t kmsg,
295 const char *str)
296{
297 kprintf("%s kmsg=%p:\n", str, kmsg);
298 kprintf(" next=%p, prev=%p, size=%d",
299 kmsg->ikm_next,
300 kmsg->ikm_prev,
301 kmsg->ikm_size);
302 kprintf("\n");
303 ipc_msg_print64(kmsg->ikm_header);
304}
305
306const char *
307msgh_bit_decode64(
308 mach_msg_bits_t bit)
309{
310 switch (bit) {
311 case MACH_MSGH_BITS_COMPLEX: return "complex";
312 case MACH_MSGH_BITS_CIRCULAR: return "circular";
313 default: return (char *) 0;
314 }
315}
316
317/*
318 * ipc_msg_print64 [ debug ]
319 */
320void
321ipc_msg_print64(
322 mach_msg_header_t *msgh)
323{
324 mach_msg_bits_t mbits;
325 unsigned int bit, i;
326 const char *bit_name;
327 int needs_comma;
328
329 mbits = msgh->msgh_bits;
330 kprintf(" msgh_bits=0x%x: l=0x%x,r=0x%x\n",
331 mbits,
332 MACH_MSGH_BITS_LOCAL(msgh->msgh_bits),
333 MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
334
335 mbits = MACH_MSGH_BITS_OTHER(mbits) & MACH_MSGH_BITS_USED;
336 kprintf(" decoded bits: ");
337 needs_comma = 0;
338 for (i = 0, bit = 1; i < sizeof(mbits) * 8; ++i, bit <<= 1) {
339 if ((mbits & bit) == 0)
340 continue;
341 bit_name = msgh_bit_decode64((mach_msg_bits_t)bit);
342 if (bit_name)
343 kprintf("%s%s", needs_comma ? "," : "", bit_name);
344 else
345 kprintf("%sunknown(0x%x),", needs_comma ? "," : "", bit);
346 ++needs_comma;
347 }
348 if (msgh->msgh_bits & ~MACH_MSGH_BITS_USED) {
349 kprintf("%sunused=0x%x,", needs_comma ? "," : "",
350 msgh->msgh_bits & ~MACH_MSGH_BITS_USED);
351 }
352 kprintf("\n");
353
354 needs_comma = 1;
355 if (msgh->msgh_remote_port) {
356 kprintf(" remote=%p(", msgh->msgh_remote_port);
357 ipc_print_type_name64(MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
358 kprintf(")");
359 } else {
360 kprintf(" remote=null");
361 }
362
363 if (msgh->msgh_local_port) {
364 kprintf("%slocal=%p(", needs_comma ? "," : "",
365 msgh->msgh_local_port);
366 ipc_print_type_name64(MACH_MSGH_BITS_LOCAL(msgh->msgh_bits));
367 kprintf(")\n");
368 } else {
369 kprintf("local=null\n");
370 }
371
372 kprintf(" msgh_id=%d, size=%d\n",
373 msgh->msgh_id,
374 msgh->msgh_size);
375
376 if (mbits & MACH_MSGH_BITS_COMPLEX) {
377 ipc_msg_print_untyped64((mach_msg_body_t *) (msgh + 1));
378 }
379
380 ipc_msg_body_print64((void *)(msgh + 1), msgh->msgh_size);
381}
382
383
384const char *
385mm_copy_options_string64(
386 mach_msg_copy_options_t option)
387{
388 const char *name;
389
390 switch (option) {
391 case MACH_MSG_PHYSICAL_COPY:
392 name = "PHYSICAL";
393 break;
394 case MACH_MSG_VIRTUAL_COPY:
395 name = "VIRTUAL";
396 break;
397 case MACH_MSG_OVERWRITE:
398 name = "OVERWRITE";
399 break;
400 case MACH_MSG_ALLOCATE:
401 name = "ALLOCATE";
402 break;
403 case MACH_MSG_KALLOC_COPY_T:
404 name = "KALLOC_COPY_T";
405 break;
406 default:
407 name = "unknown";
408 break;
409 }
410 return name;
411}
412
413void
414ipc_msg_print_untyped64(
415 mach_msg_body_t *body)
416{
417 mach_msg_descriptor_t *saddr, *send;
418 mach_msg_descriptor_type_t type;
419
420 kprintf(" %d descriptors: \n", body->msgh_descriptor_count);
421
422 saddr = (mach_msg_descriptor_t *) (body + 1);
423 send = saddr + body->msgh_descriptor_count;
424
425 for ( ; saddr < send; saddr++ ) {
426
427 type = saddr->type.type;
428
429 switch (type) {
430
431 case MACH_MSG_PORT_DESCRIPTOR: {
432 mach_msg_port_descriptor_t *dsc;
433
434 dsc = &saddr->port;
435 kprintf(" PORT name = %p disp = ", dsc->name);
436 ipc_print_type_name64(dsc->disposition);
437 kprintf("\n");
438 break;
439 }
440 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
441 case MACH_MSG_OOL_DESCRIPTOR: {
442 mach_msg_ool_descriptor_t *dsc;
443
444 dsc = (mach_msg_ool_descriptor_t *) &saddr->out_of_line;
445 kprintf(" OOL%s addr = %p size = 0x%x copy = %s %s\n",
446 type == MACH_MSG_OOL_DESCRIPTOR ? "" : " VOLATILE",
447 dsc->address, dsc->size,
448 mm_copy_options_string64(dsc->copy),
449 dsc->deallocate ? "DEALLOC" : "");
450 break;
451 }
452 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
453 mach_msg_ool_ports_descriptor_t *dsc;
454
455 dsc = (mach_msg_ool_ports_descriptor_t *) &saddr->ool_ports;
456
457 kprintf(" OOL_PORTS addr = %p count = 0x%x ",
458 dsc->address, dsc->count);
459 kprintf("disp = ");
460 ipc_print_type_name64(dsc->disposition);
461 kprintf(" copy = %s %s\n",
462 mm_copy_options_string64(dsc->copy),
463 dsc->deallocate ? "DEALLOC" : "");
464 break;
465 }
466
467 default: {
468 kprintf(" UNKNOWN DESCRIPTOR 0x%x\n", type);
469 break;
470 }
471 }
472 }
473}
474
475#define DEBUG_IPC_KMSG_PRINT(kmsg,string) \
476 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
477 ipc_kmsg_print64(kmsg, string); \
478 }
479#define DEBUG_IPC_MSG_BODY_PRINT(body,size) \
480 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) { \
481 ipc_msg_body_print64(body,size);\
482 }
483#else /* !DEBUG_MSGS_K64 */
484#define DEBUG_IPC_KMSG_PRINT(kmsg,string)
485#define DEBUG_IPC_MSG_BODY_PRINT(body,size)
486#endif /* !DEBUG_MSGS_K64 */
55e303ae 487
1c79356b 488extern vm_map_t ipc_kernel_copy_map;
316670eb 489extern vm_size_t ipc_kmsg_max_space;
1c79356b 490extern vm_size_t ipc_kmsg_max_vm_space;
316670eb 491extern vm_size_t ipc_kmsg_max_body_space;
1c79356b
A
492extern vm_size_t msg_ool_size_small;
493
494#define MSG_OOL_SIZE_SMALL msg_ool_size_small
495
91447636
A
496#if defined(__LP64__)
497#define MAP_SIZE_DIFFERS(map) (map->max_offset < MACH_VM_MAX_ADDRESS)
498#define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor32_t
499#define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor32_t
500#else
501#define MAP_SIZE_DIFFERS(map) (map->max_offset > VM_MAX_ADDRESS)
502#define OTHER_OOL_DESCRIPTOR mach_msg_ool_descriptor64_t
503#define OTHER_OOL_PORTS_DESCRIPTOR mach_msg_ool_ports_descriptor64_t
504#endif
505
b0d623f7
A
506#define DESC_SIZE_ADJUSTMENT ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
507 sizeof(mach_msg_ool_descriptor32_t)))
91447636
A
508
509/* scatter list macros */
510
511#define SKIP_PORT_DESCRIPTORS(s, c) \
512MACRO_BEGIN \
513 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
514 while ((c) > 0) { \
515 if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
516 break; \
517 (s)++; (c)--; \
518 } \
519 if (c == 0) \
520 (s) = MACH_MSG_DESCRIPTOR_NULL; \
521 } \
522MACRO_END
523
524#define INCREMENT_SCATTER(s, c, d) \
525MACRO_BEGIN \
526 if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
527 s = (d) ? (mach_msg_descriptor_t *) \
528 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) : \
529 (s + 1); \
530 (c)--; \
531 } \
532MACRO_END
533
534/* zone for cached ipc_kmsg_t structures */
535zone_t ipc_kmsg_zone;
1c79356b
A
536
537/*
538 * Forward declarations
539 */
540
541void ipc_kmsg_clean(
542 ipc_kmsg_t kmsg);
543
544void ipc_kmsg_clean_body(
545 ipc_kmsg_t kmsg,
91447636
A
546 mach_msg_type_number_t number,
547 mach_msg_descriptor_t *desc);
1c79356b
A
548
549void ipc_kmsg_clean_partial(
550 ipc_kmsg_t kmsg,
551 mach_msg_type_number_t number,
91447636 552 mach_msg_descriptor_t *desc,
1c79356b
A
553 vm_offset_t paddr,
554 vm_size_t length);
555
1c79356b
A
556mach_msg_return_t ipc_kmsg_copyin_body(
557 ipc_kmsg_t kmsg,
558 ipc_space_t space,
559 vm_map_t map);
560
1c79356b
A
561/*
562 * We keep a per-processor cache of kernel message buffers.
563 * The cache saves the overhead/locking of using kalloc/kfree.
564 * The per-processor cache seems to miss less than a per-thread cache,
565 * and it also uses less memory. Access to the cache doesn't
566 * require locking.
567 */
1c79356b
A
568
569/*
570 * Routine: ipc_kmsg_alloc
571 * Purpose:
572 * Allocate a kernel message structure. If we can get one from
573 * the cache, that is best. Otherwise, allocate a new one.
574 * Conditions:
575 * Nothing locked.
576 */
577ipc_kmsg_t
578ipc_kmsg_alloc(
579 mach_msg_size_t msg_and_trailer_size)
580{
91447636 581 mach_msg_size_t max_expanded_size;
1c79356b
A
582 ipc_kmsg_t kmsg;
583
91447636
A
584 /*
585 * LP64support -
586 * Pad the allocation in case we need to expand the
587 * message descrptors for user spaces with pointers larger than
b0d623f7 588 * the kernel's own, or vice versa. We don't know how many descriptors
91447636
A
589 * there are yet, so just assume the whole body could be
590 * descriptors (if there could be any at all).
591 *
592 * The expansion space is left in front of the header,
593 * because it is easier to pull the header and descriptors
594 * forward as we process them than it is to push all the
595 * data backwards.
596 */
8ad349bb 597 mach_msg_size_t size = msg_and_trailer_size - MAX_TRAILER_SIZE;
316670eb
A
598
599 /* compare against implementation upper limit for the body */
600 if (size > ipc_kmsg_max_body_space)
601 return IKM_NULL;
602
8ad349bb 603 if (size > sizeof(mach_msg_base_t)) {
b0d623f7
A
604 mach_msg_size_t max_desc = (mach_msg_size_t)(((size - sizeof(mach_msg_base_t)) /
605 sizeof(mach_msg_ool_descriptor32_t)) *
606 DESC_SIZE_ADJUSTMENT);
316670eb
A
607
608 /* make sure expansion won't cause wrap */
b7266188 609 if (msg_and_trailer_size > MACH_MSG_SIZE_MAX - max_desc)
8ad349bb 610 return IKM_NULL;
b0d623f7 611
8ad349bb
A
612 max_expanded_size = msg_and_trailer_size + max_desc;
613 } else
8ad349bb 614 max_expanded_size = msg_and_trailer_size;
91447636 615
316670eb 616 if (max_expanded_size < IKM_SAVED_MSG_SIZE)
8ad349bb 617 max_expanded_size = IKM_SAVED_MSG_SIZE; /* round up for ikm_cache */
91447636
A
618
619 if (max_expanded_size == IKM_SAVED_MSG_SIZE) {
620 struct ikm_cache *cache;
621 unsigned int i;
1c79356b
A
622
623 disable_preemption();
91447636
A
624 cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
625 if ((i = cache->avail) > 0) {
1c79356b 626 assert(i <= IKM_STASH);
91447636
A
627 kmsg = cache->entries[--i];
628 cache->avail = i;
1c79356b 629 enable_preemption();
b7266188
A
630 ikm_check_init(kmsg, max_expanded_size);
631 ikm_set_header(kmsg, msg_and_trailer_size);
1c79356b
A
632 return (kmsg);
633 }
634 enable_preemption();
91447636
A
635 kmsg = (ipc_kmsg_t)zalloc(ipc_kmsg_zone);
636 } else {
637 kmsg = (ipc_kmsg_t)kalloc(ikm_plus_overhead(max_expanded_size));
1c79356b
A
638 }
639
1c79356b 640 if (kmsg != IKM_NULL) {
91447636 641 ikm_init(kmsg, max_expanded_size);
b7266188 642 ikm_set_header(kmsg, msg_and_trailer_size);
1c79356b 643 }
2d21ac55 644
1c79356b
A
645 return(kmsg);
646}
647
648/*
649 * Routine: ipc_kmsg_free
650 * Purpose:
651 * Free a kernel message buffer. If the kms is preallocated
652 * to a port, just "put it back (marked unused)." We have to
653 * do this with the port locked. The port may have its hold
654 * on our message released. In that case, we have to just
655 * revert the message to a traditional one and free it normally.
656 * Conditions:
657 * Nothing locked.
658 */
659
660void
661ipc_kmsg_free(
662 ipc_kmsg_t kmsg)
663{
664 mach_msg_size_t size = kmsg->ikm_size;
665 ipc_port_t port;
666
2d21ac55
A
667#if CONFIG_MACF_MACH
668 if (kmsg->ikm_sender != NULL) {
669 task_deallocate(kmsg->ikm_sender);
670 kmsg->ikm_sender = NULL;
671 }
672#endif
673
1c79356b
A
674 /*
675 * Check to see if the message is bound to the port. If so,
676 * mark it not in use. If the port isn't already dead, then
91447636 677 * leave the message associated with it. Otherwise, free it.
1c79356b
A
678 */
679 port = ikm_prealloc_inuse_port(kmsg);
680 if (port != IP_NULL) {
681 ip_lock(port);
682 ikm_prealloc_clear_inuse(kmsg, port);
683 if (ip_active(port) && (port->ip_premsg == kmsg)) {
684 assert(IP_PREALLOC(port));
685 ip_unlock(port);
316670eb 686 ip_release(port);
1c79356b
A
687 return;
688 }
316670eb
A
689 ip_unlock(port);
690 ip_release(port); /* May be last reference */
1c79356b
A
691 }
692
693 /*
694 * Peek and see if it has to go back in the cache.
695 */
91447636
A
696 if (kmsg->ikm_size == IKM_SAVED_MSG_SIZE) {
697 struct ikm_cache *cache;
698 unsigned int i;
1c79356b
A
699
700 disable_preemption();
91447636
A
701 cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
702 if ((i = cache->avail) < IKM_STASH) {
703 cache->entries[i] = kmsg;
704 cache->avail = i + 1;
1c79356b
A
705 enable_preemption();
706 return;
707 }
708 enable_preemption();
91447636
A
709 zfree(ipc_kmsg_zone, kmsg);
710 return;
1c79356b 711 }
91447636 712 kfree(kmsg, ikm_plus_overhead(size));
1c79356b
A
713}
714
715
716/*
717 * Routine: ipc_kmsg_enqueue
718 * Purpose:
719 * Enqueue a kmsg.
720 */
721
722void
723ipc_kmsg_enqueue(
724 ipc_kmsg_queue_t queue,
725 ipc_kmsg_t kmsg)
726{
727 ipc_kmsg_enqueue_macro(queue, kmsg);
728}
729
730/*
731 * Routine: ipc_kmsg_dequeue
732 * Purpose:
733 * Dequeue and return a kmsg.
734 */
735
736ipc_kmsg_t
737ipc_kmsg_dequeue(
738 ipc_kmsg_queue_t queue)
739{
740 ipc_kmsg_t first;
741
742 first = ipc_kmsg_queue_first(queue);
743
744 if (first != IKM_NULL)
745 ipc_kmsg_rmqueue_first_macro(queue, first);
746
747 return first;
748}
749
750/*
751 * Routine: ipc_kmsg_rmqueue
752 * Purpose:
753 * Pull a kmsg out of a queue.
754 */
755
756void
757ipc_kmsg_rmqueue(
758 ipc_kmsg_queue_t queue,
759 ipc_kmsg_t kmsg)
760{
761 ipc_kmsg_t next, prev;
762
763 assert(queue->ikmq_base != IKM_NULL);
764
765 next = kmsg->ikm_next;
766 prev = kmsg->ikm_prev;
767
768 if (next == kmsg) {
769 assert(prev == kmsg);
770 assert(queue->ikmq_base == kmsg);
771
772 queue->ikmq_base = IKM_NULL;
773 } else {
774 if (queue->ikmq_base == kmsg)
775 queue->ikmq_base = next;
776
777 next->ikm_prev = prev;
778 prev->ikm_next = next;
779 }
780 /* XXX Temporary debug logic */
2d21ac55
A
781 assert((kmsg->ikm_next = IKM_BOGUS) == IKM_BOGUS);
782 assert((kmsg->ikm_prev = IKM_BOGUS) == IKM_BOGUS);
1c79356b
A
783}
784
785/*
786 * Routine: ipc_kmsg_queue_next
787 * Purpose:
788 * Return the kmsg following the given kmsg.
789 * (Or IKM_NULL if it is the last one in the queue.)
790 */
791
792ipc_kmsg_t
793ipc_kmsg_queue_next(
794 ipc_kmsg_queue_t queue,
795 ipc_kmsg_t kmsg)
796{
797 ipc_kmsg_t next;
798
799 assert(queue->ikmq_base != IKM_NULL);
800
801 next = kmsg->ikm_next;
802 if (queue->ikmq_base == next)
803 next = IKM_NULL;
804
805 return next;
806}
807
808/*
809 * Routine: ipc_kmsg_destroy
810 * Purpose:
811 * Destroys a kernel message. Releases all rights,
812 * references, and memory held by the message.
813 * Frees the message.
814 * Conditions:
815 * No locks held.
816 */
817
818void
819ipc_kmsg_destroy(
820 ipc_kmsg_t kmsg)
821{
1c79356b 822 /*
6d2010ae
A
823 * Destroying a message can cause more messages to be destroyed.
824 * Curtail recursion by putting messages on the deferred
825 * destruction queue. If this was the first message on the
826 * queue, this instance must process the full queue.
1c79356b 827 */
6d2010ae
A
828 if (ipc_kmsg_delayed_destroy(kmsg))
829 ipc_kmsg_reap_delayed();
830}
1c79356b 831
6d2010ae
A
832/*
833 * Routine: ipc_kmsg_delayed_destroy
834 * Purpose:
835 * Enqueues a kernel message for deferred destruction.
836 * Returns:
837 * Boolean indicator that the caller is responsible to reap
838 * deferred messages.
839 */
1c79356b 840
6d2010ae
A
841boolean_t ipc_kmsg_delayed_destroy(
842 ipc_kmsg_t kmsg)
843{
844 ipc_kmsg_queue_t queue = &(current_thread()->ith_messages);
845 boolean_t first = ipc_kmsg_queue_empty(queue);
1c79356b 846
6d2010ae
A
847 ipc_kmsg_enqueue(queue, kmsg);
848 return first;
1c79356b
A
849}
850
851/*
6d2010ae 852 * Routine: ipc_kmsg_destroy_queue
1c79356b 853 * Purpose:
6d2010ae
A
854 * Destroys messages from the per-thread
855 * deferred reaping queue.
1c79356b
A
856 * Conditions:
857 * No locks held.
858 */
6d2010ae 859
91447636 860void
6d2010ae 861ipc_kmsg_reap_delayed(void)
1c79356b 862{
6d2010ae
A
863 ipc_kmsg_queue_t queue = &(current_thread()->ith_messages);
864 ipc_kmsg_t kmsg;
1c79356b 865
6d2010ae
A
866 /*
867 * must leave kmsg in queue while cleaning it to assure
868 * no nested calls recurse into here.
869 */
870 while ((kmsg = ipc_kmsg_queue_first(queue)) != IKM_NULL) {
871 ipc_kmsg_clean(kmsg);
872 ipc_kmsg_rmqueue(queue, kmsg);
873 ipc_kmsg_free(kmsg);
874 }
1c79356b
A
875}
876
877/*
878 * Routine: ipc_kmsg_clean_body
879 * Purpose:
880 * Cleans the body of a kernel message.
881 * Releases all rights, references, and memory.
882 *
883 * Conditions:
884 * No locks held.
885 */
6d2010ae 886static unsigned int _ipc_kmsg_clean_invalid_desc = 0;
1c79356b
A
887void
888ipc_kmsg_clean_body(
91447636
A
889 __unused ipc_kmsg_t kmsg,
890 mach_msg_type_number_t number,
891 mach_msg_descriptor_t *saddr)
1c79356b 892{
b0d623f7 893 mach_msg_type_number_t i;
1c79356b
A
894
895 if ( number == 0 )
896 return;
897
b0d623f7 898 for (i = 0 ; i < number; i++, saddr++ ) {
1c79356b
A
899
900 switch (saddr->type.type) {
901
902 case MACH_MSG_PORT_DESCRIPTOR: {
903 mach_msg_port_descriptor_t *dsc;
904
905 dsc = &saddr->port;
906
907 /*
908 * Destroy port rights carried in the message
909 */
910 if (!IO_VALID((ipc_object_t) dsc->name))
911 continue;
912 ipc_object_destroy((ipc_object_t) dsc->name, dsc->disposition);
913 break;
914 }
915 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
916 case MACH_MSG_OOL_DESCRIPTOR : {
917 mach_msg_ool_descriptor_t *dsc;
918
b0d623f7 919 dsc = (mach_msg_ool_descriptor_t *)&saddr->out_of_line;
1c79356b
A
920
921 /*
922 * Destroy memory carried in the message
923 */
924 if (dsc->size == 0) {
925 assert(dsc->address == (void *) 0);
926 } else {
927 vm_map_copy_discard((vm_map_copy_t) dsc->address);
928 }
929 break;
930 }
931 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
932 ipc_object_t *objects;
933 mach_msg_type_number_t j;
934 mach_msg_ool_ports_descriptor_t *dsc;
935
b0d623f7 936 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
1c79356b
A
937 objects = (ipc_object_t *) dsc->address;
938
939 if (dsc->count == 0) {
940 break;
941 }
942
943 assert(objects != (ipc_object_t *) 0);
944
945 /* destroy port rights carried in the message */
946
947 for (j = 0; j < dsc->count; j++) {
948 ipc_object_t object = objects[j];
949
950 if (!IO_VALID(object))
951 continue;
952
953 ipc_object_destroy(object, dsc->disposition);
954 }
955
956 /* destroy memory carried in the message */
957
958 assert(dsc->count != 0);
959
91447636 960 kfree(dsc->address,
b0d623f7 961 (vm_size_t) dsc->count * sizeof(mach_port_t));
1c79356b
A
962 break;
963 }
964 default : {
6d2010ae 965 _ipc_kmsg_clean_invalid_desc++; /* don't understand this type of descriptor */
1c79356b
A
966 }
967 }
968 }
969}
970
971/*
972 * Routine: ipc_kmsg_clean_partial
973 * Purpose:
974 * Cleans a partially-acquired kernel message.
975 * number is the index of the type descriptor
976 * in the body of the message that contained the error.
977 * If dolast, the memory and port rights in this last
978 * type spec are also cleaned. In that case, number
979 * specifies the number of port rights to clean.
980 * Conditions:
981 * Nothing locked.
982 */
983
984void
985ipc_kmsg_clean_partial(
986 ipc_kmsg_t kmsg,
987 mach_msg_type_number_t number,
91447636 988 mach_msg_descriptor_t *desc,
1c79356b
A
989 vm_offset_t paddr,
990 vm_size_t length)
991{
992 ipc_object_t object;
91447636 993 mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
1c79356b 994
91447636 995 object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
1c79356b 996 assert(IO_VALID(object));
6d2010ae 997 ipc_object_destroy_dest(object, MACH_MSGH_BITS_REMOTE(mbits));
1c79356b 998
91447636 999 object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
1000 if (IO_VALID(object))
1001 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
1002
1003 if (paddr) {
1004 (void) vm_deallocate(ipc_kernel_copy_map, paddr, length);
1005 }
1006
91447636 1007 ipc_kmsg_clean_body(kmsg, number, desc);
1c79356b
A
1008}
1009
1010/*
1011 * Routine: ipc_kmsg_clean
1012 * Purpose:
1013 * Cleans a kernel message. Releases all rights,
1014 * references, and memory held by the message.
1015 * Conditions:
1016 * No locks held.
1017 */
1018
1019void
1020ipc_kmsg_clean(
1021 ipc_kmsg_t kmsg)
1022{
1023 ipc_object_t object;
1024 mach_msg_bits_t mbits;
1025
91447636
A
1026 mbits = kmsg->ikm_header->msgh_bits;
1027 object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
1c79356b 1028 if (IO_VALID(object))
6d2010ae 1029 ipc_object_destroy_dest(object, MACH_MSGH_BITS_REMOTE(mbits));
1c79356b 1030
91447636 1031 object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
1032 if (IO_VALID(object))
1033 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
1034
1035 if (mbits & MACH_MSGH_BITS_COMPLEX) {
1036 mach_msg_body_t *body;
1037
91447636
A
1038 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
1039 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count,
1040 (mach_msg_descriptor_t *)(body + 1));
1c79356b 1041 }
2d21ac55
A
1042
1043#if CONFIG_MACF_MACH
1044 if (kmsg->ikm_sender != NULL) {
1045 task_deallocate(kmsg->ikm_sender);
1046 kmsg->ikm_sender = NULL;
1047 }
1048#endif
1c79356b
A
1049}
1050
1051/*
1052 * Routine: ipc_kmsg_set_prealloc
1053 * Purpose:
1054 * Assign a kmsg as a preallocated message buffer to a port.
1055 * Conditions:
1056 * port locked.
1057 */
1058
1059void
1060ipc_kmsg_set_prealloc(
1061 ipc_kmsg_t kmsg,
1062 ipc_port_t port)
1063{
1064 assert(kmsg->ikm_prealloc == IP_NULL);
1065
1066 kmsg->ikm_prealloc = IP_NULL;
1067 IP_SET_PREALLOC(port, kmsg);
1068}
1069
1070/*
1071 * Routine: ipc_kmsg_clear_prealloc
1072 * Purpose:
1073 * Release the Assignment of a preallocated message buffer from a port.
1074 * Conditions:
1075 * port locked.
1076 */
1077void
1078ipc_kmsg_clear_prealloc(
1079 ipc_kmsg_t kmsg,
1080 ipc_port_t port)
1081{
1082 assert(kmsg->ikm_prealloc == port);
1083
1084 kmsg->ikm_prealloc = IP_NULL;
1085 IP_CLEAR_PREALLOC(port, kmsg);
1086}
1087
b7266188
A
1088/*
1089 * Routine: ipc_kmsg_prealloc
1090 * Purpose:
1091 * Wraper to ipc_kmsg_alloc() to account for
1092 * header expansion requirements.
1093 */
1094ipc_kmsg_t
1095ipc_kmsg_prealloc(mach_msg_size_t size)
1096{
1097#if defined(__LP64__)
1098 if (size > MACH_MSG_SIZE_MAX - LEGACY_HEADER_SIZE_DELTA)
1099 return IKM_NULL;
1100
1101 size += LEGACY_HEADER_SIZE_DELTA;
1102#endif
1103 return ipc_kmsg_alloc(size);
1104}
91447636
A
1105
1106
1c79356b
A
1107/*
1108 * Routine: ipc_kmsg_get
1109 * Purpose:
1110 * Allocates a kernel message buffer.
1111 * Copies a user message to the message buffer.
1112 * Conditions:
1113 * Nothing locked.
1114 * Returns:
1115 * MACH_MSG_SUCCESS Acquired a message buffer.
1116 * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
1117 * MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
316670eb 1118 * MACH_SEND_TOO_LARGE Message too large to ever be sent.
1c79356b
A
1119 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1120 * MACH_SEND_INVALID_DATA Couldn't copy message data.
1121 */
1122
1123mach_msg_return_t
1124ipc_kmsg_get(
91447636
A
1125 mach_vm_address_t msg_addr,
1126 mach_msg_size_t size,
1c79356b
A
1127 ipc_kmsg_t *kmsgp)
1128{
1129 mach_msg_size_t msg_and_trailer_size;
1130 ipc_kmsg_t kmsg;
55e303ae 1131 mach_msg_max_trailer_t *trailer;
b0d623f7
A
1132 mach_msg_legacy_base_t legacy_base;
1133 mach_msg_size_t len_copied;
1134 legacy_base.body.msgh_descriptor_count = 0;
1c79356b 1135
b0d623f7 1136 if ((size < sizeof(mach_msg_legacy_header_t)) || (size & 3))
1c79356b
A
1137 return MACH_SEND_MSG_TOO_SMALL;
1138
316670eb 1139 if (size > ipc_kmsg_max_body_space)
8ad349bb
A
1140 return MACH_SEND_TOO_LARGE;
1141
b0d623f7
A
1142 if(size == sizeof(mach_msg_legacy_header_t))
1143 len_copied = sizeof(mach_msg_legacy_header_t);
1144 else
1145 len_copied = sizeof(mach_msg_legacy_base_t);
1c79356b 1146
b0d623f7
A
1147 if (copyinmsg(msg_addr, (char *)&legacy_base, len_copied))
1148 return MACH_SEND_INVALID_DATA;
1149
1150 msg_addr += sizeof(legacy_base.header);
1151#if defined(__LP64__)
1152 size += LEGACY_HEADER_SIZE_DELTA;
1153#endif
1154 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
1155 unsigned int j;
1156 for (j=0; j<sizeof(legacy_base.header); j++) {
1157 kprintf("%02x\n", ((unsigned char*)&legacy_base.header)[j]);
1158 }
1159 }
1c79356b 1160
b0d623f7
A
1161 msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1162 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1c79356b
A
1163 if (kmsg == IKM_NULL)
1164 return MACH_SEND_NO_BUFFER;
1165
b0d623f7
A
1166 kmsg->ikm_header->msgh_size = size;
1167 kmsg->ikm_header->msgh_bits = legacy_base.header.msgh_bits;
1168 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_remote_port);
1169 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_local_port);
1170 kmsg->ikm_header->msgh_reserved = legacy_base.header.msgh_reserved;
1171 kmsg->ikm_header->msgh_id = legacy_base.header.msgh_id;
1172
1173 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
1174 " size: 0x%.8x\n"
1175 " bits: 0x%.8x\n"
1176 " remote_port: %p\n"
1177 " local_port: %p\n"
1178 " reserved: 0x%.8x\n"
1179 " id: %.8d\n",
1180 kmsg->ikm_header->msgh_size,
1181 kmsg->ikm_header->msgh_bits,
1182 kmsg->ikm_header->msgh_remote_port,
1183 kmsg->ikm_header->msgh_local_port,
1184 kmsg->ikm_header->msgh_reserved,
1185 kmsg->ikm_header->msgh_id);
1186
1187 if (copyinmsg(msg_addr, (char *)(kmsg->ikm_header + 1), size - (mach_msg_size_t)sizeof(mach_msg_header_t))) {
1c79356b
A
1188 ipc_kmsg_free(kmsg);
1189 return MACH_SEND_INVALID_DATA;
1190 }
1191
b0d623f7
A
1192 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
1193 {
1194 kprintf("body: size: %lu\n", (size - sizeof(mach_msg_header_t)));
1195 uint32_t i;
1196 for(i=0;i*4 < (size - sizeof(mach_msg_header_t));i++)
1197 {
1198 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
1199 }
1200 }
1201 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_get()");
1c79356b
A
1202
1203 /*
1204 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1205 * However, the internal size field of the trailer (msgh_trailer_size)
1206 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
1207 * the cases where no implicit data is requested.
1208 */
91447636
A
1209 trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
1210 trailer->msgh_sender = current_thread()->task->sec_token;
1211 trailer->msgh_audit = current_thread()->task->audit_token;
1c79356b
A
1212 trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1213 trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
b0d623f7 1214
55e303ae 1215#ifdef ppc
b36670ce 1216 if(trcWork.traceMask) dbgTrace(0x1100, (unsigned int)kmsg->ikm_header->msgh_id,
91447636
A
1217 (unsigned int)kmsg->ikm_header->msgh_remote_port,
1218 (unsigned int)kmsg->ikm_header->msgh_local_port, 0);
55e303ae 1219#endif
2d21ac55
A
1220
1221#if CONFIG_MACF_MACH
1222 /* XXX - why do we zero sender labels here instead of in mach_msg()? */
1223 task_t cur = current_task();
1224 if (cur) {
1225 task_reference(cur);
1226 kmsg->ikm_sender = cur;
1227 } else
1228 trailer->msgh_labels.sender = 0;
1229#else
b0d623f7 1230 trailer->msgh_labels.sender = 0;
2d21ac55
A
1231#endif
1232
1c79356b
A
1233 *kmsgp = kmsg;
1234 return MACH_MSG_SUCCESS;
1235}
1236
1237/*
1238 * Routine: ipc_kmsg_get_from_kernel
1239 * Purpose:
91447636
A
1240 * First checks for a preallocated message
1241 * reserved for kernel clients. If not found -
1242 * allocates a new kernel message buffer.
1c79356b
A
1243 * Copies a kernel message to the message buffer.
1244 * Only resource errors are allowed.
1245 * Conditions:
1246 * Nothing locked.
1247 * Ports in header are ipc_port_t.
1248 * Returns:
1249 * MACH_MSG_SUCCESS Acquired a message buffer.
1250 * MACH_SEND_NO_BUFFER Couldn't allocate a message buffer.
1251 */
1252
1253mach_msg_return_t
1254ipc_kmsg_get_from_kernel(
1255 mach_msg_header_t *msg,
91447636 1256 mach_msg_size_t size,
1c79356b
A
1257 ipc_kmsg_t *kmsgp)
1258{
1259 ipc_kmsg_t kmsg;
1260 mach_msg_size_t msg_and_trailer_size;
55e303ae 1261 mach_msg_max_trailer_t *trailer;
1c79356b
A
1262 ipc_port_t dest_port;
1263
1264 assert(size >= sizeof(mach_msg_header_t));
316670eb 1265 assert((size & 3) == 0);
1c79356b 1266
1c79356b
A
1267 dest_port = (ipc_port_t)msg->msgh_remote_port;
1268
1269 msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1270
1271 /*
1272 * See if the port has a pre-allocated kmsg for kernel
1273 * clients. These are set up for those kernel clients
1274 * which cannot afford to wait.
1275 */
6d2010ae 1276 if (IP_VALID(dest_port) && IP_PREALLOC(dest_port)) {
b7266188
A
1277 mach_msg_size_t max_desc = 0;
1278
1c79356b
A
1279 ip_lock(dest_port);
1280 if (!ip_active(dest_port)) {
1281 ip_unlock(dest_port);
1282 return MACH_SEND_NO_BUFFER;
1283 }
1284 assert(IP_PREALLOC(dest_port));
1285 kmsg = dest_port->ip_premsg;
1c79356b
A
1286 if (ikm_prealloc_inuse(kmsg)) {
1287 ip_unlock(dest_port);
1288 return MACH_SEND_NO_BUFFER;
1289 }
b7266188
A
1290#if !defined(__LP64__)
1291 if (msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
1292 assert(size > sizeof(mach_msg_base_t));
1293 max_desc = ((mach_msg_base_t *)msg)->body.msgh_descriptor_count *
1294 DESC_SIZE_ADJUSTMENT;
1295 }
1296#endif
1297 if (msg_and_trailer_size > kmsg->ikm_size - max_desc) {
1298 ip_unlock(dest_port);
1299 return MACH_SEND_TOO_LARGE;
1300 }
1c79356b 1301 ikm_prealloc_set_inuse(kmsg, dest_port);
b7266188 1302 ikm_set_header(kmsg, msg_and_trailer_size);
1c79356b 1303 ip_unlock(dest_port);
b0d623f7
A
1304 }
1305 else
b0d623f7 1306 {
1c79356b
A
1307 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1308 if (kmsg == IKM_NULL)
1309 return MACH_SEND_NO_BUFFER;
1310 }
1311
91447636 1312 (void) memcpy((void *) kmsg->ikm_header, (const void *) msg, size);
1c79356b 1313
91447636 1314 kmsg->ikm_header->msgh_size = size;
1c79356b
A
1315
1316 /*
1317 * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
1318 * However, the internal size field of the trailer (msgh_trailer_size)
1319 * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
1320 * optimize the cases where no implicit data is requested.
1321 */
55e303ae 1322 trailer = (mach_msg_max_trailer_t *)
91447636 1323 ((vm_offset_t)kmsg->ikm_header + size);
1c79356b 1324 trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
55e303ae 1325 trailer->msgh_audit = KERNEL_AUDIT_TOKEN;
1c79356b
A
1326 trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1327 trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
1328
2d21ac55
A
1329 trailer->msgh_labels.sender = 0;
1330
1331#if CONFIG_MACF_MACH
1332 kmsg->ikm_sender = NULL;
1333#endif
1c79356b
A
1334 *kmsgp = kmsg;
1335 return MACH_MSG_SUCCESS;
1336}
1337
1338/*
1339 * Routine: ipc_kmsg_send
1340 * Purpose:
1341 * Send a message. The message holds a reference
1342 * for the destination port in the msgh_remote_port field.
1343 *
1344 * If unsuccessful, the caller still has possession of
1345 * the message and must do something with it. If successful,
1346 * the message is queued, given to a receiver, destroyed,
1347 * or handled directly by the kernel via mach_msg.
1348 * Conditions:
1349 * Nothing locked.
1350 * Returns:
1351 * MACH_MSG_SUCCESS The message was accepted.
1352 * MACH_SEND_TIMED_OUT Caller still has message.
1353 * MACH_SEND_INTERRUPTED Caller still has message.
6d2010ae 1354 * MACH_SEND_INVALID_DEST Caller still has message.
1c79356b 1355 */
39236c6e
A
1356
1357
1c79356b
A
1358mach_msg_return_t
1359ipc_kmsg_send(
1360 ipc_kmsg_t kmsg,
1361 mach_msg_option_t option,
91447636 1362 mach_msg_timeout_t send_timeout)
1c79356b 1363{
1c79356b 1364 ipc_port_t port;
b0d623f7
A
1365 mach_msg_return_t error = MACH_MSG_SUCCESS;
1366 spl_t s;
91447636 1367
39236c6e
A
1368#if IMPORTANCE_INHERITANCE
1369 boolean_t did_importance = FALSE;
1370#if IMPORTANCE_DEBUG
1371 mach_msg_id_t imp_msgh_id = -1;
1372 int sender_pid = -1;
1373#endif /* IMPORTANCE_DEBUG */
1374#endif /* IMPORTANCE_INHERITANCE */
1375
1376 /* don't allow the creation of a circular loop */
1377 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_CIRCULAR) {
1378 ipc_kmsg_destroy(kmsg);
1379 return MACH_MSG_SUCCESS;
1380 }
1381
91447636 1382 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1c79356b 1383 assert(IP_VALID(port));
1c79356b
A
1384 ip_lock(port);
1385
1386 if (port->ip_receiver == ipc_space_kernel) {
1387
1388 /*
1389 * We can check ip_receiver == ipc_space_kernel
1390 * before checking that the port is active because
1391 * ipc_port_dealloc_kernel clears ip_receiver
1392 * before destroying a kernel port.
1393 */
1394 assert(ip_active(port));
1395 port->ip_messages.imq_seqno++;
1396 ip_unlock(port);
1397
1398 current_task()->messages_sent++;
1399
1400 /*
1401 * Call the server routine, and get the reply message to send.
1402 */
1403 kmsg = ipc_kobject_server(kmsg);
1404 if (kmsg == IKM_NULL)
1405 return MACH_MSG_SUCCESS;
1406
91447636 1407 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1c79356b
A
1408 assert(IP_VALID(port));
1409 ip_lock(port);
1410 /* fall thru with reply - same options */
1411 }
1412
39236c6e
A
1413#if IMPORTANCE_INHERITANCE
1414 retry:
1415#endif /* IMPORTANCE_INHERITANCE */
1416
1c79356b
A
1417 /*
1418 * Can't deliver to a dead port.
1419 * However, we can pretend it got sent
1420 * and was then immediately destroyed.
1421 */
1422 if (!ip_active(port)) {
1423 /*
1424 * We can't let ipc_kmsg_destroy deallocate
1425 * the port right, because we might end up
1426 * in an infinite loop trying to deliver
1427 * a send-once notification.
1428 */
316670eb 1429 ip_unlock(port);
1c79356b 1430 ip_release(port);
91447636 1431 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1c79356b
A
1432 ipc_kmsg_destroy(kmsg);
1433 return MACH_MSG_SUCCESS;
1434 }
1435
39236c6e
A
1436#if IMPORTANCE_INHERITANCE
1437 /*
1438 * Need to see if this message needs importance donation and/or
1439 * propagation. That routine can drop the port lock. If it does
1440 * we'll have to revalidate the destination.
1441 */
1442 if ((did_importance == FALSE) &&
1443 (port->ip_impdonation != 0) &&
1444 ((option & MACH_SEND_NOIMPORTANCE) == 0) &&
1445 (((option & MACH_SEND_IMPORTANCE) != 0) ||
1446 (task_is_importance_donor(current_task())))) {
1447
1448 did_importance = TRUE;
1449 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_RAISEIMP;
1450
1451#if IMPORTANCE_DEBUG
1452 if (kdebug_enable) {
1453 mach_msg_max_trailer_t *dbgtrailer = (mach_msg_max_trailer_t *)
1454 ((vm_offset_t)kmsg->ikm_header + round_msg(kmsg->ikm_header->msgh_size));
1455 sender_pid = dbgtrailer->msgh_audit.val[5];
1456 imp_msgh_id = kmsg->ikm_header->msgh_id;
1457
1458 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_MSG, IMP_MSG_SEND)) | DBG_FUNC_START,
1459 audit_token_pid_from_task(current_task()), sender_pid, imp_msgh_id, 0, 0);
1460 }
1461#endif /* IMPORTANCE_DEBUG */
1c79356b 1462
39236c6e
A
1463 if (ipc_port_importance_delta(port, 1) == TRUE) {
1464 ip_lock(port);
1465 goto retry;
1466 }
1c79356b 1467 }
39236c6e 1468#endif /* IMPORTANCE_INHERITANCE */
1c79356b
A
1469
1470 /*
1471 * We have a valid message and a valid reference on the port.
b0d623f7
A
1472 * we can unlock the port and call mqueue_send() on its message
1473 * queue. Lock message queue while port is locked.
1c79356b 1474 */
b0d623f7
A
1475 s = splsched();
1476 imq_lock(&port->ip_messages);
1c79356b 1477 ip_unlock(port);
39236c6e 1478
b0d623f7
A
1479 error = ipc_mqueue_send(&port->ip_messages, kmsg, option,
1480 send_timeout, s);
1481
39236c6e
A
1482#if IMPORTANCE_INHERITANCE
1483 if (did_importance == TRUE) {
1484 __unused int importance_cleared = 0;
1485 switch (error) {
1486 case MACH_SEND_TIMED_OUT:
1487 case MACH_SEND_NO_BUFFER:
1488 case MACH_SEND_INTERRUPTED:
1489 /*
1490 * We still have the kmsg and its
1491 * reference on the port. But we
1492 * have to back out the importance
1493 * boost.
1494 *
1495 * The port could have changed hands,
1496 * be inflight to another destination,
1497 * etc... But in those cases our
1498 * back-out will find the new owner
1499 * (and all the operations that
1500 * transferred the right should have
1501 * applied their own boost adjustments
1502 * to the old owner(s)).
1503 */
1504 importance_cleared = 1;
1505 ip_lock(port);
1506 if (ipc_port_importance_delta(port, -1) == FALSE)
1507 ip_unlock(port);
1508 break;
1509
1510 case MACH_SEND_INVALID_DEST:
1511 /*
1512 * In the case that the receive right has
1513 * gone away, the assertion count for the
1514 * message we were trying to enqueue was
1515 * already subtracted from the destination
1516 * task (as part of port destruction).
1517 */
1518 break;
1519
1520 case MACH_MSG_SUCCESS:
1521 default:
1522 break;
1523 }
1524#if IMPORTANCE_DEBUG
1525 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_MSG, IMP_MSG_SEND)) | DBG_FUNC_END,
1526 audit_token_pid_from_task(current_task()), sender_pid, imp_msgh_id, importance_cleared, 0);
1527#endif /* IMPORTANCE_DEBUG */
1528 }
1529#endif /* IMPORTANCE_INHERITANCE */
1530
b0d623f7
A
1531 /*
1532 * If the port has been destroyed while we wait, treat the message
1533 * as a successful delivery (like we do for an inactive port).
1534 */
1535 if (error == MACH_SEND_INVALID_DEST) {
1536 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1537 ipc_kmsg_destroy(kmsg);
1538 return MACH_MSG_SUCCESS;
1539 }
1540 return error;
1c79356b
A
1541}
1542
1543/*
1544 * Routine: ipc_kmsg_put
1545 * Purpose:
1546 * Copies a message buffer to a user message.
1547 * Copies only the specified number of bytes.
1548 * Frees the message buffer.
1549 * Conditions:
1550 * Nothing locked. The message buffer must have clean
1551 * header fields.
1552 * Returns:
1553 * MACH_MSG_SUCCESS Copied data out of message buffer.
1554 * MACH_RCV_INVALID_DATA Couldn't copy to user message.
1555 */
1556
1557mach_msg_return_t
1558ipc_kmsg_put(
91447636 1559 mach_vm_address_t msg_addr,
1c79356b
A
1560 ipc_kmsg_t kmsg,
1561 mach_msg_size_t size)
1562{
1563 mach_msg_return_t mr;
1564
b0d623f7
A
1565 DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_put()");
1566
1567
1568 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
1569 " size: 0x%.8x\n"
1570 " bits: 0x%.8x\n"
1571 " remote_port: %p\n"
1572 " local_port: %p\n"
1573 " reserved: 0x%.8x\n"
1574 " id: %.8d\n",
1575 kmsg->ikm_header->msgh_size,
1576 kmsg->ikm_header->msgh_bits,
1577 kmsg->ikm_header->msgh_remote_port,
1578 kmsg->ikm_header->msgh_local_port,
1579 kmsg->ikm_header->msgh_reserved,
1580 kmsg->ikm_header->msgh_id);
1581
1582#if defined(__LP64__)
1583 if (current_task() != kernel_task) { /* don't if receiver expects fully-cooked in-kernel msg; ux_exception */
1584 mach_msg_legacy_header_t *legacy_header =
1585 (mach_msg_legacy_header_t *)((vm_offset_t)(kmsg->ikm_header) + LEGACY_HEADER_SIZE_DELTA);
1586
1587 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
1588 mach_msg_size_t msg_size = kmsg->ikm_header->msgh_size;
1589 mach_port_name_t remote_port = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_remote_port);
1590 mach_port_name_t local_port = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_local_port);
1591 mach_msg_size_t reserved = kmsg->ikm_header->msgh_reserved;
1592 mach_msg_id_t id = kmsg->ikm_header->msgh_id;
1593
1594 legacy_header->msgh_id = id;
1595 legacy_header->msgh_reserved = reserved;
1596 legacy_header->msgh_local_port = local_port;
1597 legacy_header->msgh_remote_port = remote_port;
1598 legacy_header->msgh_size = msg_size - LEGACY_HEADER_SIZE_DELTA;
1599 legacy_header->msgh_bits = bits;
1600
1601 size -= LEGACY_HEADER_SIZE_DELTA;
1602 kmsg->ikm_header = (mach_msg_header_t *)legacy_header;
1603 }
1604#endif
1605
1606 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
1607 kprintf("ipc_kmsg_put header+body: %d\n", (size));
1608 uint32_t i;
1609 for(i=0;i*4 < size;i++)
1610 {
1611 kprintf("%.4x\n",((uint32_t *)kmsg->ikm_header)[i]);
1612 }
1613 kprintf("type: %d\n", ((mach_msg_type_descriptor_t *)(((mach_msg_base_t *)kmsg->ikm_header)+1))->type);
1614 }
91447636 1615 if (copyoutmsg((const char *) kmsg->ikm_header, msg_addr, size))
1c79356b
A
1616 mr = MACH_RCV_INVALID_DATA;
1617 else
1618 mr = MACH_MSG_SUCCESS;
1619
1620 ipc_kmsg_free(kmsg);
1621 return mr;
1622}
1623
1624/*
1625 * Routine: ipc_kmsg_put_to_kernel
1626 * Purpose:
1627 * Copies a message buffer to a kernel message.
1628 * Frees the message buffer.
1629 * No errors allowed.
1630 * Conditions:
1631 * Nothing locked.
1632 */
1633
1634void
1635ipc_kmsg_put_to_kernel(
1636 mach_msg_header_t *msg,
1637 ipc_kmsg_t kmsg,
1638 mach_msg_size_t size)
1639{
91447636 1640 (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, size);
1c79356b
A
1641
1642 ipc_kmsg_free(kmsg);
1643}
1644
1645/*
1646 * Routine: ipc_kmsg_copyin_header
1647 * Purpose:
1648 * "Copy-in" port rights in the header of a message.
1649 * Operates atomically; if it doesn't succeed the
1650 * message header and the space are left untouched.
1651 * If it does succeed the remote/local port fields
1652 * contain object pointers instead of port names,
1653 * and the bits field is updated. The destination port
1654 * will be a valid port pointer.
1655 *
1c79356b
A
1656 * Conditions:
1657 * Nothing locked.
1658 * Returns:
1659 * MACH_MSG_SUCCESS Successful copyin.
1660 * MACH_SEND_INVALID_HEADER
1661 * Illegal value in the message header bits.
1662 * MACH_SEND_INVALID_DEST The space is dead.
1c79356b
A
1663 * MACH_SEND_INVALID_DEST Can't copyin destination port.
1664 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1665 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
1666 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
1667 */
1668
1669mach_msg_return_t
1670ipc_kmsg_copyin_header(
1671 mach_msg_header_t *msg,
1672 ipc_space_t space,
39236c6e 1673 mach_msg_option_t *optionp)
1c79356b
A
1674{
1675 mach_msg_bits_t mbits = msg->msgh_bits & MACH_MSGH_BITS_USER;
b0d623f7
A
1676 mach_port_name_t dest_name = CAST_MACH_PORT_TO_NAME(msg->msgh_remote_port);
1677 mach_port_name_t reply_name = CAST_MACH_PORT_TO_NAME(msg->msgh_local_port);
1c79356b
A
1678 kern_return_t kr;
1679
1680 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
1681 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
1682 ipc_object_t dest_port, reply_port;
6d2010ae 1683 ipc_entry_t dest_entry, reply_entry;
316670eb
A
1684 ipc_port_t dest_soright, reply_soright;
1685 ipc_port_t release_port = IP_NULL;
1686
39236c6e
A
1687#if IMPORTANCE_INHERITANCE
1688 int assertcnt = 0;
1689 boolean_t needboost = FALSE;
1690#endif /* IMPORTANCE_INHERITANCE */
1691
316670eb
A
1692 queue_head_t links_data;
1693 queue_t links = &links_data;
1694 wait_queue_link_t wql;
1695
1696 queue_init(links);
1c79356b
A
1697
1698 if ((mbits != msg->msgh_bits) ||
1699 (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type)) ||
1700 ((reply_type == 0) ?
1701 (reply_name != MACH_PORT_NULL) :
1702 !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type)))
1703 return MACH_SEND_INVALID_HEADER;
1704
1705 reply_soright = IP_NULL; /* in case we go to invalid dest early */
1706
1707 is_write_lock(space);
316670eb 1708 if (!is_active(space))
1c79356b
A
1709 goto invalid_dest;
1710
1711 if (!MACH_PORT_VALID(dest_name))
1712 goto invalid_dest;
1713
2d21ac55
A
1714#if CONFIG_MACF_MACH
1715 /*
1716 * We do the port send check here instead of in ipc_kmsg_send()
1717 * because copying the header involves copying the port rights too
1718 * and we need to do the send check before anything is actually copied.
1719 */
6d2010ae
A
1720 dest_entry = ipc_entry_lookup(space, dest_name);
1721 if (dest_entry != IE_NULL) {
2d21ac55 1722 int error = 0;
6d2010ae 1723 ipc_port_t port = (ipc_port_t) dest_entry->ie_object;
2d21ac55
A
1724 if (port == IP_NULL)
1725 goto invalid_dest;
1726 ip_lock(port);
1727 if (ip_active(port)) {
1728 task_t self = current_task();
1729 tasklabel_lock(self);
1730 error = mac_port_check_send(&self->maclabel,
1731 &port->ip_label);
1732 tasklabel_unlock(self);
1733 }
1734 ip_unlock(port);
1735 if (error != 0)
1736 goto invalid_dest;
1737 }
1738#endif
1c79356b 1739
1c79356b 1740 if (dest_name == reply_name) {
1c79356b
A
1741 mach_port_name_t name = dest_name;
1742
1743 /*
1744 * Destination and reply ports are the same!
1745 * This is a little tedious to make atomic, because
1746 * there are 25 combinations of dest_type/reply_type.
1747 * However, most are easy. If either is move-sonce,
1748 * then there must be an error. If either are
1749 * make-send or make-sonce, then we must be looking
1750 * at a receive right so the port can't die.
1751 * The hard cases are the combinations of
1752 * copy-send and make-send.
1753 */
1754
6d2010ae
A
1755 dest_entry = ipc_entry_lookup(space, name);
1756 if (dest_entry == IE_NULL)
1c79356b
A
1757 goto invalid_dest;
1758
6d2010ae 1759 reply_entry = dest_entry;
1c79356b
A
1760 assert(reply_type != 0); /* because name not null */
1761
6d2010ae 1762 if (!ipc_right_copyin_check(space, name, reply_entry, reply_type))
1c79356b
A
1763 goto invalid_reply;
1764
1765 if ((dest_type == MACH_MSG_TYPE_MOVE_SEND_ONCE) ||
1766 (reply_type == MACH_MSG_TYPE_MOVE_SEND_ONCE)) {
1767 /*
1768 * Why must there be an error? To get a valid
1769 * destination, this entry must name a live
1770 * port (not a dead name or dead port). However
1771 * a successful move-sonce will destroy a
1772 * live entry. Therefore the other copyin,
1773 * whatever it is, would fail. We've already
1774 * checked for reply port errors above,
1775 * so report a destination error.
1776 */
1777
1778 goto invalid_dest;
1779 } else if ((dest_type == MACH_MSG_TYPE_MAKE_SEND) ||
1780 (dest_type == MACH_MSG_TYPE_MAKE_SEND_ONCE) ||
1781 (reply_type == MACH_MSG_TYPE_MAKE_SEND) ||
1782 (reply_type == MACH_MSG_TYPE_MAKE_SEND_ONCE)) {
39236c6e
A
1783
1784#if IMPORTANCE_INHERITANCE
6d2010ae 1785 kr = ipc_right_copyin(space, name, dest_entry,
1c79356b 1786 dest_type, FALSE,
316670eb
A
1787 &dest_port, &dest_soright,
1788 &release_port,
39236c6e 1789 &assertcnt,
316670eb 1790 links);
39236c6e
A
1791 assert(assertcnt == 0);
1792#else
1793 kr = ipc_right_copyin(space, name, dest_entry,
1794 dest_type, FALSE,
1795 &dest_port, &dest_soright,
1796 &release_port,
1797 links);
1798#endif /* IMPORTANCE_INHERITANCE */
1799
1c79356b
A
1800 if (kr != KERN_SUCCESS)
1801 goto invalid_dest;
1802
1803 /*
1804 * Either dest or reply needs a receive right.
1805 * We know the receive right is there, because
1806 * of the copyin_check and copyin calls. Hence
1807 * the port is not in danger of dying. If dest
1808 * used the receive right, then the right needed
1809 * by reply (and verified by copyin_check) will
1810 * still be there.
1811 */
1812
1813 assert(IO_VALID(dest_port));
1c79356b
A
1814 assert(dest_soright == IP_NULL);
1815
39236c6e
A
1816#if IMPORTANCE_INHERITANCE
1817 kr = ipc_right_copyin(space, name, reply_entry,
1818 reply_type, TRUE,
1819 &reply_port, &reply_soright,
1820 &release_port,
1821 &assertcnt,
1822 links);
1823 assert(assertcnt == 0);
1824#else
6d2010ae 1825 kr = ipc_right_copyin(space, name, reply_entry,
1c79356b 1826 reply_type, TRUE,
316670eb
A
1827 &reply_port, &reply_soright,
1828 &release_port,
1829 links);
39236c6e 1830#endif /* IMPORTANCE_INHERITANCE */
1c79356b
A
1831
1832 assert(kr == KERN_SUCCESS);
1833 assert(reply_port == dest_port);
6d2010ae 1834 assert(reply_entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
1c79356b
A
1835 assert(reply_soright == IP_NULL);
1836 } else if ((dest_type == MACH_MSG_TYPE_COPY_SEND) &&
1837 (reply_type == MACH_MSG_TYPE_COPY_SEND)) {
1838 /*
1839 * To make this atomic, just do one copy-send,
1840 * and dup the send right we get out.
1841 */
1842
39236c6e 1843#if IMPORTANCE_INHERITANCE
6d2010ae 1844 kr = ipc_right_copyin(space, name, dest_entry,
1c79356b 1845 dest_type, FALSE,
316670eb
A
1846 &dest_port, &dest_soright,
1847 &release_port,
39236c6e 1848 &assertcnt,
316670eb 1849 links);
39236c6e
A
1850 assert(assertcnt == 0);
1851#else
1852 kr = ipc_right_copyin(space, name, dest_entry,
1853 dest_type, FALSE,
1854 &dest_port, &dest_soright,
1855 &release_port,
1856 links);
1857#endif /* IMPORTANCE_INHERITANCE */
1858
1c79356b
A
1859 if (kr != KERN_SUCCESS)
1860 goto invalid_dest;
1861
6d2010ae 1862 assert(dest_entry->ie_bits & MACH_PORT_TYPE_SEND);
1c79356b
A
1863 assert(dest_soright == IP_NULL);
1864
1865 /*
1866 * It's OK if the port we got is dead now,
1867 * so reply_port is IP_DEAD, because the msg
1868 * won't go anywhere anyway.
1869 */
1870
1871 reply_port = (ipc_object_t)
1872 ipc_port_copy_send((ipc_port_t) dest_port);
1873 reply_soright = IP_NULL;
1874 } else if ((dest_type == MACH_MSG_TYPE_MOVE_SEND) &&
1875 (reply_type == MACH_MSG_TYPE_MOVE_SEND)) {
1876 /*
1877 * This is an easy case. Just use our
1878 * handy-dandy special-purpose copyin call
1879 * to get two send rights for the price of one.
1880 */
1881
6d2010ae 1882 kr = ipc_right_copyin_two(space, name, dest_entry,
316670eb
A
1883 &dest_port, &dest_soright,
1884 &release_port);
1c79356b
A
1885 if (kr != KERN_SUCCESS)
1886 goto invalid_dest;
1887
1888 /* the entry might need to be deallocated */
6d2010ae
A
1889 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
1890 ipc_entry_dealloc(space, name, dest_entry);
1891 dest_entry = IE_NULL;
1892 }
1c79356b
A
1893
1894 reply_port = dest_port;
1895 reply_soright = IP_NULL;
1896 } else {
1897 ipc_port_t soright;
1898
1899 assert(((dest_type == MACH_MSG_TYPE_COPY_SEND) &&
1900 (reply_type == MACH_MSG_TYPE_MOVE_SEND)) ||
1901 ((dest_type == MACH_MSG_TYPE_MOVE_SEND) &&
1902 (reply_type == MACH_MSG_TYPE_COPY_SEND)));
1903
1904 /*
1905 * To make this atomic, just do a move-send,
1906 * and dup the send right we get out.
1907 */
1908
39236c6e 1909#if IMPORTANCE_INHERITANCE
6d2010ae 1910 kr = ipc_right_copyin(space, name, dest_entry,
1c79356b 1911 MACH_MSG_TYPE_MOVE_SEND, FALSE,
316670eb
A
1912 &dest_port, &soright,
1913 &release_port,
39236c6e 1914 &assertcnt,
316670eb 1915 links);
39236c6e
A
1916 assert(assertcnt == 0);
1917#else
1918 kr = ipc_right_copyin(space, name, dest_entry,
1919 MACH_MSG_TYPE_MOVE_SEND, FALSE,
1920 &dest_port, &soright,
1921 &release_port,
1922 links);
1923#endif /* IMPORTANCE_INHERITANCE */
1924
1c79356b
A
1925 if (kr != KERN_SUCCESS)
1926 goto invalid_dest;
1927
1928 /* the entry might need to be deallocated */
1929
6d2010ae
A
1930 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
1931 ipc_entry_dealloc(space, name, dest_entry);
1932 dest_entry = IE_NULL;
1933 }
1c79356b
A
1934
1935 /*
1936 * It's OK if the port we got is dead now,
1937 * so reply_port is IP_DEAD, because the msg
1938 * won't go anywhere anyway.
1939 */
1940
1941 reply_port = (ipc_object_t)
1942 ipc_port_copy_send((ipc_port_t) dest_port);
1943
1944 if (dest_type == MACH_MSG_TYPE_MOVE_SEND) {
1945 dest_soright = soright;
1946 reply_soright = IP_NULL;
1947 } else {
1948 dest_soright = IP_NULL;
1949 reply_soright = soright;
1950 }
1951 }
1952 } else if (!MACH_PORT_VALID(reply_name)) {
1c79356b
A
1953 /*
1954 * No reply port! This is an easy case
1955 * to make atomic. Just copyin the destination.
1956 */
1957
6d2010ae
A
1958 dest_entry = ipc_entry_lookup(space, dest_name);
1959 if (dest_entry == IE_NULL)
1c79356b
A
1960 goto invalid_dest;
1961
39236c6e 1962#if IMPORTANCE_INHERITANCE
6d2010ae 1963 kr = ipc_right_copyin(space, dest_name, dest_entry,
1c79356b 1964 dest_type, FALSE,
316670eb
A
1965 &dest_port, &dest_soright,
1966 &release_port,
39236c6e 1967 &assertcnt,
316670eb 1968 links);
39236c6e
A
1969 assert(assertcnt == 0);
1970#else
1971 kr = ipc_right_copyin(space, dest_name, dest_entry,
1972 dest_type, FALSE,
1973 &dest_port, &dest_soright,
1974 &release_port,
1975 links);
1976#endif /* IMPORTANCE_INHERITANCE */
1977
1c79356b
A
1978 if (kr != KERN_SUCCESS)
1979 goto invalid_dest;
1980
1981 /* the entry might need to be deallocated */
6d2010ae
A
1982 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
1983 ipc_entry_dealloc(space, dest_name, dest_entry);
1984 dest_entry = IE_NULL;
1985 }
1c79356b 1986
b0d623f7 1987 reply_port = (ipc_object_t)CAST_MACH_NAME_TO_PORT(reply_name);
1c79356b
A
1988 reply_soright = IP_NULL;
1989 } else {
1c79356b
A
1990 /*
1991 * This is the tough case to make atomic.
1992 * The difficult problem is serializing with port death.
1993 * At the time we copyin dest_port, it must be alive.
1994 * If reply_port is alive when we copyin it, then
1995 * we are OK, because we serialize before the death
1996 * of both ports. Assume reply_port is dead at copyin.
1997 * Then if dest_port dies/died after reply_port died,
1998 * we are OK, because we serialize between the death
1999 * of the two ports. So the bad case is when dest_port
2000 * dies after its copyin, reply_port dies before its
2001 * copyin, and dest_port dies before reply_port. Then
2002 * the copyins operated as if dest_port was alive
2003 * and reply_port was dead, which shouldn't have happened
2004 * because they died in the other order.
2005 *
2006 * Note that it is easy for a user task to tell if
2007 * a copyin happened before or after a port died.
2008 * For example, suppose both dest and reply are
2009 * send-once rights (types are both move-sonce) and
2010 * both rights have dead-name requests registered.
2011 * If a port dies before copyin, a dead-name notification
2012 * is generated and the dead name's urefs are incremented,
2013 * and if the copyin happens first, a port-deleted
2014 * notification is generated.
2015 *
2016 * Note that although the entries are different,
2017 * dest_port and reply_port might still be the same.
2018 *
2019 * JMM - The code to handle this was too expensive and, anyway,
2020 * we intend to separate the dest lookup from the reply copyin
2021 * by a wide margin, so the user will have to learn to deal!
6d2010ae 2022 * I will be making the change soon in rdar://problem/6275821.
1c79356b
A
2023 */
2024
2025 dest_entry = ipc_entry_lookup(space, dest_name);
2026 if (dest_entry == IE_NULL)
2027 goto invalid_dest;
2028
2029 reply_entry = ipc_entry_lookup(space, reply_name);
2030 if (reply_entry == IE_NULL)
2031 goto invalid_reply;
2032
2033 assert(dest_entry != reply_entry); /* names are not equal */
2034 assert(reply_type != 0); /* because reply_name not null */
2035
2036 if (!ipc_right_copyin_check(space, reply_name, reply_entry,
2037 reply_type))
2038 goto invalid_reply;
2039
39236c6e
A
2040#if IMPORTANCE_INHERITANCE
2041 kr = ipc_right_copyin(space, dest_name, dest_entry,
2042 dest_type, FALSE,
2043 &dest_port, &dest_soright,
2044 &release_port,
2045 &assertcnt,
2046 links);
2047 assert(assertcnt == 0);
2048#else
1c79356b
A
2049 kr = ipc_right_copyin(space, dest_name, dest_entry,
2050 dest_type, FALSE,
316670eb
A
2051 &dest_port, &dest_soright,
2052 &release_port,
2053 links);
39236c6e
A
2054#endif /* IMPORTANCE_INHERITANCE */
2055
1c79356b
A
2056 if (kr != KERN_SUCCESS)
2057 goto invalid_dest;
2058
2059 assert(IO_VALID(dest_port));
2060
39236c6e 2061#if IMPORTANCE_INHERITANCE
1c79356b
A
2062 kr = ipc_right_copyin(space, reply_name, reply_entry,
2063 reply_type, TRUE,
316670eb
A
2064 &reply_port, &reply_soright,
2065 &release_port,
39236c6e 2066 &assertcnt,
316670eb 2067 links);
39236c6e
A
2068 assert(assertcnt == 0);
2069#else
2070 kr = ipc_right_copyin(space, reply_name, reply_entry,
2071 reply_type, TRUE,
2072 &reply_port, &reply_soright,
2073 &release_port,
2074 links);
2075#endif /* IMPORTANCE_INHERITANCE */
2076
1c79356b
A
2077 assert(kr == KERN_SUCCESS);
2078
2079 /* the entries might need to be deallocated */
2080
6d2010ae 2081 if (IE_BITS_TYPE(reply_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
1c79356b 2082 ipc_entry_dealloc(space, reply_name, reply_entry);
6d2010ae
A
2083 reply_entry = IE_NULL;
2084 }
1c79356b 2085
6d2010ae 2086 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
1c79356b 2087 ipc_entry_dealloc(space, dest_name, dest_entry);
6d2010ae
A
2088 dest_entry = IE_NULL;
2089 }
1c79356b
A
2090 }
2091
6d2010ae
A
2092 dest_type = ipc_object_copyin_type(dest_type);
2093 reply_type = ipc_object_copyin_type(reply_type);
2094
1c79356b 2095 /*
6d2010ae
A
2096 * JMM - Without rdar://problem/6275821, this is the last place we can
2097 * re-arm the send-possible notifications. It may trigger unexpectedly
39236c6e
A
2098 * early (send may NOT have failed), but better than missing. We assure
2099 * we won't miss by forcing MACH_SEND_ALWAYS if we got past arming.
1c79356b 2100 */
39236c6e
A
2101 if (((*optionp & MACH_SEND_NOTIFY) != 0) &&
2102 dest_type != MACH_MSG_TYPE_PORT_SEND_ONCE &&
6d2010ae
A
2103 dest_entry != IE_NULL && dest_entry->ie_request != IE_REQ_NONE) {
2104 ipc_port_t dport = (ipc_port_t)dest_port;
2105
2106 assert(dport != IP_NULL);
2107 ip_lock(dport);
39236c6e
A
2108 if (ip_active(dport) && dport->ip_receiver != ipc_space_kernel) {
2109 if (ip_full(dport)) {
2110#if IMPORTANCE_INHERITANCE
2111 needboost = ipc_port_request_sparm(dport, dest_name,
2112 dest_entry->ie_request,
2113 (*optionp & MACH_SEND_NOIMPORTANCE));
2114 if (needboost == FALSE)
2115 ip_unlock(dport);
2116#else
2117
2118 ipc_port_request_sparm(dport, dest_name, dest_entry->ie_request);
2119 ip_unlock(dport);
2120#endif /* IMPORTANCE_INHERITANCE */
2121 } else {
2122 *optionp |= MACH_SEND_ALWAYS;
2123 ip_unlock(dport);
2124 }
2125 } else {
2126 ip_unlock(dport);
6d2010ae 2127 }
1c79356b
A
2128 }
2129
2130 is_write_unlock(space);
2131
39236c6e
A
2132#if IMPORTANCE_INHERITANCE
2133 /*
2134 * If our request is the first boosting send-possible
2135 * notification this cycle, push the boost down the
2136 * destination port.
2137 */
2138 if (needboost == TRUE) {
2139 ipc_port_t dport = (ipc_port_t)dest_port;
2140
2141 /* dport still locked from above */
2142 if (ipc_port_importance_delta(dport, 1) == FALSE)
2143 ip_unlock(dport);
2144 }
2145#endif /* IMPORTANCE_INHERITANCE */
2146
1c79356b
A
2147 if (dest_soright != IP_NULL)
2148 ipc_notify_port_deleted(dest_soright, dest_name);
2149
2150 if (reply_soright != IP_NULL)
2151 ipc_notify_port_deleted(reply_soright, reply_name);
2152
1c79356b
A
2153 msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
2154 MACH_MSGH_BITS(dest_type, reply_type));
2155 msg->msgh_remote_port = (ipc_port_t)dest_port;
2156 msg->msgh_local_port = (ipc_port_t)reply_port;
2157
316670eb
A
2158 while(!queue_empty(links)) {
2159 wql = (wait_queue_link_t) dequeue(links);
2160 wait_queue_link_free(wql);
2161 }
2162
2163 if (release_port != IP_NULL)
2164 ip_release(release_port);
2165
39236c6e 2166
1c79356b
A
2167 return MACH_MSG_SUCCESS;
2168
2169invalid_reply:
2170 is_write_unlock(space);
316670eb
A
2171
2172 while(!queue_empty(links)) {
2173 wql = (wait_queue_link_t) dequeue(links);
2174 wait_queue_link_free(wql);
2175 }
2176
2177 if (release_port != IP_NULL)
2178 ip_release(release_port);
2179
1c79356b
A
2180 return MACH_SEND_INVALID_REPLY;
2181
2182invalid_dest:
2183 is_write_unlock(space);
316670eb
A
2184
2185 while(!queue_empty(links)) {
2186 wql = (wait_queue_link_t) dequeue(links);
2187 wait_queue_link_free(wql);
2188 }
2189
2190 if (release_port != IP_NULL)
2191 ip_release(release_port);
2192
1c79356b
A
2193 if (reply_soright != IP_NULL)
2194 ipc_notify_port_deleted(reply_soright, reply_name);
316670eb 2195
1c79356b
A
2196 return MACH_SEND_INVALID_DEST;
2197}
2198
b0d623f7
A
2199mach_msg_descriptor_t *ipc_kmsg_copyin_port_descriptor(
2200 volatile mach_msg_port_descriptor_t *dsc,
2201 mach_msg_legacy_port_descriptor_t *user_dsc,
2202 ipc_space_t space,
2203 ipc_object_t dest,
2204 ipc_kmsg_t kmsg,
2205 mach_msg_return_t *mr);
2206
2207void ipc_print_type_name(
2208 int type_name);
2209mach_msg_descriptor_t *
2210ipc_kmsg_copyin_port_descriptor(
2211 volatile mach_msg_port_descriptor_t *dsc,
2212 mach_msg_legacy_port_descriptor_t *user_dsc_in,
2213 ipc_space_t space,
2214 ipc_object_t dest,
2215 ipc_kmsg_t kmsg,
2216 mach_msg_return_t *mr)
2217{
2218 volatile mach_msg_legacy_port_descriptor_t *user_dsc = user_dsc_in;
2219 mach_msg_type_name_t user_disp;
2220 mach_msg_type_name_t result_disp;
2221 mach_port_name_t name;
2222 ipc_object_t object;
2223
2224 user_disp = user_dsc->disposition;
2225 result_disp = ipc_object_copyin_type(user_disp);
2226
2227 name = (mach_port_name_t)user_dsc->name;
2228 if (MACH_PORT_VALID(name)) {
2229
2230 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
2231 if (kr != KERN_SUCCESS) {
2232 *mr = MACH_SEND_INVALID_RIGHT;
2233 return NULL;
2234 }
2235
2236 if ((result_disp == MACH_MSG_TYPE_PORT_RECEIVE) &&
2237 ipc_port_check_circularity((ipc_port_t) object,
2238 (ipc_port_t) dest)) {
2239 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2240 }
2241 dsc->name = (ipc_port_t) object;
2242 } else {
2243 dsc->name = CAST_MACH_NAME_TO_PORT(name);
2244 }
2245 dsc->disposition = result_disp;
2246 dsc->type = MACH_MSG_PORT_DESCRIPTOR;
2247
2248 dsc->pad_end = 0; // debug, unnecessary
2249
2250 return (mach_msg_descriptor_t *)(user_dsc_in+1);
2251}
2252
2253mach_msg_descriptor_t * ipc_kmsg_copyin_ool_descriptor(
2254 mach_msg_ool_descriptor_t *dsc,
2255 mach_msg_descriptor_t *user_dsc,
2256 int is_64bit,
2257 vm_offset_t *paddr,
2258 vm_map_copy_t *copy,
2259 vm_size_t *space_needed,
2260 vm_map_t map,
2261 mach_msg_return_t *mr);
2262mach_msg_descriptor_t *
2263ipc_kmsg_copyin_ool_descriptor(
2264 mach_msg_ool_descriptor_t *dsc,
2265 mach_msg_descriptor_t *user_dsc,
2266 int is_64bit,
2267 vm_offset_t *paddr,
2268 vm_map_copy_t *copy,
2269 vm_size_t *space_needed,
2270 vm_map_t map,
2271 mach_msg_return_t *mr)
2272{
2273 vm_size_t length;
2274 boolean_t dealloc;
2275 mach_msg_copy_options_t copy_options;
2276 mach_vm_offset_t addr;
2277 mach_msg_descriptor_type_t dsc_type;
2278
2279 if (is_64bit) {
2280 mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2281
2282 addr = (mach_vm_offset_t) user_ool_dsc->address;
2283 length = user_ool_dsc->size;
2284 dealloc = user_ool_dsc->deallocate;
2285 copy_options = user_ool_dsc->copy;
2286 dsc_type = user_ool_dsc->type;
2287
2288 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2289 } else {
2290 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2291
2292 addr = CAST_USER_ADDR_T(user_ool_dsc->address);
2293 dealloc = user_ool_dsc->deallocate;
2294 copy_options = user_ool_dsc->copy;
2295 dsc_type = user_ool_dsc->type;
2296 length = user_ool_dsc->size;
2297
2298 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2299 }
2300
2301 dsc->size = (mach_msg_size_t)length;
2302 dsc->deallocate = dealloc;
2303 dsc->copy = copy_options;
2304 dsc->type = dsc_type;
2305
2306 if (length == 0) {
2307 dsc->address = NULL;
2308 } else if ((length >= MSG_OOL_SIZE_SMALL) &&
2309 (copy_options == MACH_MSG_PHYSICAL_COPY) && !dealloc) {
2310
2311 /*
2312 * If the request is a physical copy and the source
2313 * is not being deallocated, then allocate space
2314 * in the kernel's pageable ipc copy map and copy
2315 * the data in. The semantics guarantee that the
2316 * data will have been physically copied before
2317 * the send operation terminates. Thus if the data
2318 * is not being deallocated, we must be prepared
2319 * to page if the region is sufficiently large.
2320 */
2321 if (copyin(addr, (char *)*paddr, length)) {
2322 *mr = MACH_SEND_INVALID_MEMORY;
2323 return NULL;
2324 }
2325
2326 /*
2327 * The kernel ipc copy map is marked no_zero_fill.
2328 * If the transfer is not a page multiple, we need
2329 * to zero fill the balance.
2330 */
2331 if (!page_aligned(length)) {
2332 (void) memset((void *) (*paddr + length), 0,
2333 round_page(length) - length);
2334 }
2335 if (vm_map_copyin(ipc_kernel_copy_map, (vm_map_address_t)*paddr,
2336 (vm_map_size_t)length, TRUE, copy) != KERN_SUCCESS) {
2337 *mr = MACH_MSG_VM_KERNEL;
2338 return NULL;
2339 }
2340 dsc->address = (void *)*copy;
2341 *paddr += round_page(length);
2342 *space_needed -= round_page(length);
2343 } else {
2344
2345 /*
2346 * Make a vm_map_copy_t of the of the data. If the
2347 * data is small, this will do an optimized physical
2348 * copy. Otherwise, it will do a virtual copy.
2349 *
2350 * NOTE: A virtual copy is OK if the original is being
2351 * deallocted, even if a physical copy was requested.
2352 */
2353 kern_return_t kr = vm_map_copyin(map, addr,
2354 (vm_map_size_t)length, dealloc, copy);
2355 if (kr != KERN_SUCCESS) {
2356 *mr = (kr == KERN_RESOURCE_SHORTAGE) ?
2357 MACH_MSG_VM_KERNEL :
2358 MACH_SEND_INVALID_MEMORY;
2359 return NULL;
2360 }
2361 dsc->address = (void *)*copy;
2362 }
2363 return user_dsc;
2364}
2365
2366mach_msg_descriptor_t * ipc_kmsg_copyin_ool_ports_descriptor(
2367 mach_msg_ool_ports_descriptor_t *dsc,
2368 mach_msg_descriptor_t *user_dsc,
2369 int is_64bit,
2370 vm_map_t map,
2371 ipc_space_t space,
2372 ipc_object_t dest,
2373 ipc_kmsg_t kmsg,
2374 mach_msg_return_t *mr);
2375mach_msg_descriptor_t *
2376ipc_kmsg_copyin_ool_ports_descriptor(
2377 mach_msg_ool_ports_descriptor_t *dsc,
2378 mach_msg_descriptor_t *user_dsc,
2379 int is_64bit,
2380 vm_map_t map,
2381 ipc_space_t space,
2382 ipc_object_t dest,
2383 ipc_kmsg_t kmsg,
2384 mach_msg_return_t *mr)
2385{
2386 void *data;
2387 ipc_object_t *objects;
2388 unsigned int i;
2389 mach_vm_offset_t addr;
2390 mach_msg_type_name_t user_disp;
2391 mach_msg_type_name_t result_disp;
2392 mach_msg_type_number_t count;
2393 mach_msg_copy_options_t copy_option;
2394 boolean_t deallocate;
2395 mach_msg_descriptor_type_t type;
2396 vm_size_t ports_length, names_length;
2397
2398 if (is_64bit) {
2399 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2400
2401 addr = (mach_vm_offset_t)user_ool_dsc->address;
2402 count = user_ool_dsc->count;
2403 deallocate = user_ool_dsc->deallocate;
2404 copy_option = user_ool_dsc->copy;
2405 user_disp = user_ool_dsc->disposition;
2406 type = user_ool_dsc->type;
2407
2408 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2409 } else {
2410 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
2411
2412 addr = CAST_USER_ADDR_T(user_ool_dsc->address);
2413 count = user_ool_dsc->count;
2414 deallocate = user_ool_dsc->deallocate;
2415 copy_option = user_ool_dsc->copy;
2416 user_disp = user_ool_dsc->disposition;
2417 type = user_ool_dsc->type;
2418
2419 user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
2420 }
2421
2422 dsc->deallocate = deallocate;
2423 dsc->copy = copy_option;
2424 dsc->type = type;
2425 dsc->count = count;
2426 dsc->address = NULL; /* for now */
2427
2428 result_disp = ipc_object_copyin_type(user_disp);
2429 dsc->disposition = result_disp;
2430
2431 if (count > (INT_MAX / sizeof(mach_port_t))) {
2432 *mr = MACH_SEND_TOO_LARGE;
2433 return NULL;
2434 }
2435
2436 /* calculate length of data in bytes, rounding up */
2437 ports_length = count * sizeof(mach_port_t);
2438 names_length = count * sizeof(mach_port_name_t);
2439
2440 if (ports_length == 0) {
2441 return user_dsc;
2442 }
2443
2444 data = kalloc(ports_length);
2445
2446 if (data == NULL) {
2447 *mr = MACH_SEND_NO_BUFFER;
2448 return NULL;
2449 }
2450
2451#ifdef __LP64__
2452 mach_port_name_t *names = &((mach_port_name_t *)data)[count];
2453#else
2454 mach_port_name_t *names = ((mach_port_name_t *)data);
2455#endif
2456
2457 if (copyinmap(map, addr, names, names_length) != KERN_SUCCESS) {
2458 kfree(data, ports_length);
2459 *mr = MACH_SEND_INVALID_MEMORY;
2460 return NULL;
2461 }
2462
2463 if (deallocate) {
2464 (void) mach_vm_deallocate(map, addr, (mach_vm_size_t)ports_length);
2465 }
2466
2467 objects = (ipc_object_t *) data;
2468 dsc->address = data;
2469
2470 for ( i = 0; i < count; i++) {
2471 mach_port_name_t name = names[i];
2472 ipc_object_t object;
2473
2474 if (!MACH_PORT_VALID(name)) {
2475 objects[i] = (ipc_object_t)CAST_MACH_NAME_TO_PORT(name);
2476 continue;
2477 }
2478
2479 kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
2480
2481 if (kr != KERN_SUCCESS) {
2482 unsigned int j;
2483
2484 for(j = 0; j < i; j++) {
2485 object = objects[j];
2486 if (IPC_OBJECT_VALID(object))
2487 ipc_object_destroy(object, result_disp);
2488 }
2489 kfree(data, ports_length);
2490 dsc->address = NULL;
2491 *mr = MACH_SEND_INVALID_RIGHT;
2492 return NULL;
2493 }
2494
2495 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2496 ipc_port_check_circularity(
2497 (ipc_port_t) object,
2498 (ipc_port_t) dest))
2499 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
2500
2501 objects[i] = object;
2502 }
2503
2504 return user_dsc;
2505}
2506
1c79356b
A
2507/*
2508 * Routine: ipc_kmsg_copyin_body
2509 * Purpose:
2510 * "Copy-in" port rights and out-of-line memory
2511 * in the message body.
2512 *
2513 * In all failure cases, the message is left holding
2514 * no rights or memory. However, the message buffer
2515 * is not deallocated. If successful, the message
2516 * contains a valid destination port.
2517 * Conditions:
2518 * Nothing locked.
2519 * Returns:
2520 * MACH_MSG_SUCCESS Successful copyin.
2521 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2522 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2523 * MACH_SEND_INVALID_TYPE Bad type specification.
2524 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2525 * MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
2526 * MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
2527 */
2528
2529mach_msg_return_t
2530ipc_kmsg_copyin_body(
2531 ipc_kmsg_t kmsg,
2532 ipc_space_t space,
2533 vm_map_t map)
2534{
2535 ipc_object_t dest;
2536 mach_msg_body_t *body;
91447636 2537 mach_msg_descriptor_t *daddr, *naddr;
b0d623f7 2538 mach_msg_descriptor_t *user_addr, *kern_addr;
91447636 2539 mach_msg_type_number_t dsc_count;
b0d623f7 2540 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
91447636 2541 boolean_t complex = FALSE;
1c79356b
A
2542 vm_size_t space_needed = 0;
2543 vm_offset_t paddr = 0;
1c79356b 2544 vm_map_copy_t copy = VM_MAP_COPY_NULL;
91447636
A
2545 mach_msg_type_number_t i;
2546 mach_msg_return_t mr = MACH_MSG_SUCCESS;
b0d623f7
A
2547
2548 vm_size_t descriptor_size = 0;
2549
1c79356b
A
2550 /*
2551 * Determine if the target is a kernel port.
2552 */
91447636
A
2553 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
2554 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
2555 naddr = (mach_msg_descriptor_t *) (body + 1);
1c79356b 2556
91447636
A
2557 dsc_count = body->msgh_descriptor_count;
2558 if (dsc_count == 0)
2559 return MACH_MSG_SUCCESS;
2560
1c79356b
A
2561 /*
2562 * Make an initial pass to determine kernal VM space requirements for
91447636
A
2563 * physical copies and possible contraction of the descriptors from
2564 * processes with pointers larger than the kernel's.
1c79356b 2565 */
2d21ac55 2566 daddr = NULL;
91447636
A
2567 for (i = 0; i < dsc_count; i++) {
2568 daddr = naddr;
2569
2570 /* make sure the descriptor fits in the message */
b0d623f7 2571 if (is_task_64bit) {
91447636
A
2572 switch (daddr->type.type) {
2573 case MACH_MSG_OOL_DESCRIPTOR:
2574 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2575 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
b0d623f7
A
2576 descriptor_size += 16;
2577 naddr = (typeof(naddr))((vm_offset_t)daddr + 16);
2578 break;
91447636 2579 default:
b0d623f7
A
2580 descriptor_size += 12;
2581 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
2582 break;
91447636 2583 }
91447636 2584 } else {
b0d623f7
A
2585 descriptor_size += 12;
2586 naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
91447636
A
2587 }
2588
2589 if (naddr > (mach_msg_descriptor_t *)
2590 ((vm_offset_t)kmsg->ikm_header + kmsg->ikm_header->msgh_size)) {
2d21ac55 2591 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
91447636
A
2592 mr = MACH_SEND_MSG_TOO_SMALL;
2593 goto out;
2594 }
1c79356b 2595
91447636
A
2596 switch (daddr->type.type) {
2597 mach_msg_size_t size;
1c79356b 2598
91447636
A
2599 case MACH_MSG_OOL_DESCRIPTOR:
2600 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
b0d623f7
A
2601 size = (is_task_64bit) ?
2602 ((mach_msg_ool_descriptor64_t *)daddr)->size :
91447636
A
2603 daddr->out_of_line.size;
2604
2605 if (daddr->out_of_line.copy != MACH_MSG_PHYSICAL_COPY &&
2606 daddr->out_of_line.copy != MACH_MSG_VIRTUAL_COPY) {
2607 /*
2608 * Invalid copy option
2609 */
2d21ac55 2610 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
91447636
A
2611 mr = MACH_SEND_INVALID_TYPE;
2612 goto out;
2613 }
2614
2615 if ((size >= MSG_OOL_SIZE_SMALL) &&
2616 (daddr->out_of_line.copy == MACH_MSG_PHYSICAL_COPY) &&
2617 !(daddr->out_of_line.deallocate)) {
2618
2619 /*
2620 * Out-of-line memory descriptor, accumulate kernel
2621 * memory requirements
2622 */
39236c6e
A
2623 if (space_needed + round_page(size) <= space_needed) {
2624 /* Overflow dectected */
2625 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2626 mr = MACH_MSG_VM_KERNEL;
2627 goto out;
2628 }
2629
91447636
A
2630 space_needed += round_page(size);
2631 if (space_needed > ipc_kmsg_max_vm_space) {
2632
1c79356b 2633 /*
91447636 2634 * Per message kernel memory limit exceeded
1c79356b 2635 */
2d21ac55 2636 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
91447636
A
2637 mr = MACH_MSG_VM_KERNEL;
2638 goto out;
1c79356b 2639 }
91447636 2640 }
1c79356b
A
2641 }
2642 }
2643
2644 /*
2645 * Allocate space in the pageable kernel ipc copy map for all the
2646 * ool data that is to be physically copied. Map is marked wait for
2647 * space.
2648 */
2649 if (space_needed) {
b0d623f7
A
2650 if (vm_allocate(ipc_kernel_copy_map, &paddr, space_needed,
2651 VM_FLAGS_ANYWHERE) != KERN_SUCCESS) {
2652 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2653 mr = MACH_MSG_VM_KERNEL;
2654 goto out;
2655 }
1c79356b
A
2656 }
2657
b0d623f7
A
2658 /* user_addr = just after base as it was copied in */
2659 user_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
2660 /* Shift the mach_msg_base_t down to make for dsc_count*16bytes of descriptors */
2661 if(descriptor_size != 16*dsc_count) {
2662 vm_offset_t dsc_adjust = 16*dsc_count - descriptor_size;
2663 memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
2664 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
2665 /* Update the message size for the larger in-kernel representation */
2666 kmsg->ikm_header->msgh_size += (mach_msg_size_t)dsc_adjust;
2667 }
1c79356b 2668
1c79356b 2669
b0d623f7
A
2670 /* kern_addr = just after base after it has been (conditionally) moved */
2671 kern_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
2672
2673 /* handle the OOL regions and port descriptors. */
2674 for(i=0;i<dsc_count;i++) {
2675 switch (user_addr->type.type) {
2676 case MACH_MSG_PORT_DESCRIPTOR:
2677 user_addr = ipc_kmsg_copyin_port_descriptor((mach_msg_port_descriptor_t *)kern_addr,
2678 (mach_msg_legacy_port_descriptor_t *)user_addr, space, dest, kmsg, &mr);
2679 kern_addr++;
2680 complex = TRUE;
2681 break;
2682 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2683 case MACH_MSG_OOL_DESCRIPTOR:
2684 user_addr = ipc_kmsg_copyin_ool_descriptor((mach_msg_ool_descriptor_t *)kern_addr,
2685 user_addr, is_task_64bit, &paddr, &copy, &space_needed, map, &mr);
2686 kern_addr++;
2687 complex = TRUE;
2688 break;
2689 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2690 user_addr = ipc_kmsg_copyin_ool_ports_descriptor((mach_msg_ool_ports_descriptor_t *)kern_addr,
2691 user_addr, is_task_64bit, map, space, dest, kmsg, &mr);
2692 kern_addr++;
2693 complex = TRUE;
2694 break;
2695 default:
2696 /* Invalid descriptor */
2697 mr = MACH_SEND_INVALID_TYPE;
2698 break;
2699 }
91447636 2700
b0d623f7
A
2701 if (MACH_MSG_SUCCESS != mr) {
2702 /* clean from start of message descriptors to i */
2703 ipc_kmsg_clean_partial(kmsg, i,
2704 (mach_msg_descriptor_t *)((mach_msg_base_t *)kmsg->ikm_header + 1),
2705 paddr, space_needed);
2706 goto out;
2707 }
2708 } /* End of loop */
1c79356b 2709
91447636
A
2710 if (!complex) {
2711 kmsg->ikm_header->msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
2712 }
91447636 2713 out:
91447636 2714 return mr;
1c79356b
A
2715}
2716
2717
2718/*
2719 * Routine: ipc_kmsg_copyin
2720 * Purpose:
2721 * "Copy-in" port rights and out-of-line memory
2722 * in the message.
2723 *
2724 * In all failure cases, the message is left holding
2725 * no rights or memory. However, the message buffer
2726 * is not deallocated. If successful, the message
2727 * contains a valid destination port.
2728 * Conditions:
2729 * Nothing locked.
2730 * Returns:
2731 * MACH_MSG_SUCCESS Successful copyin.
2732 * MACH_SEND_INVALID_HEADER
2733 * Illegal value in the message header bits.
1c79356b
A
2734 * MACH_SEND_INVALID_DEST Can't copyin destination port.
2735 * MACH_SEND_INVALID_REPLY Can't copyin reply port.
2736 * MACH_SEND_INVALID_MEMORY Can't grab out-of-line memory.
2737 * MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
2738 * MACH_SEND_INVALID_TYPE Bad type specification.
2739 * MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
2740 */
2741
2742mach_msg_return_t
2743ipc_kmsg_copyin(
2744 ipc_kmsg_t kmsg,
2745 ipc_space_t space,
2746 vm_map_t map,
39236c6e 2747 mach_msg_option_t *optionp)
1c79356b
A
2748{
2749 mach_msg_return_t mr;
39236c6e
A
2750
2751 kmsg->ikm_header->msgh_bits &= MACH_MSGH_BITS_USER;
2752
2753 mr = ipc_kmsg_copyin_header(kmsg->ikm_header, space, optionp);
2754
1c79356b
A
2755 if (mr != MACH_MSG_SUCCESS)
2756 return mr;
2757
b0d623f7
A
2758 DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_copyin header:\n%.8x\n%.8x\n%p\n%p\n%.8x\n%.8x\n",
2759 kmsg->ikm_header->msgh_size,
2760 kmsg->ikm_header->msgh_bits,
2761 kmsg->ikm_header->msgh_remote_port,
2762 kmsg->ikm_header->msgh_local_port,
2763 kmsg->ikm_header->msgh_reserved,
2764 kmsg->ikm_header->msgh_id);
2765
91447636 2766 if ((kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0)
1c79356b
A
2767 return MACH_MSG_SUCCESS;
2768
b0d623f7
A
2769 mr = ipc_kmsg_copyin_body( kmsg, space, map);
2770
2771 if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
2772 {
2773 kprintf("body:\n");
2774 uint32_t i;
2775 for(i=0;i*4 < (kmsg->ikm_header->msgh_size - sizeof(mach_msg_header_t));i++)
2776 {
2777 kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
2778 }
2779 }
39236c6e 2780
b0d623f7 2781 return mr;
1c79356b
A
2782}
2783
2784/*
2785 * Routine: ipc_kmsg_copyin_from_kernel
2786 * Purpose:
2787 * "Copy-in" port rights and out-of-line memory
2788 * in a message sent from the kernel.
2789 *
2790 * Because the message comes from the kernel,
2791 * the implementation assumes there are no errors
2792 * or peculiarities in the message.
1c79356b
A
2793 * Conditions:
2794 * Nothing locked.
2795 */
2796
6d2010ae 2797mach_msg_return_t
1c79356b
A
2798ipc_kmsg_copyin_from_kernel(
2799 ipc_kmsg_t kmsg)
2800{
91447636 2801 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
1c79356b
A
2802 mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
2803 mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
91447636
A
2804 ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
2805 ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
2806
2807 /* translate the destination and reply ports */
6d2010ae
A
2808 if (!IO_VALID(remote))
2809 return MACH_SEND_INVALID_DEST;
1c79356b
A
2810
2811 ipc_object_copyin_from_kernel(remote, rname);
2812 if (IO_VALID(local))
2813 ipc_object_copyin_from_kernel(local, lname);
2814
2815 /*
2816 * The common case is a complex message with no reply port,
2817 * because that is what the memory_object interface uses.
2818 */
2819
2820 if (bits == (MACH_MSGH_BITS_COMPLEX |
2821 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
2822 bits = (MACH_MSGH_BITS_COMPLEX |
2823 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
2824
91447636 2825 kmsg->ikm_header->msgh_bits = bits;
1c79356b
A
2826 } else {
2827 bits = (MACH_MSGH_BITS_OTHER(bits) |
2828 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
2829 ipc_object_copyin_type(lname)));
2830
91447636 2831 kmsg->ikm_header->msgh_bits = bits;
1c79356b 2832 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
6d2010ae 2833 return MACH_MSG_SUCCESS;
1c79356b
A
2834 }
2835 {
b0d623f7 2836 mach_msg_descriptor_t *saddr;
1c79356b 2837 mach_msg_body_t *body;
b0d623f7 2838 mach_msg_type_number_t i, count;
1c79356b 2839
91447636 2840 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
1c79356b 2841 saddr = (mach_msg_descriptor_t *) (body + 1);
b0d623f7 2842 count = body->msgh_descriptor_count;
1c79356b 2843
b0d623f7 2844 for (i = 0; i < count; i++, saddr++) {
1c79356b
A
2845
2846 switch (saddr->type.type) {
2847
2848 case MACH_MSG_PORT_DESCRIPTOR: {
2849 mach_msg_type_name_t name;
2850 ipc_object_t object;
2851 mach_msg_port_descriptor_t *dsc;
2852
2853 dsc = &saddr->port;
2854
2855 /* this is really the type SEND, SEND_ONCE, etc. */
2856 name = dsc->disposition;
2857 object = (ipc_object_t) dsc->name;
2858 dsc->disposition = ipc_object_copyin_type(name);
2859
2860 if (!IO_VALID(object)) {
2861 break;
2862 }
2863
2864 ipc_object_copyin_from_kernel(object, name);
2865
2866 /* CDY avoid circularity when the destination is also */
2867 /* the kernel. This check should be changed into an */
2868 /* assert when the new kobject model is in place since*/
2869 /* ports will not be used in kernel to kernel chats */
2870
2871 if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
2872 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2873 ipc_port_check_circularity((ipc_port_t) object,
2874 (ipc_port_t) remote)) {
91447636 2875 kmsg->ikm_header->msgh_bits |=
1c79356b
A
2876 MACH_MSGH_BITS_CIRCULAR;
2877 }
2878 }
2879 break;
2880 }
2881 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2882 case MACH_MSG_OOL_DESCRIPTOR: {
2883 /*
2884 * The sender should supply ready-made memory, i.e.
2885 * a vm_map_copy_t, so we don't need to do anything.
2886 */
2887 break;
2888 }
2889 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
2890 ipc_object_t *objects;
91447636 2891 unsigned int j;
1c79356b
A
2892 mach_msg_type_name_t name;
2893 mach_msg_ool_ports_descriptor_t *dsc;
2894
b0d623f7 2895 dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
1c79356b
A
2896
2897 /* this is really the type SEND, SEND_ONCE, etc. */
2898 name = dsc->disposition;
2899 dsc->disposition = ipc_object_copyin_type(name);
2900
2901 objects = (ipc_object_t *) dsc->address;
2902
2903 for ( j = 0; j < dsc->count; j++) {
2904 ipc_object_t object = objects[j];
2905
2906 if (!IO_VALID(object))
2907 continue;
2908
2909 ipc_object_copyin_from_kernel(object, name);
2910
2911 if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
2912 ipc_port_check_circularity(
2913 (ipc_port_t) object,
2914 (ipc_port_t) remote))
91447636 2915 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
1c79356b
A
2916 }
2917 break;
2918 }
2919 default: {
2920#if MACH_ASSERT
2921 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
2922#endif /* MACH_ASSERT */
2923 }
2924 }
2925 }
2926 }
6d2010ae 2927 return MACH_MSG_SUCCESS;
1c79356b
A
2928}
2929
b0d623f7 2930#if IKM_SUPPORT_LEGACY
6d2010ae 2931mach_msg_return_t
b0d623f7
A
2932ipc_kmsg_copyin_from_kernel_legacy(
2933 ipc_kmsg_t kmsg)
2934{
2935 mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
2936 mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
2937 mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
2938 ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
2939 ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
2940
2941 /* translate the destination and reply ports */
6d2010ae
A
2942 if (!IO_VALID(remote))
2943 return MACH_SEND_INVALID_DEST;
b0d623f7
A
2944
2945 ipc_object_copyin_from_kernel(remote, rname);
2946 if (IO_VALID(local))
2947 ipc_object_copyin_from_kernel(local, lname);
2948
2949 /*
2950 * The common case is a complex message with no reply port,
2951 * because that is what the memory_object interface uses.
2952 */
2953
2954 if (bits == (MACH_MSGH_BITS_COMPLEX |
2955 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
2956 bits = (MACH_MSGH_BITS_COMPLEX |
2957 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
2958
2959 kmsg->ikm_header->msgh_bits = bits;
2960 } else {
2961 bits = (MACH_MSGH_BITS_OTHER(bits) |
2962 MACH_MSGH_BITS(ipc_object_copyin_type(rname),
2963 ipc_object_copyin_type(lname)));
2964
2965 kmsg->ikm_header->msgh_bits = bits;
2966 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
6d2010ae 2967 return MACH_MSG_SUCCESS;
b0d623f7
A
2968 }
2969 {
2970 mach_msg_legacy_descriptor_t *saddr;
2971 mach_msg_descriptor_t *daddr;
2972 mach_msg_body_t *body;
2973 mach_msg_type_number_t i, count;
2974
2975 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
2976 saddr = (typeof(saddr)) (body + 1);
2977 count = body->msgh_descriptor_count;
2978
2979 if(count) {
2980 vm_offset_t dsc_adjust = 4*count;
2981 memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
2982 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
2983 /* Update the message size for the larger in-kernel representation */
2984 kmsg->ikm_header->msgh_size += dsc_adjust;
2985 }
2986 daddr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
2987
2988 for (i = 0; i < count; i++, saddr++, daddr++) {
2989 switch (saddr->type.type) {
2990
2991 case MACH_MSG_PORT_DESCRIPTOR: {
2992 mach_msg_type_name_t name;
2993 ipc_object_t object;
2994 mach_msg_legacy_port_descriptor_t *dsc;
2995 mach_msg_port_descriptor_t *dest_dsc;
2996
2997 dsc = (typeof(dsc))&saddr->port;
2998 dest_dsc = &daddr->port;
2999
3000 /* this is really the type SEND, SEND_ONCE, etc. */
3001 name = dsc->disposition;
3002 object = (ipc_object_t) CAST_MACH_NAME_TO_PORT(dsc->name);
3003 dest_dsc->disposition = ipc_object_copyin_type(name);
3004 dest_dsc->name = (mach_port_t)object;
3005 dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
3006
3007 if (!IO_VALID(object)) {
3008 break;
3009 }
3010
3011 ipc_object_copyin_from_kernel(object, name);
3012
3013 /* CDY avoid circularity when the destination is also */
3014 /* the kernel. This check should be changed into an */
3015 /* assert when the new kobject model is in place since*/
3016 /* ports will not be used in kernel to kernel chats */
3017
3018 if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
3019 if ((dest_dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
3020 ipc_port_check_circularity((ipc_port_t) object,
3021 (ipc_port_t) remote)) {
3022 kmsg->ikm_header->msgh_bits |=
3023 MACH_MSGH_BITS_CIRCULAR;
3024 }
3025 }
3026 break;
3027 }
3028 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3029 case MACH_MSG_OOL_DESCRIPTOR: {
3030 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
3031 * so we don't need to do anything special. */
3032
3033 mach_msg_ool_descriptor32_t *source_dsc = &saddr->out_of_line32;
3034 mach_msg_ool_descriptor_t *dest_dsc = (typeof(dest_dsc))&daddr->out_of_line;
3035
3036 vm_offset_t address = source_dsc->address;
3037 vm_size_t size = source_dsc->size;
3038 boolean_t deallocate = source_dsc->deallocate;
3039 mach_msg_copy_options_t copy = source_dsc->copy;
3040 mach_msg_descriptor_type_t type = source_dsc->type;
3041
3042 dest_dsc->address = (void *)address;
3043 dest_dsc->size = size;
3044 dest_dsc->deallocate = deallocate;
3045 dest_dsc->copy = copy;
3046 dest_dsc->type = type;
3047 break;
3048 }
3049 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
3050 ipc_object_t *objects;
3051 unsigned int j;
3052 mach_msg_type_name_t name;
3053 mach_msg_ool_ports_descriptor_t *dest_dsc;
3054
3055 mach_msg_ool_ports_descriptor32_t *source_dsc = &saddr->ool_ports32;
3056 dest_dsc = (typeof(dest_dsc))&daddr->ool_ports;
3057
3058 boolean_t deallocate = source_dsc->deallocate;
3059 mach_msg_copy_options_t copy = source_dsc->copy;
3060 mach_msg_size_t port_count = source_dsc->count;
3061 mach_msg_type_name_t disposition = source_dsc->disposition;
3062
3063 /* this is really the type SEND, SEND_ONCE, etc. */
3064 name = disposition;
3065 disposition = ipc_object_copyin_type(name);
3066
3067 objects = (ipc_object_t *) (uintptr_t)source_dsc->address;
3068
3069 for ( j = 0; j < port_count; j++) {
3070 ipc_object_t object = objects[j];
3071
3072 if (!IO_VALID(object))
3073 continue;
3074
3075 ipc_object_copyin_from_kernel(object, name);
3076
3077 if ((disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
3078 ipc_port_check_circularity(
3079 (ipc_port_t) object,
3080 (ipc_port_t) remote))
3081 kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
3082 }
3083
3084 dest_dsc->address = objects;
3085 dest_dsc->deallocate = deallocate;
3086 dest_dsc->copy = copy;
3087 dest_dsc->disposition = disposition;
3088 dest_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3089 dest_dsc->count = port_count;
3090 break;
3091 }
3092 default: {
3093#if MACH_ASSERT
3094 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
3095#endif /* MACH_ASSERT */
3096 }
3097 }
3098 }
3099 }
6d2010ae 3100 return MACH_MSG_SUCCESS;
b0d623f7
A
3101}
3102#endif /* IKM_SUPPORT_LEGACY */
3103
1c79356b
A
3104/*
3105 * Routine: ipc_kmsg_copyout_header
3106 * Purpose:
3107 * "Copy-out" port rights in the header of a message.
3108 * Operates atomically; if it doesn't succeed the
3109 * message header and the space are left untouched.
3110 * If it does succeed the remote/local port fields
3111 * contain port names instead of object pointers,
3112 * and the bits field is updated.
1c79356b
A
3113 * Conditions:
3114 * Nothing locked.
3115 * Returns:
3116 * MACH_MSG_SUCCESS Copied out port rights.
3117 * MACH_RCV_INVALID_NOTIFY
3118 * Notify is non-null and doesn't name a receive right.
3119 * (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
3120 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
3121 * The space is dead.
3122 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
3123 * No room in space for another name.
3124 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
3125 * Couldn't allocate memory for the reply port.
3126 * MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
3127 * Couldn't allocate memory for the dead-name request.
3128 */
3129
3130mach_msg_return_t
3131ipc_kmsg_copyout_header(
3132 mach_msg_header_t *msg,
6d2010ae 3133 ipc_space_t space)
1c79356b
A
3134{
3135 mach_msg_bits_t mbits = msg->msgh_bits;
3136 ipc_port_t dest = (ipc_port_t) msg->msgh_remote_port;
3137
3138 assert(IP_VALID(dest));
3139
6d2010ae
A
3140 /*
3141 * While we still hold a reference on the received-from port,
3142 * process all send-possible notfications we received along with
3143 * the message.
3144 */
3145 ipc_port_spnotify(dest);
3146
1c79356b
A
3147 {
3148 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
3149 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
3150 ipc_port_t reply = (ipc_port_t) msg->msgh_local_port;
316670eb 3151 ipc_port_t release_port = IP_NULL;
1c79356b
A
3152 mach_port_name_t dest_name, reply_name;
3153
3154 if (IP_VALID(reply)) {
1c79356b
A
3155 ipc_entry_t entry;
3156 kern_return_t kr;
3157
3158 /*
6d2010ae
A
3159 * Get reply port entry (if none, skip to dest port
3160 * copyout). This may require growing the space.
1c79356b
A
3161 */
3162
3163 is_write_lock(space);
3164
3165 for (;;) {
316670eb 3166 if (!is_active(space)) {
1c79356b
A
3167 is_write_unlock(space);
3168 return (MACH_RCV_HEADER_ERROR|
3169 MACH_MSG_IPC_SPACE);
3170 }
3171
1c79356b
A
3172 if ((reply_type != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
3173 ipc_right_reverse(space, (ipc_object_t) reply,
3174 &reply_name, &entry)) {
3175 /* reply port is locked and active */
1c79356b
A
3176 assert(entry->ie_bits &
3177 MACH_PORT_TYPE_SEND_RECEIVE);
3178 break;
3179 }
3180
3181 ip_lock(reply);
3182 if (!ip_active(reply)) {
316670eb 3183 ip_unlock(reply);
1c79356b
A
3184 ip_lock(dest);
3185 is_write_unlock(space);
3186
316670eb 3187 release_port = reply;
1c79356b
A
3188 reply = IP_DEAD;
3189 reply_name = MACH_PORT_DEAD;
3190 goto copyout_dest;
3191 }
3192
b0d623f7 3193 reply_name = CAST_MACH_PORT_TO_NAME(reply);
1c79356b
A
3194 kr = ipc_entry_get(space, &reply_name, &entry);
3195 if (kr != KERN_SUCCESS) {
3196 ip_unlock(reply);
3197
1c79356b
A
3198 /* space is locked */
3199 kr = ipc_entry_grow_table(space,
3200 ITS_SIZE_NONE);
3201 if (kr != KERN_SUCCESS) {
6d2010ae
A
3202 return (MACH_RCV_HEADER_ERROR|
3203 MACH_MSG_IPC_SPACE);
1c79356b
A
3204 }
3205 /* space is locked again; start over */
3206
3207 continue;
3208 }
3209 assert(IE_BITS_TYPE(entry->ie_bits) ==
3210 MACH_PORT_TYPE_NONE);
3211 assert(entry->ie_object == IO_NULL);
3212
1c79356b 3213 entry->ie_object = (ipc_object_t) reply;
1c79356b
A
3214 break;
3215 }
3216
3217 /* space and reply port are locked and active */
3218
3219 ip_reference(reply); /* hold onto the reply port */
3220
3221 kr = ipc_right_copyout(space, reply_name, entry,
3222 reply_type, TRUE, (ipc_object_t) reply);
39236c6e 3223
1c79356b
A
3224 /* reply port is unlocked */
3225 assert(kr == KERN_SUCCESS);
3226
1c79356b
A
3227 ip_lock(dest);
3228 is_write_unlock(space);
39236c6e 3229
1c79356b
A
3230 } else {
3231 /*
3232 * No reply port! This is an easy case.
3233 * We only need to have the space locked
6d2010ae 3234 * when locking the destination.
1c79356b
A
3235 */
3236
3237 is_read_lock(space);
316670eb 3238 if (!is_active(space)) {
1c79356b
A
3239 is_read_unlock(space);
3240 return MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE;
3241 }
3242
1c79356b
A
3243 ip_lock(dest);
3244 is_read_unlock(space);
3245
b0d623f7 3246 reply_name = CAST_MACH_PORT_TO_NAME(reply);
1c79356b
A
3247 }
3248
3249 /*
3250 * At this point, the space is unlocked and the destination
3251 * port is locked. (Lock taken while space was locked.)
3252 * reply_name is taken care of; we still need dest_name.
3253 * We still hold a ref for reply (if it is valid).
3254 *
3255 * If the space holds receive rights for the destination,
3256 * we return its name for the right. Otherwise the task
3257 * managed to destroy or give away the receive right between
3258 * receiving the message and this copyout. If the destination
3259 * is dead, return MACH_PORT_DEAD, and if the receive right
3260 * exists somewhere else (another space, in transit)
3261 * return MACH_PORT_NULL.
3262 *
3263 * Making this copyout operation atomic with the previous
3264 * copyout of the reply port is a bit tricky. If there was
3265 * no real reply port (it wasn't IP_VALID) then this isn't
3266 * an issue. If the reply port was dead at copyout time,
3267 * then we are OK, because if dest is dead we serialize
3268 * after the death of both ports and if dest is alive
3269 * we serialize after reply died but before dest's (later) death.
3270 * So assume reply was alive when we copied it out. If dest
3271 * is alive, then we are OK because we serialize before
3272 * the ports' deaths. So assume dest is dead when we look at it.
3273 * If reply dies/died after dest, then we are OK because
3274 * we serialize after dest died but before reply dies.
3275 * So the hard case is when reply is alive at copyout,
3276 * dest is dead at copyout, and reply died before dest died.
3277 * In this case pretend that dest is still alive, so
3278 * we serialize while both ports are alive.
3279 *
3280 * Because the space lock is held across the copyout of reply
3281 * and locking dest, the receive right for dest can't move
3282 * in or out of the space while the copyouts happen, so
3283 * that isn't an atomicity problem. In the last hard case
3284 * above, this implies that when dest is dead that the
3285 * space couldn't have had receive rights for dest at
3286 * the time reply was copied-out, so when we pretend
3287 * that dest is still alive, we can return MACH_PORT_NULL.
3288 *
3289 * If dest == reply, then we have to make it look like
3290 * either both copyouts happened before the port died,
3291 * or both happened after the port died. This special
3292 * case works naturally if the timestamp comparison
3293 * is done correctly.
3294 */
3295
3296 copyout_dest:
3297
3298 if (ip_active(dest)) {
3299 ipc_object_copyout_dest(space, (ipc_object_t) dest,
3300 dest_type, &dest_name);
3301 /* dest is unlocked */
39236c6e 3302
1c79356b
A
3303 } else {
3304 ipc_port_timestamp_t timestamp;
3305
3306 timestamp = dest->ip_timestamp;
316670eb 3307 ip_unlock(dest);
1c79356b 3308 ip_release(dest);
1c79356b
A
3309
3310 if (IP_VALID(reply)) {
3311 ip_lock(reply);
3312 if (ip_active(reply) ||
3313 IP_TIMESTAMP_ORDER(timestamp,
3314 reply->ip_timestamp))
3315 dest_name = MACH_PORT_DEAD;
3316 else
3317 dest_name = MACH_PORT_NULL;
3318 ip_unlock(reply);
3319 } else
3320 dest_name = MACH_PORT_DEAD;
3321 }
3322
3323 if (IP_VALID(reply))
316670eb
A
3324 ip_release(reply);
3325
3326 if (IP_VALID(release_port))
3327 ip_release(release_port);
1c79356b
A
3328
3329 msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
3330 MACH_MSGH_BITS(reply_type, dest_type));
b0d623f7
A
3331 msg->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
3332 msg->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
1c79356b
A
3333 }
3334
3335 return MACH_MSG_SUCCESS;
3336}
3337
3338/*
3339 * Routine: ipc_kmsg_copyout_object
3340 * Purpose:
3341 * Copy-out a port right. Always returns a name,
3342 * even for unsuccessful return codes. Always
3343 * consumes the supplied object.
3344 * Conditions:
3345 * Nothing locked.
3346 * Returns:
3347 * MACH_MSG_SUCCESS The space acquired the right
3348 * (name is valid) or the object is dead (MACH_PORT_DEAD).
3349 * MACH_MSG_IPC_SPACE No room in space for the right,
3350 * or the space is dead. (Name is MACH_PORT_NULL.)
3351 * MACH_MSG_IPC_KERNEL Kernel resource shortage.
3352 * (Name is MACH_PORT_NULL.)
3353 */
3354
3355mach_msg_return_t
3356ipc_kmsg_copyout_object(
3357 ipc_space_t space,
3358 ipc_object_t object,
3359 mach_msg_type_name_t msgt_name,
3360 mach_port_name_t *namep)
3361{
3362 kern_return_t kr;
3363
3364 if (!IO_VALID(object)) {
b0d623f7 3365 *namep = CAST_MACH_PORT_TO_NAME(object);
1c79356b
A
3366 return MACH_MSG_SUCCESS;
3367 }
3368
3369 kr = ipc_object_copyout(space, object, msgt_name, TRUE, namep);
3370 if (kr != KERN_SUCCESS) {
3371 ipc_object_destroy(object, msgt_name);
3372
3373 if (kr == KERN_INVALID_CAPABILITY)
3374 *namep = MACH_PORT_DEAD;
3375 else {
3376 *namep = MACH_PORT_NULL;
3377
3378 if (kr == KERN_RESOURCE_SHORTAGE)
3379 return MACH_MSG_IPC_KERNEL;
3380 else
3381 return MACH_MSG_IPC_SPACE;
3382 }
3383 }
3384
3385 return MACH_MSG_SUCCESS;
3386}
3387
b0d623f7
A
3388mach_msg_descriptor_t *
3389ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3390 mach_msg_descriptor_t *user_dsc,
3391 ipc_space_t space,
3392 kern_return_t *mr);
3393mach_msg_descriptor_t *
3394ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
3395 mach_msg_descriptor_t *dest_dsc,
3396 ipc_space_t space,
3397 kern_return_t *mr)
3398{
3399 mach_port_t port;
3400 mach_port_name_t name;
3401 mach_msg_type_name_t disp;
3402
3403
3404 /* Copyout port right carried in the message */
3405 port = dsc->port.name;
3406 disp = dsc->port.disposition;
3407 *mr |= ipc_kmsg_copyout_object(space,
3408 (ipc_object_t)port,
3409 disp,
3410 &name);
3411
3412 if(current_task() == kernel_task)
3413 {
3414 mach_msg_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
3415 user_dsc--; // point to the start of this port descriptor
3416 user_dsc->name = CAST_MACH_NAME_TO_PORT(name);
3417 user_dsc->disposition = disp;
3418 user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
3419 dest_dsc = (typeof(dest_dsc))user_dsc;
3420 } else {
3421 mach_msg_legacy_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
3422 user_dsc--; // point to the start of this port descriptor
3423 user_dsc->name = CAST_MACH_PORT_TO_NAME(name);
3424 user_dsc->disposition = disp;
3425 user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
3426 dest_dsc = (typeof(dest_dsc))user_dsc;
3427 }
3428
3429 return (mach_msg_descriptor_t *)dest_dsc;
3430}
3431
3432mach_msg_descriptor_t *
3433ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descriptor_t *user_dsc, int is_64bit, vm_map_t map, mach_msg_return_t *mr);
3434mach_msg_descriptor_t *
3435ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descriptor_t *user_dsc, int is_64bit, vm_map_t map, mach_msg_return_t *mr)
3436{
3437 vm_map_copy_t copy;
316670eb 3438 vm_map_address_t rcv_addr;
b0d623f7
A
3439 mach_msg_copy_options_t copy_options;
3440 mach_msg_size_t size;
3441 mach_msg_descriptor_type_t dsc_type;
3442
3443 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
3444
3445 copy = (vm_map_copy_t) dsc->address;
3446 size = dsc->size;
3447 copy_options = dsc->copy;
3448 assert(copy_options != MACH_MSG_KALLOC_COPY_T);
3449 dsc_type = dsc->type;
3450 rcv_addr = 0;
3451
3452 if (copy != VM_MAP_COPY_NULL) {
3453 /*
3454 * Check to see if there is an overwrite descriptor
3455 * specified in the scatter list for this ool data.
3456 * The descriptor has already been verified.
3457 */
3458#if 0
3459 if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
3460 if (differs) {
3461 OTHER_OOL_DESCRIPTOR *scatter_dsc;
3462
3463 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
3464 if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
3465 rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
3466 copy_options = MACH_MSG_OVERWRITE;
3467 } else {
3468 copy_options = MACH_MSG_VIRTUAL_COPY;
3469 }
3470 } else {
3471 mach_msg_ool_descriptor_t *scatter_dsc;
3472
3473 scatter_dsc = &saddr->out_of_line;
3474 if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
3475 rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
3476 copy_options = MACH_MSG_OVERWRITE;
3477 } else {
3478 copy_options = MACH_MSG_VIRTUAL_COPY;
3479 }
3480 }
3481 INCREMENT_SCATTER(saddr, sdsc_count, differs);
3482 }
3483#endif
3484
3485
3486 /*
3487 * Whether the data was virtually or physically
3488 * copied we have a vm_map_copy_t for it.
3489 * If there's an overwrite region specified
3490 * overwrite it, otherwise do a virtual copy out.
3491 */
3492 kern_return_t kr;
3493 if (copy_options == MACH_MSG_OVERWRITE && rcv_addr != 0) {
3494 kr = vm_map_copy_overwrite(map, rcv_addr,
3495 copy, TRUE);
3496 } else {
3497 kr = vm_map_copyout(map, &rcv_addr, copy);
3498 }
3499 if (kr != KERN_SUCCESS) {
3500 if (kr == KERN_RESOURCE_SHORTAGE)
3501 *mr |= MACH_MSG_VM_KERNEL;
3502 else
3503 *mr |= MACH_MSG_VM_SPACE;
3504 vm_map_copy_discard(copy);
3505 rcv_addr = 0;
3506 size = 0;
3507 }
3508 } else {
3509 rcv_addr = 0;
3510 size = 0;
3511 }
3512
3513 /*
3514 * Now update the descriptor as the user would see it.
3515 * This may require expanding the descriptor to the user
3516 * visible size. There is already space allocated for
3517 * this in what naddr points to.
3518 */
3519 if(current_task() == kernel_task)
3520 {
3521 mach_msg_ool_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3522 user_ool_dsc--;
3523
3524 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
3525 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3526 TRUE : FALSE;
3527 user_ool_dsc->copy = copy_options;
3528 user_ool_dsc->type = dsc_type;
3529 user_ool_dsc->size = size;
3530
3531 user_dsc = (typeof(user_dsc))user_ool_dsc;
3532 } else if (is_64bit) {
3533 mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3534 user_ool_dsc--;
3535
3536 user_ool_dsc->address = rcv_addr;
3537 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3538 TRUE : FALSE;
3539 user_ool_dsc->copy = copy_options;
3540 user_ool_dsc->type = dsc_type;
3541 user_ool_dsc->size = size;
3542
3543 user_dsc = (typeof(user_dsc))user_ool_dsc;
3544 } else {
3545 mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3546 user_ool_dsc--;
3547
3548 user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
3549 user_ool_dsc->size = size;
3550 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3551 TRUE : FALSE;
3552 user_ool_dsc->copy = copy_options;
3553 user_ool_dsc->type = dsc_type;
3554
3555 user_dsc = (typeof(user_dsc))user_ool_dsc;
3556 }
3557 return user_dsc;
3558}
3559
3560mach_msg_descriptor_t *
3561ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
3562 mach_msg_descriptor_t *user_dsc,
3563 int is_64bit,
3564 vm_map_t map,
3565 ipc_space_t space,
3566 ipc_kmsg_t kmsg,
3567 mach_msg_return_t *mr);
3568mach_msg_descriptor_t *
3569ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
3570 mach_msg_descriptor_t *user_dsc,
3571 int is_64bit,
3572 vm_map_t map,
3573 ipc_space_t space,
3574 ipc_kmsg_t kmsg,
3575 mach_msg_return_t *mr)
3576{
39236c6e 3577 mach_vm_offset_t rcv_addr = 0;
b0d623f7
A
3578 mach_msg_type_name_t disp;
3579 mach_msg_type_number_t count, i;
3580 vm_size_t ports_length, names_length;
3581
3582 mach_msg_copy_options_t copy_options = MACH_MSG_VIRTUAL_COPY;
3583
3584 //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
3585
3586 count = dsc->count;
3587 disp = dsc->disposition;
3588 ports_length = count * sizeof(mach_port_t);
3589 names_length = count * sizeof(mach_port_name_t);
3590
3591 if (ports_length != 0 && dsc->address != 0) {
3592
3593 /*
3594 * Check to see if there is an overwrite descriptor
3595 * specified in the scatter list for this ool data.
3596 * The descriptor has already been verified.
3597 */
3598#if 0
3599 if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
3600 if (differs) {
3601 OTHER_OOL_DESCRIPTOR *scatter_dsc;
3602
3603 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
3604 rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
3605 copy_options = scatter_dsc->copy;
3606 } else {
3607 mach_msg_ool_descriptor_t *scatter_dsc;
3608
3609 scatter_dsc = &saddr->out_of_line;
3610 rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
3611 copy_options = scatter_dsc->copy;
3612 }
3613 INCREMENT_SCATTER(saddr, sdsc_count, differs);
3614 }
3615#endif
3616
3617 if (copy_options == MACH_MSG_VIRTUAL_COPY) {
3618 /*
3619 * Dynamically allocate the region
3620 */
3621 int anywhere = VM_MAKE_TAG(VM_MEMORY_MACH_MSG)|
3622 VM_FLAGS_ANYWHERE;
3623
3624 kern_return_t kr;
3625 if ((kr = mach_vm_allocate(map, &rcv_addr,
3626 (mach_vm_size_t)names_length,
3627 anywhere)) != KERN_SUCCESS) {
3628 ipc_kmsg_clean_body(kmsg, 1, (mach_msg_descriptor_t *)dsc);
3629 rcv_addr = 0;
3630
3631 if (kr == KERN_RESOURCE_SHORTAGE){
3632 *mr |= MACH_MSG_VM_KERNEL;
3633 } else {
3634 *mr |= MACH_MSG_VM_SPACE;
3635 }
3636 }
3637 }
3638
3639 /*
3640 * Handle the port rights and copy out the names
3641 * for those rights out to user-space.
3642 */
3643 if (rcv_addr != 0) {
3644 mach_port_t *objects = (mach_port_t *) dsc->address;
3645 mach_port_name_t *names = (mach_port_name_t *) dsc->address;
3646
3647 /* copyout port rights carried in the message */
3648
3649 for ( i = 0; i < count ; i++) {
3650 ipc_object_t object = (ipc_object_t)objects[i];
3651
3652 *mr |= ipc_kmsg_copyout_object(space, object,
3653 disp, &names[i]);
3654 }
3655
3656 /* copyout to memory allocated above */
3657 void *data = dsc->address;
3658 if (copyoutmap(map, data, rcv_addr, names_length) != KERN_SUCCESS)
3659 *mr |= MACH_MSG_VM_SPACE;
3660 kfree(data, ports_length);
3661 }
3662 } else {
3663 rcv_addr = 0;
3664 }
3665
3666 /*
3667 * Now update the descriptor based on the information
3668 * calculated above.
3669 */
3670 if(current_task() == kernel_task) {
3671 mach_msg_ool_ports_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3672 user_ool_dsc--;
3673
3674 user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
3675 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3676 TRUE : FALSE;
3677 user_ool_dsc->copy = copy_options;
3678 user_ool_dsc->disposition = disp;
3679 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3680 user_ool_dsc->count = count;
3681
3682 user_dsc = (typeof(user_dsc))user_ool_dsc;
3683 } if (is_64bit) {
3684 mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3685 user_ool_dsc--;
3686
3687 user_ool_dsc->address = rcv_addr;
3688 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3689 TRUE : FALSE;
3690 user_ool_dsc->copy = copy_options;
3691 user_ool_dsc->disposition = disp;
3692 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3693 user_ool_dsc->count = count;
3694
3695 user_dsc = (typeof(user_dsc))user_ool_dsc;
3696 } else {
3697 mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
3698 user_ool_dsc--;
3699
3700 user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
3701 user_ool_dsc->count = count;
3702 user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
3703 TRUE : FALSE;
3704 user_ool_dsc->copy = copy_options;
3705 user_ool_dsc->disposition = disp;
3706 user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
3707
3708 user_dsc = (typeof(user_dsc))user_ool_dsc;
3709 }
3710 return user_dsc;
3711}
3712
1c79356b
A
3713/*
3714 * Routine: ipc_kmsg_copyout_body
3715 * Purpose:
3716 * "Copy-out" port rights and out-of-line memory
3717 * in the body of a message.
3718 *
3719 * The error codes are a combination of special bits.
3720 * The copyout proceeds despite errors.
3721 * Conditions:
3722 * Nothing locked.
3723 * Returns:
3724 * MACH_MSG_SUCCESS Successful copyout.
3725 * MACH_MSG_IPC_SPACE No room for port right in name space.
3726 * MACH_MSG_VM_SPACE No room for memory in address space.
3727 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
3728 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
3729 * MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
3730 */
3731
3732mach_msg_return_t
3733ipc_kmsg_copyout_body(
3734 ipc_kmsg_t kmsg,
3735 ipc_space_t space,
3736 vm_map_t map,
3737 mach_msg_body_t *slist)
3738{
3739 mach_msg_body_t *body;
b0d623f7 3740 mach_msg_descriptor_t *kern_dsc, *user_dsc;
91447636 3741 mach_msg_descriptor_t *saddr;
b0d623f7
A
3742 mach_msg_type_number_t dsc_count, sdsc_count;
3743 int i;
1c79356b 3744 mach_msg_return_t mr = MACH_MSG_SUCCESS;
b0d623f7 3745 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
1c79356b 3746
91447636
A
3747 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3748 dsc_count = body->msgh_descriptor_count;
b0d623f7
A
3749 kern_dsc = (mach_msg_descriptor_t *) (body + 1);
3750 /* Point user_dsc just after the end of all the descriptors */
3751 user_dsc = &kern_dsc[dsc_count];
1c79356b 3752
b0d623f7 3753 /* Do scatter list setup */
1c79356b 3754 if (slist != MACH_MSG_BODY_NULL) {
b0d623f7 3755 panic("Scatter lists disabled");
91447636
A
3756 saddr = (mach_msg_descriptor_t *) (slist + 1);
3757 sdsc_count = slist->msgh_descriptor_count;
1c79356b
A
3758 }
3759 else {
91447636
A
3760 saddr = MACH_MSG_DESCRIPTOR_NULL;
3761 sdsc_count = 0;
1c79356b
A
3762 }
3763
b0d623f7
A
3764 /* Now process the descriptors */
3765 for (i = dsc_count-1; i >= 0; i--) {
3766 switch (kern_dsc[i].type.type) {
3767
3768 case MACH_MSG_PORT_DESCRIPTOR:
3769 user_dsc = ipc_kmsg_copyout_port_descriptor(&kern_dsc[i], user_dsc, space, &mr);
3770 break;
3771 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3772 case MACH_MSG_OOL_DESCRIPTOR :
3773 user_dsc = ipc_kmsg_copyout_ool_descriptor(
3774 (mach_msg_ool_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, &mr);
3775 break;
3776 case MACH_MSG_OOL_PORTS_DESCRIPTOR :
3777 user_dsc = ipc_kmsg_copyout_ool_ports_descriptor(
3778 (mach_msg_ool_ports_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, space, kmsg, &mr);
3779 break;
3780 default : {
3781 panic("untyped IPC copyout body: invalid message descriptor");
3782 }
3783 }
91447636
A
3784 }
3785
b0d623f7
A
3786 if(user_dsc != kern_dsc) {
3787 vm_offset_t dsc_adjust = (vm_offset_t)user_dsc - (vm_offset_t)kern_dsc;
3788 memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
3789 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
3790 /* Update the message size for the smaller user representation */
3791 kmsg->ikm_header->msgh_size -= (mach_msg_size_t)dsc_adjust;
1c79356b 3792 }
b0d623f7 3793
1c79356b
A
3794 return mr;
3795}
3796
91447636
A
3797/*
3798 * Routine: ipc_kmsg_copyout_size
3799 * Purpose:
3800 * Compute the size of the message as copied out to the given
3801 * map. If the destination map's pointers are a different size
3802 * than the kernel's, we have to allow for expansion/
3803 * contraction of the descriptors as appropriate.
3804 * Conditions:
3805 * Nothing locked.
3806 * Returns:
3807 * size of the message as it would be received.
3808 */
3809
3810mach_msg_size_t
3811ipc_kmsg_copyout_size(
3812 ipc_kmsg_t kmsg,
3813 vm_map_t map)
3814{
b0d623f7 3815 mach_msg_size_t send_size;
91447636 3816
b0d623f7 3817 send_size = kmsg->ikm_header->msgh_size;
91447636 3818
b0d623f7 3819 boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
91447636 3820
b0d623f7
A
3821#if defined(__LP64__)
3822 send_size -= LEGACY_HEADER_SIZE_DELTA;
3823#endif
91447636 3824
b0d623f7 3825 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
91447636 3826
b0d623f7
A
3827 mach_msg_body_t *body;
3828 mach_msg_descriptor_t *saddr, *eaddr;
91447636 3829
b0d623f7
A
3830 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3831 saddr = (mach_msg_descriptor_t *) (body + 1);
3832 eaddr = saddr + body->msgh_descriptor_count;
3833
3834 for ( ; saddr < eaddr; saddr++ ) {
3835 switch (saddr->type.type) {
3836 case MACH_MSG_OOL_DESCRIPTOR:
3837 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3838 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3839 if(!is_task_64bit)
3840 send_size -= DESC_SIZE_ADJUSTMENT;
3841 break;
3842 case MACH_MSG_PORT_DESCRIPTOR:
3843 send_size -= DESC_SIZE_ADJUSTMENT;
3844 break;
3845 default:
3846 break;
3847 }
3848 }
3849 }
3850 return send_size;
91447636
A
3851}
3852
1c79356b
A
3853/*
3854 * Routine: ipc_kmsg_copyout
3855 * Purpose:
3856 * "Copy-out" port rights and out-of-line memory
3857 * in the message.
3858 * Conditions:
3859 * Nothing locked.
3860 * Returns:
3861 * MACH_MSG_SUCCESS Copied out all rights and memory.
1c79356b
A
3862 * MACH_RCV_HEADER_ERROR + special bits
3863 * Rights and memory in the message are intact.
3864 * MACH_RCV_BODY_ERROR + special bits
3865 * The message header was successfully copied out.
3866 * As much of the body was handled as possible.
3867 */
3868
3869mach_msg_return_t
3870ipc_kmsg_copyout(
3871 ipc_kmsg_t kmsg,
3872 ipc_space_t space,
3873 vm_map_t map,
1c79356b
A
3874 mach_msg_body_t *slist)
3875{
3876 mach_msg_return_t mr;
3877
6d2010ae 3878 mr = ipc_kmsg_copyout_header(kmsg->ikm_header, space);
2d21ac55 3879 if (mr != MACH_MSG_SUCCESS) {
1c79356b 3880 return mr;
2d21ac55 3881 }
1c79356b 3882
91447636 3883 if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
1c79356b
A
3884 mr = ipc_kmsg_copyout_body(kmsg, space, map, slist);
3885
3886 if (mr != MACH_MSG_SUCCESS)
3887 mr |= MACH_RCV_BODY_ERROR;
3888 }
3889
3890 return mr;
3891}
3892
3893/*
3894 * Routine: ipc_kmsg_copyout_pseudo
3895 * Purpose:
3896 * Does a pseudo-copyout of the message.
3897 * This is like a regular copyout, except
3898 * that the ports in the header are handled
3899 * as if they are in the body. They aren't reversed.
3900 *
3901 * The error codes are a combination of special bits.
3902 * The copyout proceeds despite errors.
3903 * Conditions:
3904 * Nothing locked.
3905 * Returns:
3906 * MACH_MSG_SUCCESS Successful copyout.
3907 * MACH_MSG_IPC_SPACE No room for port right in name space.
3908 * MACH_MSG_VM_SPACE No room for memory in address space.
3909 * MACH_MSG_IPC_KERNEL Resource shortage handling port right.
3910 * MACH_MSG_VM_KERNEL Resource shortage handling memory.
3911 */
3912
3913mach_msg_return_t
3914ipc_kmsg_copyout_pseudo(
3915 ipc_kmsg_t kmsg,
3916 ipc_space_t space,
3917 vm_map_t map,
3918 mach_msg_body_t *slist)
3919{
91447636
A
3920 mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
3921 ipc_object_t dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
3922 ipc_object_t reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
3923 mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
3924 mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
3925 mach_port_name_t dest_name, reply_name;
3926 mach_msg_return_t mr;
3927
3928 assert(IO_VALID(dest));
3929
3930 mr = (ipc_kmsg_copyout_object(space, dest, dest_type, &dest_name) |
3931 ipc_kmsg_copyout_object(space, reply, reply_type, &reply_name));
3932
39236c6e 3933 kmsg->ikm_header->msgh_bits = mbits & MACH_MSGH_BITS_USER;
b0d623f7
A
3934 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(dest_name);
3935 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(reply_name);
1c79356b
A
3936
3937 if (mbits & MACH_MSGH_BITS_COMPLEX) {
3938 mr |= ipc_kmsg_copyout_body(kmsg, space, map, slist);
3939 }
3940
3941 return mr;
3942}
3943
3944/*
3945 * Routine: ipc_kmsg_copyout_dest
3946 * Purpose:
3947 * Copies out the destination port in the message.
3948 * Destroys all other rights and memory in the message.
3949 * Conditions:
3950 * Nothing locked.
3951 */
3952
3953void
3954ipc_kmsg_copyout_dest(
3955 ipc_kmsg_t kmsg,
3956 ipc_space_t space)
3957{
3958 mach_msg_bits_t mbits;
3959 ipc_object_t dest;
3960 ipc_object_t reply;
3961 mach_msg_type_name_t dest_type;
3962 mach_msg_type_name_t reply_type;
3963 mach_port_name_t dest_name, reply_name;
3964
91447636
A
3965 mbits = kmsg->ikm_header->msgh_bits;
3966 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
3967 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
1c79356b
A
3968 dest_type = MACH_MSGH_BITS_REMOTE(mbits);
3969 reply_type = MACH_MSGH_BITS_LOCAL(mbits);
3970
3971 assert(IO_VALID(dest));
3972
3973 io_lock(dest);
3974 if (io_active(dest)) {
3975 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
3976 /* dest is unlocked */
3977 } else {
316670eb 3978 io_unlock(dest);
1c79356b 3979 io_release(dest);
1c79356b
A
3980 dest_name = MACH_PORT_DEAD;
3981 }
3982
3983 if (IO_VALID(reply)) {
3984 ipc_object_destroy(reply, reply_type);
3985 reply_name = MACH_PORT_NULL;
3986 } else
b0d623f7 3987 reply_name = CAST_MACH_PORT_TO_NAME(reply);
1c79356b 3988
91447636 3989 kmsg->ikm_header->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
1c79356b 3990 MACH_MSGH_BITS(reply_type, dest_type));
b0d623f7
A
3991 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
3992 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
1c79356b
A
3993
3994 if (mbits & MACH_MSGH_BITS_COMPLEX) {
3995 mach_msg_body_t *body;
3996
91447636
A
3997 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3998 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count,
3999 (mach_msg_descriptor_t *)(body + 1));
1c79356b
A
4000 }
4001}
91447636 4002
1c79356b
A
4003/*
4004 * Routine: ipc_kmsg_copyin_scatter
4005 * Purpose:
4006 * allocate and copyin a scatter list
4007 * Algorithm:
4008 * The gather (kmsg) is valid since it has been copied in.
4009 * Gather list descriptors are sequentially paired with scatter
4010 * list descriptors, with port descriptors in either list ignored.
4011 * Descriptors are consistent if the type fileds match and size
4012 * of the scatter descriptor is less than or equal to the
4013 * size of the gather descriptor. A MACH_MSG_ALLOCATE copy
4014 * strategy in a scatter descriptor matches any size in the
4015 * corresponding gather descriptor assuming they are the same type.
4016 * Either list may be larger than the other. During the
4017 * subsequent copy out, excess scatter descriptors are ignored
4018 * and excess gather descriptors default to dynamic allocation.
4019 *
4020 * In the case of a size error, the scatter list is released.
4021 * Conditions:
4022 * Nothing locked.
4023 * Returns:
4024 * the allocated message body containing the scatter list.
4025 */
4026
4027mach_msg_body_t *
91447636
A
4028ipc_kmsg_get_scatter(
4029 mach_vm_address_t msg_addr,
4030 mach_msg_size_t slist_size,
4031 ipc_kmsg_t kmsg)
1c79356b
A
4032{
4033 mach_msg_body_t *slist;
4034 mach_msg_body_t *body;
4035 mach_msg_descriptor_t *gstart, *gend;
4036 mach_msg_descriptor_t *sstart, *send;
4037
b0d623f7
A
4038#if defined(__LP64__)
4039 panic("ipc_kmsg_get_scatter called!");
4040#endif
1c79356b
A
4041
4042 if (slist_size < sizeof(mach_msg_base_t))
4043 return MACH_MSG_BODY_NULL;
4044
b0d623f7 4045 slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
1c79356b
A
4046 slist = (mach_msg_body_t *)kalloc(slist_size);
4047 if (slist == MACH_MSG_BODY_NULL)
4048 return slist;
4049
91447636
A
4050 if (copyin(msg_addr + sizeof(mach_msg_header_t), (char *)slist, slist_size)) {
4051 kfree(slist, slist_size);
1c79356b
A
4052 return MACH_MSG_BODY_NULL;
4053 }
4054
4055 if ((slist->msgh_descriptor_count* sizeof(mach_msg_descriptor_t)
4056 + sizeof(mach_msg_size_t)) > slist_size) {
91447636 4057 kfree(slist, slist_size);
1c79356b
A
4058 return MACH_MSG_BODY_NULL;
4059 }
4060
91447636 4061 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
1c79356b
A
4062 gstart = (mach_msg_descriptor_t *) (body + 1);
4063 gend = gstart + body->msgh_descriptor_count;
4064
4065 sstart = (mach_msg_descriptor_t *) (slist + 1);
4066 send = sstart + slist->msgh_descriptor_count;
4067
4068 while (gstart < gend) {
4069 mach_msg_descriptor_type_t g_type;
4070
4071 /*
4072 * Skip port descriptors in gather list.
4073 */
4074 g_type = gstart->type.type;
4075
4076 if (g_type != MACH_MSG_PORT_DESCRIPTOR) {
4077
4078 /*
4079 * A scatter list with a 0 descriptor count is treated as an
4080 * automatic size mismatch.
4081 */
4082 if (slist->msgh_descriptor_count == 0) {
91447636 4083 kfree(slist, slist_size);
1c79356b
A
4084 return MACH_MSG_BODY_NULL;
4085 }
4086
4087 /*
4088 * Skip port descriptors in scatter list.
4089 */
4090 while (sstart < send) {
4091 if (sstart->type.type != MACH_MSG_PORT_DESCRIPTOR)
4092 break;
4093 sstart++;
4094 }
4095
4096 /*
4097 * No more scatter descriptors, we're done
4098 */
4099 if (sstart >= send) {
4100 break;
4101 }
4102
4103 /*
4104 * Check type, copy and size fields
4105 */
4106 if (g_type == MACH_MSG_OOL_DESCRIPTOR ||
4107 g_type == MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
4108 if (sstart->type.type != MACH_MSG_OOL_DESCRIPTOR &&
4109 sstart->type.type != MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
91447636 4110 kfree(slist, slist_size);
1c79356b
A
4111 return MACH_MSG_BODY_NULL;
4112 }
4113 if (sstart->out_of_line.copy == MACH_MSG_OVERWRITE &&
4114 gstart->out_of_line.size > sstart->out_of_line.size) {
91447636 4115 kfree(slist, slist_size);
1c79356b
A
4116 return MACH_MSG_BODY_NULL;
4117 }
4118 }
4119 else {
4120 if (sstart->type.type != MACH_MSG_OOL_PORTS_DESCRIPTOR) {
91447636 4121 kfree(slist, slist_size);
1c79356b
A
4122 return MACH_MSG_BODY_NULL;
4123 }
4124 if (sstart->ool_ports.copy == MACH_MSG_OVERWRITE &&
4125 gstart->ool_ports.count > sstart->ool_ports.count) {
91447636 4126 kfree(slist, slist_size);
1c79356b
A
4127 return MACH_MSG_BODY_NULL;
4128 }
4129 }
4130 sstart++;
4131 }
4132 gstart++;
4133 }
4134 return slist;
4135}
4136
4137
4138/*
4139 * Routine: ipc_kmsg_free_scatter
4140 * Purpose:
4141 * Deallocate a scatter list. Since we actually allocated
4142 * a body without a header, and since the header was originally
4143 * accounted for in slist_size, we have to ajust it down
4144 * before freeing the scatter list.
4145 */
4146void
4147ipc_kmsg_free_scatter(
4148 mach_msg_body_t *slist,
4149 mach_msg_size_t slist_size)
4150{
b0d623f7
A
4151#if defined(__LP64__)
4152 panic("%s called; halting!", __func__);
4153#endif
4154
4155 slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
91447636 4156 kfree(slist, slist_size);
1c79356b
A
4157}
4158
4159
4160/*
4161 * Routine: ipc_kmsg_copyout_to_kernel
4162 * Purpose:
4163 * Copies out the destination and reply ports in the message.
4164 * Leaves all other rights and memory in the message alone.
4165 * Conditions:
4166 * Nothing locked.
4167 *
4168 * Derived from ipc_kmsg_copyout_dest.
4169 * Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
4170 * We really do want to save rights and memory.
4171 */
4172
4173void
4174ipc_kmsg_copyout_to_kernel(
4175 ipc_kmsg_t kmsg,
4176 ipc_space_t space)
4177{
4178 ipc_object_t dest;
4179 ipc_object_t reply;
4180 mach_msg_type_name_t dest_type;
4181 mach_msg_type_name_t reply_type;
4182 mach_port_name_t dest_name, reply_name;
4183
91447636
A
4184 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4185 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
4186 dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
4187 reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
1c79356b
A
4188
4189 assert(IO_VALID(dest));
4190
4191 io_lock(dest);
4192 if (io_active(dest)) {
4193 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4194 /* dest is unlocked */
4195 } else {
316670eb 4196 io_unlock(dest);
1c79356b 4197 io_release(dest);
1c79356b
A
4198 dest_name = MACH_PORT_DEAD;
4199 }
4200
b0d623f7 4201 reply_name = CAST_MACH_PORT_TO_NAME(reply);
1c79356b 4202
91447636
A
4203 kmsg->ikm_header->msgh_bits =
4204 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
1c79356b 4205 MACH_MSGH_BITS(reply_type, dest_type));
b0d623f7
A
4206 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
4207 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
1c79356b
A
4208}
4209
b0d623f7
A
4210#if IKM_SUPPORT_LEGACY
4211void
4212ipc_kmsg_copyout_to_kernel_legacy(
4213 ipc_kmsg_t kmsg,
4214 ipc_space_t space)
4215{
4216 ipc_object_t dest;
4217 ipc_object_t reply;
4218 mach_msg_type_name_t dest_type;
4219 mach_msg_type_name_t reply_type;
4220 mach_port_name_t dest_name, reply_name;
4221
4222 dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
4223 reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
4224 dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
4225 reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
4226
4227 assert(IO_VALID(dest));
4228
4229 io_lock(dest);
4230 if (io_active(dest)) {
4231 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
4232 /* dest is unlocked */
4233 } else {
316670eb 4234 io_unlock(dest);
b0d623f7 4235 io_release(dest);
b0d623f7
A
4236 dest_name = MACH_PORT_DEAD;
4237 }
4238
4239 reply_name = CAST_MACH_PORT_TO_NAME(reply);
4240
4241 kmsg->ikm_header->msgh_bits =
4242 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
4243 MACH_MSGH_BITS(reply_type, dest_type));
4244 kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
4245 kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
4246
4247 mach_msg_descriptor_t *saddr;
4248 mach_msg_legacy_descriptor_t *daddr;
4249 mach_msg_type_number_t i, count = ((mach_msg_base_t *)kmsg->ikm_header)->body.msgh_descriptor_count;
4250 saddr = (mach_msg_descriptor_t *) (((mach_msg_base_t *)kmsg->ikm_header) + 1);
4251 saddr = &saddr[count-1];
4252 daddr = (mach_msg_legacy_descriptor_t *)&saddr[count];
4253 daddr--;
4254
4255 vm_offset_t dsc_adjust = 0;
4256
4257 for (i = 0; i < count; i++, saddr--, daddr--) {
4258 switch (saddr->type.type) {
4259 case MACH_MSG_PORT_DESCRIPTOR: {
4260 mach_msg_port_descriptor_t *dsc = &saddr->port;
4261 mach_msg_legacy_port_descriptor_t *dest_dsc = &daddr->port;
4262
4263 mach_port_t name = dsc->name;
4264 mach_msg_type_name_t disposition = dsc->disposition;
4265
4266 dest_dsc->name = CAST_MACH_PORT_TO_NAME(name);
4267 dest_dsc->disposition = disposition;
4268 dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
4269 break;
4270 }
4271 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4272 case MACH_MSG_OOL_DESCRIPTOR: {
4273 /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
4274 * so we don't need to do anything special. */
4275
4276 mach_msg_ool_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->out_of_line;
4277
4278 mach_msg_ool_descriptor32_t *dest_dsc = &daddr->out_of_line32;
4279
4280 vm_offset_t address = (vm_offset_t)source_dsc->address;
4281 vm_size_t size = source_dsc->size;
4282 boolean_t deallocate = source_dsc->deallocate;
4283 mach_msg_copy_options_t copy = source_dsc->copy;
4284 mach_msg_descriptor_type_t type = source_dsc->type;
4285
4286 dest_dsc->address = address;
4287 dest_dsc->size = size;
4288 dest_dsc->deallocate = deallocate;
4289 dest_dsc->copy = copy;
4290 dest_dsc->type = type;
4291 break;
4292 }
4293 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
4294 mach_msg_ool_ports_descriptor_t *source_dsc = (typeof(source_dsc))&saddr->ool_ports;
4295
4296 mach_msg_ool_ports_descriptor32_t *dest_dsc = &daddr->ool_ports32;
4297
4298 vm_offset_t address = (vm_offset_t)source_dsc->address;
4299 vm_size_t port_count = source_dsc->count;
4300 boolean_t deallocate = source_dsc->deallocate;
4301 mach_msg_copy_options_t copy = source_dsc->copy;
4302 mach_msg_descriptor_type_t type = source_dsc->type;
4303
4304 dest_dsc->address = address;
4305 dest_dsc->count = port_count;
4306 dest_dsc->deallocate = deallocate;
4307 dest_dsc->copy = copy;
4308 dest_dsc->type = type;
4309 break;
4310 }
4311 default: {
4312#if MACH_ASSERT
4313 panic("ipc_kmsg_copyin_from_kernel: bad descriptor");
4314#endif /* MACH_ASSERT */
4315 }
4316 }
4317 }
4318
4319 if(count) {
4320 dsc_adjust = 4*count;
4321 memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
4322 kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
4323 /* Update the message size for the smaller user representation */
4324 kmsg->ikm_header->msgh_size -= dsc_adjust;
4325 }
4326}
4327#endif /* IKM_SUPPORT_LEGACY */
4328
316670eb
A
4329mach_msg_trailer_size_t
4330ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space,
4331 mach_msg_option_t option, thread_t thread,
4332 mach_port_seqno_t seqno, boolean_t minimal_trailer,
4333 mach_vm_offset_t context)
1c79356b 4334{
316670eb 4335 mach_msg_max_trailer_t *trailer;
1c79356b 4336
316670eb
A
4337 (void)thread;
4338 trailer = (mach_msg_max_trailer_t *)
4339 ((vm_offset_t)kmsg->ikm_header +
4340 round_msg(kmsg->ikm_header->msgh_size));
1c79356b 4341
316670eb
A
4342 if (!(option & MACH_RCV_TRAILER_MASK)) {
4343 return trailer->msgh_trailer_size;
1c79356b 4344 }
1c79356b 4345
316670eb
A
4346 trailer->msgh_seqno = seqno;
4347 trailer->msgh_context = context;
4348 trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit(thread), option);
1c79356b 4349
316670eb
A
4350 if (minimal_trailer) {
4351 goto done;
1c79356b
A
4352 }
4353
316670eb
A
4354 if (MACH_RCV_TRAILER_ELEMENTS(option) >=
4355 MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV)){
4356#if CONFIG_MACF_MACH
4357 if (kmsg->ikm_sender != NULL &&
4358 IP_VALID(kmsg->ikm_header->msgh_remote_port) &&
4359 mac_port_check_method(kmsg->ikm_sender,
4360 &kmsg->ikm_sender->maclabel,
4361 &kmsg->ikm_header->msgh_remote_port->ip_label,
4362 kmsg->ikm_header->msgh_id) == 0)
4363 trailer->msgh_ad = 1;
4364 else
4365#endif
4366 trailer->msgh_ad = 0;
1c79356b 4367 }
1c79356b 4368
316670eb
A
4369 /*
4370 * The ipc_kmsg_t holds a reference to the label of a label
4371 * handle, not the port. We must get a reference to the port
4372 * and a send right to copyout to the receiver.
4373 */
1c79356b 4374
316670eb
A
4375 if (option & MACH_RCV_TRAILER_ELEMENTS (MACH_RCV_TRAILER_LABELS)) {
4376#if CONFIG_MACF_MACH
4377 if (kmsg->ikm_sender != NULL) {
4378 ipc_labelh_t lh = kmsg->ikm_sender->label;
4379 kern_return_t kr;
4380
4381 ip_lock(lh->lh_port);
4382 lh->lh_port->ip_mscount++;
4383 lh->lh_port->ip_srights++;
4384 ip_reference(lh->lh_port);
4385 ip_unlock(lh->lh_port);
4386
4387 kr = ipc_object_copyout(space, (ipc_object_t)lh->lh_port,
4388 MACH_MSG_TYPE_PORT_SEND, 0,
4389 &trailer->msgh_labels.sender);
4390 if (kr != KERN_SUCCESS) {
4391 ip_release(lh->lh_port);
4392 trailer->msgh_labels.sender = 0;
4393 }
4394 } else {
4395 trailer->msgh_labels.sender = 0;
4396 }
4397#else
4398 (void)space;
4399 trailer->msgh_labels.sender = 0;
4400#endif
1c79356b 4401 }
1c79356b 4402
1c79356b 4403
316670eb 4404done:
39236c6e 4405
316670eb 4406 return trailer->msgh_trailer_size;
1c79356b 4407}