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