1/*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
49 *  School of Computer Science
50 *  Carnegie Mellon University
51 *  Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 * 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 */
63/*
64 */
65/*
66 *	File:	ipc/ipc_kmsg.c
67 *	Author:	Rich Draves
68 *	Date:	1989
69 *
70 *	Operations on kernel messages.
71 */
72
73
74#include <mach/mach_types.h>
75#include <mach/boolean.h>
76#include <mach/kern_return.h>
77#include <mach/message.h>
78#include <mach/port.h>
79#include <mach/vm_map.h>
80#include <mach/mach_vm.h>
81#include <mach/vm_statistics.h>
82
83#include <kern/kern_types.h>
84#include <kern/assert.h>
85#include <kern/debug.h>
86#include <kern/ipc_kobject.h>
87#include <kern/kalloc.h>
88#include <kern/zalloc.h>
89#include <kern/processor.h>
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>
95#include <kern/cpu_data.h>
96
97#include <machine/machlimits.h>
98
99#include <vm/vm_map.h>
100#include <vm/vm_object.h>
101#include <vm/vm_kern.h>
102
103#include <ipc/port.h>
104#include <ipc/ipc_types.h>
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
115#include <security/mac_mach_internal.h>
116
117#include <string.h>
118
119#ifdef ppc
120#include <ppc/Firmware.h>
121#include <ppc/low_trace.h>
122#endif
123
124#if DEBUG
125#define DEBUG_MSGS_K64 1
126#endif
127
128#include <sys/kdebug.h>
129#include <libkern/OSAtomic.h>
130
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 */
487
488extern vm_map_t		ipc_kernel_copy_map;
489extern vm_size_t	ipc_kmsg_max_space;
490extern vm_size_t	ipc_kmsg_max_vm_space;
491extern vm_size_t	ipc_kmsg_max_body_space;
492extern vm_size_t	msg_ool_size_small;
493
494#define MSG_OOL_SIZE_SMALL	msg_ool_size_small
495
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
506#define DESC_SIZE_ADJUSTMENT	((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
507				 sizeof(mach_msg_ool_descriptor32_t)))
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;
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,
546    	mach_msg_type_number_t	number,
547	mach_msg_descriptor_t	*desc);
548
549void ipc_kmsg_clean_partial(
550	ipc_kmsg_t		kmsg,
551	mach_msg_type_number_t	number,
552	mach_msg_descriptor_t	*desc,
553	vm_offset_t		paddr,
554	vm_size_t		length);
555
556mach_msg_return_t ipc_kmsg_copyin_body(
557	ipc_kmsg_t		kmsg,
558	ipc_space_t		space,
559	vm_map_t		map);
560
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 */
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{
581	mach_msg_size_t max_expanded_size;
582	ipc_kmsg_t kmsg;
583
584	/*
585	 * LP64support -
586	 * Pad the allocation in case we need to expand the
587	 * message descrptors for user spaces with pointers larger than
588	 * the kernel's own, or vice versa.  We don't know how many descriptors
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	 */
597	mach_msg_size_t size = msg_and_trailer_size - MAX_TRAILER_SIZE;
598
599	/* compare against implementation upper limit for the body */
600	if (size > ipc_kmsg_max_body_space)
601		return IKM_NULL;
602
603	if (size > sizeof(mach_msg_base_t)) {
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);
607
608		/* make sure expansion won't cause wrap */
609		if (msg_and_trailer_size > MACH_MSG_SIZE_MAX - max_desc)
610			return IKM_NULL;
611
612		max_expanded_size = msg_and_trailer_size + max_desc;
613	} else
614		max_expanded_size = msg_and_trailer_size;
615
616	if (max_expanded_size < IKM_SAVED_MSG_SIZE)
617		max_expanded_size = IKM_SAVED_MSG_SIZE; 	/* round up for ikm_cache */
618
619	if (max_expanded_size == IKM_SAVED_MSG_SIZE) {
620		struct ikm_cache	*cache;
621		unsigned int		i;
622
623		disable_preemption();
624		cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
625		if ((i = cache->avail) > 0) {
626			assert(i <= IKM_STASH);
627			kmsg = cache->entries[--i];
628			cache->avail = i;
629			enable_preemption();
630			ikm_check_init(kmsg, max_expanded_size);
631			ikm_set_header(kmsg, msg_and_trailer_size);
632			return (kmsg);
633		}
634		enable_preemption();
635		kmsg = (ipc_kmsg_t)zalloc(ipc_kmsg_zone);
636	} else {
637		kmsg = (ipc_kmsg_t)kalloc(ikm_plus_overhead(max_expanded_size));
638	}
639
640	if (kmsg != IKM_NULL) {
641		ikm_init(kmsg, max_expanded_size);
642		ikm_set_header(kmsg, msg_and_trailer_size);
643	}
644
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
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
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
677	 * leave the message associated with it.  Otherwise, free it.
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);
686			ip_release(port);
687			return;
688		}
689                ip_unlock(port);
690		ip_release(port); /* May be last reference */
691	}
692
693	/*
694	 * Peek and see if it has to go back in the cache.
695	 */
696	if (kmsg->ikm_size == IKM_SAVED_MSG_SIZE) {
697		struct ikm_cache	*cache;
698		unsigned int		i;
699
700		disable_preemption();
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;
705			enable_preemption();
706			return;
707		}
708		enable_preemption();
709		zfree(ipc_kmsg_zone, kmsg);
710		return;
711	}
712	kfree(kmsg, ikm_plus_overhead(size));
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 */
781	assert((kmsg->ikm_next = IKM_BOGUS) == IKM_BOGUS);
782	assert((kmsg->ikm_prev = IKM_BOGUS) == IKM_BOGUS);
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{
822	/*
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.
827	 */
828	if (ipc_kmsg_delayed_destroy(kmsg))
829		ipc_kmsg_reap_delayed();
830}
831
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 */
840
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);
846
847	ipc_kmsg_enqueue(queue, kmsg);
848	return first;
849}
850
851/*
852 *	Routine:	ipc_kmsg_destroy_queue
853 *	Purpose:
854 *		Destroys messages from the per-thread
855 *		deferred reaping queue.
856 *	Conditions:
857 *		No locks held.
858 */
859
860void
861ipc_kmsg_reap_delayed(void)
862{
863	ipc_kmsg_queue_t queue = &(current_thread()->ith_messages);
864	ipc_kmsg_t kmsg;
865
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	}
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 */
886static unsigned int _ipc_kmsg_clean_invalid_desc = 0;
887void
888ipc_kmsg_clean_body(
889	__unused ipc_kmsg_t	kmsg,
890	mach_msg_type_number_t	number,
891	mach_msg_descriptor_t	*saddr)
892{
893    mach_msg_type_number_t	i;
894
895    if ( number == 0 )
896	return;
897
898    for (i = 0 ; i < number; i++, saddr++ ) {
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
919		dsc = (mach_msg_ool_descriptor_t *)&saddr->out_of_line;
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
936		dsc = (mach_msg_ool_ports_descriptor_t	*)&saddr->ool_ports;
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
960		kfree(dsc->address,
961		     (vm_size_t) dsc->count * sizeof(mach_port_t));
962		break;
963	    }
964	    default : {
965		    _ipc_kmsg_clean_invalid_desc++; /* don't understand this type of descriptor */
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,
988	mach_msg_descriptor_t	*desc,
989	vm_offset_t		paddr,
990	vm_size_t		length)
991{
992	ipc_object_t object;
993	mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
994
995	object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
996	assert(IO_VALID(object));
997	ipc_object_destroy_dest(object, MACH_MSGH_BITS_REMOTE(mbits));
998
999	object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
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
1007	ipc_kmsg_clean_body(kmsg, number, desc);
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
1026	mbits = kmsg->ikm_header->msgh_bits;
1027	object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
1028	if (IO_VALID(object))
1029		ipc_object_destroy_dest(object, MACH_MSGH_BITS_REMOTE(mbits));
1030
1031	object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
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
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));
1041	}
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
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
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}
1105
1106
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.
1118 *		MACH_SEND_TOO_LARGE	Message too large to ever be sent.
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(
1125	mach_vm_address_t	msg_addr,
1126	mach_msg_size_t	size,
1127	ipc_kmsg_t		*kmsgp)
1128{
1129	mach_msg_size_t			msg_and_trailer_size;
1130	ipc_kmsg_t 			kmsg;
1131	mach_msg_max_trailer_t	 	*trailer;
1132	mach_msg_legacy_base_t	    legacy_base;
1133	mach_msg_size_t             len_copied;
1134	legacy_base.body.msgh_descriptor_count = 0;
1135
1136	if ((size < sizeof(mach_msg_legacy_header_t)) || (size & 3))
1137		return MACH_SEND_MSG_TOO_SMALL;
1138
1139	if (size > ipc_kmsg_max_body_space)
1140		return MACH_SEND_TOO_LARGE;
1141
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);
1146
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	}
1160
1161	msg_and_trailer_size = size + MAX_TRAILER_SIZE;
1162	kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1163	if (kmsg == IKM_NULL)
1164		return MACH_SEND_NO_BUFFER;
1165
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))) {
1188		ipc_kmsg_free(kmsg);
1189		return MACH_SEND_INVALID_DATA;
1190	}
1191
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()");
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	 */
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;
1212	trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1213	trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
1214
1215#ifdef ppc
1216	if(trcWork.traceMask) dbgTrace(0x1100, (unsigned int)kmsg->ikm_header->msgh_id,
1217		(unsigned int)kmsg->ikm_header->msgh_remote_port,
1218		(unsigned int)kmsg->ikm_header->msgh_local_port, 0);
1219#endif
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
1230	trailer->msgh_labels.sender = 0;
1231#endif
1232
1233	*kmsgp = kmsg;
1234	return MACH_MSG_SUCCESS;
1235}
1236
1237/*
1238 *	Routine:	ipc_kmsg_get_from_kernel
1239 *	Purpose:
1240 *		First checks for a preallocated message
1241 *		reserved for kernel clients.  If not found -
1242 *		allocates a new kernel message buffer.
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,
1256	mach_msg_size_t	size,
1257	ipc_kmsg_t		*kmsgp)
1258{
1259	ipc_kmsg_t 	kmsg;
1260	mach_msg_size_t	msg_and_trailer_size;
1261	mach_msg_max_trailer_t *trailer;
1262	ipc_port_t	dest_port;
1263
1264	assert(size >= sizeof(mach_msg_header_t));
1265	assert((size & 3) == 0);
1266
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	 */
1276	if (IP_VALID(dest_port) && IP_PREALLOC(dest_port)) {
1277		mach_msg_size_t max_desc = 0;
1278
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;
1286		if (ikm_prealloc_inuse(kmsg)) {
1287			ip_unlock(dest_port);
1288			return MACH_SEND_NO_BUFFER;
1289		}
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		}
1301		ikm_prealloc_set_inuse(kmsg, dest_port);
1302		ikm_set_header(kmsg, msg_and_trailer_size);
1303		ip_unlock(dest_port);
1304	}
1305	else
1306	{
1307		kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
1308		if (kmsg == IKM_NULL)
1309			return MACH_SEND_NO_BUFFER;
1310	}
1311
1312	(void) memcpy((void *) kmsg->ikm_header, (const void *) msg, size);
1313
1314	kmsg->ikm_header->msgh_size = size;
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	 */
1322	trailer = (mach_msg_max_trailer_t *)
1323	          ((vm_offset_t)kmsg->ikm_header + size);
1324	trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
1325	trailer->msgh_audit = KERNEL_AUDIT_TOKEN;
1326	trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
1327	trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
1328
1329	trailer->msgh_labels.sender = 0;
1330
1331#if CONFIG_MACF_MACH
1332	kmsg->ikm_sender = NULL;
1333#endif
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.
1354 *		MACH_SEND_INVALID_DEST	Caller still has message.
1355 */
1356
1357
1358mach_msg_return_t
1359ipc_kmsg_send(
1360	ipc_kmsg_t		kmsg,
1361	mach_msg_option_t	option,
1362	mach_msg_timeout_t	send_timeout)
1363{
1364	ipc_port_t port;
1365	mach_msg_return_t error = MACH_MSG_SUCCESS;
1366	spl_t s;
1367
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
1382	port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1383	assert(IP_VALID(port));
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
1407		port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
1408		assert(IP_VALID(port));
1409		ip_lock(port);
1410		/* fall thru with reply - same options */
1411	}
1412
1413#if IMPORTANCE_INHERITANCE
1414 retry:
1415#endif /* IMPORTANCE_INHERITANCE */
1416
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		 */
1429		ip_unlock(port);
1430		ip_release(port);
1431		kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
1432		ipc_kmsg_destroy(kmsg);
1433		return MACH_MSG_SUCCESS;
1434	}
1435
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 */
1462
1463		if (ipc_port_importance_delta(port, 1) == TRUE) {
1464			ip_lock(port);
1465			goto retry;
1466		}
1467	}
1468#endif /* IMPORTANCE_INHERITANCE */
1469
1470	/*
1471	 * We have a valid message and a valid reference on the port.
1472	 * we can unlock the port and call mqueue_send() on its message
1473	 * queue. Lock message queue while port is locked.
1474	 */
1475	s = splsched();
1476	imq_lock(&port->ip_messages);
1477	ip_unlock(port);
1478
1479	error = ipc_mqueue_send(&port->ip_messages, kmsg, option,
1480			send_timeout, s);
1481
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
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;
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(
1559	mach_vm_address_t	msg_addr,
1560	ipc_kmsg_t		kmsg,
1561	mach_msg_size_t		size)
1562{
1563	mach_msg_return_t mr;
1564
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	}
1615	if (copyoutmsg((const char *) kmsg->ikm_header, msg_addr, size))
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{
1640	(void) memcpy((void *) msg, (const void *) kmsg->ikm_header, size);
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 *
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.
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,
1673	mach_msg_option_t	*optionp)
1674{
1675	mach_msg_bits_t mbits = msg->msgh_bits & MACH_MSGH_BITS_USER;
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);
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;
1683	ipc_entry_t dest_entry, reply_entry;
1684	ipc_port_t dest_soright, reply_soright;
1685	ipc_port_t release_port = IP_NULL;
1686
1687#if IMPORTANCE_INHERITANCE
1688	int assertcnt = 0;
1689	boolean_t needboost = FALSE;
1690#endif /* IMPORTANCE_INHERITANCE */
1691
1692	queue_head_t links_data;
1693	queue_t links = &links_data;
1694	wait_queue_link_t wql;
1695
1696	queue_init(links);
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);
1708	if (!is_active(space))
1709		goto invalid_dest;
1710
1711	if (!MACH_PORT_VALID(dest_name))
1712		goto invalid_dest;
1713
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	 */
1720	dest_entry = ipc_entry_lookup(space, dest_name);
1721	if (dest_entry != IE_NULL) {
1722		int error = 0;
1723		ipc_port_t port = (ipc_port_t) dest_entry->ie_object;
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
1739
1740	if (dest_name == reply_name) {
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
1755		dest_entry = ipc_entry_lookup(space, name);
1756		if (dest_entry == IE_NULL)
1757			goto invalid_dest;
1758
1759		reply_entry = dest_entry;
1760		assert(reply_type != 0); /* because name not null */
1761
1762		if (!ipc_right_copyin_check(space, name, reply_entry, reply_type))
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)) {
1783
1784#if IMPORTANCE_INHERITANCE
1785			kr = ipc_right_copyin(space, name, dest_entry,
1786					      dest_type, FALSE,
1787					      &dest_port, &dest_soright,
1788					      &release_port,
1789					      &assertcnt,
1790					      links);
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
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));
1814			assert(dest_soright == IP_NULL);
1815
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
1825			kr = ipc_right_copyin(space, name, reply_entry,
1826					      reply_type, TRUE,
1827					      &reply_port, &reply_soright,
1828					      &release_port,
1829					      links);
1830#endif /* IMPORTANCE_INHERITANCE */
1831
1832			assert(kr == KERN_SUCCESS);
1833			assert(reply_port == dest_port);
1834			assert(reply_entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
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
1843#if IMPORTANCE_INHERITANCE
1844			kr = ipc_right_copyin(space, name, dest_entry,
1845					      dest_type, FALSE,
1846					      &dest_port, &dest_soright,
1847					      &release_port,
1848					      &assertcnt,
1849					      links);
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
1859			if (kr != KERN_SUCCESS)
1860				goto invalid_dest;
1861
1862			assert(dest_entry->ie_bits & MACH_PORT_TYPE_SEND);
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
1882			kr = ipc_right_copyin_two(space, name, dest_entry,
1883						  &dest_port, &dest_soright,
1884						  &release_port);
1885			if (kr != KERN_SUCCESS)
1886				goto invalid_dest;
1887
1888			/* the entry might need to be deallocated */
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			}
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
1909#if IMPORTANCE_INHERITANCE
1910			kr = ipc_right_copyin(space, name, dest_entry,
1911					      MACH_MSG_TYPE_MOVE_SEND, FALSE,
1912					      &dest_port, &soright,
1913					      &release_port,
1914					      &assertcnt,
1915					      links);
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
1925			if (kr != KERN_SUCCESS)
1926				goto invalid_dest;
1927
1928			/* the entry might need to be deallocated */
1929
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			}
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)) {
1953		/*
1954		 *	No reply port!  This is an easy case
1955		 *	to make atomic.  Just copyin the destination.
1956		 */
1957
1958		dest_entry = ipc_entry_lookup(space, dest_name);
1959		if (dest_entry == IE_NULL)
1960			goto invalid_dest;
1961
1962#if IMPORTANCE_INHERITANCE
1963		kr = ipc_right_copyin(space, dest_name, dest_entry,
1964				      dest_type, FALSE,
1965				      &dest_port, &dest_soright,
1966				      &release_port,
1967				      &assertcnt,
1968				      links);
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
1978		if (kr != KERN_SUCCESS)
1979			goto invalid_dest;
1980
1981		/* the entry might need to be deallocated */
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		}
1986
1987		reply_port = (ipc_object_t)CAST_MACH_NAME_TO_PORT(reply_name);
1988		reply_soright = IP_NULL;
1989	} else {
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!
2022		 * I will be making the change soon in rdar://problem/6275821.
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
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
2049		kr = ipc_right_copyin(space, dest_name, dest_entry,
2050				      dest_type, FALSE,
2051				      &dest_port, &dest_soright,
2052				      &release_port,
2053				      links);
2054#endif /* IMPORTANCE_INHERITANCE */
2055
2056		if (kr != KERN_SUCCESS)
2057			goto invalid_dest;
2058
2059		assert(IO_VALID(dest_port));
2060
2061#if IMPORTANCE_INHERITANCE
2062		kr = ipc_right_copyin(space, reply_name, reply_entry,
2063				      reply_type, TRUE,
2064				      &reply_port, &reply_soright,
2065				      &release_port,
2066				      &assertcnt,
2067				      links);
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
2077		assert(kr == KERN_SUCCESS);
2078
2079		/* the entries might need to be deallocated */
2080
2081		if (IE_BITS_TYPE(reply_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
2082			ipc_entry_dealloc(space, reply_name, reply_entry);
2083			reply_entry = IE_NULL;
2084		}
2085
2086		if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE) {
2087			ipc_entry_dealloc(space, dest_name, dest_entry);
2088			dest_entry = IE_NULL;
2089		}
2090	}
2091
2092	dest_type = ipc_object_copyin_type(dest_type);
2093	reply_type = ipc_object_copyin_type(reply_type);
2094
2095	/*
2096	 * JMM - Without rdar://problem/6275821, this is the last place we can
2097	 * re-arm the send-possible notifications.  It may trigger unexpectedly
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.
2100	 */
2101	if (((*optionp & MACH_SEND_NOTIFY) != 0) &&
2102	    dest_type != MACH_MSG_TYPE_PORT_SEND_ONCE &&
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);
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);
2127		}
2128	}
2129
2130	is_write_unlock(space);
2131
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
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
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
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
2166
2167	return MACH_MSG_SUCCESS;
2168
2169invalid_reply:
2170	is_write_unlock(space);
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
2180	return MACH_SEND_INVALID_REPLY;
2181
2182invalid_dest:
2183	is_write_unlock(space);
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
2193	if (reply_soright != IP_NULL)
2194		ipc_notify_port_deleted(reply_soright, reply_name);
2195
2196	return MACH_SEND_INVALID_DEST;
2197}
2198
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
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;
2537    mach_msg_descriptor_t	*daddr, *naddr;
2538    mach_msg_descriptor_t	*user_addr, *kern_addr;
2539    mach_msg_type_number_t	dsc_count;
2540    boolean_t 			is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
2541    boolean_t 			complex = FALSE;
2542    vm_size_t			space_needed = 0;
2543    vm_offset_t			paddr = 0;
2544    vm_map_copy_t		copy = VM_MAP_COPY_NULL;
2545    mach_msg_type_number_t	i;
2546    mach_msg_return_t		mr = MACH_MSG_SUCCESS;
2547
2548    vm_size_t           descriptor_size = 0;
2549
2550    /*
2551     * Determine if the target is a kernel port.
2552     */
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);
2556
2557    dsc_count = body->msgh_descriptor_count;
2558    if (dsc_count == 0)
2559	return MACH_MSG_SUCCESS;
2560
2561    /*
2562     * Make an initial pass to determine kernal VM space requirements for
2563     * physical copies and possible contraction of the descriptors from
2564     * processes with pointers larger than the kernel's.
2565     */
2566    daddr = NULL;
2567    for (i = 0; i < dsc_count; i++) {
2568	daddr = naddr;
2569
2570	/* make sure the descriptor fits in the message */
2571	if (is_task_64bit) {
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:
2576		    descriptor_size += 16;
2577            naddr = (typeof(naddr))((vm_offset_t)daddr + 16);
2578            break;
2579	    default:
2580		    descriptor_size += 12;
2581            naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
2582            break;
2583	    }
2584	} else {
2585        descriptor_size += 12;
2586        naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
2587	}
2588
2589	if (naddr > (mach_msg_descriptor_t *)
2590	    ((vm_offset_t)kmsg->ikm_header + kmsg->ikm_header->msgh_size)) {
2591	    ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2592	    mr = MACH_SEND_MSG_TOO_SMALL;
2593	    goto out;
2594	}
2595
2596	switch (daddr->type.type) {
2597	    mach_msg_size_t size;
2598
2599	case MACH_MSG_OOL_DESCRIPTOR:
2600	case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
2601        size = (is_task_64bit) ?
2602		((mach_msg_ool_descriptor64_t *)daddr)->size :
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		 */
2610		ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
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		 */
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
2630		space_needed += round_page(size);
2631		if (space_needed > ipc_kmsg_max_vm_space) {
2632
2633		    /*
2634		     * Per message kernel memory limit exceeded
2635		     */
2636		    ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
2637		    mr = MACH_MSG_VM_KERNEL;
2638		    goto out;
2639		}
2640	    }
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) {
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        }
2656    }
2657
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    }
2668
2669
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        }
2700
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 */
2709
2710    if (!complex) {
2711	kmsg->ikm_header->msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
2712    }
2713 out:
2714    return mr;
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.
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,
2747	mach_msg_option_t	*optionp)
2748{
2749    mach_msg_return_t 		mr;
2750
2751    kmsg->ikm_header->msgh_bits &= MACH_MSGH_BITS_USER;
2752
2753    mr = ipc_kmsg_copyin_header(kmsg->ikm_header, space, optionp);
2754
2755    if (mr != MACH_MSG_SUCCESS)
2756	return mr;
2757
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
2766    if ((kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0)
2767	return MACH_MSG_SUCCESS;
2768
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	}
2780
2781	return mr;
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.
2793 *	Conditions:
2794 *		Nothing locked.
2795 */
2796
2797mach_msg_return_t
2798ipc_kmsg_copyin_from_kernel(
2799	ipc_kmsg_t	kmsg)
2800{
2801	mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
2802	mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
2803	mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
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;
2806
2807	/* translate the destination and reply ports */
2808	if (!IO_VALID(remote))
2809		return MACH_SEND_INVALID_DEST;
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
2825		kmsg->ikm_header->msgh_bits = bits;
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
2831		kmsg->ikm_header->msgh_bits = bits;
2832		if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
2833			return MACH_MSG_SUCCESS;
2834	}
2835    {
2836    	mach_msg_descriptor_t	*saddr;
2837    	mach_msg_body_t		*body;
2838	mach_msg_type_number_t	i, count;
2839
2840    	body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
2841    	saddr = (mach_msg_descriptor_t *) (body + 1);
2842	count = body->msgh_descriptor_count;
2843
2844    	for (i = 0; i < count; i++, saddr++) {
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)) {
2875		           kmsg->ikm_header->msgh_bits |=
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;
2891		    unsigned int			j;
2892		    mach_msg_type_name_t    		name;
2893		    mach_msg_ool_ports_descriptor_t 	*dsc;
2894
2895		    dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
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))
2915			    kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
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    }
2927    return MACH_MSG_SUCCESS;
2928}
2929
2930#if IKM_SUPPORT_LEGACY
2931mach_msg_return_t
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 */
2942	if (!IO_VALID(remote))
2943		return MACH_SEND_INVALID_DEST;
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)
2967			return MACH_MSG_SUCCESS;
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    }
3100    return MACH_MSG_SUCCESS;
3101}
3102#endif /* IKM_SUPPORT_LEGACY */
3103
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.
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,
3133	ipc_space_t		space)
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
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
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;
3151	ipc_port_t release_port = IP_NULL;
3152	mach_port_name_t dest_name, reply_name;
3153
3154	if (IP_VALID(reply)) {
3155		ipc_entry_t entry;
3156		kern_return_t kr;
3157
3158		/*
3159		 *	Get reply port entry (if none, skip to dest port
3160		 *	copyout).  This may require growing the space.
3161		 */
3162
3163		is_write_lock(space);
3164
3165		for (;;) {
3166			if (!is_active(space)) {
3167				is_write_unlock(space);
3168				return (MACH_RCV_HEADER_ERROR|
3169					MACH_MSG_IPC_SPACE);
3170			}
3171
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 */
3176				assert(entry->ie_bits &
3177				       MACH_PORT_TYPE_SEND_RECEIVE);
3178				break;
3179			}
3180
3181			ip_lock(reply);
3182			if (!ip_active(reply)) {
3183				ip_unlock(reply);
3184				ip_lock(dest);
3185				is_write_unlock(space);
3186
3187				release_port = reply;
3188				reply = IP_DEAD;
3189				reply_name = MACH_PORT_DEAD;
3190				goto copyout_dest;
3191			}
3192
3193			reply_name = CAST_MACH_PORT_TO_NAME(reply);
3194			kr = ipc_entry_get(space, &reply_name, &entry);
3195			if (kr != KERN_SUCCESS) {
3196				ip_unlock(reply);
3197
3198				/* space is locked */
3199				kr = ipc_entry_grow_table(space,
3200							  ITS_SIZE_NONE);
3201				if (kr != KERN_SUCCESS) {
3202					return (MACH_RCV_HEADER_ERROR|
3203						MACH_MSG_IPC_SPACE);
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
3213			entry->ie_object = (ipc_object_t) reply;
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);
3223
3224		/* reply port is unlocked */
3225		assert(kr == KERN_SUCCESS);
3226
3227		ip_lock(dest);
3228		is_write_unlock(space);
3229
3230	} else {
3231		/*
3232		 *	No reply port!  This is an easy case.
3233		 *	We only need to have the space locked
3234		 *	when locking the destination.
3235		 */
3236
3237		is_read_lock(space);
3238		if (!is_active(space)) {
3239			is_read_unlock(space);
3240			return MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE;
3241		}
3242
3243		ip_lock(dest);
3244		is_read_unlock(space);
3245
3246		reply_name = CAST_MACH_PORT_TO_NAME(reply);
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 */
3302
3303	} else {
3304		ipc_port_timestamp_t timestamp;
3305
3306		timestamp = dest->ip_timestamp;
3307		ip_unlock(dest);
3308		ip_release(dest);
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))
3324		ip_release(reply);
3325
3326	if (IP_VALID(release_port))
3327		ip_release(release_port);
3328
3329	msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
3330			  MACH_MSGH_BITS(reply_type, dest_type));
3331	msg->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
3332	msg->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
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)) {
3365		*namep = CAST_MACH_PORT_TO_NAME(object);
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
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;
3438    vm_map_address_t			rcv_addr;
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{
3577    mach_vm_offset_t		rcv_addr = 0;
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
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;
3740    mach_msg_descriptor_t 	*kern_dsc, *user_dsc;
3741    mach_msg_descriptor_t	*saddr;
3742    mach_msg_type_number_t	dsc_count, sdsc_count;
3743    int i;
3744    mach_msg_return_t 		mr = MACH_MSG_SUCCESS;
3745    boolean_t 			is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
3746
3747    body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
3748    dsc_count = body->msgh_descriptor_count;
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];
3752
3753    /* Do scatter list setup */
3754    if (slist != MACH_MSG_BODY_NULL) {
3755    panic("Scatter lists disabled");
3756	saddr = (mach_msg_descriptor_t *) (slist + 1);
3757	sdsc_count = slist->msgh_descriptor_count;
3758    }
3759    else {
3760	saddr = MACH_MSG_DESCRIPTOR_NULL;
3761	sdsc_count = 0;
3762    }
3763
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        }
3784    }
3785
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;
3792    }
3793
3794    return mr;
3795}
3796
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{
3815    mach_msg_size_t		send_size;
3816
3817    send_size = kmsg->ikm_header->msgh_size;
3818
3819    boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
3820
3821#if defined(__LP64__)
3822	send_size -= LEGACY_HEADER_SIZE_DELTA;
3823#endif
3824
3825    if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
3826
3827        mach_msg_body_t *body;
3828        mach_msg_descriptor_t *saddr, *eaddr;
3829
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;
3851}
3852
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.
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,
3874	mach_msg_body_t		*slist)
3875{
3876	mach_msg_return_t mr;
3877
3878	mr = ipc_kmsg_copyout_header(kmsg->ikm_header, space);
3879	if (mr != MACH_MSG_SUCCESS) {
3880		return mr;
3881	}
3882
3883	if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
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{
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;
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
3933	kmsg->ikm_header->msgh_bits = mbits & MACH_MSGH_BITS_USER;
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);
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
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;
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 {
3978		io_unlock(dest);
3979		io_release(dest);
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
3987		reply_name = CAST_MACH_PORT_TO_NAME(reply);
3988
3989	kmsg->ikm_header->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
3990				      MACH_MSGH_BITS(reply_type, dest_type));
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);
3993
3994	if (mbits & MACH_MSGH_BITS_COMPLEX) {
3995		mach_msg_body_t *body;
3996
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));
4000	}
4001}
4002
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 *
4028ipc_kmsg_get_scatter(
4029	mach_vm_address_t       msg_addr,
4030       mach_msg_size_t         slist_size,
4031	ipc_kmsg_t              kmsg)
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
4038#if defined(__LP64__)
4039        panic("ipc_kmsg_get_scatter called!");
4040#endif
4041
4042        if (slist_size < sizeof(mach_msg_base_t))
4043                return MACH_MSG_BODY_NULL;
4044
4045        slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
4046        slist = (mach_msg_body_t *)kalloc(slist_size);
4047        if (slist == MACH_MSG_BODY_NULL)
4048                return slist;
4049
4050        if (copyin(msg_addr + sizeof(mach_msg_header_t), (char *)slist, slist_size)) {
4051                kfree(slist, slist_size);
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) {
4057                kfree(slist, slist_size);
4058                return MACH_MSG_BODY_NULL;
4059        }
4060
4061        body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
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) {
4083                        kfree(slist, slist_size);
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) {
4110                        kfree(slist, slist_size);
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) {
4115                        kfree(slist, slist_size);
4116                        return MACH_MSG_BODY_NULL;
4117                    }
4118                }
4119                else {
4120		  if (sstart->type.type != MACH_MSG_OOL_PORTS_DESCRIPTOR) {
4121                        kfree(slist, slist_size);
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) {
4126                        kfree(slist, slist_size);
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{
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);
4156        kfree(slist, slist_size);
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
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);
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 {
4196		io_unlock(dest);
4197		io_release(dest);
4198		dest_name = MACH_PORT_DEAD;
4199	}
4200
4201	reply_name = CAST_MACH_PORT_TO_NAME(reply);
4202
4203	kmsg->ikm_header->msgh_bits =
4204		(MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
4205					MACH_MSGH_BITS(reply_type, dest_type));
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);
4208}
4209
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 {
4234		io_unlock(dest);
4235		io_release(dest);
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
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)
4334{
4335	mach_msg_max_trailer_t *trailer;
4336
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));
4341
4342	if (!(option & MACH_RCV_TRAILER_MASK)) {
4343		return trailer->msgh_trailer_size;
4344	}
4345
4346	trailer->msgh_seqno = seqno;
4347	trailer->msgh_context = context;
4348	trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit(thread), option);
4349
4350	if (minimal_trailer) {
4351		goto done;
4352	}
4353
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;
4367	}
4368
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	 */
4374
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
4401	}
4402
4403
4404done:
4405
4406	return trailer->msgh_trailer_size;
4407}
4408