|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: ipc/ipc_object.c ! 54: * Author: Rich Draves ! 55: * Date: 1989 ! 56: * ! 57: * Functions to manipulate IPC objects. ! 58: */ ! 59: ! 60: #include <dipc.h> ! 61: #include <mach_rt.h> ! 62: ! 63: #include <mach/boolean.h> ! 64: #include <mach/kern_return.h> ! 65: #include <mach/port.h> ! 66: #include <mach/message.h> ! 67: #include <kern/misc_protos.h> ! 68: #include <ipc/port.h> ! 69: #include <ipc/ipc_space.h> ! 70: #include <ipc/ipc_entry.h> ! 71: #include <ipc/ipc_object.h> ! 72: #include <ipc/ipc_hash.h> ! 73: #include <ipc/ipc_right.h> ! 74: #include <ipc/ipc_notify.h> ! 75: #include <ipc/ipc_pset.h> ! 76: ! 77: zone_t ipc_object_zones[IOT_NUMBER]; ! 78: ! 79: /* ! 80: * Routine: ipc_object_reference ! 81: * Purpose: ! 82: * Take a reference to an object. ! 83: */ ! 84: ! 85: void ! 86: ipc_object_reference( ! 87: ipc_object_t object) ! 88: { ! 89: io_lock(object); ! 90: assert(object->io_references > 0); ! 91: io_reference(object); ! 92: io_unlock(object); ! 93: } ! 94: ! 95: /* ! 96: * Routine: ipc_object_release ! 97: * Purpose: ! 98: * Release a reference to an object. ! 99: */ ! 100: ! 101: void ! 102: ipc_object_release( ! 103: ipc_object_t object) ! 104: { ! 105: io_lock(object); ! 106: assert(object->io_references > 0); ! 107: io_release(object); ! 108: io_check_unlock(object); ! 109: } ! 110: ! 111: /* ! 112: * Routine: ipc_object_translate ! 113: * Purpose: ! 114: * Look up an object in a space. ! 115: * Conditions: ! 116: * Nothing locked before. If successful, the object ! 117: * is returned locked. The caller doesn't get a ref. ! 118: * Returns: ! 119: * KERN_SUCCESS Objected returned locked. ! 120: * KERN_INVALID_TASK The space is dead. ! 121: * KERN_INVALID_NAME The name doesn't denote a right. ! 122: * KERN_INVALID_RIGHT Name doesn't denote the correct right. ! 123: */ ! 124: ! 125: kern_return_t ! 126: ipc_object_translate( ! 127: ipc_space_t space, ! 128: mach_port_name_t name, ! 129: mach_port_right_t right, ! 130: ipc_object_t *objectp) ! 131: { ! 132: ipc_entry_t entry; ! 133: ipc_object_t object; ! 134: kern_return_t kr; ! 135: ! 136: kr = ipc_right_lookup_read(space, name, &entry); ! 137: if (kr != KERN_SUCCESS) ! 138: return kr; ! 139: /* space is read-locked and active */ ! 140: ! 141: if ((entry->ie_bits & MACH_PORT_TYPE(right)) == MACH_PORT_TYPE_NONE) { ! 142: is_read_unlock(space); ! 143: return KERN_INVALID_RIGHT; ! 144: } ! 145: ! 146: object = entry->ie_object; ! 147: assert(object != IO_NULL); ! 148: ! 149: io_lock(object); ! 150: is_read_unlock(space); ! 151: ! 152: *objectp = object; ! 153: return KERN_SUCCESS; ! 154: } ! 155: ! 156: /* ! 157: * Routine: ipc_object_alloc_dead ! 158: * Purpose: ! 159: * Allocate a dead-name entry. ! 160: * Conditions: ! 161: * Nothing locked. ! 162: * Returns: ! 163: * KERN_SUCCESS The dead name is allocated. ! 164: * KERN_INVALID_TASK The space is dead. ! 165: * KERN_NO_SPACE No room for an entry in the space. ! 166: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 167: */ ! 168: ! 169: kern_return_t ! 170: ipc_object_alloc_dead( ! 171: ipc_space_t space, ! 172: mach_port_name_t *namep) ! 173: { ! 174: ipc_entry_t entry; ! 175: kern_return_t kr; ! 176: ! 177: int i; ! 178: ! 179: ! 180: kr = ipc_entry_alloc(space, namep, &entry); ! 181: if (kr != KERN_SUCCESS) ! 182: return kr; ! 183: /* space is write-locked */ ! 184: ! 185: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ ! 186: ! 187: assert(entry->ie_object == IO_NULL); ! 188: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; ! 189: ! 190: is_write_unlock(space); ! 191: return KERN_SUCCESS; ! 192: } ! 193: ! 194: /* ! 195: * Routine: ipc_object_alloc_dead_name ! 196: * Purpose: ! 197: * Allocate a dead-name entry, with a specific name. ! 198: * Conditions: ! 199: * Nothing locked. ! 200: * Returns: ! 201: * KERN_SUCCESS The dead name is allocated. ! 202: * KERN_INVALID_TASK The space is dead. ! 203: * KERN_NAME_EXISTS The name already denotes a right. ! 204: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 205: */ ! 206: ! 207: kern_return_t ! 208: ipc_object_alloc_dead_name( ! 209: ipc_space_t space, ! 210: mach_port_name_t name) ! 211: { ! 212: ipc_entry_t entry; ! 213: kern_return_t kr; ! 214: ! 215: int i; ! 216: ! 217: ! 218: kr = ipc_entry_alloc_name(space, name, &entry); ! 219: if (kr != KERN_SUCCESS) ! 220: return kr; ! 221: /* space is write-locked */ ! 222: ! 223: if (ipc_right_inuse(space, name, entry)) ! 224: return KERN_NAME_EXISTS; ! 225: ! 226: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ ! 227: ! 228: assert(entry->ie_object == IO_NULL); ! 229: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; ! 230: ! 231: is_write_unlock(space); ! 232: return KERN_SUCCESS; ! 233: } ! 234: ! 235: /* ! 236: * Routine: ipc_object_alloc ! 237: * Purpose: ! 238: * Allocate an object. ! 239: * Conditions: ! 240: * Nothing locked. If successful, the object is returned locked. ! 241: * The caller doesn't get a reference for the object. ! 242: * Returns: ! 243: * KERN_SUCCESS The object is allocated. ! 244: * KERN_INVALID_TASK The space is dead. ! 245: * KERN_NO_SPACE No room for an entry in the space. ! 246: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 247: */ ! 248: ! 249: kern_return_t ! 250: ipc_object_alloc( ! 251: ipc_space_t space, ! 252: ipc_object_type_t otype, ! 253: mach_port_type_t type, ! 254: mach_port_urefs_t urefs, ! 255: mach_port_name_t *namep, ! 256: ipc_object_t *objectp) ! 257: { ! 258: ipc_object_t object; ! 259: ipc_entry_t entry; ! 260: kern_return_t kr; ! 261: ! 262: assert(otype < IOT_NUMBER); ! 263: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); ! 264: assert(type != MACH_PORT_TYPE_NONE); ! 265: assert(urefs <= MACH_PORT_UREFS_MAX); ! 266: ! 267: object = io_alloc(otype); ! 268: if (object == IO_NULL) ! 269: return KERN_RESOURCE_SHORTAGE; ! 270: ! 271: if (otype == IOT_PORT) { ! 272: ipc_port_t port = (ipc_port_t)object; ! 273: ! 274: bzero((char *)port, sizeof(*port)); ! 275: } else if (otype == IOT_PORT_SET) { ! 276: ipc_pset_t pset = (ipc_pset_t)object; ! 277: ! 278: bzero((char *)pset, sizeof(*pset)); ! 279: } ! 280: ! 281: io_lock_init(object); ! 282: *namep = (mach_port_name_t)object; ! 283: kr = ipc_entry_alloc(space, namep, &entry); ! 284: if (kr != KERN_SUCCESS) { ! 285: io_free(otype, object); ! 286: return kr; ! 287: } ! 288: /* space is write-locked */ ! 289: ! 290: entry->ie_bits |= type | urefs; ! 291: entry->ie_object = object; ! 292: ! 293: io_lock(object); ! 294: is_write_unlock(space); ! 295: ! 296: object->io_references = 1; /* for entry, not caller */ ! 297: object->io_bits = io_makebits(TRUE, otype, 0); ! 298: ! 299: *objectp = object; ! 300: return KERN_SUCCESS; ! 301: } ! 302: ! 303: /* ! 304: * Routine: ipc_object_alloc_name ! 305: * Purpose: ! 306: * Allocate an object, with a specific name. ! 307: * Conditions: ! 308: * Nothing locked. If successful, the object is returned locked. ! 309: * The caller doesn't get a reference for the object. ! 310: * Returns: ! 311: * KERN_SUCCESS The object is allocated. ! 312: * KERN_INVALID_TASK The space is dead. ! 313: * KERN_NAME_EXISTS The name already denotes a right. ! 314: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 315: */ ! 316: ! 317: kern_return_t ! 318: ipc_object_alloc_name( ! 319: ipc_space_t space, ! 320: ipc_object_type_t otype, ! 321: mach_port_type_t type, ! 322: mach_port_urefs_t urefs, ! 323: mach_port_name_t name, ! 324: ipc_object_t *objectp) ! 325: { ! 326: ipc_object_t object; ! 327: ipc_entry_t entry; ! 328: kern_return_t kr; ! 329: ! 330: assert(otype < IOT_NUMBER); ! 331: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); ! 332: assert(type != MACH_PORT_TYPE_NONE); ! 333: assert(urefs <= MACH_PORT_UREFS_MAX); ! 334: ! 335: object = io_alloc(otype); ! 336: if (object == IO_NULL) ! 337: return KERN_RESOURCE_SHORTAGE; ! 338: ! 339: if (otype == IOT_PORT) { ! 340: ipc_port_t port = (ipc_port_t)object; ! 341: ! 342: bzero((char *)port, sizeof(*port)); ! 343: } else if (otype == IOT_PORT_SET) { ! 344: ipc_pset_t pset = (ipc_pset_t)object; ! 345: ! 346: bzero((char *)pset, sizeof(*pset)); ! 347: } ! 348: ! 349: io_lock_init(object); ! 350: kr = ipc_entry_alloc_name(space, name, &entry); ! 351: if (kr != KERN_SUCCESS) { ! 352: io_free(otype, object); ! 353: return kr; ! 354: } ! 355: /* space is write-locked */ ! 356: ! 357: if (ipc_right_inuse(space, name, entry)) { ! 358: io_free(otype, object); ! 359: return KERN_NAME_EXISTS; ! 360: } ! 361: ! 362: entry->ie_bits |= type | urefs; ! 363: entry->ie_object = object; ! 364: ! 365: io_lock(object); ! 366: is_write_unlock(space); ! 367: ! 368: object->io_references = 1; /* for entry, not caller */ ! 369: object->io_bits = io_makebits(TRUE, otype, 0); ! 370: ! 371: *objectp = object; ! 372: return KERN_SUCCESS; ! 373: } ! 374: ! 375: /* ! 376: * Routine: ipc_object_copyin_type ! 377: * Purpose: ! 378: * Convert a send type name to a received type name. ! 379: */ ! 380: ! 381: mach_msg_type_name_t ! 382: ipc_object_copyin_type( ! 383: mach_msg_type_name_t msgt_name) ! 384: { ! 385: switch (msgt_name) { ! 386: case 0: ! 387: return 0; ! 388: ! 389: case MACH_MSG_TYPE_MOVE_RECEIVE: ! 390: case MACH_MSG_TYPE_COPY_RECEIVE: ! 391: return MACH_MSG_TYPE_PORT_RECEIVE; ! 392: ! 393: case MACH_MSG_TYPE_MOVE_SEND_ONCE: ! 394: case MACH_MSG_TYPE_MAKE_SEND_ONCE: ! 395: return MACH_MSG_TYPE_PORT_SEND_ONCE; ! 396: ! 397: case MACH_MSG_TYPE_MOVE_SEND: ! 398: case MACH_MSG_TYPE_MAKE_SEND: ! 399: case MACH_MSG_TYPE_COPY_SEND: ! 400: return MACH_MSG_TYPE_PORT_SEND; ! 401: ! 402: default: ! 403: panic("ipc_object_copyin_type: strange rights"); ! 404: return (mach_msg_type_name_t) 0; /* Shut up the compiler */ ! 405: } ! 406: } ! 407: ! 408: /* ! 409: * Routine: ipc_object_copyin ! 410: * Purpose: ! 411: * Copyin a capability from a space. ! 412: * If successful, the caller gets a ref ! 413: * for the resulting object, unless it is IO_DEAD. ! 414: * Conditions: ! 415: * Nothing locked. ! 416: * Returns: ! 417: * KERN_SUCCESS Acquired an object, possibly IO_DEAD. ! 418: * KERN_INVALID_TASK The space is dead. ! 419: * KERN_INVALID_NAME Name doesn't exist in space. ! 420: * KERN_INVALID_RIGHT Name doesn't denote correct right. ! 421: */ ! 422: ! 423: kern_return_t ! 424: ipc_object_copyin( ! 425: ipc_space_t space, ! 426: mach_port_name_t name, ! 427: mach_msg_type_name_t msgt_name, ! 428: ipc_object_t *objectp) ! 429: { ! 430: ipc_entry_t entry; ! 431: ipc_port_t soright; ! 432: kern_return_t kr; ! 433: ! 434: int i; ! 435: ! 436: /* ! 437: * Could first try a read lock when doing ! 438: * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND, ! 439: * and MACH_MSG_TYPE_MAKE_SEND_ONCE. ! 440: */ ! 441: ! 442: kr = ipc_right_lookup_write(space, name, &entry); ! 443: if (kr != KERN_SUCCESS) ! 444: return kr; ! 445: /* space is write-locked and active */ ! 446: ! 447: kr = ipc_right_copyin(space, name, entry, ! 448: msgt_name, TRUE, ! 449: objectp, &soright); ! 450: if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) ! 451: ipc_entry_dealloc(space, name, entry); ! 452: is_write_unlock(space); ! 453: ! 454: if ((kr == KERN_SUCCESS) && (soright != IP_NULL)) ! 455: ipc_notify_port_deleted(soright, name); ! 456: ! 457: return kr; ! 458: } ! 459: ! 460: /* ! 461: * Routine: ipc_object_copyin_from_kernel ! 462: * Purpose: ! 463: * Copyin a naked capability from the kernel. ! 464: * ! 465: * MACH_MSG_TYPE_MOVE_RECEIVE ! 466: * The receiver must be ipc_space_kernel. ! 467: * Consumes the naked receive right. ! 468: * MACH_MSG_TYPE_COPY_SEND ! 469: * A naked send right must be supplied. ! 470: * The port gains a reference, and a send right ! 471: * if the port is still active. ! 472: * MACH_MSG_TYPE_MAKE_SEND ! 473: * The receiver must be ipc_space_kernel. ! 474: * The port gains a reference and a send right. ! 475: * MACH_MSG_TYPE_MOVE_SEND ! 476: * Consumes a naked send right. ! 477: * MACH_MSG_TYPE_MAKE_SEND_ONCE ! 478: * The port gains a reference and a send-once right. ! 479: * Receiver also be the caller of device subsystem, ! 480: * so no assertion. ! 481: * MACH_MSG_TYPE_MOVE_SEND_ONCE ! 482: * Consumes a naked send-once right. ! 483: * Conditions: ! 484: * Nothing locked. ! 485: */ ! 486: ! 487: void ! 488: ipc_object_copyin_from_kernel( ! 489: ipc_object_t object, ! 490: mach_msg_type_name_t msgt_name) ! 491: { ! 492: assert(IO_VALID(object)); ! 493: ! 494: switch (msgt_name) { ! 495: case MACH_MSG_TYPE_MOVE_RECEIVE: { ! 496: ipc_port_t port = (ipc_port_t) object; ! 497: ! 498: ip_lock(port); ! 499: assert(ip_active(port)); ! 500: assert(port->ip_receiver_name != MACH_PORT_NULL); ! 501: assert(port->ip_receiver == ipc_space_kernel); ! 502: ! 503: /* relevant part of ipc_port_clear_receiver */ ! 504: ipc_port_set_mscount(port, 0); ! 505: ! 506: port->ip_receiver_name = MACH_PORT_NULL; ! 507: port->ip_destination = IP_NULL; ! 508: ip_unlock(port); ! 509: break; ! 510: } ! 511: ! 512: case MACH_MSG_TYPE_COPY_SEND: { ! 513: ipc_port_t port = (ipc_port_t) object; ! 514: ! 515: ip_lock(port); ! 516: if (ip_active(port)) { ! 517: assert(port->ip_srights > 0); ! 518: port->ip_srights++; ! 519: } ! 520: ip_reference(port); ! 521: ip_unlock(port); ! 522: break; ! 523: } ! 524: ! 525: case MACH_MSG_TYPE_MAKE_SEND: { ! 526: ipc_port_t port = (ipc_port_t) object; ! 527: ! 528: ip_lock(port); ! 529: assert(ip_active(port)); ! 530: assert(port->ip_receiver_name != MACH_PORT_NULL); ! 531: assert(port->ip_receiver == ipc_space_kernel); ! 532: ! 533: ip_reference(port); ! 534: port->ip_mscount++; ! 535: port->ip_srights++; ! 536: ip_unlock(port); ! 537: break; ! 538: } ! 539: ! 540: case MACH_MSG_TYPE_MOVE_SEND: ! 541: /* move naked send right into the message */ ! 542: break; ! 543: ! 544: case MACH_MSG_TYPE_MAKE_SEND_ONCE: { ! 545: ipc_port_t port = (ipc_port_t) object; ! 546: ! 547: ip_lock(port); ! 548: assert(ip_active(port)); ! 549: assert(port->ip_receiver_name != MACH_PORT_NULL); ! 550: ! 551: ip_reference(port); ! 552: port->ip_sorights++; ! 553: ip_unlock(port); ! 554: break; ! 555: } ! 556: ! 557: case MACH_MSG_TYPE_MOVE_SEND_ONCE: ! 558: /* move naked send-once right into the message */ ! 559: break; ! 560: ! 561: default: ! 562: panic("ipc_object_copyin_from_kernel: strange rights"); ! 563: } ! 564: } ! 565: ! 566: /* ! 567: * Routine: ipc_object_destroy ! 568: * Purpose: ! 569: * Destroys a naked capability. ! 570: * Consumes a ref for the object. ! 571: * ! 572: * A receive right should be in limbo or in transit. ! 573: * Conditions: ! 574: * Nothing locked. ! 575: */ ! 576: ! 577: void ! 578: ipc_object_destroy( ! 579: ipc_object_t object, ! 580: mach_msg_type_name_t msgt_name) ! 581: { ! 582: assert(IO_VALID(object)); ! 583: assert(io_otype(object) == IOT_PORT); ! 584: ! 585: switch (msgt_name) { ! 586: case MACH_MSG_TYPE_PORT_SEND: ! 587: ipc_port_release_send((ipc_port_t) object); ! 588: break; ! 589: ! 590: case MACH_MSG_TYPE_PORT_SEND_ONCE: ! 591: ipc_notify_send_once((ipc_port_t) object); ! 592: break; ! 593: ! 594: case MACH_MSG_TYPE_PORT_RECEIVE: ! 595: ipc_port_release_receive((ipc_port_t) object); ! 596: break; ! 597: ! 598: default: ! 599: panic("ipc_object_destroy: strange rights"); ! 600: } ! 601: } ! 602: ! 603: /* ! 604: * Routine: ipc_object_copyout ! 605: * Purpose: ! 606: * Copyout a capability, placing it into a space. ! 607: * If successful, consumes a ref for the object. ! 608: * Conditions: ! 609: * Nothing locked. ! 610: * Returns: ! 611: * KERN_SUCCESS Copied out object, consumed ref. ! 612: * KERN_INVALID_TASK The space is dead. ! 613: * KERN_INVALID_CAPABILITY The object is dead. ! 614: * KERN_NO_SPACE No room in space for another right. ! 615: * KERN_RESOURCE_SHORTAGE No memory available. ! 616: * KERN_UREFS_OVERFLOW Urefs limit exceeded ! 617: * and overflow wasn't specified. ! 618: */ ! 619: ! 620: kern_return_t ! 621: ipc_object_copyout( ! 622: ipc_space_t space, ! 623: ipc_object_t object, ! 624: mach_msg_type_name_t msgt_name, ! 625: boolean_t overflow, ! 626: mach_port_name_t *namep) ! 627: { ! 628: mach_port_name_t name; ! 629: ipc_entry_t entry; ! 630: kern_return_t kr; ! 631: ! 632: assert(IO_VALID(object)); ! 633: assert(io_otype(object) == IOT_PORT); ! 634: ! 635: is_write_lock(space); ! 636: ! 637: for (;;) { ! 638: if (!space->is_active) { ! 639: is_write_unlock(space); ! 640: return KERN_INVALID_TASK; ! 641: } ! 642: ! 643: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && ! 644: ipc_right_reverse(space, object, &name, &entry)) { ! 645: /* object is locked and active */ ! 646: ! 647: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); ! 648: break; ! 649: } ! 650: ! 651: name = (mach_port_name_t)object; ! 652: kr = ipc_entry_get(space, &name, &entry); ! 653: if (kr != KERN_SUCCESS) { ! 654: /* unlocks/locks space, so must start again */ ! 655: ! 656: kr = ipc_entry_grow_table(space, ITS_SIZE_NONE); ! 657: if (kr != KERN_SUCCESS) ! 658: return kr; /* space is unlocked */ ! 659: ! 660: continue; ! 661: } ! 662: ! 663: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); ! 664: assert(entry->ie_object == IO_NULL); ! 665: ! 666: io_lock(object); ! 667: if (!io_active(object)) { ! 668: io_unlock(object); ! 669: ipc_entry_dealloc(space, name, entry); ! 670: is_write_unlock(space); ! 671: return KERN_INVALID_CAPABILITY; ! 672: } ! 673: ! 674: entry->ie_object = object; ! 675: break; ! 676: } ! 677: ! 678: /* space is write-locked and active, object is locked and active */ ! 679: ! 680: kr = ipc_right_copyout(space, name, entry, ! 681: msgt_name, overflow, object); ! 682: /* object is unlocked */ ! 683: is_write_unlock(space); ! 684: ! 685: if (kr == KERN_SUCCESS) ! 686: *namep = name; ! 687: return kr; ! 688: } ! 689: ! 690: /* ! 691: * Routine: ipc_object_copyout_name ! 692: * Purpose: ! 693: * Copyout a capability, placing it into a space. ! 694: * The specified name is used for the capability. ! 695: * If successful, consumes a ref for the object. ! 696: * Conditions: ! 697: * Nothing locked. ! 698: * Returns: ! 699: * KERN_SUCCESS Copied out object, consumed ref. ! 700: * KERN_INVALID_TASK The space is dead. ! 701: * KERN_INVALID_CAPABILITY The object is dead. ! 702: * KERN_RESOURCE_SHORTAGE No memory available. ! 703: * KERN_UREFS_OVERFLOW Urefs limit exceeded ! 704: * and overflow wasn't specified. ! 705: * KERN_RIGHT_EXISTS Space has rights under another name. ! 706: * KERN_NAME_EXISTS Name is already used. ! 707: */ ! 708: ! 709: kern_return_t ! 710: ipc_object_copyout_name( ! 711: ipc_space_t space, ! 712: ipc_object_t object, ! 713: mach_msg_type_name_t msgt_name, ! 714: boolean_t overflow, ! 715: mach_port_name_t name) ! 716: { ! 717: mach_port_name_t oname; ! 718: ipc_entry_t oentry; ! 719: ipc_entry_t entry; ! 720: kern_return_t kr; ! 721: ! 722: int i; ! 723: ! 724: assert(IO_VALID(object)); ! 725: assert(io_otype(object) == IOT_PORT); ! 726: ! 727: kr = ipc_entry_alloc_name(space, name, &entry); ! 728: if (kr != KERN_SUCCESS) ! 729: return kr; ! 730: /* space is write-locked and active */ ! 731: ! 732: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && ! 733: ipc_right_reverse(space, object, &oname, &oentry)) { ! 734: /* object is locked and active */ ! 735: ! 736: if (name != oname) { ! 737: io_unlock(object); ! 738: ! 739: if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) ! 740: ipc_entry_dealloc(space, name, entry); ! 741: ! 742: is_write_unlock(space); ! 743: return KERN_RIGHT_EXISTS; ! 744: } ! 745: ! 746: assert(entry == oentry); ! 747: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); ! 748: } else { ! 749: if (ipc_right_inuse(space, name, entry)) ! 750: return KERN_NAME_EXISTS; ! 751: ! 752: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); ! 753: assert(entry->ie_object == IO_NULL); ! 754: ! 755: io_lock(object); ! 756: if (!io_active(object)) { ! 757: io_unlock(object); ! 758: ipc_entry_dealloc(space, name, entry); ! 759: is_write_unlock(space); ! 760: return KERN_INVALID_CAPABILITY; ! 761: } ! 762: ! 763: entry->ie_object = object; ! 764: } ! 765: ! 766: /* space is write-locked and active, object is locked and active */ ! 767: ! 768: kr = ipc_right_copyout(space, name, entry, ! 769: msgt_name, overflow, object); ! 770: /* object is unlocked */ ! 771: is_write_unlock(space); ! 772: return kr; ! 773: } ! 774: ! 775: /* ! 776: * Routine: ipc_object_copyout_dest ! 777: * Purpose: ! 778: * Translates/consumes the destination right of a message. ! 779: * This is unlike normal copyout because the right is consumed ! 780: * in a funny way instead of being given to the receiving space. ! 781: * The receiver gets his name for the port, if he has receive ! 782: * rights, otherwise MACH_PORT_NULL. ! 783: * Conditions: ! 784: * The object is locked and active. Nothing else locked. ! 785: * The object is unlocked and loses a reference. ! 786: */ ! 787: ! 788: void ! 789: ipc_object_copyout_dest( ! 790: ipc_space_t space, ! 791: ipc_object_t object, ! 792: mach_msg_type_name_t msgt_name, ! 793: mach_port_name_t *namep) ! 794: { ! 795: mach_port_name_t name; ! 796: ! 797: assert(IO_VALID(object)); ! 798: assert(io_active(object)); ! 799: ! 800: io_release(object); ! 801: ! 802: /* ! 803: * If the space is the receiver/owner of the object, ! 804: * then we quietly consume the right and return ! 805: * the space's name for the object. Otherwise ! 806: * we destroy the right and return MACH_PORT_NULL. ! 807: */ ! 808: ! 809: switch (msgt_name) { ! 810: case MACH_MSG_TYPE_PORT_SEND: { ! 811: ipc_port_t port = (ipc_port_t) object; ! 812: ipc_port_t nsrequest = IP_NULL; ! 813: mach_port_mscount_t mscount; ! 814: ! 815: if (port->ip_receiver == space) ! 816: name = port->ip_receiver_name; ! 817: else ! 818: name = MACH_PORT_NULL; ! 819: ! 820: assert(port->ip_srights > 0); ! 821: if (--port->ip_srights == 0 && ! 822: port->ip_nsrequest != IP_NULL) { ! 823: nsrequest = port->ip_nsrequest; ! 824: port->ip_nsrequest = IP_NULL; ! 825: mscount = port->ip_mscount; ! 826: ip_unlock(port); ! 827: ipc_notify_no_senders(nsrequest, mscount); ! 828: } else ! 829: ip_unlock(port); ! 830: break; ! 831: } ! 832: ! 833: case MACH_MSG_TYPE_PORT_SEND_ONCE: { ! 834: ipc_port_t port = (ipc_port_t) object; ! 835: ! 836: assert(port->ip_sorights > 0); ! 837: ! 838: if (port->ip_receiver == space) { ! 839: /* quietly consume the send-once right */ ! 840: ! 841: port->ip_sorights--; ! 842: name = port->ip_receiver_name; ! 843: ip_unlock(port); ! 844: } else { ! 845: /* ! 846: * A very bizarre case. The message ! 847: * was received, but before this copyout ! 848: * happened the space lost receive rights. ! 849: * We can't quietly consume the soright ! 850: * out from underneath some other task, ! 851: * so generate a send-once notification. ! 852: */ ! 853: ! 854: ip_reference(port); /* restore ref */ ! 855: ip_unlock(port); ! 856: ! 857: ipc_notify_send_once(port); ! 858: name = MACH_PORT_NULL; ! 859: } ! 860: ! 861: break; ! 862: } ! 863: ! 864: default: ! 865: panic("ipc_object_copyout_dest: strange rights"); ! 866: } ! 867: ! 868: *namep = name; ! 869: } ! 870: ! 871: /* ! 872: * Routine: ipc_object_rename ! 873: * Purpose: ! 874: * Rename an entry in a space. ! 875: * Conditions: ! 876: * Nothing locked. ! 877: * Returns: ! 878: * KERN_SUCCESS Renamed the entry. ! 879: * KERN_INVALID_TASK The space was dead. ! 880: * KERN_INVALID_NAME oname didn't denote an entry. ! 881: * KERN_NAME_EXISTS nname already denoted an entry. ! 882: * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry. ! 883: */ ! 884: ! 885: kern_return_t ! 886: ipc_object_rename( ! 887: ipc_space_t space, ! 888: mach_port_name_t oname, ! 889: mach_port_name_t nname) ! 890: { ! 891: ipc_entry_t oentry, nentry; ! 892: kern_return_t kr; ! 893: ! 894: int i; ! 895: ! 896: kr = ipc_entry_alloc_name(space, nname, &nentry); ! 897: if (kr != KERN_SUCCESS) ! 898: return kr; ! 899: ! 900: /* space is write-locked and active */ ! 901: ! 902: if (ipc_right_inuse(space, nname, nentry)) { ! 903: /* space is unlocked */ ! 904: return KERN_NAME_EXISTS; ! 905: } ! 906: ! 907: /* don't let ipc_entry_lookup see the uninitialized new entry */ ! 908: ! 909: if ((oname == nname) || ! 910: ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) { ! 911: ipc_entry_dealloc(space, nname, nentry); ! 912: is_write_unlock(space); ! 913: return KERN_INVALID_NAME; ! 914: } ! 915: ! 916: kr = ipc_right_rename(space, oname, oentry, nname, nentry); ! 917: /* space is unlocked */ ! 918: return kr; ! 919: } ! 920: ! 921: #if MACH_ASSERT ! 922: /* ! 923: * Check whether the object is a port if so, free it. But ! 924: * keep track of that fact. ! 925: */ ! 926: void ! 927: io_free( ! 928: unsigned int otype, ! 929: ipc_object_t object) ! 930: { ! 931: ipc_port_t port; ! 932: ! 933: if (otype == IOT_PORT) { ! 934: port = (ipc_port_t) object; ! 935: #if MACH_ASSERT ! 936: ipc_port_track_dealloc(port); ! 937: #endif /* MACH_ASSERT */ ! 938: } ! 939: zfree(ipc_object_zones[otype], (vm_offset_t) object); ! 940: } ! 941: #endif /* MACH_ASSERT */ ! 942: ! 943: #if MACH_RT ! 944: /* ! 945: * Routine: ipc_object_is_rt ! 946: * Purpose: ! 947: * Determine if an object is a real-time object. ! 948: * Conditions: ! 949: * Nothing locked. ! 950: */ ! 951: ! 952: boolean_t ! 953: ipc_object_is_rt( ! 954: ipc_object_t object) ! 955: { ! 956: assert(IO_VALID(object)); ! 957: ! 958: switch (io_otype(object)) { ! 959: case IOT_PORT: ! 960: return IP_RT((ipc_port_t) object); ! 961: case IOT_PORT_SET: ! 962: return FALSE; ! 963: default: ! 964: #if MACH_ASSERT ! 965: assert(FALSE); ! 966: #else ! 967: panic("ipc_object_is_rt: strange object type"); ! 968: #endif ! 969: } ! 970: return FALSE; ! 971: } ! 972: #endif /* MACH_RT */ ! 973: ! 974: #include <mach_kdb.h> ! 975: #if MACH_KDB ! 976: ! 977: #include <ddb/db_output.h> ! 978: ! 979: #define printf kdbprintf ! 980: ! 981: /* ! 982: * Routine: ipc_object_print ! 983: * Purpose: ! 984: * Pretty-print an object for kdb. ! 985: */ ! 986: ! 987: char *ikot_print_array[IKOT_MAX_TYPE] = { ! 988: "(NONE) ", ! 989: "(THREAD) ", ! 990: "(TASK) ", ! 991: "(HOST) ", ! 992: "(HOST_PRIV) ", ! 993: "(PROCESSOR) ", ! 994: "(PSET) ", ! 995: "(PSET_NAME) ", ! 996: "(PAGER) ", ! 997: "(PAGER_REQUEST) ", ! 998: "(DEVICE) ", /* 10 */ ! 999: "(XMM_OBJECT) ", ! 1000: "(XMM_PAGER) ", ! 1001: "(XMM_KERNEL) ", ! 1002: "(XMM_REPLY) ", ! 1003: "(PAGER_TERMINATING)", ! 1004: "(PAGING_NAME) ", ! 1005: "(HOST_SECURITY) ", ! 1006: "(LEDGER) ", ! 1007: "(MASTER_DEVICE) ", ! 1008: "(ACTIVATION) ", /* 20 */ ! 1009: "(SUBSYSTEM) ", ! 1010: "(IO_DONE_QUEUE) ", ! 1011: "(SEMAPHORE) ", ! 1012: "(LOCK_SET) ", ! 1013: "(CLOCK) ", ! 1014: "(CLOCK_CTRL) ", /* 26 */ ! 1015: "(IOKIT) ", /* 27 */ ! 1016: "(NAMED_MEM_ENTRY) ", /* 28 */ ! 1017: /* << new entries here */ ! 1018: "(UNKNOWN) " /* magic catchall */ ! 1019: }; /* Please keep in sync with kern/ipc_kobject.h */ ! 1020: ! 1021: void ! 1022: ipc_object_print( ! 1023: ipc_object_t object) ! 1024: { ! 1025: int kotype; ! 1026: ! 1027: iprintf("%s", io_active(object) ? "active" : "dead"); ! 1028: printf(", refs=%d", object->io_references); ! 1029: printf(", otype=%d", io_otype(object)); ! 1030: kotype = io_kotype(object); ! 1031: if (kotype >= 0 && kotype < IKOT_MAX_TYPE) ! 1032: printf(", kotype=%d %s\n", io_kotype(object), ! 1033: ikot_print_array[kotype]); ! 1034: else ! 1035: printf(", kotype=0x%x %s\n", io_kotype(object), ! 1036: ikot_print_array[IKOT_UNKNOWN]); ! 1037: } ! 1038: ! 1039: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.