|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990,1989,1988,1987 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: * File: ipc_tt.c 28: * Purpose: 29: * Task and thread related IPC functions. 30: */ 31: 32: #include <mach_ipc_compat.h> 33: 34: #include <mach/boolean.h> 35: #include <mach/kern_return.h> 36: #include <mach/mach_param.h> 37: #include <mach/task_special_ports.h> 38: #include <mach/thread_special_ports.h> 39: #include <vm/vm_kern.h> 40: #include <kern/task.h> 41: #include <kern/thread.h> 42: #include <kern/ipc_kobject.h> 43: #include <kern/ipc_tt.h> 44: #include <ipc/ipc_space.h> 45: #include <ipc/ipc_table.h> 46: #include <ipc/ipc_port.h> 47: #include <ipc/ipc_right.h> 48: #include <ipc/ipc_entry.h> 49: #include <ipc/ipc_object.h> 50: 51: 52: 53: /* 54: * Routine: ipc_task_init 55: * Purpose: 56: * Initialize a task's IPC state. 57: * 58: * If non-null, some state will be inherited from the parent. 59: * The parent must be appropriately initialized. 60: * Conditions: 61: * Nothing locked. 62: */ 63: 64: void 65: ipc_task_init( 66: task_t task, 67: task_t parent) 68: { 69: ipc_space_t space; 70: ipc_port_t kport; 71: kern_return_t kr; 72: int i; 73: 74: 75: kr = ipc_space_create(&ipc_table_entries[0], &space); 76: if (kr != KERN_SUCCESS) 77: panic("ipc_task_init"); 78: 79: 80: kport = ipc_port_alloc_kernel(); 81: if (kport == IP_NULL) 82: panic("ipc_task_init"); 83: 84: itk_lock_init(task); 85: task->itk_self = kport; 86: task->itk_sself = ipc_port_make_send(kport); 87: task->itk_space = space; 88: 89: if (parent == TASK_NULL) { 90: task->itk_exception = IP_NULL; 91: task->itk_bootstrap = IP_NULL; 92: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) 93: task->itk_registered[i] = IP_NULL; 94: } else { 95: itk_lock(parent); 96: assert(parent->itk_self != IP_NULL); 97: 98: /* inherit registered ports */ 99: 100: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) 101: task->itk_registered[i] = 102: ipc_port_copy_send(parent->itk_registered[i]); 103: 104: /* inherit exception and bootstrap ports */ 105: 106: task->itk_exception = 107: ipc_port_copy_send(parent->itk_exception); 108: task->itk_bootstrap = 109: ipc_port_copy_send(parent->itk_bootstrap); 110: 111: itk_unlock(parent); 112: } 113: } 114: 115: /* 116: * Routine: ipc_task_enable 117: * Purpose: 118: * Enable a task for IPC access. 119: * Conditions: 120: * Nothing locked. 121: */ 122: 123: void 124: ipc_task_enable( 125: task_t task) 126: { 127: ipc_port_t kport; 128: 129: itk_lock(task); 130: kport = task->itk_self; 131: if (kport != IP_NULL) 132: ipc_kobject_set(kport, (ipc_kobject_t) task, IKOT_TASK); 133: itk_unlock(task); 134: } 135: 136: /* 137: * Routine: ipc_task_disable 138: * Purpose: 139: * Disable IPC access to a task. 140: * Conditions: 141: * Nothing locked. 142: */ 143: 144: void 145: ipc_task_disable( 146: task_t task) 147: { 148: ipc_port_t kport; 149: 150: itk_lock(task); 151: kport = task->itk_self; 152: if (kport != IP_NULL) 153: ipc_kobject_set(kport, IKO_NULL, IKOT_NONE); 154: itk_unlock(task); 155: } 156: 157: /* 158: * Routine: ipc_task_terminate 159: * Purpose: 160: * Clean up and destroy a task's IPC state. 161: * Conditions: 162: * Nothing locked. The task must be suspended. 163: * (Or the current thread must be in the task.) 164: */ 165: 166: void 167: ipc_task_terminate( 168: task_t task) 169: { 170: ipc_port_t kport; 171: int i; 172: 173: itk_lock(task); 174: kport = task->itk_self; 175: 176: if (kport == IP_NULL) { 177: /* the task is already terminated (can this happen?) */ 178: itk_unlock(task); 179: return; 180: } 181: 182: task->itk_self = IP_NULL; 183: itk_unlock(task); 184: 185: /* release the naked send rights */ 186: 187: if (IP_VALID(task->itk_sself)) 188: ipc_port_release_send(task->itk_sself); 189: if (IP_VALID(task->itk_exception)) 190: ipc_port_release_send(task->itk_exception); 191: if (IP_VALID(task->itk_bootstrap)) 192: ipc_port_release_send(task->itk_bootstrap); 193: 194: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) 195: if (IP_VALID(task->itk_registered[i])) 196: ipc_port_release_send(task->itk_registered[i]); 197: 198: /* destroy the space, leaving just a reference for it */ 199: 200: ipc_space_destroy(task->itk_space); 201: 202: /* destroy the kernel port */ 203: 204: ipc_port_dealloc_kernel(kport); 205: } 206: 207: /* 208: * Routine: ipc_thread_init 209: * Purpose: 210: * Initialize a thread's IPC state. 211: * Conditions: 212: * Nothing locked. 213: */ 214: 215: void 216: ipc_thread_init(thread) 217: thread_t thread; 218: { 219: ipc_port_t kport; 220: 221: kport = ipc_port_alloc_kernel(); 222: if (kport == IP_NULL) 223: panic("ipc_thread_init"); 224: 225: ipc_thread_links_init(thread); 226: ipc_kmsg_queue_init(&thread->ith_messages); 227: 228: ith_lock_init(thread); 229: thread->ith_self = kport; 230: thread->ith_sself = ipc_port_make_send(kport); 231: thread->ith_exception = IP_NULL; 232: 233: thread->ith_mig_reply = MACH_PORT_NULL; 234: thread->ith_rpc_reply = IP_NULL; 235: 236: #if MACH_IPC_COMPAT 237: { 238: ipc_space_t space = thread->task->itk_space; 239: ipc_port_t port; 240: mach_port_t name; 241: kern_return_t kr; 242: 243: kr = ipc_port_alloc_compat(space, &name, &port); 244: if (kr != KERN_SUCCESS) 245: panic("ipc_thread_init"); 246: /* port is locked and active */ 247: 248: /* 249: * Now we have a reply port. We need to make a naked 250: * send right to stash in ith_reply. We can't use 251: * ipc_port_make_send, because we can't unlock the port 252: * before making the right. Also we don't want to 253: * increment ip_mscount. The net effect of all this 254: * is the same as doing 255: * ipc_port_alloc_kernel get the port 256: * ipc_port_make_send make the send right 257: * ipc_object_copyin_from_kernel grab receive right 258: * ipc_object_copyout_compat and give to user 259: */ 260: 261: port->ip_srights++; 262: ip_reference(port); 263: ip_unlock(port); 264: 265: thread->ith_reply = port; 266: } 267: #endif MACH_IPC_COMPAT 268: } 269: 270: /* 271: * Routine: ipc_thread_enable 272: * Purpose: 273: * Enable a thread for IPC access. 274: * Conditions: 275: * Nothing locked. 276: */ 277: 278: void 279: ipc_thread_enable(thread) 280: thread_t thread; 281: { 282: ipc_port_t kport; 283: 284: ith_lock(thread); 285: kport = thread->ith_self; 286: if (kport != IP_NULL) 287: ipc_kobject_set(kport, (ipc_kobject_t) thread, IKOT_THREAD); 288: ith_unlock(thread); 289: } 290: 291: /* 292: * Routine: ipc_thread_disable 293: * Purpose: 294: * Disable IPC access to a thread. 295: * Conditions: 296: * Nothing locked. 297: */ 298: 299: void 300: ipc_thread_disable(thread) 301: thread_t thread; 302: { 303: ipc_port_t kport; 304: 305: ith_lock(thread); 306: kport = thread->ith_self; 307: if (kport != IP_NULL) 308: ipc_kobject_set(kport, IKO_NULL, IKOT_NONE); 309: ith_unlock(thread); 310: } 311: 312: /* 313: * Routine: ipc_thread_terminate 314: * Purpose: 315: * Clean up and destroy a thread's IPC state. 316: * Conditions: 317: * Nothing locked. The thread must be suspended. 318: * (Or be the current thread.) 319: */ 320: 321: void 322: ipc_thread_terminate(thread) 323: thread_t thread; 324: { 325: ipc_port_t kport; 326: 327: ith_lock(thread); 328: kport = thread->ith_self; 329: 330: if (kport == IP_NULL) { 331: /* the thread is already terminated (can this happen?) */ 332: ith_unlock(thread); 333: return; 334: } 335: 336: thread->ith_self = IP_NULL; 337: ith_unlock(thread); 338: 339: assert(ipc_kmsg_queue_empty(&thread->ith_messages)); 340: 341: /* release the naked send rights */ 342: 343: if (IP_VALID(thread->ith_sself)) 344: ipc_port_release_send(thread->ith_sself); 345: if (IP_VALID(thread->ith_exception)) 346: ipc_port_release_send(thread->ith_exception); 347: 348: #if MACH_IPC_COMPAT 349: if (IP_VALID(thread->ith_reply)) { 350: ipc_space_t space = thread->task->itk_space; 351: ipc_port_t port = thread->ith_reply; 352: ipc_entry_t entry; 353: mach_port_t name; 354: 355: /* destroy any rights the task may have for the port */ 356: 357: is_write_lock(space); 358: if (space->is_active && 359: ipc_right_reverse(space, (ipc_object_t) port, 360: &name, &entry)) { 361: /* reply port is locked and active */ 362: ip_unlock(port); 363: 364: (void) ipc_right_destroy(space, name, entry); 365: /* space is unlocked */ 366: } else 367: is_write_unlock(space); 368: 369: ipc_port_release_send(port); 370: } 371: 372: /* 373: * Note we do *not* destroy any rights the space may have 374: * for the thread's kernel port. The old IPC code did this, 375: * to avoid generating a notification when the port is 376: * destroyed. However, this isn't a good idea when 377: * the kernel port is interposed, because then it doesn't 378: * happen, exposing the interposition to the task. 379: * Because we don't need the efficiency hack, I flushed 380: * this behaviour, introducing a small incompatibility 381: * with the old IPC code. 382: */ 383: #endif MACH_IPC_COMPAT 384: 385: /* destroy the kernel port */ 386: 387: ipc_port_dealloc_kernel(kport); 388: } 389: 390: #if 0 391: /* 392: * Routine: retrieve_task_self 393: * Purpose: 394: * Return a send right (possibly null/dead) 395: * for the task's user-visible self port. 396: * Conditions: 397: * Nothing locked. 398: */ 399: 400: ipc_port_t 401: retrieve_task_self(task) 402: task_t task; 403: { 404: ipc_port_t port; 405: 406: assert(task != TASK_NULL); 407: 408: itk_lock(task); 409: if (task->itk_self != IP_NULL) 410: port = ipc_port_copy_send(task->itk_sself); 411: else 412: port = IP_NULL; 413: itk_unlock(task); 414: 415: return port; 416: } 417: 418: /* 419: * Routine: retrieve_thread_self 420: * Purpose: 421: * Return a send right (possibly null/dead) 422: * for the thread's user-visible self port. 423: * Conditions: 424: * Nothing locked. 425: */ 426: 427: ipc_port_t 428: retrieve_thread_self(thread) 429: thread_t thread; 430: { 431: ipc_port_t port; 432: 433: assert(thread != ITH_NULL); 434: 435: ith_lock(thread); 436: if (thread->ith_self != IP_NULL) 437: port = ipc_port_copy_send(thread->ith_sself); 438: else 439: port = IP_NULL; 440: ith_unlock(thread); 441: 442: return port; 443: } 444: #endif 0 445: 446: /* 447: * Routine: retrieve_task_self_fast 448: * Purpose: 449: * Optimized version of retrieve_task_self, 450: * that only works for the current task. 451: * 452: * Return a send right (possibly null/dead) 453: * for the task's user-visible self port. 454: * Conditions: 455: * Nothing locked. 456: */ 457: 458: ipc_port_t 459: retrieve_task_self_fast( 460: register task_t task) 461: { 462: register ipc_port_t port; 463: 464: assert(task == current_task()); 465: 466: itk_lock(task); 467: assert(task->itk_self != IP_NULL); 468: 469: if ((port = task->itk_sself) == task->itk_self) { 470: /* no interposing */ 471: 472: ip_lock(port); 473: assert(ip_active(port)); 474: ip_reference(port); 475: port->ip_srights++; 476: ip_unlock(port); 477: } else 478: port = ipc_port_copy_send(port); 479: itk_unlock(task); 480: 481: return port; 482: } 483: 484: /* 485: * Routine: retrieve_thread_self_fast 486: * Purpose: 487: * Optimized version of retrieve_thread_self, 488: * that only works for the current thread. 489: * 490: * Return a send right (possibly null/dead) 491: * for the thread's user-visible self port. 492: * Conditions: 493: * Nothing locked. 494: */ 495: 496: ipc_port_t 497: retrieve_thread_self_fast(thread) 498: register thread_t thread; 499: { 500: register ipc_port_t port; 501: 502: assert(thread == current_thread()); 503: 504: ith_lock(thread); 505: assert(thread->ith_self != IP_NULL); 506: 507: if ((port = thread->ith_sself) == thread->ith_self) { 508: /* no interposing */ 509: 510: ip_lock(port); 511: assert(ip_active(port)); 512: ip_reference(port); 513: port->ip_srights++; 514: ip_unlock(port); 515: } else 516: port = ipc_port_copy_send(port); 517: ith_unlock(thread); 518: 519: return port; 520: } 521: 522: #if 0 523: /* 524: * Routine: retrieve_task_exception 525: * Purpose: 526: * Return a send right (possibly null/dead) 527: * for the task's exception port. 528: * Conditions: 529: * Nothing locked. 530: */ 531: 532: ipc_port_t 533: retrieve_task_exception(task) 534: task_t task; 535: { 536: ipc_port_t port; 537: 538: assert(task != TASK_NULL); 539: 540: itk_lock(task); 541: if (task->itk_self != IP_NULL) 542: port = ipc_port_copy_send(task->itk_exception); 543: else 544: port = IP_NULL; 545: itk_unlock(task); 546: 547: return port; 548: } 549: 550: /* 551: * Routine: retrieve_thread_exception 552: * Purpose: 553: * Return a send right (possibly null/dead) 554: * for the thread's exception port. 555: * Conditions: 556: * Nothing locked. 557: */ 558: 559: ipc_port_t 560: retrieve_thread_exception(thread) 561: thread_t thread; 562: { 563: ipc_port_t port; 564: 565: assert(thread != ITH_NULL); 566: 567: ith_lock(thread); 568: if (thread->ith_self != IP_NULL) 569: port = ipc_port_copy_send(thread->ith_exception); 570: else 571: port = IP_NULL; 572: ith_unlock(thread); 573: 574: return port; 575: } 576: #endif 0 577: 578: /* 579: * Routine: mach_task_self [mach trap] 580: * Purpose: 581: * Give the caller send rights for his own task port. 582: * Conditions: 583: * Nothing locked. 584: * Returns: 585: * MACH_PORT_NULL if there are any resource failures 586: * or other errors. 587: */ 588: 589: mach_port_t 590: mach_task_self(void) 591: { 592: task_t task = current_task(); 593: ipc_port_t sright; 594: 595: sright = retrieve_task_self_fast(task); 596: return ipc_port_copyout_send(sright, task->itk_space); 597: } 598: 599: /* 600: * Routine: mach_thread_self [mach trap] 601: * Purpose: 602: * Give the caller send rights for his own thread port. 603: * Conditions: 604: * Nothing locked. 605: * Returns: 606: * MACH_PORT_NULL if there are any resource failures 607: * or other errors. 608: */ 609: 610: mach_port_t 611: mach_thread_self() 612: { 613: thread_t thread = current_thread(); 614: task_t task = thread->task; 615: ipc_port_t sright; 616: 617: sright = retrieve_thread_self_fast(thread); 618: return ipc_port_copyout_send(sright, task->itk_space); 619: } 620: 621: /* 622: * Routine: mach_reply_port [mach trap] 623: * Purpose: 624: * Allocate a port for the caller. 625: * Conditions: 626: * Nothing locked. 627: * Returns: 628: * MACH_PORT_NULL if there are any resource failures 629: * or other errors. 630: */ 631: 632: mach_port_t 633: mach_reply_port(void) 634: { 635: ipc_port_t port; 636: mach_port_t name; 637: kern_return_t kr; 638: 639: kr = ipc_port_alloc(current_task()->itk_space, &name, &port); 640: if (kr == KERN_SUCCESS) 641: ip_unlock(port); 642: else 643: name = MACH_PORT_NULL; 644: 645: return name; 646: } 647: 648: #if MACH_IPC_COMPAT 649: 650: /* 651: * Routine: retrieve_task_notify 652: * Purpose: 653: * Return a reference (or null) for 654: * the task's notify port. 655: * Conditions: 656: * Nothing locked. 657: */ 658: 659: ipc_port_t 660: retrieve_task_notify(task) 661: task_t task; 662: { 663: ipc_space_t space = task->itk_space; 664: ipc_port_t port; 665: 666: is_read_lock(space); 667: if (space->is_active) { 668: port = space->is_notify; 669: if (IP_VALID(port)) 670: ipc_port_reference(port); 671: } else 672: port = IP_NULL; 673: is_read_unlock(space); 674: 675: return port; 676: } 677: 678: /* 679: * Routine: retrieve_thread_reply 680: * Purpose: 681: * Return a reference (or null) for 682: * the thread's reply port. 683: * Conditions: 684: * Nothing locked. 685: */ 686: 687: ipc_port_t 688: retrieve_thread_reply(thread) 689: thread_t thread; 690: { 691: ipc_port_t port; 692: 693: ith_lock(thread); 694: if (thread->ith_self != IP_NULL) { 695: port = thread->ith_reply; 696: if (IP_VALID(port)) 697: ipc_port_reference(port); 698: } else 699: port = IP_NULL; 700: ith_unlock(thread); 701: 702: return port; 703: } 704: 705: /* 706: * Routine: task_self [mach trap] 707: * Purpose: 708: * Give the caller send rights for his task port. 709: * If new, the send right is marked with IE_BITS_COMPAT. 710: * Conditions: 711: * Nothing locked. 712: * Returns: 713: * MACH_PORT_NULL if there are any resource failures 714: * or other errors. 715: */ 716: 717: port_name_t 718: task_self() 719: { 720: task_t task = current_task(); 721: ipc_port_t sright; 722: mach_port_t name; 723: 724: sright = retrieve_task_self_fast(task); 725: name = ipc_port_copyout_send_compat(sright, task->itk_space); 726: return (port_name_t) name; 727: } 728: 729: /* 730: * Routine: task_notify [mach trap] 731: * Purpose: 732: * Give the caller the name of his own notify port. 733: * Conditions: 734: * Nothing locked. 735: * Returns: 736: * MACH_PORT_NULL if there isn't a notify port, 737: * if it is dead, or if the caller doesn't hold 738: * receive rights for it. 739: */ 740: 741: port_name_t 742: task_notify() 743: { 744: task_t task = current_task(); 745: ipc_port_t notify; 746: mach_port_t name; 747: 748: notify = retrieve_task_notify(task); 749: name = ipc_port_copyout_receiver(notify, task->itk_space); 750: return (port_name_t) name; 751: } 752: 753: /* 754: * Routine: thread_self [mach trap] 755: * Purpose: 756: * Give the caller send rights for his own thread port. 757: * If new, the send right is marked with IE_BITS_COMPAT. 758: * Conditions: 759: * Nothing locked. 760: * Returns: 761: * MACH_PORT_NULL if there are any resource failures 762: * or other errors. 763: */ 764: 765: port_name_t 766: thread_self() 767: { 768: thread_t thread = current_thread(); 769: task_t task = thread->task; 770: ipc_port_t sright; 771: mach_port_t name; 772: 773: sright = retrieve_thread_self_fast(thread); 774: name = ipc_port_copyout_send_compat(sright, task->itk_space); 775: return (port_name_t) name; 776: } 777: 778: /* 779: * Routine: thread_reply [mach trap] 780: * Purpose: 781: * Give the caller the name of his own reply port. 782: * Conditions: 783: * Nothing locked. 784: * Returns: 785: * MACH_PORT_NULL if there isn't a reply port, 786: * if it is dead, or if the caller doesn't hold 787: * receive rights for it. 788: */ 789: 790: port_name_t 791: thread_reply() 792: { 793: task_t task = current_task(); 794: thread_t thread = current_thread(); 795: ipc_port_t reply; 796: mach_port_t name; 797: 798: reply = retrieve_thread_reply(thread); 799: name = ipc_port_copyout_receiver(reply, task->itk_space); 800: return (port_name_t) name; 801: } 802: 803: #endif MACH_IPC_COMPAT 804: 805: /* 806: * Routine: task_get_special_port [kernel call] 807: * Purpose: 808: * Clones a send right for one of the task's 809: * special ports. 810: * Conditions: 811: * Nothing locked. 812: * Returns: 813: * KERN_SUCCESS Extracted a send right. 814: * KERN_INVALID_ARGUMENT The task is null. 815: * KERN_FAILURE The task/space is dead. 816: * KERN_INVALID_ARGUMENT Invalid special port. 817: */ 818: 819: kern_return_t 820: task_get_special_port( 821: task_t task, 822: int which, 823: ipc_port_t *portp) 824: { 825: ipc_port_t *whichp; 826: ipc_port_t port; 827: 828: if (task == TASK_NULL) 829: return KERN_INVALID_ARGUMENT; 830: 831: switch (which) { 832: #if MACH_IPC_COMPAT 833: case TASK_NOTIFY_PORT: { 834: ipc_space_t space = task->itk_space; 835: 836: is_read_lock(space); 837: if (!space->is_active) { 838: is_read_unlock(space); 839: return KERN_FAILURE; 840: } 841: 842: port = ipc_port_copy_send(space->is_notify); 843: is_read_unlock(space); 844: 845: *portp = port; 846: return KERN_SUCCESS; 847: } 848: #endif MACH_IPC_COMPAT 849: 850: case TASK_KERNEL_PORT: 851: whichp = &task->itk_sself; 852: break; 853: 854: case TASK_EXCEPTION_PORT: 855: whichp = &task->itk_exception; 856: break; 857: 858: case TASK_BOOTSTRAP_PORT: 859: whichp = &task->itk_bootstrap; 860: break; 861: 862: default: 863: return KERN_INVALID_ARGUMENT; 864: } 865: 866: itk_lock(task); 867: if (task->itk_self == IP_NULL) { 868: itk_unlock(task); 869: return KERN_FAILURE; 870: } 871: 872: port = ipc_port_copy_send(*whichp); 873: itk_unlock(task); 874: 875: *portp = port; 876: return KERN_SUCCESS; 877: } 878: 879: /* 880: * Routine: task_set_special_port [kernel call] 881: * Purpose: 882: * Changes one of the task's special ports, 883: * setting it to the supplied send right. 884: * Conditions: 885: * Nothing locked. If successful, consumes 886: * the supplied send right. 887: * Returns: 888: * KERN_SUCCESS Changed the special port. 889: * KERN_INVALID_ARGUMENT The task is null. 890: * KERN_FAILURE The task/space is dead. 891: * KERN_INVALID_ARGUMENT Invalid special port. 892: */ 893: 894: kern_return_t 895: task_set_special_port( 896: task_t task, 897: int which, 898: ipc_port_t port) 899: { 900: ipc_port_t *whichp; 901: ipc_port_t old; 902: 903: if (task == TASK_NULL) 904: return KERN_INVALID_ARGUMENT; 905: 906: switch (which) { 907: #if MACH_IPC_COMPAT 908: case TASK_NOTIFY_PORT: { 909: ipc_space_t space = task->itk_space; 910: 911: is_write_lock(space); 912: if (!space->is_active) { 913: is_write_unlock(space); 914: return KERN_FAILURE; 915: } 916: 917: old = space->is_notify; 918: space->is_notify = port; 919: is_write_unlock(space); 920: 921: if (IP_VALID(old)) 922: ipc_port_release_send(old); 923: return KERN_SUCCESS; 924: } 925: #endif MACH_IPC_COMPAT 926: 927: case TASK_KERNEL_PORT: 928: whichp = &task->itk_sself; 929: break; 930: 931: case TASK_EXCEPTION_PORT: 932: whichp = &task->itk_exception; 933: break; 934: 935: case TASK_BOOTSTRAP_PORT: 936: whichp = &task->itk_bootstrap; 937: break; 938: 939: default: 940: return KERN_INVALID_ARGUMENT; 941: } 942: 943: itk_lock(task); 944: if (task->itk_self == IP_NULL) { 945: itk_unlock(task); 946: return KERN_FAILURE; 947: } 948: 949: old = *whichp; 950: *whichp = port; 951: itk_unlock(task); 952: 953: if (IP_VALID(old)) 954: ipc_port_release_send(old); 955: return KERN_SUCCESS; 956: } 957: 958: /* 959: * Routine: thread_get_special_port [kernel call] 960: * Purpose: 961: * Clones a send right for one of the thread's 962: * special ports. 963: * Conditions: 964: * Nothing locked. 965: * Returns: 966: * KERN_SUCCESS Extracted a send right. 967: * KERN_INVALID_ARGUMENT The thread is null. 968: * KERN_FAILURE The thread is dead. 969: * KERN_INVALID_ARGUMENT Invalid special port. 970: */ 971: 972: kern_return_t 973: thread_get_special_port(thread, which, portp) 974: thread_t thread; 975: int which; 976: ipc_port_t *portp; 977: { 978: ipc_port_t *whichp; 979: ipc_port_t port; 980: 981: if (thread == ITH_NULL) 982: return KERN_INVALID_ARGUMENT; 983: 984: switch (which) { 985: #if MACH_IPC_COMPAT 986: case THREAD_REPLY_PORT: 987: whichp = &thread->ith_reply; 988: break; 989: #endif MACH_IPC_COMPAT 990: 991: case THREAD_KERNEL_PORT: 992: whichp = &thread->ith_sself; 993: break; 994: 995: case THREAD_EXCEPTION_PORT: 996: whichp = &thread->ith_exception; 997: break; 998: 999: default: 1000: return KERN_INVALID_ARGUMENT; 1001: } 1002: 1003: ith_lock(thread); 1004: if (thread->ith_self == IP_NULL) { 1005: ith_unlock(thread); 1006: return KERN_FAILURE; 1007: } 1008: 1009: port = ipc_port_copy_send(*whichp); 1010: ith_unlock(thread); 1011: 1012: *portp = port; 1013: return KERN_SUCCESS; 1014: } 1015: 1016: /* 1017: * Routine: thread_set_special_port [kernel call] 1018: * Purpose: 1019: * Changes one of the thread's special ports, 1020: * setting it to the supplied send right. 1021: * Conditions: 1022: * Nothing locked. If successful, consumes 1023: * the supplied send right. 1024: * Returns: 1025: * KERN_SUCCESS Changed the special port. 1026: * KERN_INVALID_ARGUMENT The thread is null. 1027: * KERN_FAILURE The thread is dead. 1028: * KERN_INVALID_ARGUMENT Invalid special port. 1029: */ 1030: 1031: kern_return_t 1032: thread_set_special_port(thread, which, port) 1033: thread_t thread; 1034: int which; 1035: ipc_port_t port; 1036: { 1037: ipc_port_t *whichp; 1038: ipc_port_t old; 1039: 1040: if (thread == ITH_NULL) 1041: return KERN_INVALID_ARGUMENT; 1042: 1043: switch (which) { 1044: #if MACH_IPC_COMPAT 1045: case THREAD_REPLY_PORT: 1046: whichp = &thread->ith_reply; 1047: break; 1048: #endif MACH_IPC_COMPAT 1049: 1050: case THREAD_KERNEL_PORT: 1051: whichp = &thread->ith_sself; 1052: break; 1053: 1054: case THREAD_EXCEPTION_PORT: 1055: whichp = &thread->ith_exception; 1056: break; 1057: 1058: default: 1059: return KERN_INVALID_ARGUMENT; 1060: } 1061: 1062: ith_lock(thread); 1063: if (thread->ith_self == IP_NULL) { 1064: ith_unlock(thread); 1065: return KERN_FAILURE; 1066: } 1067: 1068: old = *whichp; 1069: *whichp = port; 1070: ith_unlock(thread); 1071: 1072: if (IP_VALID(old)) 1073: ipc_port_release_send(old); 1074: return KERN_SUCCESS; 1075: } 1076: 1077: /* 1078: * Routine: mach_ports_register [kernel call] 1079: * Purpose: 1080: * Stash a handful of port send rights in the task. 1081: * Child tasks will inherit these rights, but they 1082: * must use mach_ports_lookup to acquire them. 1083: * 1084: * The rights are supplied in a (wired) kalloc'd segment. 1085: * Rights which aren't supplied are assumed to be null. 1086: * Conditions: 1087: * Nothing locked. If successful, consumes 1088: * the supplied rights and memory. 1089: * Returns: 1090: * KERN_SUCCESS Stashed the port rights. 1091: * KERN_INVALID_ARGUMENT The task is null. 1092: * KERN_INVALID_ARGUMENT The task is dead. 1093: * KERN_INVALID_ARGUMENT Too many port rights supplied. 1094: */ 1095: 1096: kern_return_t 1097: mach_ports_register( 1098: task_t task, 1099: mach_port_array_t memory, 1100: mach_msg_type_number_t portsCnt) 1101: { 1102: ipc_port_t ports[TASK_PORT_REGISTER_MAX]; 1103: int i; 1104: 1105: if ((task == TASK_NULL) || 1106: (portsCnt > TASK_PORT_REGISTER_MAX)) 1107: return KERN_INVALID_ARGUMENT; 1108: 1109: /* 1110: * Pad the port rights with nulls. 1111: */ 1112: 1113: for (i = 0; i < portsCnt; i++) 1114: ports[i] = memory[i]; 1115: for (; i < TASK_PORT_REGISTER_MAX; i++) 1116: ports[i] = IP_NULL; 1117: 1118: itk_lock(task); 1119: if (task->itk_self == IP_NULL) { 1120: itk_unlock(task); 1121: return KERN_INVALID_ARGUMENT; 1122: } 1123: 1124: /* 1125: * Replace the old send rights with the new. 1126: * Release the old rights after unlocking. 1127: */ 1128: 1129: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) { 1130: ipc_port_t old; 1131: 1132: old = task->itk_registered[i]; 1133: task->itk_registered[i] = ports[i]; 1134: ports[i] = old; 1135: } 1136: 1137: itk_unlock(task); 1138: 1139: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) 1140: if (IP_VALID(ports[i])) 1141: ipc_port_release_send(ports[i]); 1142: 1143: /* 1144: * Now that the operation is known to be successful, 1145: * we can free the memory. 1146: */ 1147: 1148: if (portsCnt != 0) 1149: kfree((vm_offset_t) memory, 1150: (vm_size_t) (portsCnt * sizeof(mach_port_t))); 1151: 1152: return KERN_SUCCESS; 1153: } 1154: 1155: /* 1156: * Routine: mach_ports_lookup [kernel call] 1157: * Purpose: 1158: * Retrieves (clones) the stashed port send rights. 1159: * Conditions: 1160: * Nothing locked. If successful, the caller gets 1161: * rights and memory. 1162: * Returns: 1163: * KERN_SUCCESS Retrieved the send rights. 1164: * KERN_INVALID_ARGUMENT The task is null. 1165: * KERN_INVALID_ARGUMENT The task is dead. 1166: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 1167: */ 1168: 1169: kern_return_t 1170: mach_ports_lookup(task, portsp, portsCnt) 1171: task_t task; 1172: ipc_port_t **portsp; 1173: mach_msg_type_number_t *portsCnt; 1174: { 1175: vm_offset_t memory; 1176: vm_size_t size; 1177: ipc_port_t *ports; 1178: int i; 1179: 1180: if (task == TASK_NULL) 1181: return KERN_INVALID_ARGUMENT; 1182: 1183: size = (vm_size_t) (TASK_PORT_REGISTER_MAX * sizeof(ipc_port_t)); 1184: 1185: memory = kalloc(size); 1186: if (memory == 0) 1187: return KERN_RESOURCE_SHORTAGE; 1188: 1189: itk_lock(task); 1190: if (task->itk_self == IP_NULL) { 1191: itk_unlock(task); 1192: 1193: kfree(memory, size); 1194: return KERN_INVALID_ARGUMENT; 1195: } 1196: 1197: ports = (ipc_port_t *) memory; 1198: 1199: /* 1200: * Clone port rights. Because kalloc'd memory 1201: * is wired, we won't fault while holding the task lock. 1202: */ 1203: 1204: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) 1205: ports[i] = ipc_port_copy_send(task->itk_registered[i]); 1206: 1207: itk_unlock(task); 1208: 1.1.1.2 ! root 1209: *portsp = ports; 1.1 root 1210: *portsCnt = TASK_PORT_REGISTER_MAX; 1211: return KERN_SUCCESS; 1212: } 1213: 1214: /* 1215: * Routine: convert_port_to_task 1216: * Purpose: 1217: * Convert from a port to a task. 1218: * Doesn't consume the port ref; produces a task ref, 1219: * which may be null. 1220: * Conditions: 1221: * Nothing locked. 1222: */ 1223: 1224: task_t 1225: convert_port_to_task( 1226: ipc_port_t port) 1227: { 1228: task_t task = TASK_NULL; 1229: 1230: if (IP_VALID(port)) { 1231: ip_lock(port); 1232: if (ip_active(port) && 1233: (ip_kotype(port) == IKOT_TASK)) { 1234: task = (task_t) port->ip_kobject; 1235: task_reference(task); 1236: } 1237: ip_unlock(port); 1238: } 1239: 1240: return task; 1241: } 1242: 1243: /* 1244: * Routine: convert_port_to_space 1245: * Purpose: 1246: * Convert from a port to a space. 1247: * Doesn't consume the port ref; produces a space ref, 1248: * which may be null. 1249: * Conditions: 1250: * Nothing locked. 1251: */ 1252: 1253: ipc_space_t 1254: convert_port_to_space( 1255: ipc_port_t port) 1256: { 1257: ipc_space_t space = IS_NULL; 1258: 1259: if (IP_VALID(port)) { 1260: ip_lock(port); 1261: if (ip_active(port) && 1262: (ip_kotype(port) == IKOT_TASK)) { 1263: space = ((task_t) port->ip_kobject)->itk_space; 1264: is_reference(space); 1265: } 1266: ip_unlock(port); 1267: } 1268: 1269: return space; 1270: } 1271: 1272: /* 1273: * Routine: convert_port_to_map 1274: * Purpose: 1275: * Convert from a port to a map. 1276: * Doesn't consume the port ref; produces a map ref, 1277: * which may be null. 1278: * Conditions: 1279: * Nothing locked. 1280: */ 1281: 1282: vm_map_t 1283: convert_port_to_map(port) 1284: ipc_port_t port; 1285: { 1286: vm_map_t map = VM_MAP_NULL; 1287: 1288: if (IP_VALID(port)) { 1289: ip_lock(port); 1290: if (ip_active(port) && 1291: (ip_kotype(port) == IKOT_TASK)) { 1292: map = ((task_t) port->ip_kobject)->map; 1293: vm_map_reference(map); 1294: } 1295: ip_unlock(port); 1296: } 1297: 1298: return map; 1299: } 1300: 1301: /* 1302: * Routine: convert_port_to_thread 1303: * Purpose: 1304: * Convert from a port to a thread. 1305: * Doesn't consume the port ref; produces a thread ref, 1306: * which may be null. 1307: * Conditions: 1308: * Nothing locked. 1309: */ 1310: 1311: thread_t 1312: convert_port_to_thread(port) 1313: ipc_port_t port; 1314: { 1315: thread_t thread = THREAD_NULL; 1316: 1317: if (IP_VALID(port)) { 1318: ip_lock(port); 1319: if (ip_active(port) && 1320: (ip_kotype(port) == IKOT_THREAD)) { 1321: thread = (thread_t) port->ip_kobject; 1322: thread_reference(thread); 1323: } 1324: ip_unlock(port); 1325: } 1326: 1327: return thread; 1328: } 1329: 1330: /* 1331: * Routine: convert_task_to_port 1332: * Purpose: 1333: * Convert from a task to a port. 1334: * Consumes a task ref; produces a naked send right 1.1.1.2 ! root 1335: * which may be invalid. 1.1 root 1336: * Conditions: 1337: * Nothing locked. 1338: */ 1339: 1340: ipc_port_t 1341: convert_task_to_port(task) 1342: task_t task; 1343: { 1344: ipc_port_t port; 1345: 1346: itk_lock(task); 1347: if (task->itk_self != IP_NULL) 1348: port = ipc_port_make_send(task->itk_self); 1349: else 1350: port = IP_NULL; 1351: itk_unlock(task); 1352: 1353: task_deallocate(task); 1354: return port; 1355: } 1356: 1357: /* 1358: * Routine: convert_thread_to_port 1359: * Purpose: 1360: * Convert from a thread to a port. 1361: * Consumes a thread ref; produces a naked send right 1362: * which may be invalid. 1363: * Conditions: 1364: * Nothing locked. 1365: */ 1366: 1367: ipc_port_t 1368: convert_thread_to_port(thread) 1369: thread_t thread; 1370: { 1371: ipc_port_t port; 1372: 1373: ith_lock(thread); 1374: if (thread->ith_self != IP_NULL) 1375: port = ipc_port_make_send(thread->ith_self); 1376: else 1377: port = IP_NULL; 1378: ith_unlock(thread); 1379: 1380: thread_deallocate(thread); 1381: return port; 1382: } 1383: 1384: /* 1385: * Routine: space_deallocate 1386: * Purpose: 1387: * Deallocate a space ref produced by convert_port_to_space. 1388: * Conditions: 1389: * Nothing locked. 1390: */ 1391: 1392: void 1393: space_deallocate(space) 1394: ipc_space_t space; 1395: { 1396: if (space != IS_NULL) 1397: is_release(space); 1398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.