|
|
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; \
! 313: mach_port_index_t index = MACH_PORT_INDEX(name); \
1.1 root 314: \
315: is_read_lock(space); \
316: assert(space->is_active); \
317: \
318: if ((index >= space->is_table_size) || \
319: (((entry = &space->is_table[index])->ie_bits & \
320: (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) != \
321: (MACH_PORT_GEN(name) | MACH_PORT_TYPE_SEND))) { \
322: is_read_unlock(space); \
323: abort; \
324: } \
325: \
326: port = (ipc_port_t) entry->ie_object; \
327: assert(port != IP_NULL); \
328: \
329: ip_lock(port); \
330: /* can safely unlock space now that port is locked */ \
331: is_read_unlock(space); \
332: MACRO_END
333:
334: device_t
1.1.1.4 ! root 335: port_name_to_device(mach_port_t name)
1.1 root 336: {
1.1.1.4 ! root 337: ipc_port_t port;
! 338: device_t device;
1.1.1.2 root 339:
1.1 root 340: fast_send_right_lookup(name, port, goto abort);
341: /* port is locked */
1.1.1.2 root 342:
1.1 root 343: /*
344: * Now map the port object to a device object.
345: * This is an inline version of dev_port_lookup().
346: */
347: if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
348: device = (device_t) port->ip_kobject;
349: device_reference(device);
350: ip_unlock(port);
1.1.1.2 root 351: return device;
1.1 root 352: }
1.1.1.2 root 353:
1.1 root 354: ip_unlock(port);
355: return DEVICE_NULL;
1.1.1.2 root 356:
1.1 root 357: /*
358: * The slow case. The port wasn't easily accessible.
359: */
360: abort: {
361: ipc_port_t kern_port;
362: kern_return_t kr;
1.1.1.2 root 363:
1.1 root 364: kr = ipc_object_copyin(current_space(), name,
365: MACH_MSG_TYPE_COPY_SEND,
366: (ipc_object_t *) &kern_port);
367: if (kr != KERN_SUCCESS)
368: return DEVICE_NULL;
1.1.1.2 root 369:
1.1 root 370: device = dev_port_lookup(kern_port);
371: if (IP_VALID(kern_port))
372: ipc_port_release_send(kern_port);
373: return device;
374: }
375: }
376:
377: thread_t
1.1.1.4 ! root 378: port_name_to_thread(mach_port_t name)
1.1 root 379: {
1.1.1.4 ! root 380: ipc_port_t port;
1.1 root 381:
382: fast_send_right_lookup(name, port, goto abort);
383: /* port is locked */
384:
385: if (ip_active(port) &&
386: (ip_kotype(port) == IKOT_THREAD)) {
1.1.1.4 ! root 387: thread_t thread;
1.1 root 388:
389: thread = (thread_t) port->ip_kobject;
390: assert(thread != THREAD_NULL);
391:
392: /* thread referencing is a bit complicated,
393: so don't bother to expand inline */
394: thread_reference(thread);
395: ip_unlock(port);
396:
397: return thread;
398: }
399:
400: ip_unlock(port);
401: return THREAD_NULL;
402:
403: abort: {
404: thread_t thread;
405: ipc_port_t kern_port;
406: kern_return_t kr;
407:
408: kr = ipc_object_copyin(current_space(), name,
409: MACH_MSG_TYPE_COPY_SEND,
410: (ipc_object_t *) &kern_port);
411: if (kr != KERN_SUCCESS)
412: return THREAD_NULL;
413:
414: thread = convert_port_to_thread(kern_port);
415: if (IP_VALID(kern_port))
416: ipc_port_release_send(kern_port);
417:
418: return thread;
419: }
420: }
421:
422: task_t
1.1.1.4 ! root 423: port_name_to_task(mach_port_t name)
1.1 root 424: {
1.1.1.4 ! root 425: ipc_port_t port;
1.1 root 426:
427: fast_send_right_lookup(name, port, goto abort);
428: /* port is locked */
429:
430: if (ip_active(port) &&
431: (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 ! root 432: task_t task;
1.1 root 433:
434: task = (task_t) port->ip_kobject;
435: assert(task != TASK_NULL);
436:
437: task_lock(task);
438: /* can safely unlock port now that task is locked */
439: ip_unlock(port);
440:
441: task->ref_count++;
442: task_unlock(task);
443:
444: return task;
445: }
446:
447: ip_unlock(port);
448: return TASK_NULL;
449:
450: abort: {
451: task_t task;
452: ipc_port_t kern_port;
453: kern_return_t kr;
454:
455: kr = ipc_object_copyin(current_space(), name,
456: MACH_MSG_TYPE_COPY_SEND,
457: (ipc_object_t *) &kern_port);
458: if (kr != KERN_SUCCESS)
459: return TASK_NULL;
460:
461: task = convert_port_to_task(kern_port);
462: if (IP_VALID(kern_port))
463: ipc_port_release_send(kern_port);
464:
465: return task;
466: }
467: }
468:
469: vm_map_t
470: port_name_to_map(
471: mach_port_t name)
472: {
1.1.1.4 ! root 473: ipc_port_t port;
1.1 root 474:
475: fast_send_right_lookup(name, port, goto abort);
476: /* port is locked */
477:
478: if (ip_active(port) &&
479: (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 ! root 480: vm_map_t map;
1.1 root 481:
482: map = ((task_t) port->ip_kobject)->map;
483: assert(map != VM_MAP_NULL);
484:
485: simple_lock(&map->ref_lock);
486: /* can safely unlock port now that map is locked */
487: ip_unlock(port);
488:
489: map->ref_count++;
490: simple_unlock(&map->ref_lock);
491:
492: return map;
493: }
494:
495: ip_unlock(port);
496: return VM_MAP_NULL;
497:
498: abort: {
499: vm_map_t map;
500: ipc_port_t kern_port;
501: kern_return_t kr;
502:
503: kr = ipc_object_copyin(current_space(), name,
504: MACH_MSG_TYPE_COPY_SEND,
505: (ipc_object_t *) &kern_port);
506: if (kr != KERN_SUCCESS)
507: return VM_MAP_NULL;
508:
509: map = convert_port_to_map(kern_port);
510: if (IP_VALID(kern_port))
511: ipc_port_release_send(kern_port);
512:
513: return map;
514: }
515: }
516:
517: ipc_space_t
1.1.1.4 ! root 518: port_name_to_space(mach_port_t name)
1.1 root 519: {
1.1.1.4 ! root 520: ipc_port_t port;
1.1 root 521:
522: fast_send_right_lookup(name, port, goto abort);
523: /* port is locked */
524:
525: if (ip_active(port) &&
526: (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 ! root 527: ipc_space_t space;
1.1 root 528:
529: space = ((task_t) port->ip_kobject)->itk_space;
530: assert(space != IS_NULL);
531:
532: simple_lock(&space->is_ref_lock_data);
533: /* can safely unlock port now that space is locked */
534: ip_unlock(port);
535:
536: space->is_references++;
537: simple_unlock(&space->is_ref_lock_data);
538:
539: return space;
540: }
541:
542: ip_unlock(port);
543: return IS_NULL;
544:
545: abort: {
546: ipc_space_t space;
547: ipc_port_t kern_port;
548: kern_return_t kr;
549:
550: kr = ipc_object_copyin(current_space(), name,
551: MACH_MSG_TYPE_COPY_SEND,
552: (ipc_object_t *) &kern_port);
553: if (kr != KERN_SUCCESS)
554: return IS_NULL;
555:
556: space = convert_port_to_space(kern_port);
557: if (IP_VALID(kern_port))
558: ipc_port_release_send(kern_port);
559:
560: return space;
561: }
562: }
563:
564: /*
565: * Hack to translate a thread port to a thread pointer for calling
566: * thread_get_state and thread_set_state. This is only necessary
567: * because the IPC message for these two operations overflows the
568: * kernel stack.
569: *
570: * AARGH!
571: */
572:
1.1.1.4 ! root 573: kern_return_t thread_get_state_KERNEL(
! 574: mach_port_t thread_port, /* port right for thread */
! 575: int flavor,
! 576: thread_state_t old_state, /* pointer to OUT array */
! 577: natural_t *old_state_count) /* IN/OUT */
1.1 root 578: {
579: thread_t thread;
580: kern_return_t result;
581:
582: thread = port_name_to_thread(thread_port);
583: result = thread_get_state(thread, flavor, old_state, old_state_count);
584: thread_deallocate(thread);
585:
586: return result;
587: }
588:
1.1.1.4 ! root 589: kern_return_t thread_set_state_KERNEL(
! 590: mach_port_t thread_port, /* port right for thread */
! 591: int flavor,
! 592: thread_state_t new_state,
! 593: natural_t new_state_count)
1.1 root 594: {
595: thread_t thread;
596: kern_return_t result;
597:
598: thread = port_name_to_thread(thread_port);
599: result = thread_set_state(thread, flavor, new_state, new_state_count);
600: thread_deallocate(thread);
601:
602: return result;
603: }
604:
605: /*
606: * Things to keep in mind:
607: *
608: * The idea here is to duplicate the semantics of the true kernel RPC.
609: * The destination port/object should be checked first, before anything
610: * that the user might notice (like ipc_object_copyin). Return
611: * MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
612: * knows to fall back on an RPC. For other return values, it won't
613: * retry with an RPC. The retry might get a different (incorrect) rc.
614: * Return values are only set (and should only be set, with copyout)
1.1.1.4 ! root 615: * on successful calls.
1.1 root 616: */
617:
618: kern_return_t
619: syscall_vm_map(
620: mach_port_t target_map,
621: vm_offset_t *address,
622: vm_size_t size,
623: vm_offset_t mask,
624: boolean_t anywhere,
625: mach_port_t memory_object,
626: vm_offset_t offset,
627: boolean_t copy,
628: vm_prot_t cur_protection,
629: vm_prot_t max_protection,
630: vm_inherit_t inheritance)
631: {
632: vm_map_t map;
633: ipc_port_t port;
634: vm_offset_t addr;
635: kern_return_t result;
636:
637: map = port_name_to_map(target_map);
638: if (map == VM_MAP_NULL)
639: return MACH_SEND_INTERRUPTED;
640:
641: if (MACH_PORT_VALID(memory_object)) {
642: result = ipc_object_copyin(current_space(), memory_object,
643: MACH_MSG_TYPE_COPY_SEND,
644: (ipc_object_t *) &port);
645: if (result != KERN_SUCCESS) {
646: vm_map_deallocate(map);
647: return result;
648: }
649: } else
650: port = (ipc_port_t) memory_object;
651:
1.1.1.4 ! root 652: copyin(address, &addr, sizeof(vm_offset_t));
1.1 root 653: result = vm_map(map, &addr, size, mask, anywhere,
654: port, offset, copy,
655: cur_protection, max_protection, inheritance);
656: if (result == KERN_SUCCESS)
1.1.1.4 ! root 657: copyout(&addr, address, sizeof(vm_offset_t));
1.1 root 658: if (IP_VALID(port))
659: ipc_port_release_send(port);
660: vm_map_deallocate(map);
661:
662: return result;
663: }
664:
1.1.1.4 ! root 665: kern_return_t syscall_vm_allocate(
! 666: mach_port_t target_map,
! 667: vm_offset_t *address,
! 668: vm_size_t size,
! 669: boolean_t anywhere)
1.1 root 670: {
671: vm_map_t map;
672: vm_offset_t addr;
673: kern_return_t result;
674:
675: map = port_name_to_map(target_map);
676: if (map == VM_MAP_NULL)
677: return MACH_SEND_INTERRUPTED;
678:
1.1.1.4 ! root 679: copyin(address, &addr, sizeof(vm_offset_t));
1.1 root 680: result = vm_allocate(map, &addr, size, anywhere);
681: if (result == KERN_SUCCESS)
1.1.1.4 ! root 682: copyout(&addr, address, sizeof(vm_offset_t));
1.1 root 683: vm_map_deallocate(map);
684:
685: return result;
686: }
687:
1.1.1.4 ! root 688: kern_return_t syscall_vm_deallocate(
! 689: mach_port_t target_map,
! 690: vm_offset_t start,
! 691: vm_size_t size)
1.1 root 692: {
693: vm_map_t map;
694: kern_return_t result;
695:
696: map = port_name_to_map(target_map);
697: if (map == VM_MAP_NULL)
698: return MACH_SEND_INTERRUPTED;
699:
700: result = vm_deallocate(map, start, size);
701: vm_map_deallocate(map);
702:
703: return result;
704: }
705:
1.1.1.4 ! root 706: kern_return_t syscall_task_create(
! 707: mach_port_t parent_task,
! 708: boolean_t inherit_memory,
! 709: mach_port_t *child_task) /* OUT */
1.1 root 710: {
711: task_t t, c;
712: ipc_port_t port;
713: mach_port_t name;
714: kern_return_t result;
715:
716: t = port_name_to_task(parent_task);
717: if (t == TASK_NULL)
718: return MACH_SEND_INTERRUPTED;
719:
720: result = task_create(t, inherit_memory, &c);
721: if (result == KERN_SUCCESS) {
722: port = (ipc_port_t) convert_task_to_port(c);
723: /* always returns a name, even for non-success return codes */
724: (void) ipc_kmsg_copyout_object(current_space(),
725: (ipc_object_t) port,
726: MACH_MSG_TYPE_PORT_SEND, &name);
1.1.1.4 ! root 727: copyout(&name, child_task,
1.1 root 728: sizeof(mach_port_t));
729: }
730: task_deallocate(t);
731:
732: return result;
733: }
734:
1.1.1.4 ! root 735: kern_return_t syscall_task_terminate(mach_port_t task)
1.1 root 736: {
737: task_t t;
738: kern_return_t result;
739:
740: t = port_name_to_task(task);
741: if (t == TASK_NULL)
742: return MACH_SEND_INTERRUPTED;
743:
744: result = task_terminate(t);
745: task_deallocate(t);
746:
747: return result;
748: }
749:
1.1.1.4 ! root 750: kern_return_t syscall_task_suspend(mach_port_t task)
1.1 root 751: {
752: task_t t;
753: kern_return_t result;
754:
755: t = port_name_to_task(task);
756: if (t == TASK_NULL)
757: return MACH_SEND_INTERRUPTED;
758:
759: result = task_suspend(t);
760: task_deallocate(t);
761:
762: return result;
763: }
764:
1.1.1.4 ! root 765: kern_return_t syscall_task_set_special_port(
! 766: mach_port_t task,
! 767: int which_port,
! 768: mach_port_t port_name)
1.1 root 769: {
770: task_t t;
771: ipc_port_t port;
772: kern_return_t result;
773:
774: t = port_name_to_task(task);
775: if (t == TASK_NULL)
776: return MACH_SEND_INTERRUPTED;
777:
778: if (MACH_PORT_VALID(port_name)) {
779: result = ipc_object_copyin(current_space(), port_name,
780: MACH_MSG_TYPE_COPY_SEND,
781: (ipc_object_t *) &port);
782: if (result != KERN_SUCCESS) {
783: task_deallocate(t);
784: return result;
785: }
786: } else
787: port = (ipc_port_t) port_name;
788:
789: result = task_set_special_port(t, which_port, port);
790: if ((result != KERN_SUCCESS) && IP_VALID(port))
791: ipc_port_release_send(port);
792: task_deallocate(t);
793:
794: return result;
795: }
796:
797: kern_return_t
1.1.1.4 ! root 798: syscall_mach_port_allocate(
! 799: mach_port_t task,
! 800: mach_port_right_t right,
! 801: mach_port_t *namep)
1.1 root 802: {
803: ipc_space_t space;
804: mach_port_t name;
805: kern_return_t kr;
806:
807: space = port_name_to_space(task);
808: if (space == IS_NULL)
809: return MACH_SEND_INTERRUPTED;
810:
811: kr = mach_port_allocate(space, right, &name);
812: if (kr == KERN_SUCCESS)
1.1.1.4 ! root 813: copyout(&name, namep, sizeof(mach_port_t));
1.1 root 814: is_release(space);
815:
816: return kr;
817: }
818:
819: kern_return_t
1.1.1.4 ! root 820: syscall_mach_port_allocate_name(
! 821: mach_port_t task,
! 822: mach_port_right_t right,
! 823: mach_port_t name)
1.1 root 824: {
825: ipc_space_t space;
826: kern_return_t kr;
827:
828: space = port_name_to_space(task);
829: if (space == IS_NULL)
830: return MACH_SEND_INTERRUPTED;
831:
832: kr = mach_port_allocate_name(space, right, name);
833: is_release(space);
834:
835: return kr;
836: }
837:
838: kern_return_t
1.1.1.4 ! root 839: syscall_mach_port_deallocate(
! 840: mach_port_t task,
! 841: mach_port_t name)
1.1 root 842: {
843: ipc_space_t space;
844: kern_return_t kr;
845:
846: space = port_name_to_space(task);
847: if (space == IS_NULL)
848: return MACH_SEND_INTERRUPTED;
849:
850: kr = mach_port_deallocate(space, name);
851: is_release(space);
852:
853: return kr;
854: }
855:
856: kern_return_t
1.1.1.4 ! root 857: syscall_mach_port_insert_right(
! 858: mach_port_t task,
! 859: mach_port_t name,
! 860: mach_port_t right,
! 861: mach_msg_type_name_t rightType)
1.1 root 862: {
863: ipc_space_t space;
864: ipc_object_t object;
865: mach_msg_type_name_t newtype;
866: kern_return_t kr;
867:
868: space = port_name_to_space(task);
869: if (space == IS_NULL)
870: return MACH_SEND_INTERRUPTED;
871:
872: if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
873: is_release(space);
874: return KERN_INVALID_VALUE;
875: }
876:
877: if (MACH_PORT_VALID(right)) {
878: kr = ipc_object_copyin(current_space(), right, rightType,
879: &object);
880: if (kr != KERN_SUCCESS) {
881: is_release(space);
882: return kr;
883: }
884: } else
885: object = (ipc_object_t) right;
886: newtype = ipc_object_copyin_type(rightType);
887:
888: kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype);
889: if ((kr != KERN_SUCCESS) && IO_VALID(object))
890: ipc_object_destroy(object, newtype);
891: is_release(space);
892:
893: return kr;
894: }
895:
1.1.1.4 ! root 896: kern_return_t syscall_thread_depress_abort(mach_port_t thread)
1.1 root 897: {
898: thread_t t;
899: kern_return_t result;
900:
901: t = port_name_to_thread(thread);
902: if (t == THREAD_NULL)
903: return MACH_SEND_INTERRUPTED;
904:
905: result = thread_depress_abort(t);
906: thread_deallocate(t);
907:
908: return result;
909: }
910:
911: /*
912: * Device traps -- these are way experimental.
913: */
914: io_return_t
915: syscall_device_write_request(mach_port_t device_name,
916: mach_port_t reply_name,
917: dev_mode_t mode,
918: recnum_t recnum,
919: vm_offset_t data,
920: vm_size_t data_count)
921: {
922: device_t dev;
1.1.1.3 root 923: /*ipc_port_t reply_port;*/
1.1 root 924: io_return_t res;
925:
926: /*
927: * First try to translate the device name.
928: *
929: * If this fails, return KERN_INVALID_CAPABILITY.
930: * Caller knows that this most likely means that
931: * device is not local to node and IPC should be used.
932: *
933: * If kernel doesn't do device traps, kern_invalid()
934: * will be called instead of this function which will
935: * return KERN_INVALID_ARGUMENT.
936: */
937: dev = port_name_to_device(device_name);
938: if (dev == DEVICE_NULL)
939: return KERN_INVALID_CAPABILITY;
940:
941: /*
942: * Translate reply port.
943: */
1.1.1.3 root 944: /*if (reply_name == MACH_PORT_NULL)
1.1 root 945: reply_port = IP_NULL;
1.1.1.3 root 946: */
947: if (reply_name != MACH_PORT_NULL) {
1.1 root 948: /* Homey don't play that. */
949: device_deallocate(dev);
950: return KERN_INVALID_RIGHT;
951: }
952:
953: /* note: doesn't take reply_port arg yet. */
954: res = ds_device_write_trap(dev, /*reply_port,*/
955: mode, recnum,
956: data, data_count);
957:
958: /*
959: * Give up reference from port_name_to_device.
960: */
961: device_deallocate(dev);
962: return res;
963: }
964:
965: io_return_t
966: syscall_device_writev_request(mach_port_t device_name,
967: mach_port_t reply_name,
968: dev_mode_t mode,
969: recnum_t recnum,
970: io_buf_vec_t *iovec,
971: vm_size_t iocount)
972: {
973: device_t dev;
1.1.1.4 ! root 974: /*ipc_port_t reply_port;*/
1.1 root 975: io_return_t res;
976:
977: /*
978: * First try to translate the device name.
979: *
980: * If this fails, return KERN_INVALID_CAPABILITY.
981: * Caller knows that this most likely means that
982: * device is not local to node and IPC should be used.
983: *
984: * If kernel doesn't do device traps, kern_invalid()
985: * will be called instead of this function which will
986: * return KERN_INVALID_ARGUMENT.
987: */
988: dev = port_name_to_device(device_name);
989: if (dev == DEVICE_NULL)
990: return KERN_INVALID_CAPABILITY;
991:
992: /*
993: * Translate reply port.
994: */
1.1.1.4 ! root 995: /*if (reply_name == MACH_PORT_NULL)
1.1 root 996: reply_port = IP_NULL;
1.1.1.4 ! root 997: */
! 998: if (reply_name != MACH_PORT_NULL) {
1.1 root 999: /* Homey don't play that. */
1000: device_deallocate(dev);
1001: return KERN_INVALID_RIGHT;
1002: }
1003:
1004: /* note: doesn't take reply_port arg yet. */
1005: res = ds_device_writev_trap(dev, /*reply_port,*/
1006: mode, recnum,
1007: iovec, iocount);
1008:
1009: /*
1010: * Give up reference from port_name_to_device.
1011: */
1012: device_deallocate(dev);
1013: return res;
1014: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.