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