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