|
|
1.1.1.2 root 1: /*
1.1 root 2: * Mach Operating System
3: * Copyright (c) 1991,1990 Carnegie Mellon University
4: * All Rights Reserved.
1.1.1.2 root 5: *
1.1 root 6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
1.1.1.2 root 11: *
1.1 root 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2 root 15: *
1.1 root 16: * Carnegie Mellon requests users of this software to return to
1.1.1.2 root 17: *
1.1 root 18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
1.1.1.2 root 22: *
1.1 root 23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26:
27: #include <mach/boolean.h>
28: #include <mach/port.h>
29: #include <mach/message.h>
30: #include <mach/thread_status.h>
1.1.1.3 root 31: #include <machine/locore.h>
1.1 root 32: #include <kern/ast.h>
1.1.1.3 root 33: #include <kern/debug.h>
1.1 root 34: #include <kern/ipc_tt.h>
1.1.1.3 root 35: #include <kern/syscall_subr.h>
1.1 root 36: #include <kern/thread.h>
37: #include <kern/task.h>
38: #include <kern/ipc_kobject.h>
1.1.1.3 root 39: #include <kern/ipc_tt.h>
1.1.1.4 root 40: #include <kern/ipc_mig.h>
1.1 root 41: #include <vm/vm_map.h>
42: #include <vm/vm_user.h>
43: #include <ipc/port.h>
44: #include <ipc/ipc_kmsg.h>
45: #include <ipc/ipc_entry.h>
46: #include <ipc/ipc_object.h>
47: #include <ipc/ipc_mqueue.h>
48: #include <ipc/ipc_space.h>
49: #include <ipc/ipc_port.h>
50: #include <ipc/ipc_pset.h>
51: #include <ipc/ipc_thread.h>
1.1.1.3 root 52: #include <ipc/mach_port.h>
53: #include <device/dev_hdr.h>
1.1 root 54: #include <device/device_types.h>
1.1.1.3 root 55: #include <device/ds_routines.h>
1.1 root 56:
57: /*
58: * Routine: mach_msg_send_from_kernel
59: * Purpose:
60: * Send a message from the kernel.
61: *
62: * This is used by the client side of KernelUser interfaces
63: * to implement SimpleRoutines. Currently, this includes
64: * device_reply and memory_object messages.
65: * Conditions:
66: * Nothing locked.
67: * Returns:
68: * MACH_MSG_SUCCESS Sent the message.
69: * MACH_SEND_INVALID_DATA Bad destination port.
70: */
71:
72: mach_msg_return_t
73: mach_msg_send_from_kernel(
74: mach_msg_header_t *msg,
75: mach_msg_size_t send_size)
76: {
77: ipc_kmsg_t kmsg;
78: mach_msg_return_t mr;
79:
80: if (!MACH_PORT_VALID(msg->msgh_remote_port))
81: return MACH_SEND_INVALID_DEST;
82:
83: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
84: if (mr != MACH_MSG_SUCCESS)
85: panic("mach_msg_send_from_kernel");
86:
87: ipc_kmsg_copyin_from_kernel(kmsg);
88: ipc_mqueue_send_always(kmsg);
89:
90: return MACH_MSG_SUCCESS;
91: }
92:
93: mach_msg_return_t
94: mach_msg_rpc_from_kernel(msg, send_size, reply_size)
1.1.1.4 root 95: const mach_msg_header_t *msg;
1.1 root 96: mach_msg_size_t send_size;
97: mach_msg_size_t reply_size;
98: {
99: panic("mach_msg_rpc_from_kernel"); /*XXX*/
100: }
101:
102: /*
103: * Routine: mach_msg_abort_rpc
104: * Purpose:
105: * Destroy the thread's ith_rpc_reply port.
106: * This will interrupt a mach_msg_rpc_from_kernel
107: * with a MACH_RCV_PORT_DIED return code.
108: * Conditions:
109: * Nothing locked.
110: */
111:
112: void
1.1.1.4 root 113: mach_msg_abort_rpc(ipc_thread_t thread)
1.1 root 114: {
115: ipc_port_t reply = IP_NULL;
116:
117: ith_lock(thread);
118: if (thread->ith_self != IP_NULL) {
119: reply = thread->ith_rpc_reply;
120: thread->ith_rpc_reply = IP_NULL;
121: }
122: ith_unlock(thread);
123:
124: if (reply != IP_NULL)
125: ipc_port_dealloc_reply(reply);
126: }
127:
128: /*
129: * Routine: mach_msg
130: * Purpose:
131: * Like mach_msg_trap except that message buffers
132: * live in kernel space. Doesn't handle any options.
133: *
134: * This is used by in-kernel server threads to make
135: * kernel calls, to receive request messages, and
136: * to send reply messages.
137: * Conditions:
138: * Nothing locked.
139: * Returns:
140: */
141:
142: mach_msg_return_t
1.1.1.4 root 143: mach_msg(
144: mach_msg_header_t *msg,
145: mach_msg_option_t option,
146: mach_msg_size_t send_size,
147: mach_msg_size_t rcv_size,
148: mach_port_t rcv_name,
149: mach_msg_timeout_t time_out,
150: mach_port_t notify)
1.1 root 151: {
152: ipc_space_t space = current_space();
153: vm_map_t map = current_map();
154: ipc_kmsg_t kmsg;
155: mach_port_seqno_t seqno;
156: mach_msg_return_t mr;
157:
158: if (option & MACH_SEND_MSG) {
159: mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
160: if (mr != MACH_MSG_SUCCESS)
161: panic("mach_msg");
162:
163: mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
164: if (mr != MACH_MSG_SUCCESS) {
165: ikm_free(kmsg);
166: return mr;
167: }
168:
169: do
170: mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
171: MACH_MSG_TIMEOUT_NONE);
172: while (mr == MACH_SEND_INTERRUPTED);
173: assert(mr == MACH_MSG_SUCCESS);
174: }
175:
176: if (option & MACH_RCV_MSG) {
177: do {
178: ipc_object_t object;
179: ipc_mqueue_t mqueue;
180:
181: mr = ipc_mqueue_copyin(space, rcv_name,
182: &mqueue, &object);
183: if (mr != MACH_MSG_SUCCESS)
184: return mr;
185: /* hold ref for object; mqueue is locked */
186:
187: mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
188: MACH_MSG_SIZE_MAX,
189: MACH_MSG_TIMEOUT_NONE,
190: FALSE, IMQ_NULL_CONTINUE,
191: &kmsg, &seqno);
192: /* mqueue is unlocked */
193: ipc_object_release(object);
194: } while (mr == MACH_RCV_INTERRUPTED);
195: if (mr != MACH_MSG_SUCCESS)
196: return mr;
197:
198: kmsg->ikm_header.msgh_seqno = seqno;
199:
200: if (rcv_size < kmsg->ikm_header.msgh_size) {
201: ipc_kmsg_copyout_dest(kmsg, space);
202: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
203: return MACH_RCV_TOO_LARGE;
204: }
205:
206: mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
207: if (mr != MACH_MSG_SUCCESS) {
208: if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
209: ipc_kmsg_put_to_kernel(msg, kmsg,
210: kmsg->ikm_header.msgh_size);
211: } else {
212: ipc_kmsg_copyout_dest(kmsg, space);
213: ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
214: }
215:
216: return mr;
217: }
218:
219: ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
220: }
221:
222: return MACH_MSG_SUCCESS;
223: }
224:
225: /*
226: * Routine: mig_get_reply_port
227: * Purpose:
228: * Called by client side interfaces living in the kernel
229: * to get a reply port. This port is used for
230: * mach_msg() calls which are kernel calls.
231: */
232:
233: mach_port_t
234: mig_get_reply_port(void)
235: {
236: ipc_thread_t self = current_thread();
237:
238: if (self->ith_mig_reply == MACH_PORT_NULL)
239: self->ith_mig_reply = mach_reply_port();
240:
241: return self->ith_mig_reply;
242: }
243:
244: /*
245: * Routine: mig_dealloc_reply_port
246: * Purpose:
247: * Called by client side interfaces to get rid of a reply port.
248: * Shouldn't ever be called inside the kernel, because
249: * kernel calls shouldn't prompt Mig to call it.
250: */
251:
252: void
253: mig_dealloc_reply_port(
254: mach_port_t reply_port)
255: {
256: panic("mig_dealloc_reply_port");
257: }
258:
259: /*
260: * Routine: mig_put_reply_port
261: * Purpose:
1.1.1.2 root 262: * Called by client side interfaces after each RPC to
1.1 root 263: * let the client recycle the reply port if it wishes.
264: */
265: void
266: mig_put_reply_port(
267: mach_port_t reply_port)
268: {
269: }
270:
271: /*
272: * mig_strncpy.c - by Joshua Block
273: *
1.1.1.4 root 274: * mig_strncpy -- Bounded string copy. Does what the library routine
275: * strncpy does: Copies the (null terminated) string in src into dest,
276: * a buffer of length len. Returns the length of the destination
277: * string excluding the terminating null.
1.1 root 278: *
279: * Parameters:
1.1.1.2 root 280: *
1.1 root 281: * dest - Pointer to destination buffer.
1.1.1.2 root 282: *
1.1 root 283: * src - Pointer to source string.
1.1.1.2 root 284: *
1.1 root 285: * len - Length of destination buffer.
286: */
1.1.1.4 root 287: vm_size_t
288: mig_strncpy(dest, src, len)
289: char *dest;
290: const char *src;
291: int len;
292: {
293: char *dest_ = dest;
294: int i;
295:
296: if (len <= 0)
297: return 0;
298:
299: for (i = 0; i < len; i++) {
300: if (! (*dest = *src))
301: break;
302: dest++;
303: src++;
304: }
1.1 root 305:
1.1.1.4 root 306: return dest - dest_;
1.1 root 307: }
308:
309: #define fast_send_right_lookup(name, port, abort) \
310: MACRO_BEGIN \
1.1.1.4 root 311: ipc_space_t space = current_space(); \
312: ipc_entry_t entry; \
1.1 root 313: \
314: is_read_lock(space); \
315: assert(space->is_active); \
316: \
1.1.1.5 ! root 317: entry = ipc_entry_lookup (space, name); \
! 318: if (entry == IE_NULL) { \
! 319: is_read_unlock (space); \
! 320: abort; \
! 321: } \
! 322: \
! 323: if (IE_BITS_TYPE (entry->ie_bits) != MACH_PORT_TYPE_SEND) { \
! 324: is_read_unlock (space); \
1.1 root 325: abort; \
326: } \
327: \
328: port = (ipc_port_t) entry->ie_object; \
329: assert(port != IP_NULL); \
330: \
331: ip_lock(port); \
332: /* can safely unlock space now that port is locked */ \
333: is_read_unlock(space); \
334: MACRO_END
335:
336: device_t
1.1.1.4 root 337: port_name_to_device(mach_port_t name)
1.1 root 338: {
1.1.1.4 root 339: ipc_port_t port;
340: device_t device;
1.1.1.2 root 341:
1.1 root 342: fast_send_right_lookup(name, port, goto abort);
343: /* port is locked */
1.1.1.2 root 344:
1.1 root 345: /*
346: * Now map the port object to a device object.
347: * This is an inline version of dev_port_lookup().
348: */
349: if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
350: device = (device_t) port->ip_kobject;
351: device_reference(device);
352: ip_unlock(port);
1.1.1.2 root 353: return device;
1.1 root 354: }
1.1.1.2 root 355:
1.1 root 356: ip_unlock(port);
357: return DEVICE_NULL;
1.1.1.2 root 358:
1.1 root 359: /*
360: * The slow case. The port wasn't easily accessible.
361: */
362: abort: {
363: ipc_port_t kern_port;
364: kern_return_t kr;
1.1.1.2 root 365:
1.1 root 366: kr = ipc_object_copyin(current_space(), name,
367: MACH_MSG_TYPE_COPY_SEND,
368: (ipc_object_t *) &kern_port);
369: if (kr != KERN_SUCCESS)
370: return DEVICE_NULL;
1.1.1.2 root 371:
1.1 root 372: device = dev_port_lookup(kern_port);
373: if (IP_VALID(kern_port))
374: ipc_port_release_send(kern_port);
375: return device;
376: }
377: }
378:
379: thread_t
1.1.1.4 root 380: port_name_to_thread(mach_port_t name)
1.1 root 381: {
1.1.1.4 root 382: ipc_port_t port;
1.1 root 383:
384: fast_send_right_lookup(name, port, goto abort);
385: /* port is locked */
386:
387: if (ip_active(port) &&
388: (ip_kotype(port) == IKOT_THREAD)) {
1.1.1.4 root 389: thread_t thread;
1.1 root 390:
391: thread = (thread_t) port->ip_kobject;
392: assert(thread != THREAD_NULL);
393:
394: /* thread referencing is a bit complicated,
395: so don't bother to expand inline */
396: thread_reference(thread);
397: ip_unlock(port);
398:
399: return thread;
400: }
401:
402: ip_unlock(port);
403: return THREAD_NULL;
404:
405: abort: {
406: thread_t thread;
407: ipc_port_t kern_port;
408: kern_return_t kr;
409:
410: kr = ipc_object_copyin(current_space(), name,
411: MACH_MSG_TYPE_COPY_SEND,
412: (ipc_object_t *) &kern_port);
413: if (kr != KERN_SUCCESS)
414: return THREAD_NULL;
415:
416: thread = convert_port_to_thread(kern_port);
417: if (IP_VALID(kern_port))
418: ipc_port_release_send(kern_port);
419:
420: return thread;
421: }
422: }
423:
424: task_t
1.1.1.4 root 425: port_name_to_task(mach_port_t name)
1.1 root 426: {
1.1.1.4 root 427: ipc_port_t port;
1.1 root 428:
429: fast_send_right_lookup(name, port, goto abort);
430: /* port is locked */
431:
432: if (ip_active(port) &&
433: (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 root 434: task_t task;
1.1 root 435:
436: task = (task_t) port->ip_kobject;
437: assert(task != TASK_NULL);
438:
439: task_lock(task);
440: /* can safely unlock port now that task is locked */
441: ip_unlock(port);
442:
443: task->ref_count++;
444: task_unlock(task);
445:
446: return task;
447: }
448:
449: ip_unlock(port);
450: return TASK_NULL;
451:
452: abort: {
453: task_t task;
454: ipc_port_t kern_port;
455: kern_return_t kr;
456:
457: kr = ipc_object_copyin(current_space(), name,
458: MACH_MSG_TYPE_COPY_SEND,
459: (ipc_object_t *) &kern_port);
460: if (kr != KERN_SUCCESS)
461: return TASK_NULL;
462:
463: task = convert_port_to_task(kern_port);
464: if (IP_VALID(kern_port))
465: ipc_port_release_send(kern_port);
466:
467: return task;
468: }
469: }
470:
471: vm_map_t
472: port_name_to_map(
473: mach_port_t name)
474: {
1.1.1.4 root 475: ipc_port_t port;
1.1 root 476:
477: fast_send_right_lookup(name, port, goto abort);
478: /* port is locked */
479:
480: if (ip_active(port) &&
481: (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 root 482: vm_map_t map;
1.1 root 483:
484: map = ((task_t) port->ip_kobject)->map;
485: assert(map != VM_MAP_NULL);
486:
487: simple_lock(&map->ref_lock);
488: /* can safely unlock port now that map is locked */
489: ip_unlock(port);
490:
491: map->ref_count++;
492: simple_unlock(&map->ref_lock);
493:
494: return map;
495: }
496:
497: ip_unlock(port);
498: return VM_MAP_NULL;
499:
500: abort: {
501: vm_map_t map;
502: ipc_port_t kern_port;
503: kern_return_t kr;
504:
505: kr = ipc_object_copyin(current_space(), name,
506: MACH_MSG_TYPE_COPY_SEND,
507: (ipc_object_t *) &kern_port);
508: if (kr != KERN_SUCCESS)
509: return VM_MAP_NULL;
510:
511: map = convert_port_to_map(kern_port);
512: if (IP_VALID(kern_port))
513: ipc_port_release_send(kern_port);
514:
515: return map;
516: }
517: }
518:
519: ipc_space_t
1.1.1.4 root 520: port_name_to_space(mach_port_t name)
1.1 root 521: {
1.1.1.4 root 522: ipc_port_t port;
1.1 root 523:
524: fast_send_right_lookup(name, port, goto abort);
525: /* port is locked */
526:
527: if (ip_active(port) &&
528: (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 root 529: ipc_space_t space;
1.1 root 530:
531: space = ((task_t) port->ip_kobject)->itk_space;
532: assert(space != IS_NULL);
533:
534: simple_lock(&space->is_ref_lock_data);
535: /* can safely unlock port now that space is locked */
536: ip_unlock(port);
537:
538: space->is_references++;
539: simple_unlock(&space->is_ref_lock_data);
540:
541: return space;
542: }
543:
544: ip_unlock(port);
545: return IS_NULL;
546:
547: abort: {
548: ipc_space_t space;
549: ipc_port_t kern_port;
550: kern_return_t kr;
551:
552: kr = ipc_object_copyin(current_space(), name,
553: MACH_MSG_TYPE_COPY_SEND,
554: (ipc_object_t *) &kern_port);
555: if (kr != KERN_SUCCESS)
556: return IS_NULL;
557:
558: space = convert_port_to_space(kern_port);
559: if (IP_VALID(kern_port))
560: ipc_port_release_send(kern_port);
561:
562: return space;
563: }
564: }
565:
566: /*
567: * Hack to translate a thread port to a thread pointer for calling
568: * thread_get_state and thread_set_state. This is only necessary
569: * because the IPC message for these two operations overflows the
570: * kernel stack.
571: *
572: * AARGH!
573: */
574:
1.1.1.4 root 575: kern_return_t thread_get_state_KERNEL(
576: mach_port_t thread_port, /* port right for thread */
577: int flavor,
578: thread_state_t old_state, /* pointer to OUT array */
579: natural_t *old_state_count) /* IN/OUT */
1.1 root 580: {
581: thread_t thread;
582: kern_return_t result;
583:
584: thread = port_name_to_thread(thread_port);
585: result = thread_get_state(thread, flavor, old_state, old_state_count);
586: thread_deallocate(thread);
587:
588: return result;
589: }
590:
1.1.1.4 root 591: kern_return_t thread_set_state_KERNEL(
592: mach_port_t thread_port, /* port right for thread */
593: int flavor,
594: thread_state_t new_state,
595: natural_t new_state_count)
1.1 root 596: {
597: thread_t thread;
598: kern_return_t result;
599:
600: thread = port_name_to_thread(thread_port);
601: result = thread_set_state(thread, flavor, new_state, new_state_count);
602: thread_deallocate(thread);
603:
604: return result;
605: }
606:
607: /*
608: * Things to keep in mind:
609: *
610: * The idea here is to duplicate the semantics of the true kernel RPC.
611: * The destination port/object should be checked first, before anything
612: * that the user might notice (like ipc_object_copyin). Return
613: * MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
614: * knows to fall back on an RPC. For other return values, it won't
615: * retry with an RPC. The retry might get a different (incorrect) rc.
616: * Return values are only set (and should only be set, with copyout)
1.1.1.4 root 617: * on successful calls.
1.1 root 618: */
619:
620: kern_return_t
621: syscall_vm_map(
622: mach_port_t target_map,
623: vm_offset_t *address,
624: vm_size_t size,
625: vm_offset_t mask,
626: boolean_t anywhere,
627: mach_port_t memory_object,
628: vm_offset_t offset,
629: boolean_t copy,
630: vm_prot_t cur_protection,
631: vm_prot_t max_protection,
632: vm_inherit_t inheritance)
633: {
634: vm_map_t map;
635: ipc_port_t port;
636: vm_offset_t addr;
637: kern_return_t result;
638:
639: map = port_name_to_map(target_map);
640: if (map == VM_MAP_NULL)
641: return MACH_SEND_INTERRUPTED;
642:
643: if (MACH_PORT_VALID(memory_object)) {
644: result = ipc_object_copyin(current_space(), memory_object,
645: MACH_MSG_TYPE_COPY_SEND,
646: (ipc_object_t *) &port);
647: if (result != KERN_SUCCESS) {
648: vm_map_deallocate(map);
649: return result;
650: }
651: } else
652: port = (ipc_port_t) memory_object;
653:
1.1.1.4 root 654: copyin(address, &addr, sizeof(vm_offset_t));
1.1 root 655: result = vm_map(map, &addr, size, mask, anywhere,
656: port, offset, copy,
657: cur_protection, max_protection, inheritance);
658: if (result == KERN_SUCCESS)
1.1.1.4 root 659: copyout(&addr, address, sizeof(vm_offset_t));
1.1 root 660: if (IP_VALID(port))
661: ipc_port_release_send(port);
662: vm_map_deallocate(map);
663:
664: return result;
665: }
666:
1.1.1.4 root 667: kern_return_t syscall_vm_allocate(
668: mach_port_t target_map,
669: vm_offset_t *address,
670: vm_size_t size,
671: boolean_t anywhere)
1.1 root 672: {
673: vm_map_t map;
674: vm_offset_t addr;
675: kern_return_t result;
676:
677: map = port_name_to_map(target_map);
678: if (map == VM_MAP_NULL)
679: return MACH_SEND_INTERRUPTED;
680:
1.1.1.4 root 681: copyin(address, &addr, sizeof(vm_offset_t));
1.1 root 682: result = vm_allocate(map, &addr, size, anywhere);
683: if (result == KERN_SUCCESS)
1.1.1.4 root 684: copyout(&addr, address, sizeof(vm_offset_t));
1.1 root 685: vm_map_deallocate(map);
686:
687: return result;
688: }
689:
1.1.1.4 root 690: kern_return_t syscall_vm_deallocate(
691: mach_port_t target_map,
692: vm_offset_t start,
693: vm_size_t size)
1.1 root 694: {
695: vm_map_t map;
696: kern_return_t result;
697:
698: map = port_name_to_map(target_map);
699: if (map == VM_MAP_NULL)
700: return MACH_SEND_INTERRUPTED;
701:
702: result = vm_deallocate(map, start, size);
703: vm_map_deallocate(map);
704:
705: return result;
706: }
707:
1.1.1.4 root 708: kern_return_t syscall_task_create(
709: mach_port_t parent_task,
710: boolean_t inherit_memory,
711: mach_port_t *child_task) /* OUT */
1.1 root 712: {
713: task_t t, c;
714: ipc_port_t port;
715: mach_port_t name;
716: kern_return_t result;
717:
718: t = port_name_to_task(parent_task);
719: if (t == TASK_NULL)
720: return MACH_SEND_INTERRUPTED;
721:
722: result = task_create(t, inherit_memory, &c);
723: if (result == KERN_SUCCESS) {
724: port = (ipc_port_t) convert_task_to_port(c);
725: /* always returns a name, even for non-success return codes */
726: (void) ipc_kmsg_copyout_object(current_space(),
727: (ipc_object_t) port,
728: MACH_MSG_TYPE_PORT_SEND, &name);
1.1.1.4 root 729: copyout(&name, child_task,
1.1 root 730: sizeof(mach_port_t));
731: }
732: task_deallocate(t);
733:
734: return result;
735: }
736:
1.1.1.4 root 737: kern_return_t syscall_task_terminate(mach_port_t task)
1.1 root 738: {
739: task_t t;
740: kern_return_t result;
741:
742: t = port_name_to_task(task);
743: if (t == TASK_NULL)
744: return MACH_SEND_INTERRUPTED;
745:
746: result = task_terminate(t);
747: task_deallocate(t);
748:
749: return result;
750: }
751:
1.1.1.4 root 752: kern_return_t syscall_task_suspend(mach_port_t task)
1.1 root 753: {
754: task_t t;
755: kern_return_t result;
756:
757: t = port_name_to_task(task);
758: if (t == TASK_NULL)
759: return MACH_SEND_INTERRUPTED;
760:
761: result = task_suspend(t);
762: task_deallocate(t);
763:
764: return result;
765: }
766:
1.1.1.4 root 767: kern_return_t syscall_task_set_special_port(
768: mach_port_t task,
769: int which_port,
770: mach_port_t port_name)
1.1 root 771: {
772: task_t t;
773: ipc_port_t port;
774: kern_return_t result;
775:
776: t = port_name_to_task(task);
777: if (t == TASK_NULL)
778: return MACH_SEND_INTERRUPTED;
779:
780: if (MACH_PORT_VALID(port_name)) {
781: result = ipc_object_copyin(current_space(), port_name,
782: MACH_MSG_TYPE_COPY_SEND,
783: (ipc_object_t *) &port);
784: if (result != KERN_SUCCESS) {
785: task_deallocate(t);
786: return result;
787: }
788: } else
789: port = (ipc_port_t) port_name;
790:
791: result = task_set_special_port(t, which_port, port);
792: if ((result != KERN_SUCCESS) && IP_VALID(port))
793: ipc_port_release_send(port);
794: task_deallocate(t);
795:
796: return result;
797: }
798:
799: kern_return_t
1.1.1.4 root 800: syscall_mach_port_allocate(
801: mach_port_t task,
802: mach_port_right_t right,
803: mach_port_t *namep)
1.1 root 804: {
805: ipc_space_t space;
806: mach_port_t name;
807: kern_return_t kr;
808:
809: space = port_name_to_space(task);
810: if (space == IS_NULL)
811: return MACH_SEND_INTERRUPTED;
812:
813: kr = mach_port_allocate(space, right, &name);
814: if (kr == KERN_SUCCESS)
1.1.1.4 root 815: copyout(&name, namep, sizeof(mach_port_t));
1.1 root 816: is_release(space);
817:
818: return kr;
819: }
820:
821: kern_return_t
1.1.1.4 root 822: syscall_mach_port_allocate_name(
823: mach_port_t task,
824: mach_port_right_t right,
825: mach_port_t name)
1.1 root 826: {
827: ipc_space_t space;
828: kern_return_t kr;
829:
830: space = port_name_to_space(task);
831: if (space == IS_NULL)
832: return MACH_SEND_INTERRUPTED;
833:
834: kr = mach_port_allocate_name(space, right, name);
835: is_release(space);
836:
837: return kr;
838: }
839:
840: kern_return_t
1.1.1.4 root 841: syscall_mach_port_deallocate(
842: mach_port_t task,
843: mach_port_t name)
1.1 root 844: {
845: ipc_space_t space;
846: kern_return_t kr;
847:
848: space = port_name_to_space(task);
849: if (space == IS_NULL)
850: return MACH_SEND_INTERRUPTED;
851:
852: kr = mach_port_deallocate(space, name);
853: is_release(space);
854:
855: return kr;
856: }
857:
858: kern_return_t
1.1.1.4 root 859: syscall_mach_port_insert_right(
860: mach_port_t task,
861: mach_port_t name,
862: mach_port_t right,
863: mach_msg_type_name_t rightType)
1.1 root 864: {
865: ipc_space_t space;
866: ipc_object_t object;
867: mach_msg_type_name_t newtype;
868: kern_return_t kr;
869:
870: space = port_name_to_space(task);
871: if (space == IS_NULL)
872: return MACH_SEND_INTERRUPTED;
873:
874: if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
875: is_release(space);
876: return KERN_INVALID_VALUE;
877: }
878:
879: if (MACH_PORT_VALID(right)) {
880: kr = ipc_object_copyin(current_space(), right, rightType,
881: &object);
882: if (kr != KERN_SUCCESS) {
883: is_release(space);
884: return kr;
885: }
886: } else
887: object = (ipc_object_t) right;
888: newtype = ipc_object_copyin_type(rightType);
889:
890: kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype);
891: if ((kr != KERN_SUCCESS) && IO_VALID(object))
892: ipc_object_destroy(object, newtype);
893: is_release(space);
894:
895: return kr;
896: }
897:
1.1.1.4 root 898: kern_return_t syscall_thread_depress_abort(mach_port_t thread)
1.1 root 899: {
900: thread_t t;
901: kern_return_t result;
902:
903: t = port_name_to_thread(thread);
904: if (t == THREAD_NULL)
905: return MACH_SEND_INTERRUPTED;
906:
907: result = thread_depress_abort(t);
908: thread_deallocate(t);
909:
910: return result;
911: }
912:
913: /*
914: * Device traps -- these are way experimental.
915: */
916: io_return_t
917: syscall_device_write_request(mach_port_t device_name,
918: mach_port_t reply_name,
919: dev_mode_t mode,
920: recnum_t recnum,
921: vm_offset_t data,
922: vm_size_t data_count)
923: {
924: device_t dev;
1.1.1.3 root 925: /*ipc_port_t reply_port;*/
1.1 root 926: io_return_t res;
927:
928: /*
929: * First try to translate the device name.
930: *
931: * If this fails, return KERN_INVALID_CAPABILITY.
932: * Caller knows that this most likely means that
933: * device is not local to node and IPC should be used.
934: *
935: * If kernel doesn't do device traps, kern_invalid()
936: * will be called instead of this function which will
937: * return KERN_INVALID_ARGUMENT.
938: */
939: dev = port_name_to_device(device_name);
940: if (dev == DEVICE_NULL)
941: return KERN_INVALID_CAPABILITY;
942:
943: /*
944: * Translate reply port.
945: */
1.1.1.3 root 946: /*if (reply_name == MACH_PORT_NULL)
1.1 root 947: reply_port = IP_NULL;
1.1.1.3 root 948: */
949: if (reply_name != MACH_PORT_NULL) {
1.1 root 950: /* Homey don't play that. */
951: device_deallocate(dev);
952: return KERN_INVALID_RIGHT;
953: }
954:
955: /* note: doesn't take reply_port arg yet. */
956: res = ds_device_write_trap(dev, /*reply_port,*/
957: mode, recnum,
958: data, data_count);
959:
960: /*
961: * Give up reference from port_name_to_device.
962: */
963: device_deallocate(dev);
964: return res;
965: }
966:
967: io_return_t
968: syscall_device_writev_request(mach_port_t device_name,
969: mach_port_t reply_name,
970: dev_mode_t mode,
971: recnum_t recnum,
972: io_buf_vec_t *iovec,
973: vm_size_t iocount)
974: {
975: device_t dev;
1.1.1.4 root 976: /*ipc_port_t reply_port;*/
1.1 root 977: io_return_t res;
978:
979: /*
980: * First try to translate the device name.
981: *
982: * If this fails, return KERN_INVALID_CAPABILITY.
983: * Caller knows that this most likely means that
984: * device is not local to node and IPC should be used.
985: *
986: * If kernel doesn't do device traps, kern_invalid()
987: * will be called instead of this function which will
988: * return KERN_INVALID_ARGUMENT.
989: */
990: dev = port_name_to_device(device_name);
991: if (dev == DEVICE_NULL)
992: return KERN_INVALID_CAPABILITY;
993:
994: /*
995: * Translate reply port.
996: */
1.1.1.4 root 997: /*if (reply_name == MACH_PORT_NULL)
1.1 root 998: reply_port = IP_NULL;
1.1.1.4 root 999: */
1000: if (reply_name != MACH_PORT_NULL) {
1.1 root 1001: /* Homey don't play that. */
1002: device_deallocate(dev);
1003: return KERN_INVALID_RIGHT;
1004: }
1005:
1006: /* note: doesn't take reply_port arg yet. */
1007: res = ds_device_writev_trap(dev, /*reply_port,*/
1008: mode, recnum,
1009: iovec, iocount);
1010:
1011: /*
1012: * Give up reference from port_name_to_device.
1013: */
1014: device_deallocate(dev);
1015: return res;
1016: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.