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