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