|
|
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 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: #include <norma_vm.h>
54: #include <mach_rt.h>
55: #include <dipc.h>
56:
57: #include <mach/boolean.h>
58: #include <mach/port.h>
59: #include <mach/thread_status.h>
60: #include <mach/mig_errors.h>
61: #include <mach/mach_types.h>
62: #include <mach/mach_traps.h>
63: #include <kern/ast.h>
64: #include <kern/ipc_mig.h>
65: #include <kern/task.h>
66: #include <kern/thread.h>
67: #include <kern/ipc_kobject.h>
68: #include <kern/misc_protos.h>
69: #include <vm/vm_map.h>
70: #include <vm/vm_user.h>
71: #include <ipc/port.h>
72: #include <ipc/ipc_kmsg.h>
73: #include <ipc/ipc_entry.h>
74: #include <ipc/ipc_object.h>
75: #include <ipc/ipc_mqueue.h>
76: #include <ipc/ipc_space.h>
77: #include <ipc/ipc_port.h>
78: #include <ipc/ipc_pset.h>
79:
80: /* Default (zeroed) template for qos */
81:
82: static mach_port_qos_t qos_template;
83:
84: /*
85: * Routine: mach_msg_send_from_kernel
86: * Purpose:
87: * Send a message from the kernel.
88: *
89: * This is used by the client side of KernelUser interfaces
90: * to implement SimpleRoutines. Currently, this includes
91: * memory_object messages.
92: * Conditions:
93: * Nothing locked.
94: * Returns:
95: * MACH_MSG_SUCCESS Sent the message.
96: * MACH_SEND_INVALID_DATA Bad destination port.
97: */
98:
99: mach_msg_return_t
100: mach_msg_send_from_kernel(
101: mach_msg_header_t *msg,
102: mach_msg_size_t send_size)
103: {
104: ipc_kmsg_t kmsg;
105: mach_msg_return_t mr;
106:
107: if (!MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port))
108: return MACH_SEND_INVALID_DEST;
109:
110: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
111: if (mr != MACH_MSG_SUCCESS)
112: panic("mach_msg_send_from_kernel");
113:
114: ipc_kmsg_copyin_from_kernel(kmsg);
115: ipc_kmsg_send_always(kmsg);
116:
117: return MACH_MSG_SUCCESS;
118: }
119:
120: /*
121: * Routine: mach_msg_rpc_from_kernel
122: * Purpose:
123: * Send a message from the kernel and receive a reply.
124: * Uses ith_rpc_reply for the reply port.
125: *
126: * This is used by the client side of KernelUser interfaces
127: * to implement Routines.
128: * Conditions:
129: * Nothing locked.
130: * Returns:
131: * MACH_MSG_SUCCESS Sent the message.
132: * MACH_RCV_PORT_DIED The reply port was deallocated.
133: */
134:
135: mach_msg_return_t
136: mach_msg_rpc_from_kernel(
137: mach_msg_header_t *msg,
138: mach_msg_size_t send_size,
139: mach_msg_size_t rcv_size)
140: {
141: thread_t self = current_thread();
142: ipc_port_t reply;
143: ipc_kmsg_t kmsg;
144: mach_port_seqno_t seqno;
145: mach_msg_return_t mr;
146:
147: assert(MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port));
148: assert(msg->msgh_local_port == MACH_PORT_NULL);
149:
150: self->ith_scatter_list = MACH_MSG_BODY_NULL;
151:
152: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
153: if (mr != MACH_MSG_SUCCESS)
154: panic("mach_msg_rpc_from_kernel");
155:
156: rpc_lock(self);
157:
158: reply = self->ith_rpc_reply;
159: if (reply == IP_NULL) {
160: rpc_unlock(self);
161: reply = ipc_port_alloc_reply();
162: rpc_lock(self);
163: if ((reply == IP_NULL) ||
164: (self->ith_rpc_reply != IP_NULL))
165: panic("mach_msg_rpc_from_kernel");
166: self->ith_rpc_reply = reply;
167: }
168:
169: /* insert send-once right for the reply port */
170: kmsg->ikm_header.msgh_local_port = reply;
171: kmsg->ikm_header.msgh_bits |=
172: MACH_MSGH_BITS(0, MACH_MSG_TYPE_MAKE_SEND_ONCE);
173:
174: ipc_port_reference(reply);
175: rpc_unlock(self);
176:
177: ipc_kmsg_copyin_from_kernel(kmsg);
178:
179: ipc_kmsg_send_always(kmsg);
180:
181: for (;;) {
182: ipc_mqueue_t mqueue;
183:
184: ip_lock(reply);
185: if ( !ip_active(reply)) {
186: ip_unlock(reply);
187: ipc_port_release(reply);
188: return MACH_RCV_PORT_DIED;
189: }
190: if (!self->top_act || !self->top_act->active) {
191: ip_unlock(reply);
192: ipc_port_release(reply);
193: return MACH_RCV_INTERRUPTED;
194: }
195:
196: assert(reply->ip_pset_count == 0);
197: mqueue = &reply->ip_messages;
198: ip_unlock(reply);
199:
200: mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
201: MACH_MSG_SIZE_MAX,
202: MACH_MSG_TIMEOUT_NONE,
203: THREAD_INTERRUPTIBLE,
204: &kmsg, &seqno);
205: if (mr == MACH_MSG_SUCCESS)
206: {
207: break;
208: }
209:
210: assert(mr == MACH_RCV_INTERRUPTED);
211:
212: if (self->top_act && self->top_act->handlers) {
213: ipc_port_release(reply);
214: return(mr);
215: }
216: }
217: ipc_port_release(reply);
218:
219: /*
220: * XXXXX Set manually for now ...
221: * No, why even bother, since the effort is wasted?
222: *
223: { mach_msg_format_0_trailer_t *trailer = (mach_msg_format_0_trailer_t *)
224: ((vm_offset_t)&kmsg->ikm_header + kmsg->ikm_header.msgh_size);
225: trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
226: trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
227: }
228: *****/
229:
230: if (rcv_size < kmsg->ikm_header.msgh_size) {
231: ipc_kmsg_copyout_dest(kmsg, ipc_space_reply);
232: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
233: return MACH_RCV_TOO_LARGE;
234: }
235:
236: /*
237: * We want to preserve rights and memory in reply!
238: * We don't have to put them anywhere; just leave them
239: * as they are.
240: */
241:
242: ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply);
243: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
244: return MACH_MSG_SUCCESS;
245: }
246:
247:
248: /************** These Calls are set up for kernel-loaded tasks **************/
249: /************** Apple does not plan on supporting that. These **************/
250: /************** need to be reworked to deal with the kernel **************/
251: /************** proper to eliminate the kernel specific code MIG **************/
252: /************** must generate. **************/
253:
254:
255: /*
256: * Routine: mach_msg
257: * Purpose:
258: * Like mach_msg_overwrite_trap except that message buffers
259: * live in kernel space. Doesn't handle any options.
260: *
261: * This is used by in-kernel server threads to make
262: * kernel calls, to receive request messages, and
263: * to send reply messages.
264: * Conditions:
265: * Nothing locked.
266: * Returns:
267: */
268:
269: mach_msg_return_t
270: mach_msg_overwrite(
271: mach_msg_header_t *msg,
272: mach_msg_option_t option,
273: mach_msg_size_t send_size,
274: mach_msg_size_t rcv_size,
275: mach_port_name_t rcv_name,
276: mach_msg_timeout_t timeout,
277: mach_port_name_t notify,
278: mach_msg_header_t *rcv_msg,
279: mach_msg_size_t rcv_msg_size)
280: {
281: ipc_space_t space = current_space();
282: vm_map_t map = current_map();
283: ipc_kmsg_t kmsg;
284: mach_port_seqno_t seqno;
285: mach_msg_return_t mr;
286: mach_msg_format_0_trailer_t *trailer;
287:
288: if (option & MACH_SEND_MSG) {
289: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
290: if (mr != MACH_MSG_SUCCESS)
291: panic("mach_msg");
292:
293: mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
294: if (mr != MACH_MSG_SUCCESS) {
295: ikm_free(kmsg);
296: return mr;
297: }
298:
299: do
300: mr = ipc_kmsg_send(kmsg, MACH_MSG_OPTION_NONE,
301: MACH_MSG_TIMEOUT_NONE);
302: while (mr == MACH_SEND_INTERRUPTED);
303: assert(mr == MACH_MSG_SUCCESS);
304: }
305:
306: if (option & MACH_RCV_MSG) {
307: thread_t self = current_thread();
308:
309: self->ith_scatter_list = MACH_MSG_BODY_NULL;
310: do {
311: ipc_object_t object;
312: ipc_mqueue_t mqueue;
313:
314: mr = ipc_mqueue_copyin(space, rcv_name,
315: &mqueue, &object);
316: if (mr != MACH_MSG_SUCCESS)
317: return mr;
318: /* hold ref for object */
319:
320: mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
321: MACH_MSG_SIZE_MAX,
322: MACH_MSG_TIMEOUT_NONE,
323: THREAD_ABORTSAFE,
324: &kmsg, &seqno);
325: ipc_object_release(object);
326:
327: } while (mr == MACH_RCV_INTERRUPTED);
328: if (mr != MACH_MSG_SUCCESS)
329: return mr;
330:
331: trailer = (mach_msg_format_0_trailer_t *)
332: ((vm_offset_t)&kmsg->ikm_header + kmsg->ikm_header.msgh_size);
333: if (option & MACH_RCV_TRAILER_MASK) {
334: trailer->msgh_seqno = seqno;
335: trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option);
336: }
337:
338: if (rcv_size < (kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size)) {
339: ipc_kmsg_copyout_dest(kmsg, space);
340: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
341: return MACH_RCV_TOO_LARGE;
342: }
343:
344: mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL,
345: MACH_MSG_BODY_NULL);
346: if (mr != MACH_MSG_SUCCESS) {
347: if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
348: ipc_kmsg_put_to_kernel(msg, kmsg,
349: kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size);
350: } else {
351: ipc_kmsg_copyout_dest(kmsg, space);
352: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
353: }
354:
355: return mr;
356: }
357:
358: ipc_kmsg_put_to_kernel(msg, kmsg,
359: kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size);
360: }
361:
362: return MACH_MSG_SUCCESS;
363: }
364:
365: /*
366: * Routine: mig_get_reply_port
367: * Purpose:
368: * Called by client side interfaces living in the kernel
369: * to get a reply port. This port is used for
370: * mach_msg() calls which are kernel calls.
371: */
372: mach_port_t
373: mig_get_reply_port(void)
374: {
375: thread_t self = current_thread();
376:
377: assert(self->ith_mig_reply == (mach_port_t)0);
378:
379: /*
380: * JMM - for now we have no real clients of this under the kernel
381: * loaded server model because we only have one of those. In order
382: * to avoid MIG changes, we just return null here - and return]
383: * references to ipc_port_t's instead of names.
384: *
385: * if (self->ith_mig_reply == MACH_PORT_NULL)
386: * self->ith_mig_reply = mach_reply_port();
387: */
388: return self->ith_mig_reply;
389: }
390:
391: /*
392: * Routine: mig_dealloc_reply_port
393: * Purpose:
394: * Called by client side interfaces to get rid of a reply port.
395: * Shouldn't ever be called inside the kernel, because
396: * kernel calls shouldn't prompt Mig to call it.
397: */
398:
399: void
400: mig_dealloc_reply_port(
401: mach_port_t reply_port)
402: {
403: panic("mig_dealloc_reply_port");
404: }
405:
406: /*
407: * Routine: mig_put_reply_port
408: * Purpose:
409: * Called by client side interfaces after each RPC to
410: * let the client recycle the reply port if it wishes.
411: */
412: void
413: mig_put_reply_port(
414: mach_port_t reply_port)
415: {
416: }
417:
418: /*
419: * mig_strncpy.c - by Joshua Block
420: *
421: * mig_strncp -- Bounded string copy. Does what the library routine strncpy
422: * OUGHT to do: Copies the (null terminated) string in src into dest, a
423: * buffer of length len. Assures that the copy is still null terminated
424: * and doesn't overflow the buffer, truncating the copy if necessary.
425: *
426: * Parameters:
427: *
428: * dest - Pointer to destination buffer.
429: *
430: * src - Pointer to source string.
431: *
432: * len - Length of destination buffer.
433: */
434: int
435: mig_strncpy(
436: char *dest,
437: char *src,
438: int len)
439: {
440: int i;
441:
442: if (len <= 0)
443: return 0;
444:
445: for (i=1; i<len; i++)
446: if (! (*dest++ = *src++))
447: return i;
448:
449: *dest = '\0';
450: return i;
451: }
452:
453: char *
454: mig_user_allocate(
455: vm_size_t size)
456: {
457: return (char *)kalloc(size);
458: }
459:
460: void
461: mig_user_deallocate(
462: char *data,
463: vm_size_t size)
464: {
465: kfree((vm_offset_t)data, size);
466: }
467:
468: thread_act_t
469: port_name_to_act(
470: mach_port_name_t name)
471: {
472: thread_act_t thr_act;
473: ipc_port_t kern_port;
474: kern_return_t kr;
475:
476: if (MACH_PORT_VALID(name)) {
477: kr = ipc_object_copyin(current_space(), name,
478: MACH_MSG_TYPE_COPY_SEND,
479: (ipc_object_t *) &kern_port);
480: if (kr != KERN_SUCCESS)
481: return THR_ACT_NULL;
482:
483: thr_act = convert_port_to_act(kern_port);
484:
485: if (IP_VALID(kern_port))
486: ipc_port_release_send(kern_port);
487: }
488: return thr_act;
489: }
490:
491: task_t
492: port_name_to_task(
493: mach_port_name_t name)
494: {
495: ipc_port_t kern_port;
496: kern_return_t kr;
497: task_t task = TASK_NULL;
498:
499: if (MACH_PORT_VALID(name)) {
500: kr = ipc_object_copyin(current_space(), name,
501: MACH_MSG_TYPE_COPY_SEND,
502: (ipc_object_t *) &kern_port);
503: if (kr != KERN_SUCCESS)
504: return TASK_NULL;
505:
506: task = convert_port_to_task(kern_port);
507:
508: if (IP_VALID(kern_port))
509: ipc_port_release_send(kern_port);
510: }
511: return task;
512: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.