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