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#if IMPORTANCE_INHERITANCE 512 int assertcnt = 0; 513#endif 514 515 queue_init(links); 516 517 /* 518 * Could first try a read lock when doing 519 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND, 520 * and MACH_MSG_TYPE_MAKE_SEND_ONCE. 521 */ 522 523 kr = ipc_right_lookup_write(space, name, &entry); 524 if (kr != KERN_SUCCESS) 525 return kr; 526 /* space is write-locked and active */ 527 528 release_port = IP_NULL; 529 kr = ipc_right_copyin(space, name, entry, 530 msgt_name, TRUE, 531 objectp, &soright, 532 &release_port, 533#if IMPORTANCE_INHERITANCE 534 &assertcnt, 535#endif /* IMPORTANCE_INHERITANCE */ 536 links); 537 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) 538 ipc_entry_dealloc(space, name, entry); 539 is_write_unlock(space); 540 541 while(!queue_empty(links)) { 542 wql = (wait_queue_link_t) dequeue(links); 543 wait_queue_link_free(wql); 544 } 545 546#if IMPORTANCE_INHERITANCE 547 if (assertcnt > 0 && current_task()->imp_receiver != 0) { 548 task_importance_drop_internal_assertion(current_task(), assertcnt); 549 } 550#endif /* IMPORTANCE_INHERITANCE */ 551 552 if (release_port != IP_NULL) 553 ip_release(release_port); 554 555 if ((kr == KERN_SUCCESS) && (soright != IP_NULL)) 556 ipc_notify_port_deleted(soright, name); 557 558 return kr; 559} 560 561/* 562 * Routine: ipc_object_copyin_from_kernel 563 * Purpose: 564 * Copyin a naked capability from the kernel. 565 * 566 * MACH_MSG_TYPE_MOVE_RECEIVE 567 * The receiver must be ipc_space_kernel 568 * or the receive right must already be in limbo. 569 * Consumes the naked receive right. 570 * MACH_MSG_TYPE_COPY_SEND 571 * A naked send right must be supplied. 572 * The port gains a reference, and a send right 573 * if the port is still active. 574 * MACH_MSG_TYPE_MAKE_SEND 575 * The receiver must be ipc_space_kernel. 576 * The port gains a reference and a send right. 577 * MACH_MSG_TYPE_MOVE_SEND 578 * Consumes a naked send right. 579 * MACH_MSG_TYPE_MAKE_SEND_ONCE 580 * The port gains a reference and a send-once right. 581 * Receiver also be the caller of device subsystem, 582 * so no assertion. 583 * MACH_MSG_TYPE_MOVE_SEND_ONCE 584 * Consumes a naked send-once right. 585 * Conditions: 586 * Nothing locked. 587 */ 588 589void 590ipc_object_copyin_from_kernel( 591 ipc_object_t object, 592 mach_msg_type_name_t msgt_name) 593{ 594 assert(IO_VALID(object)); 595 596 switch (msgt_name) { 597 case MACH_MSG_TYPE_MOVE_RECEIVE: { 598 ipc_port_t port = (ipc_port_t) object; 599 600 ip_lock(port); 601 assert(ip_active(port)); 602 if (port->ip_destination != IP_NULL) { 603 assert(port->ip_receiver == ipc_space_kernel); 604 605 /* relevant part of ipc_port_clear_receiver */ 606 ipc_port_set_mscount(port, 0); 607 608 port->ip_receiver_name = MACH_PORT_NULL; 609 port->ip_destination = IP_NULL; 610 } 611 ip_unlock(port); 612 break; 613 } 614 615 case MACH_MSG_TYPE_COPY_SEND: { 616 ipc_port_t port = (ipc_port_t) object; 617 618 ip_lock(port); 619 if (ip_active(port)) { 620 assert(port->ip_srights > 0); 621 port->ip_srights++; 622 } 623 ip_reference(port); 624 ip_unlock(port); 625 break; 626 } 627 628 case MACH_MSG_TYPE_MAKE_SEND: { 629 ipc_port_t port = (ipc_port_t) object; 630 631 ip_lock(port); 632 if (ip_active(port)) { 633 assert(port->ip_receiver_name != MACH_PORT_NULL); 634 assert(port->ip_receiver == ipc_space_kernel); 635 port->ip_mscount++; 636 } 637 638 port->ip_srights++; 639 ip_reference(port); 640 ip_unlock(port); 641 break; 642 } 643 644 case MACH_MSG_TYPE_MOVE_SEND: { 645 /* move naked send right into the message */ 646 assert(((ipc_port_t)object)->ip_srights); 647 break; 648 } 649 650 case MACH_MSG_TYPE_MAKE_SEND_ONCE: { 651 ipc_port_t port = (ipc_port_t) object; 652 653 ip_lock(port); 654 if (ip_active(port)) { 655 assert(port->ip_receiver_name != MACH_PORT_NULL); 656 } 657 port->ip_sorights++; 658 ip_reference(port); 659 ip_unlock(port); 660 break; 661 } 662 663 case MACH_MSG_TYPE_MOVE_SEND_ONCE: { 664 /* move naked send-once right into the message */ 665 assert(((ipc_port_t)object)->ip_sorights); 666 break; 667 } 668 669 default: 670 panic("ipc_object_copyin_from_kernel: strange rights"); 671 } 672} 673 674/* 675 * Routine: ipc_object_destroy 676 * Purpose: 677 * Destroys a naked capability. 678 * Consumes a ref for the object. 679 * 680 * A receive right should be in limbo or in transit. 681 * Conditions: 682 * Nothing locked. 683 */ 684 685void 686ipc_object_destroy( 687 ipc_object_t object, 688 mach_msg_type_name_t msgt_name) 689{ 690 assert(IO_VALID(object)); 691 assert(io_otype(object) == IOT_PORT); 692 693 switch (msgt_name) { 694 case MACH_MSG_TYPE_PORT_SEND: 695 ipc_port_release_send((ipc_port_t) object); 696 break; 697 698 case MACH_MSG_TYPE_PORT_SEND_ONCE: 699 ipc_notify_send_once((ipc_port_t) object); 700 break; 701 702 case MACH_MSG_TYPE_PORT_RECEIVE: 703 ipc_port_release_receive((ipc_port_t) object); 704 break; 705 706 default: 707 panic("ipc_object_destroy: strange rights"); 708 } 709} 710 711/* 712 * Routine: ipc_object_destroy_dest 713 * Purpose: 714 * Destroys a naked capability for the destination of 715 * of a message. Consumes a ref for the object. 716 * 717 * Conditions: 718 * Nothing locked. 719 */ 720 721void 722ipc_object_destroy_dest( 723 ipc_object_t object, 724 mach_msg_type_name_t msgt_name) 725{ 726 assert(IO_VALID(object)); 727 assert(io_otype(object) == IOT_PORT); 728 729 switch (msgt_name) { 730 case MACH_MSG_TYPE_PORT_SEND: 731 ipc_port_release_send((ipc_port_t) object); 732 break; 733 734 case MACH_MSG_TYPE_PORT_SEND_ONCE: 735 if (io_active(object) && 736 !ip_full_kernel((ipc_port_t) object)) 737 ipc_notify_send_once((ipc_port_t) object); 738 else 739 ipc_port_release_sonce((ipc_port_t) object); 740 break; 741 742 default: 743 panic("ipc_object_destroy_dest: strange rights"); 744 } 745} 746 747/* 748 * Routine: ipc_object_copyout 749 * Purpose: 750 * Copyout a capability, placing it into a space. 751 * If successful, consumes a ref for the object. 752 * Conditions: 753 * Nothing locked. 754 * Returns: 755 * KERN_SUCCESS Copied out object, consumed ref. 756 * KERN_INVALID_TASK The space is dead. 757 * KERN_INVALID_CAPABILITY The object is dead. 758 * KERN_NO_SPACE No room in space for another right. 759 * KERN_RESOURCE_SHORTAGE No memory available. 760 * KERN_UREFS_OVERFLOW Urefs limit exceeded 761 * and overflow wasn't specified. 762 */ 763 764kern_return_t 765ipc_object_copyout( 766 ipc_space_t space, 767 ipc_object_t object, 768 mach_msg_type_name_t msgt_name, 769 boolean_t overflow, 770 mach_port_name_t *namep) 771{ 772 mach_port_name_t name; 773 ipc_entry_t entry; 774 kern_return_t kr; 775 776 assert(IO_VALID(object)); 777 assert(io_otype(object) == IOT_PORT); 778 779 is_write_lock(space); 780 781 for (;;) { 782 if (!is_active(space)) { 783 is_write_unlock(space); 784 return KERN_INVALID_TASK; 785 } 786 787 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 788 ipc_right_reverse(space, object, &name, &entry)) { 789 /* object is locked and active */ 790 791 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 792 break; 793 } 794 795 name = CAST_MACH_PORT_TO_NAME(object); 796 kr = ipc_entry_get(space, &name, &entry); 797 if (kr != KERN_SUCCESS) { 798 /* unlocks/locks space, so must start again */ 799 800 kr = ipc_entry_grow_table(space, ITS_SIZE_NONE); 801 if (kr != KERN_SUCCESS) 802 return kr; /* space is unlocked */ 803 804 continue; 805 } 806 807 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 808 assert(entry->ie_object == IO_NULL); 809 810 io_lock(object); 811 if (!io_active(object)) { 812 io_unlock(object); 813 ipc_entry_dealloc(space, name, entry); 814 is_write_unlock(space); 815 return KERN_INVALID_CAPABILITY; 816 } 817 818 entry->ie_object = object; 819 break; 820 } 821 822 /* space is write-locked and active, object is locked and active */ 823 824 kr = ipc_right_copyout(space, name, entry, 825 msgt_name, overflow, object); 826 827 /* object is unlocked */ 828 is_write_unlock(space); 829 830 if (kr == KERN_SUCCESS) 831 *namep = name; 832 return kr; 833} 834 835/* 836 * Routine: ipc_object_copyout_name 837 * Purpose: 838 * Copyout a capability, placing it into a space. 839 * The specified name is used for the capability. 840 * If successful, consumes a ref for the object. 841 * Conditions: 842 * Nothing locked. 843 * Returns: 844 * KERN_SUCCESS Copied out object, consumed ref. 845 * KERN_INVALID_TASK The space is dead. 846 * KERN_INVALID_CAPABILITY The object is dead. 847 * KERN_RESOURCE_SHORTAGE No memory available. 848 * KERN_UREFS_OVERFLOW Urefs limit exceeded 849 * and overflow wasn't specified. 850 * KERN_RIGHT_EXISTS Space has rights under another name. 851 * KERN_NAME_EXISTS Name is already used. 852 */ 853 854kern_return_t 855ipc_object_copyout_name( 856 ipc_space_t space, 857 ipc_object_t object, 858 mach_msg_type_name_t msgt_name, 859 boolean_t overflow, 860 mach_port_name_t name) 861{ 862 mach_port_name_t oname; 863 ipc_entry_t oentry; 864 ipc_entry_t entry; 865 kern_return_t kr; 866 867#if IMPORTANCE_INHERITANCE 868 int assertcnt = 0; 869 task_t task = TASK_NULL; 870#endif /* IMPORTANCE_INHERITANCE */ 871 872 assert(IO_VALID(object)); 873 assert(io_otype(object) == IOT_PORT); 874 875 kr = ipc_entry_alloc_name(space, name, &entry); 876 if (kr != KERN_SUCCESS) 877 return kr; 878 /* space is write-locked and active */ 879 880 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 881 ipc_right_reverse(space, object, &oname, &oentry)) { 882 /* object is locked and active */ 883 884 if (name != oname) { 885 io_unlock(object); 886 887 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) 888 ipc_entry_dealloc(space, name, entry); 889 890 is_write_unlock(space); 891 return KERN_RIGHT_EXISTS; 892 } 893 894 assert(entry == oentry); 895 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 896 } else { 897 if (ipc_right_inuse(space, name, entry)) 898 return KERN_NAME_EXISTS; 899 900 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 901 assert(entry->ie_object == IO_NULL); 902 903 io_lock(object); 904 if (!io_active(object)) { 905 io_unlock(object); 906 ipc_entry_dealloc(space, name, entry); 907 is_write_unlock(space); 908 return KERN_INVALID_CAPABILITY; 909 } 910 911 entry->ie_object = object; 912 } 913 914 /* space is write-locked and active, object is locked and active */ 915 916#if IMPORTANCE_INHERITANCE 917 /* 918 * We are slamming a receive right into the space, without 919 * first having been enqueued on a port destined there. So, 920 * we have to arrange to boost the task appropriately if this 921 * port has assertions (and the task wants them). 922 */ 923 if (msgt_name == MACH_MSG_TYPE_PORT_RECEIVE) { 924 ipc_port_t port = (ipc_port_t)object; 925 926 if ((space->is_task != TASK_NULL) && 927 (space->is_task->imp_receiver != 0)) { 928 assertcnt = port->ip_impcount; 929 task = space->is_task; 930 task_reference(task); 931 } 932 933 /* take port out of limbo */ 934 assert(port->ip_tempowner != 0); 935 port->ip_tempowner = 0; 936 } 937 938#endif /* IMPORTANCE_INHERITANCE */ 939 940 kr = ipc_right_copyout(space, name, entry, 941 msgt_name, overflow, object); 942 943 /* object is unlocked */ 944 is_write_unlock(space); 945 946#if IMPORTANCE_INHERITANCE 947 /* 948 * Add the assertions to the task that we captured before 949 */ 950 if (task != TASK_NULL) { 951 if (assertcnt > 0) 952 task_importance_hold_internal_assertion(task, assertcnt); 953 task_deallocate(task); 954 } 955#endif /* IMPORTANCE_INHERITANCE */ 956 957 return kr; 958} 959 960/* 961 * Routine: ipc_object_copyout_dest 962 * Purpose: 963 * Translates/consumes the destination right of a message. 964 * This is unlike normal copyout because the right is consumed 965 * in a funny way instead of being given to the receiving space. 966 * The receiver gets his name for the port, if he has receive 967 * rights, otherwise MACH_PORT_NULL. 968 * Conditions: 969 * The object is locked and active. Nothing else locked. 970 * The object is unlocked and loses a reference. 971 */ 972 973void 974ipc_object_copyout_dest( 975 ipc_space_t space, 976 ipc_object_t object, 977 mach_msg_type_name_t msgt_name, 978 mach_port_name_t *namep) 979{ 980 mach_port_name_t name; 981 982 assert(IO_VALID(object)); 983 assert(io_active(object)); 984 985 io_release(object); 986 987 /* 988 * If the space is the receiver/owner of the object, 989 * then we quietly consume the right and return 990 * the space's name for the object. Otherwise 991 * we destroy the right and return MACH_PORT_NULL. 992 */ 993 994 switch (msgt_name) { 995 case MACH_MSG_TYPE_PORT_SEND: { 996 ipc_port_t port = (ipc_port_t) object; 997 ipc_port_t nsrequest = IP_NULL; 998 mach_port_mscount_t mscount; 999 1000 if (port->ip_receiver == space) 1001 name = port->ip_receiver_name; 1002 else 1003 name = MACH_PORT_NULL; 1004 1005 assert(port->ip_srights > 0); 1006 if (--port->ip_srights == 0 && 1007 port->ip_nsrequest != IP_NULL) { 1008 nsrequest = port->ip_nsrequest; 1009 port->ip_nsrequest = IP_NULL; 1010 mscount = port->ip_mscount; 1011 ip_unlock(port); 1012 ipc_notify_no_senders(nsrequest, mscount); 1013 } else 1014 ip_unlock(port); 1015 break; 1016 } 1017 1018 case MACH_MSG_TYPE_PORT_SEND_ONCE: { 1019 ipc_port_t port = (ipc_port_t) object; 1020 1021 assert(port->ip_sorights > 0); 1022 1023 if (port->ip_receiver == space) { 1024 /* quietly consume the send-once right */ 1025 1026 port->ip_sorights--; 1027 name = port->ip_receiver_name; 1028 ip_unlock(port); 1029 } else { 1030 /* 1031 * A very bizarre case. The message 1032 * was received, but before this copyout 1033 * happened the space lost receive rights. 1034 * We can't quietly consume the soright 1035 * out from underneath some other task, 1036 * so generate a send-once notification. 1037 */ 1038 1039 ip_reference(port); /* restore ref */ 1040 ip_unlock(port); 1041 1042 ipc_notify_send_once(port); 1043 name = MACH_PORT_NULL; 1044 } 1045 1046 break; 1047 } 1048 1049 default: 1050 panic("ipc_object_copyout_dest: strange rights"); 1051 name = MACH_PORT_DEAD; 1052 } 1053 1054 *namep = name; 1055} 1056 1057/* 1058 * Routine: ipc_object_rename 1059 * Purpose: 1060 * Rename an entry in a space. 1061 * Conditions: 1062 * Nothing locked. 1063 * Returns: 1064 * KERN_SUCCESS Renamed the entry. 1065 * KERN_INVALID_TASK The space was dead. 1066 * KERN_INVALID_NAME oname didn't denote an entry. 1067 * KERN_NAME_EXISTS nname already denoted an entry. 1068 * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry. 1069 */ 1070 1071kern_return_t 1072ipc_object_rename( 1073 ipc_space_t space, 1074 mach_port_name_t oname, 1075 mach_port_name_t nname) 1076{ 1077 ipc_entry_t oentry, nentry; 1078 kern_return_t kr; 1079 1080 kr = ipc_entry_alloc_name(space, nname, &nentry); 1081 if (kr != KERN_SUCCESS) 1082 return kr; 1083 1084 /* space is write-locked and active */ 1085 1086 if (ipc_right_inuse(space, nname, nentry)) { 1087 /* space is unlocked */ 1088 return KERN_NAME_EXISTS; 1089 } 1090 1091 /* don't let ipc_entry_lookup see the uninitialized new entry */ 1092 1093 if ((oname == nname) || 1094 ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) { 1095 ipc_entry_dealloc(space, nname, nentry); 1096 is_write_unlock(space); 1097 return KERN_INVALID_NAME; 1098 } 1099 1100 kr = ipc_right_rename(space, oname, oentry, nname, nentry); 1101 /* space is unlocked */ 1102 return kr; 1103} 1104 1105/* 1106 * Get a label out of a port, to be used by a kernel call 1107 * that takes a security label as a parameter. In this case, we want 1108 * to use the label stored in the label handle and not the label on its 1109 * port. 1110 * 1111 * The port should be locked for this call. The lock protecting 1112 * label handle contents should not be necessary, as they can only 1113 * be modified when a label handle with one reference is a task label. 1114 * User allocated label handles can never be modified. 1115 */ 1116#if CONFIG_MACF_MACH 1117struct label *io_getlabel (ipc_object_t objp) 1118{ 1119 ipc_port_t port = (ipc_port_t)objp; 1120 1121 assert(io_otype(objp) == IOT_PORT); 1122 1123 if (ip_kotype(port) == IKOT_LABELH) 1124 return &((ipc_labelh_t) port->ip_kobject)->lh_label; 1125 else 1126 return &port->ip_label; 1127} 1128#endif 1129 1130/* 1131 * Check whether the object is a port if so, free it. But 1132 * keep track of that fact. 1133 */ 1134void 1135io_free( 1136 unsigned int otype, 1137 ipc_object_t object) 1138{ 1139 ipc_port_t port; 1140 1141 if (otype == IOT_PORT) { 1142 port = (ipc_port_t) object; 1143 ipc_port_finalize(port); 1144 } 1145 io_lock_destroy(object); 1146 zfree(ipc_object_zones[otype], object); 1147} 1148