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