|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990,1989 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/ipc_object.c 28: * Author: Rich Draves 29: * Date: 1989 30: * 31: * Functions to manipulate IPC objects. 32: */ 33: 34: #include <mach_ipc_compat.h> 35: 36: #include <mach/boolean.h> 37: #include <mach/kern_return.h> 38: #include <mach/port.h> 39: #include <mach/message.h> 40: #include <ipc/port.h> 41: #include <ipc/ipc_space.h> 42: #include <ipc/ipc_entry.h> 43: #include <ipc/ipc_object.h> 44: #include <ipc/ipc_hash.h> 45: #include <ipc/ipc_right.h> 46: #include <ipc/ipc_notify.h> 47: #include <ipc/ipc_pset.h> 48: 49: zone_t ipc_object_zones[IOT_NUMBER]; 50: 51: 52: 53: /* 54: * Routine: ipc_object_reference 55: * Purpose: 56: * Take a reference to an object. 57: */ 58: 59: void 60: ipc_object_reference( 61: ipc_object_t object) 62: { 63: io_lock(object); 64: assert(object->io_references > 0); 65: io_reference(object); 66: io_unlock(object); 67: } 68: 69: /* 70: * Routine: ipc_object_release 71: * Purpose: 72: * Release a reference to an object. 73: */ 74: 75: void 76: ipc_object_release( 77: ipc_object_t object) 78: { 79: io_lock(object); 80: assert(object->io_references > 0); 81: io_release(object); 82: io_check_unlock(object); 83: } 84: 85: /* 86: * Routine: ipc_object_translate 87: * Purpose: 88: * Look up an object in a space. 89: * Conditions: 90: * Nothing locked before. If successful, the object 91: * is returned locked. The caller doesn't get a ref. 92: * Returns: 93: * KERN_SUCCESS Objected returned locked. 94: * KERN_INVALID_TASK The space is dead. 95: * KERN_INVALID_NAME The name doesn't denote a right. 96: * KERN_INVALID_RIGHT Name doesn't denote the correct right. 97: */ 98: 99: kern_return_t 100: ipc_object_translate( 101: ipc_space_t space, 102: mach_port_t name, 103: mach_port_right_t right, 104: ipc_object_t *objectp) 105: { 106: ipc_entry_t entry; 107: ipc_object_t object; 108: kern_return_t kr; 109: 110: kr = ipc_right_lookup_read(space, name, &entry); 111: if (kr != KERN_SUCCESS) 112: return kr; 113: /* space is read-locked and active */ 114: 115: if ((entry->ie_bits & MACH_PORT_TYPE(right)) == (mach_port_right_t) 0) { 116: is_read_unlock(space); 117: return KERN_INVALID_RIGHT; 118: } 119: 120: object = entry->ie_object; 121: assert(object != IO_NULL); 122: 123: io_lock(object); 124: is_read_unlock(space); 125: 126: *objectp = object; 127: return KERN_SUCCESS; 128: } 129: 130: /* 131: * Routine: ipc_object_alloc_dead 132: * Purpose: 133: * Allocate a dead-name entry. 134: * Conditions: 135: * Nothing locked. 136: * Returns: 137: * KERN_SUCCESS The dead name is allocated. 138: * KERN_INVALID_TASK The space is dead. 139: * KERN_NO_SPACE No room for an entry in the space. 140: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 141: */ 142: 143: kern_return_t 144: ipc_object_alloc_dead( 145: ipc_space_t space, 146: mach_port_t *namep) 147: { 148: ipc_entry_t entry; 149: kern_return_t kr; 150: 151: 152: kr = ipc_entry_alloc(space, namep, &entry); 153: if (kr != KERN_SUCCESS) 154: return kr; 155: /* space is write-locked */ 156: 157: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ 158: 159: assert(entry->ie_object == IO_NULL); 160: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; 161: 162: is_write_unlock(space); 163: return KERN_SUCCESS; 164: } 165: 166: /* 167: * Routine: ipc_object_alloc_dead_name 168: * Purpose: 169: * Allocate a dead-name entry, with a specific name. 170: * Conditions: 171: * Nothing locked. 172: * Returns: 173: * KERN_SUCCESS The dead name is allocated. 174: * KERN_INVALID_TASK The space is dead. 175: * KERN_NAME_EXISTS The name already denotes a right. 176: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 177: */ 178: 179: kern_return_t 180: ipc_object_alloc_dead_name( 181: ipc_space_t space, 182: mach_port_t name) 183: { 184: ipc_entry_t entry; 185: kern_return_t kr; 186: 187: 188: kr = ipc_entry_alloc_name(space, name, &entry); 189: if (kr != KERN_SUCCESS) 190: return kr; 191: /* space is write-locked */ 192: 193: if (ipc_right_inuse(space, name, entry)) 194: return KERN_NAME_EXISTS; 195: 196: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ 197: 198: assert(entry->ie_object == IO_NULL); 199: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; 200: 201: is_write_unlock(space); 202: return KERN_SUCCESS; 203: } 204: 205: /* 206: * Routine: ipc_object_alloc 207: * Purpose: 208: * Allocate an object. 209: * Conditions: 210: * Nothing locked. If successful, the object is returned locked. 211: * The caller doesn't get a reference for the object. 212: * Returns: 213: * KERN_SUCCESS The object is allocated. 214: * KERN_INVALID_TASK The space is dead. 215: * KERN_NO_SPACE No room for an entry in the space. 216: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 217: */ 218: 219: kern_return_t 220: ipc_object_alloc( 221: ipc_space_t space, 222: ipc_object_type_t otype, 223: mach_port_type_t type, 224: mach_port_urefs_t urefs, 225: mach_port_t *namep, 226: ipc_object_t *objectp) 227: { 228: ipc_object_t object; 229: ipc_entry_t entry; 230: kern_return_t kr; 231: 232: assert(otype < IOT_NUMBER); 233: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); 234: assert(type != MACH_PORT_TYPE_NONE); 235: assert(urefs <= MACH_PORT_UREFS_MAX); 236: 237: object = io_alloc(otype); 238: if (object == IO_NULL) 239: return KERN_RESOURCE_SHORTAGE; 240: 241: if (otype == IOT_PORT) { 242: ipc_port_t port = (ipc_port_t)object; 243: 244: bzero((char *)port, sizeof(*port)); 245: } else if (otype == IOT_PORT_SET) { 246: ipc_pset_t pset = (ipc_pset_t)object; 247: 248: bzero((char *)pset, sizeof(*pset)); 249: } 250: kr = ipc_entry_alloc(space, namep, &entry); 251: if (kr != KERN_SUCCESS) { 252: io_free(otype, object); 253: return kr; 254: } 255: /* space is write-locked */ 256: 257: entry->ie_bits |= type | urefs; 258: entry->ie_object = object; 259: 260: io_lock_init(object); 261: io_lock(object); 262: is_write_unlock(space); 263: 264: object->io_references = 1; /* for entry, not caller */ 265: object->io_bits = io_makebits(TRUE, otype, 0); 266: 267: *objectp = object; 268: return KERN_SUCCESS; 269: } 270: 271: /* 272: * Routine: ipc_object_alloc_name 273: * Purpose: 274: * Allocate an object, with a specific name. 275: * Conditions: 276: * Nothing locked. If successful, the object is returned locked. 277: * The caller doesn't get a reference for the object. 278: * Returns: 279: * KERN_SUCCESS The object is allocated. 280: * KERN_INVALID_TASK The space is dead. 281: * KERN_NAME_EXISTS The name already denotes a right. 282: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 283: */ 284: 285: kern_return_t 286: ipc_object_alloc_name( 287: ipc_space_t space, 288: ipc_object_type_t otype, 289: mach_port_type_t type, 290: mach_port_urefs_t urefs, 291: mach_port_t name, 292: ipc_object_t *objectp) 293: { 294: ipc_object_t object; 295: ipc_entry_t entry; 296: kern_return_t kr; 297: 298: assert(otype < IOT_NUMBER); 299: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); 300: assert(type != MACH_PORT_TYPE_NONE); 301: assert(urefs <= MACH_PORT_UREFS_MAX); 302: 303: object = io_alloc(otype); 304: if (object == IO_NULL) 305: return KERN_RESOURCE_SHORTAGE; 306: 307: if (otype == IOT_PORT) { 308: ipc_port_t port = (ipc_port_t)object; 309: 310: bzero((char *)port, sizeof(*port)); 311: } else if (otype == IOT_PORT_SET) { 312: ipc_pset_t pset = (ipc_pset_t)object; 313: 314: bzero((char *)pset, sizeof(*pset)); 315: } 316: 317: kr = ipc_entry_alloc_name(space, name, &entry); 318: if (kr != KERN_SUCCESS) { 319: io_free(otype, object); 320: return kr; 321: } 322: /* space is write-locked */ 323: 324: if (ipc_right_inuse(space, name, entry)) { 325: io_free(otype, object); 326: return KERN_NAME_EXISTS; 327: } 328: 329: entry->ie_bits |= type | urefs; 330: entry->ie_object = object; 331: 332: io_lock_init(object); 333: io_lock(object); 334: is_write_unlock(space); 335: 336: object->io_references = 1; /* for entry, not caller */ 337: object->io_bits = io_makebits(TRUE, otype, 0); 338: 339: *objectp = object; 340: return KERN_SUCCESS; 341: } 342: 343: /* 344: * Routine: ipc_object_copyin_type 345: * Purpose: 346: * Convert a send type name to a received type name. 347: */ 348: 349: mach_msg_type_name_t 350: ipc_object_copyin_type( 351: mach_msg_type_name_t msgt_name) 352: { 353: switch (msgt_name) { 354: case 0: 355: return 0; 356: 357: case MACH_MSG_TYPE_MOVE_RECEIVE: 358: return MACH_MSG_TYPE_PORT_RECEIVE; 359: 360: case MACH_MSG_TYPE_MOVE_SEND_ONCE: 361: case MACH_MSG_TYPE_MAKE_SEND_ONCE: 362: return MACH_MSG_TYPE_PORT_SEND_ONCE; 363: 364: case MACH_MSG_TYPE_MOVE_SEND: 365: case MACH_MSG_TYPE_MAKE_SEND: 366: case MACH_MSG_TYPE_COPY_SEND: 367: return MACH_MSG_TYPE_PORT_SEND; 368: 369: #if MACH_IPC_COMPAT 370: case MSG_TYPE_PORT: 371: return MACH_MSG_TYPE_PORT_SEND; 372: 373: case MSG_TYPE_PORT_ALL: 374: return MACH_MSG_TYPE_PORT_RECEIVE; 1.1.1.2 ! root 375: #endif /* MACH_IPC_COMPAT */ 1.1 root 376: 377: default: 378: #if MACH_ASSERT 379: assert(!"ipc_object_copyin_type: strange rights"); 380: #else 381: panic("ipc_object_copyin_type: strange rights"); 382: #endif 383: return 0; /* in case assert/panic returns */ 384: } 385: } 386: 387: /* 388: * Routine: ipc_object_copyin 389: * Purpose: 390: * Copyin a capability from a space. 391: * If successful, the caller gets a ref 392: * for the resulting object, unless it is IO_DEAD. 393: * Conditions: 394: * Nothing locked. 395: * Returns: 396: * KERN_SUCCESS Acquired an object, possibly IO_DEAD. 397: * KERN_INVALID_TASK The space is dead. 398: * KERN_INVALID_NAME Name doesn't exist in space. 399: * KERN_INVALID_RIGHT Name doesn't denote correct right. 400: */ 401: 402: kern_return_t 403: ipc_object_copyin( 404: ipc_space_t space, 405: mach_port_t name, 406: mach_msg_type_name_t msgt_name, 407: ipc_object_t *objectp) 408: { 409: ipc_entry_t entry; 410: ipc_port_t soright; 411: kern_return_t kr; 412: 413: /* 414: * Could first try a read lock when doing 415: * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND, 416: * and MACH_MSG_TYPE_MAKE_SEND_ONCE. 417: */ 418: 419: kr = ipc_right_lookup_write(space, name, &entry); 420: if (kr != KERN_SUCCESS) 421: return kr; 422: /* space is write-locked and active */ 423: 424: kr = ipc_right_copyin(space, name, entry, 425: msgt_name, TRUE, 426: objectp, &soright); 427: if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) 428: ipc_entry_dealloc(space, name, entry); 429: is_write_unlock(space); 430: 431: if ((kr == KERN_SUCCESS) && (soright != IP_NULL)) 432: ipc_notify_port_deleted(soright, name); 433: 434: return kr; 435: } 436: 437: /* 438: * Routine: ipc_object_copyin_from_kernel 439: * Purpose: 440: * Copyin a naked capability from the kernel. 441: * 442: * MACH_MSG_TYPE_MOVE_RECEIVE 443: * The receiver must be ipc_space_kernel. 444: * Consumes the naked receive right. 445: * MACH_MSG_TYPE_COPY_SEND 446: * A naked send right must be supplied. 447: * The port gains a reference, and a send right 448: * if the port is still active. 449: * MACH_MSG_TYPE_MAKE_SEND 450: * The receiver must be ipc_space_kernel. 451: * The port gains a reference and a send right. 452: * MACH_MSG_TYPE_MOVE_SEND 453: * Consumes a naked send right. 454: * MACH_MSG_TYPE_MAKE_SEND_ONCE 455: * The receiver must be ipc_space_kernel. 456: * The port gains a reference and a send-once right. 457: * MACH_MSG_TYPE_MOVE_SEND_ONCE 458: * Consumes a naked send-once right. 459: * Conditions: 460: * Nothing locked. 461: */ 462: 463: void 464: ipc_object_copyin_from_kernel( 465: ipc_object_t object, 466: mach_msg_type_name_t msgt_name) 467: { 468: assert(IO_VALID(object)); 469: 470: switch (msgt_name) { 471: case MACH_MSG_TYPE_MOVE_RECEIVE: { 472: ipc_port_t port = (ipc_port_t) object; 473: 474: ip_lock(port); 475: assert(ip_active(port)); 476: assert(port->ip_receiver_name != MACH_PORT_NULL); 477: assert(port->ip_receiver == ipc_space_kernel); 478: 479: /* relevant part of ipc_port_clear_receiver */ 480: ipc_port_set_mscount(port, 0); 481: 482: port->ip_receiver_name = MACH_PORT_NULL; 483: port->ip_destination = IP_NULL; 484: ip_unlock(port); 485: break; 486: } 487: 488: case MACH_MSG_TYPE_COPY_SEND: { 489: ipc_port_t port = (ipc_port_t) object; 490: 491: ip_lock(port); 492: if (ip_active(port)) { 493: assert(port->ip_srights > 0); 494: port->ip_srights++; 495: } 496: ip_reference(port); 497: ip_unlock(port); 498: break; 499: } 500: 501: case MACH_MSG_TYPE_MAKE_SEND: { 502: ipc_port_t port = (ipc_port_t) object; 503: 504: ip_lock(port); 505: assert(ip_active(port)); 506: assert(port->ip_receiver_name != MACH_PORT_NULL); 507: assert(port->ip_receiver == ipc_space_kernel); 508: 509: ip_reference(port); 510: port->ip_mscount++; 511: port->ip_srights++; 512: ip_unlock(port); 513: break; 514: } 515: 516: case MACH_MSG_TYPE_MOVE_SEND: 517: /* move naked send right into the message */ 518: break; 519: 520: case MACH_MSG_TYPE_MAKE_SEND_ONCE: { 521: ipc_port_t port = (ipc_port_t) object; 522: 523: ip_lock(port); 524: assert(ip_active(port)); 525: assert(port->ip_receiver_name != MACH_PORT_NULL); 526: assert(port->ip_receiver == ipc_space_kernel); 527: 528: ip_reference(port); 529: port->ip_sorights++; 530: ip_unlock(port); 531: break; 532: } 533: 534: case MACH_MSG_TYPE_MOVE_SEND_ONCE: 535: /* move naked send-once right into the message */ 536: break; 537: 538: default: 539: #if MACH_ASSERT 540: assert(!"ipc_object_copyin_from_kernel: strange rights"); 541: #else 542: panic("ipc_object_copyin_from_kernel: strange rights"); 543: #endif 544: } 545: } 546: 547: /* 548: * Routine: ipc_object_destroy 549: * Purpose: 550: * Destroys a naked capability. 551: * Consumes a ref for the object. 552: * 553: * A receive right should be in limbo or in transit. 554: * Conditions: 555: * Nothing locked. 556: */ 557: 558: void 559: ipc_object_destroy( 560: ipc_object_t object, 561: mach_msg_type_name_t msgt_name) 562: { 563: assert(IO_VALID(object)); 564: assert(io_otype(object) == IOT_PORT); 565: 566: switch (msgt_name) { 567: case MACH_MSG_TYPE_PORT_SEND: 568: ipc_port_release_send((ipc_port_t) object); 569: break; 570: 571: case MACH_MSG_TYPE_PORT_SEND_ONCE: 572: ipc_notify_send_once((ipc_port_t) object); 573: break; 574: 575: case MACH_MSG_TYPE_PORT_RECEIVE: 576: ipc_port_release_receive((ipc_port_t) object); 577: break; 578: 579: default: 580: panic("ipc_object_destroy: strange rights"); 581: } 582: } 583: 584: /* 585: * Routine: ipc_object_copyout 586: * Purpose: 587: * Copyout a capability, placing it into a space. 588: * If successful, consumes a ref for the object. 589: * Conditions: 590: * Nothing locked. 591: * Returns: 592: * KERN_SUCCESS Copied out object, consumed ref. 593: * KERN_INVALID_TASK The space is dead. 594: * KERN_INVALID_CAPABILITY The object is dead. 595: * KERN_NO_SPACE No room in space for another right. 596: * KERN_RESOURCE_SHORTAGE No memory available. 597: * KERN_UREFS_OVERFLOW Urefs limit exceeded 598: * and overflow wasn't specified. 599: */ 600: 601: kern_return_t 602: ipc_object_copyout( 603: ipc_space_t space, 604: ipc_object_t object, 605: mach_msg_type_name_t msgt_name, 606: boolean_t overflow, 607: mach_port_t *namep) 608: { 609: mach_port_t name; 610: ipc_entry_t entry; 611: kern_return_t kr; 612: 613: assert(IO_VALID(object)); 614: assert(io_otype(object) == IOT_PORT); 615: 616: is_write_lock(space); 617: 618: for (;;) { 619: if (!space->is_active) { 620: is_write_unlock(space); 621: return KERN_INVALID_TASK; 622: } 623: 624: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 625: ipc_right_reverse(space, object, &name, &entry)) { 626: /* object is locked and active */ 627: 628: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 629: break; 630: } 631: 632: kr = ipc_entry_get(space, &name, &entry); 633: if (kr != KERN_SUCCESS) { 634: /* unlocks/locks space, so must start again */ 635: 636: kr = ipc_entry_grow_table(space); 637: if (kr != KERN_SUCCESS) 638: return kr; /* space is unlocked */ 639: 640: continue; 641: } 642: 643: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 644: assert(entry->ie_object == IO_NULL); 645: 646: io_lock(object); 647: if (!io_active(object)) { 648: io_unlock(object); 649: ipc_entry_dealloc(space, name, entry); 650: is_write_unlock(space); 651: return KERN_INVALID_CAPABILITY; 652: } 653: 654: entry->ie_object = object; 655: break; 656: } 657: 658: /* space is write-locked and active, object is locked and active */ 659: 660: kr = ipc_right_copyout(space, name, entry, 661: msgt_name, overflow, object); 662: /* object is unlocked */ 663: is_write_unlock(space); 664: 665: if (kr == KERN_SUCCESS) 666: *namep = name; 667: return kr; 668: } 669: 670: #if 0 671: /* XXX same, but don't check for already-existing send rights */ 672: kern_return_t 673: ipc_object_copyout_multiname(space, object, namep) 674: ipc_space_t space; 675: ipc_object_t object; 676: mach_port_t *namep; 677: { 678: mach_port_t name; 679: ipc_entry_t entry; 680: kern_return_t kr; 681: 682: assert(IO_VALID(object)); 683: assert(io_otype(object) == IOT_PORT); 684: 685: is_write_lock(space); 686: 687: for (;;) { 688: if (!space->is_active) { 689: is_write_unlock(space); 690: return KERN_INVALID_TASK; 691: } 692: 693: kr = ipc_entry_get(space, &name, &entry); 694: if (kr != KERN_SUCCESS) { 695: /* unlocks/locks space, so must start again */ 696: 697: kr = ipc_entry_grow_table(space); 698: if (kr != KERN_SUCCESS) 699: return kr; /* space is unlocked */ 700: 701: continue; 702: } 703: 704: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 705: assert(entry->ie_object == IO_NULL); 706: 707: io_lock(object); 708: if (!io_active(object)) { 709: io_unlock(object); 710: ipc_entry_dealloc(space, name, entry); 711: is_write_unlock(space); 712: return KERN_INVALID_CAPABILITY; 713: } 714: 715: entry->ie_object = object; 716: break; 717: } 718: 719: /* space is write-locked and active, object is locked and active */ 720: 721: kr = ipc_right_copyout_multiname(space, name, entry, object); 722: /* object is unlocked */ 723: is_write_unlock(space); 724: 725: if (kr == KERN_SUCCESS) 726: *namep = name; 727: return kr; 728: } 1.1.1.2 ! root 729: #endif /* 0 */ 1.1 root 730: 731: /* 732: * Routine: ipc_object_copyout_name 733: * Purpose: 734: * Copyout a capability, placing it into a space. 735: * The specified name is used for the capability. 736: * If successful, consumes a ref for the object. 737: * Conditions: 738: * Nothing locked. 739: * Returns: 740: * KERN_SUCCESS Copied out object, consumed ref. 741: * KERN_INVALID_TASK The space is dead. 742: * KERN_INVALID_CAPABILITY The object is dead. 743: * KERN_RESOURCE_SHORTAGE No memory available. 744: * KERN_UREFS_OVERFLOW Urefs limit exceeded 745: * and overflow wasn't specified. 746: * KERN_RIGHT_EXISTS Space has rights under another name. 747: * KERN_NAME_EXISTS Name is already used. 748: */ 749: 750: kern_return_t 751: ipc_object_copyout_name( 752: ipc_space_t space, 753: ipc_object_t object, 754: mach_msg_type_name_t msgt_name, 755: boolean_t overflow, 756: mach_port_t name) 757: { 758: mach_port_t oname; 759: ipc_entry_t oentry; 760: ipc_entry_t entry; 761: kern_return_t kr; 762: 763: assert(IO_VALID(object)); 764: assert(io_otype(object) == IOT_PORT); 765: 766: kr = ipc_entry_alloc_name(space, name, &entry); 767: if (kr != KERN_SUCCESS) 768: return kr; 769: /* space is write-locked and active */ 770: 771: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 772: ipc_right_reverse(space, object, &oname, &oentry)) { 773: /* object is locked and active */ 774: 775: if (name != oname) { 776: io_unlock(object); 777: 778: if (IE_BITS_TYPE(entry->ie_bits) 779: == MACH_PORT_TYPE_NONE) 780: ipc_entry_dealloc(space, name, entry); 781: 782: is_write_unlock(space); 783: return KERN_RIGHT_EXISTS; 784: } 785: 786: assert(entry == oentry); 787: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 788: } else { 789: if (ipc_right_inuse(space, name, entry)) 790: return KERN_NAME_EXISTS; 791: 792: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 793: assert(entry->ie_object == IO_NULL); 794: 795: io_lock(object); 796: if (!io_active(object)) { 797: io_unlock(object); 798: ipc_entry_dealloc(space, name, entry); 799: is_write_unlock(space); 800: return KERN_INVALID_CAPABILITY; 801: } 802: 803: entry->ie_object = object; 804: } 805: 806: /* space is write-locked and active, object is locked and active */ 807: 808: kr = ipc_right_copyout(space, name, entry, 809: msgt_name, overflow, object); 810: /* object is unlocked */ 811: is_write_unlock(space); 812: return kr; 813: } 814: 815: /* 816: * Routine: ipc_object_copyout_dest 817: * Purpose: 818: * Translates/consumes the destination right of a message. 819: * This is unlike normal copyout because the right is consumed 820: * in a funny way instead of being given to the receiving space. 821: * The receiver gets his name for the port, if he has receive 822: * rights, otherwise MACH_PORT_NULL. 823: * Conditions: 824: * The object is locked and active. Nothing else locked. 825: * The object is unlocked and loses a reference. 826: */ 827: 828: void 829: ipc_object_copyout_dest( 830: ipc_space_t space, 831: ipc_object_t object, 832: mach_msg_type_name_t msgt_name, 833: mach_port_t *namep) 834: { 835: mach_port_t name; 836: 837: assert(IO_VALID(object)); 838: assert(io_active(object)); 839: 840: io_release(object); 841: 842: /* 843: * If the space is the receiver/owner of the object, 844: * then we quietly consume the right and return 845: * the space's name for the object. Otherwise 846: * we destroy the right and return MACH_PORT_NULL. 847: */ 848: 849: switch (msgt_name) { 850: case MACH_MSG_TYPE_PORT_SEND: { 851: ipc_port_t port = (ipc_port_t) object; 852: ipc_port_t nsrequest = IP_NULL; 853: mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */ 854: 855: assert(port->ip_srights > 0); 856: if (--port->ip_srights == 0) { 857: nsrequest = port->ip_nsrequest; 858: if (nsrequest != IP_NULL) { 859: port->ip_nsrequest = IP_NULL; 860: mscount = port->ip_mscount; 861: } 862: } 863: 864: if (port->ip_receiver == space) 865: name = port->ip_receiver_name; 866: else 867: name = MACH_PORT_NULL; 868: 869: ip_unlock(port); 870: 871: if (nsrequest != IP_NULL) 872: ipc_notify_no_senders(nsrequest, mscount); 873: 874: break; 875: } 876: 877: case MACH_MSG_TYPE_PORT_SEND_ONCE: { 878: ipc_port_t port = (ipc_port_t) object; 879: 880: assert(port->ip_sorights > 0); 881: 882: if (port->ip_receiver == space) { 883: /* quietly consume the send-once right */ 884: 885: port->ip_sorights--; 886: name = port->ip_receiver_name; 887: ip_unlock(port); 888: } else { 889: /* 890: * A very bizarre case. The message 891: * was received, but before this copyout 892: * happened the space lost receive rights. 893: * We can't quietly consume the soright 894: * out from underneath some other task, 895: * so generate a send-once notification. 896: */ 897: 898: ip_reference(port); /* restore ref */ 899: ip_unlock(port); 900: 901: ipc_notify_send_once(port); 902: name = MACH_PORT_NULL; 903: } 904: 905: break; 906: } 907: 908: default: 909: #if MACH_ASSERT 910: assert(!"ipc_object_copyout_dest: strange rights"); 911: #else 912: panic("ipc_object_copyout_dest: strange rights"); 913: #endif 914: 915: } 916: 917: *namep = name; 918: } 919: 920: /* 921: * Routine: ipc_object_rename 922: * Purpose: 923: * Rename an entry in a space. 924: * Conditions: 925: * Nothing locked. 926: * Returns: 927: * KERN_SUCCESS Renamed the entry. 928: * KERN_INVALID_TASK The space was dead. 929: * KERN_INVALID_NAME oname didn't denote an entry. 930: * KERN_NAME_EXISTS nname already denoted an entry. 931: * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry. 932: */ 933: 934: kern_return_t 935: ipc_object_rename( 936: ipc_space_t space, 937: mach_port_t oname, 938: mach_port_t nname) 939: { 940: ipc_entry_t oentry, nentry; 941: kern_return_t kr; 942: 943: kr = ipc_entry_alloc_name(space, nname, &nentry); 944: if (kr != KERN_SUCCESS) 945: return kr; 946: /* space is write-locked and active */ 947: 948: if (ipc_right_inuse(space, nname, nentry)) { 949: /* space is unlocked */ 950: return KERN_NAME_EXISTS; 951: } 952: 953: /* don't let ipc_entry_lookup see the uninitialized new entry */ 954: 955: if ((oname == nname) || 956: ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) { 957: ipc_entry_dealloc(space, nname, nentry); 958: is_write_unlock(space); 959: return KERN_INVALID_NAME; 960: } 961: 962: kr = ipc_right_rename(space, oname, oentry, nname, nentry); 963: /* space is unlocked */ 964: return kr; 965: } 966: 967: #if MACH_IPC_COMPAT 968: 969: /* 970: * Routine: ipc_object_copyout_type_compat 971: * Purpose: 972: * Convert a carried type name to an old type name. 973: */ 974: 975: mach_msg_type_name_t 976: ipc_object_copyout_type_compat(msgt_name) 977: mach_msg_type_name_t msgt_name; 978: { 979: switch (msgt_name) { 980: case MACH_MSG_TYPE_PORT_SEND: 981: case MACH_MSG_TYPE_PORT_SEND_ONCE: 982: return MSG_TYPE_PORT; 983: 984: case MACH_MSG_TYPE_PORT_RECEIVE: 985: return MSG_TYPE_PORT_ALL; 986: 987: default: 988: #if MACH_ASSERT 989: assert(!"ipc_object_copyout_type_compat: strange rights"); 990: #else 991: panic("ipc_object_copyout_type_compat: strange rights"); 992: #endif 993: } 994: } 995: 996: /* 997: * Routine: ipc_object_copyin_compat 998: * Purpose: 999: * Copyin a capability from a space. 1000: * If successful, the caller gets a ref 1001: * for the resulting object, which is always valid. 1002: * Conditions: 1003: * Nothing locked. 1004: * Returns: 1005: * KERN_SUCCESS Acquired a valid object. 1006: * KERN_INVALID_TASK The space is dead. 1007: * KERN_INVALID_NAME Name doesn't exist in space. 1008: * KERN_INVALID_RIGHT Name doesn't denote correct right. 1009: */ 1010: 1011: kern_return_t 1012: ipc_object_copyin_compat(space, name, msgt_name, dealloc, objectp) 1013: ipc_space_t space; 1014: mach_port_t name; 1015: mach_msg_type_name_t msgt_name; 1016: boolean_t dealloc; 1017: ipc_object_t *objectp; 1018: { 1019: ipc_entry_t entry; 1020: kern_return_t kr; 1021: 1022: kr = ipc_right_lookup_write(space, name, &entry); 1023: if (kr != KERN_SUCCESS) 1024: return kr; 1025: /* space is write-locked and active */ 1026: 1027: kr = ipc_right_copyin_compat(space, name, entry, 1028: msgt_name, dealloc, objectp); 1029: /* space is unlocked */ 1030: return kr; 1031: } 1032: 1033: /* 1034: * Routine: ipc_object_copyin_header 1035: * Purpose: 1036: * Copyin a capability from a space. 1037: * If successful, the caller gets a ref 1038: * for the resulting object, which is always valid. 1039: * The type of the acquired capability is returned. 1040: * Conditions: 1041: * Nothing locked. 1042: * Returns: 1043: * KERN_SUCCESS Acquired a valid object. 1044: * KERN_INVALID_TASK The space is dead. 1045: * KERN_INVALID_NAME Name doesn't exist in space. 1046: * KERN_INVALID_RIGHT Name doesn't denote correct right. 1047: */ 1048: 1049: kern_return_t 1050: ipc_object_copyin_header(space, name, objectp, msgt_namep) 1051: ipc_space_t space; 1052: mach_port_t name; 1053: ipc_object_t *objectp; 1054: mach_msg_type_name_t *msgt_namep; 1055: { 1056: ipc_entry_t entry; 1057: kern_return_t kr; 1058: 1059: kr = ipc_right_lookup_write(space, name, &entry); 1060: if (kr != KERN_SUCCESS) 1061: return kr; 1062: /* space is write-locked and active */ 1063: 1064: kr = ipc_right_copyin_header(space, name, entry, 1065: objectp, msgt_namep); 1066: /* space is unlocked */ 1067: return kr; 1068: } 1069: 1070: /* 1071: * Routine: ipc_object_copyout_compat 1072: * Purpose: 1073: * Copyout a capability, placing it into a space. 1074: * If successful, consumes a ref for the object. 1075: * 1076: * Marks new entries with IE_BITS_COMPAT. 1077: * Conditions: 1078: * Nothing locked. 1079: * Returns: 1080: * KERN_SUCCESS Copied out object, consumed ref. 1081: * KERN_INVALID_TASK The space is dead. 1082: * KERN_INVALID_CAPABILITY The object is dead. 1083: * KERN_NO_SPACE No room in space for another right. 1084: * KERN_RESOURCE_SHORTAGE No memory available. 1085: */ 1086: 1087: kern_return_t 1088: ipc_object_copyout_compat(space, object, msgt_name, namep) 1089: ipc_space_t space; 1090: ipc_object_t object; 1091: mach_msg_type_name_t msgt_name; 1092: mach_port_t *namep; 1093: { 1094: mach_port_t name; 1095: ipc_entry_t entry; 1096: ipc_port_t port; 1097: kern_return_t kr; 1098: 1099: assert(IO_VALID(object)); 1100: assert(io_otype(object) == IOT_PORT); 1101: port = (ipc_port_t) object; 1102: 1103: is_write_lock(space); 1104: 1105: for (;;) { 1106: ipc_port_request_index_t request; 1107: 1108: if (!space->is_active) { 1109: is_write_unlock(space); 1110: return KERN_INVALID_TASK; 1111: } 1112: 1113: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 1114: ipc_right_reverse(space, (ipc_object_t) port, 1115: &name, &entry)) { 1116: /* port is locked and active */ 1117: 1118: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 1119: break; 1120: } 1121: 1122: kr = ipc_entry_get(space, &name, &entry); 1123: if (kr != KERN_SUCCESS) { 1124: /* unlocks/locks space, so must start again */ 1125: 1126: kr = ipc_entry_grow_table(space); 1127: if (kr != KERN_SUCCESS) 1128: return kr; /* space is unlocked */ 1129: 1130: continue; 1131: } 1132: 1133: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 1134: assert(entry->ie_object == IO_NULL); 1135: 1136: ip_lock(port); 1137: if (!ip_active(port)) { 1138: ip_unlock(port); 1139: ipc_entry_dealloc(space, name, entry); 1140: is_write_unlock(space); 1141: return KERN_INVALID_CAPABILITY; 1142: } 1143: 1144: kr = ipc_port_dnrequest(port, name, ipr_spacem(space), 1145: &request); 1146: if (kr != KERN_SUCCESS) { 1147: ipc_entry_dealloc(space, name, entry); 1148: is_write_unlock(space); 1149: 1150: kr = ipc_port_dngrow(port); 1151: /* port is unlocked */ 1152: if (kr != KERN_SUCCESS) 1153: return kr; 1154: 1155: is_write_lock(space); 1156: continue; 1157: } 1158: 1159: is_reference(space); /* for dnrequest */ 1160: entry->ie_object = (ipc_object_t) port; 1161: entry->ie_request = request; 1162: entry->ie_bits |= IE_BITS_COMPAT; 1163: break; 1164: } 1165: 1166: /* space is write-locked and active, port is locked and active */ 1167: 1168: kr = ipc_right_copyout(space, name, entry, 1169: msgt_name, TRUE, (ipc_object_t) port); 1170: /* object is unlocked */ 1171: is_write_unlock(space); 1172: 1173: if (kr == KERN_SUCCESS) 1174: *namep = name; 1175: return kr; 1176: } 1177: 1178: /* 1179: * Routine: ipc_object_copyout_name_compat 1180: * Purpose: 1181: * Copyout a capability, placing it into a space. 1182: * The specified name is used for the capability. 1183: * If successful, consumes a ref for the object. 1184: * 1185: * Like ipc_object_copyout_name, except that 1186: * the name can't be in use at all, even for the same 1187: * port, and IE_BITS_COMPAT gets turned on. 1188: * Conditions: 1189: * Nothing locked. 1190: * Returns: 1191: * KERN_SUCCESS Copied out object, consumed ref. 1192: * KERN_INVALID_TASK The space is dead. 1193: * KERN_INVALID_CAPABILITY The object is dead. 1194: * KERN_RESOURCE_SHORTAGE No memory available. 1195: * KERN_RIGHT_EXISTS Space has rights under another name. 1196: * KERN_NAME_EXISTS Name is already used. 1197: */ 1198: 1199: kern_return_t 1200: ipc_object_copyout_name_compat(space, object, msgt_name, name) 1201: ipc_space_t space; 1202: ipc_object_t object; 1203: mach_msg_type_name_t msgt_name; 1204: mach_port_t name; 1205: { 1206: ipc_entry_t entry; 1207: ipc_port_t port; 1208: kern_return_t kr; 1209: 1210: assert(IO_VALID(object)); 1211: assert(io_otype(object) == IOT_PORT); 1212: port = (ipc_port_t) object; 1213: 1214: for (;;) { 1215: mach_port_t oname; 1216: ipc_entry_t oentry; 1217: ipc_port_request_index_t request; 1218: 1219: kr = ipc_entry_alloc_name(space, name, &entry); 1220: if (kr != KERN_SUCCESS) 1221: return kr; 1222: /* space is write-locked and active */ 1223: 1224: if (ipc_right_inuse(space, name, entry)) 1225: return KERN_NAME_EXISTS; /* space is unlocked */ 1226: 1227: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 1228: assert(entry->ie_object == IO_NULL); 1229: 1230: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 1231: ipc_right_reverse(space, (ipc_object_t) port, 1232: &oname, &oentry)) { 1233: /* port is locked and active */ 1234: 1235: ip_unlock(port); 1236: ipc_entry_dealloc(space, name, entry); 1237: is_write_unlock(space); 1238: return KERN_RIGHT_EXISTS; 1239: } 1240: 1241: ip_lock(port); 1242: if (!ip_active(port)) { 1243: ip_unlock(port); 1244: ipc_entry_dealloc(space, name, entry); 1245: is_write_unlock(space); 1246: return KERN_INVALID_CAPABILITY; 1247: } 1248: 1249: kr = ipc_port_dnrequest(port, name, ipr_spacem(space), 1250: &request); 1251: if (kr != KERN_SUCCESS) { 1252: ipc_entry_dealloc(space, name, entry); 1253: is_write_unlock(space); 1254: 1255: kr = ipc_port_dngrow(port); 1256: /* port is unlocked */ 1257: if (kr != KERN_SUCCESS) 1258: return kr; 1259: 1260: continue; 1261: } 1262: 1263: is_reference(space); /* for dnrequest */ 1264: entry->ie_object = (ipc_object_t) port; 1265: entry->ie_request = request; 1266: entry->ie_bits |= IE_BITS_COMPAT; 1267: break; 1268: } 1269: 1270: /* space is write-locked and active, port is locked and active */ 1271: 1272: kr = ipc_right_copyout(space, name, entry, 1273: msgt_name, TRUE, (ipc_object_t) port); 1274: /* object is unlocked */ 1275: is_write_unlock(space); 1276: 1277: assert(kr == KERN_SUCCESS); 1278: return kr; 1279: } 1280: 1.1.1.2 ! root 1281: #endif /* MACH_IPC_COMPAT */ 1.1 root 1282: 1283: #include <mach_kdb.h> 1284: 1285: 1286: #if MACH_KDB 1287: #define printf kdbprintf 1288: 1289: /* 1290: * Routine: ipc_object_print 1291: * Purpose: 1292: * Pretty-print an object for kdb. 1293: */ 1294: 1295: char *ikot_print_array[IKOT_MAX_TYPE] = { 1296: "(NONE) ", 1297: "(THREAD) ", 1298: "(TASK) ", 1299: "(HOST) ", 1300: "(HOST_PRIV) ", 1301: "(PROCESSOR) ", 1302: "(PSET) ", 1303: "(PSET_NAME) ", 1304: "(PAGER) ", 1305: "(PAGER_REQUEST) ", 1306: "(DEVICE) ", /* 10 */ 1307: "(XMM_OBJECT) ", 1308: "(XMM_PAGER) ", 1309: "(XMM_KERNEL) ", 1310: "(XMM_REPLY) ", 1311: "(PAGER_TERMINATING)", 1312: "(PAGING_NAME) ", 1313: "(HOST_SECURITY) ", 1314: "(LEDGER) ", 1315: "(MASTER_DEVICE) ", 1316: "(ACTIVATION) ", /* 20 */ 1317: "(SUBSYSTEM) ", 1318: "(IO_DONE_QUEUE) ", 1319: "(SEMAPHORE) ", 1320: "(LOCK_SET) ", 1321: "(CLOCK) ", 1322: "(CLOCK_CTRL) ", /* 26 */ 1323: /* << new entries here */ 1324: "(UNKNOWN) " /* magic catchall */ 1325: }; /* Please keep in sync with kern/ipc_kobject.h */ 1326: 1327: void 1328: ipc_object_print( 1329: ipc_object_t object) 1330: { 1331: int kotype; 1332: 1333: iprintf("%s", io_active(object) ? "active" : "dead"); 1334: printf(", refs=%d", object->io_references); 1335: printf(", otype=%d", io_otype(object)); 1336: kotype = io_kotype(object); 1337: if (kotype >= 0 && kotype < IKOT_MAX_TYPE) 1338: printf(", kotype=%d %s\n", io_kotype(object), 1339: ikot_print_array[kotype]); 1340: else 1341: printf(", kotype=0x%x %s\n", io_kotype(object), 1342: ikot_print_array[IKOT_UNKNOWN]); 1343: } 1344: 1345: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.