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