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_pset.h> 94#include <ipc/ipc_labelh.h> 95 96#include <security/mac_mach_internal.h> 97 98zone_t ipc_object_zones[IOT_NUMBER]; 99 100/* 101 * Routine: ipc_object_reference 102 * Purpose: 103 * Take a reference to an object. 104 */ 105 106void 107ipc_object_reference( 108 ipc_object_t object) 109{ 110 io_lock(object); 111 assert(object->io_references > 0); 112 io_reference(object); 113 io_unlock(object); 114} 115 116/* 117 * Routine: ipc_object_release 118 * Purpose: 119 * Release a reference to an object. 120 */ 121 122void 123ipc_object_release( 124 ipc_object_t object) 125{ 126 io_lock(object); 127 assert(object->io_references > 0); 128 io_release(object); 129 io_check_unlock(object); 130} 131 132/* 133 * Routine: ipc_object_translate 134 * Purpose: 135 * Look up an object in a space. 136 * Conditions: 137 * Nothing locked before. If successful, the object 138 * is returned locked. The caller doesn't get a ref. 139 * Returns: 140 * KERN_SUCCESS Object returned locked. 141 * KERN_INVALID_TASK The space is dead. 142 * KERN_INVALID_NAME The name doesn't denote a right. 143 * KERN_INVALID_RIGHT Name doesn't denote the correct right. 144 */ 145 146kern_return_t 147ipc_object_translate( 148 ipc_space_t space, 149 mach_port_name_t name, 150 mach_port_right_t right, 151 ipc_object_t *objectp) 152{ 153 ipc_entry_t entry; 154 ipc_object_t object; 155 kern_return_t kr; 156 157 kr = ipc_right_lookup_read(space, name, &entry); 158 if (kr != KERN_SUCCESS) 159 return kr; 160 /* space is read-locked and active */ 161 162 if ((entry->ie_bits & MACH_PORT_TYPE(right)) == MACH_PORT_TYPE_NONE) { 163 is_read_unlock(space); 164 return KERN_INVALID_RIGHT; 165 } 166 167 object = entry->ie_object; 168 assert(object != IO_NULL); 169 170 io_lock(object); 171 is_read_unlock(space); 172 173 *objectp = object; 174 return KERN_SUCCESS; 175} 176 177/* 178 * Routine: ipc_object_translate_two 179 * Purpose: 180 * Look up two objects in a space. 181 * Conditions: 182 * Nothing locked before. If successful, the objects 183 * are returned locked. The caller doesn't get a ref. 184 * Returns: 185 * KERN_SUCCESS Objects returned locked. 186 * KERN_INVALID_TASK The space is dead. 187 * KERN_INVALID_NAME A name doesn't denote a right. 188 * KERN_INVALID_RIGHT A name doesn't denote the correct right. 189 */ 190 191kern_return_t 192ipc_object_translate_two( 193 ipc_space_t space, 194 mach_port_name_t name1, 195 mach_port_right_t right1, 196 ipc_object_t *objectp1, 197 mach_port_name_t name2, 198 mach_port_right_t right2, 199 ipc_object_t *objectp2) 200{ 201 ipc_entry_t entry1; 202 ipc_entry_t entry2; 203 ipc_object_t object; 204 kern_return_t kr; 205 206 kr = ipc_right_lookup_two_read(space, name1, &entry1, name2, &entry2); 207 if (kr != KERN_SUCCESS) 208 return kr; 209 /* space is read-locked and active */ 210 211 if ((entry1->ie_bits & MACH_PORT_TYPE(right1)) == MACH_PORT_TYPE_NONE) { 212 is_read_unlock(space); 213 return KERN_INVALID_RIGHT; 214 } 215 216 if ((entry2->ie_bits & MACH_PORT_TYPE(right2)) == MACH_PORT_TYPE_NONE) { 217 is_read_unlock(space); 218 return KERN_INVALID_RIGHT; 219 } 220 221 object = entry1->ie_object; 222 assert(object != IO_NULL); 223 io_lock(object); 224 *objectp1 = object; 225 226 object = entry2->ie_object; 227 assert(object != IO_NULL); 228 io_lock(object); 229 *objectp2 = object; 230 231 is_read_unlock(space); 232 return KERN_SUCCESS; 233} 234 235/* 236 * Routine: ipc_object_alloc_dead 237 * Purpose: 238 * Allocate a dead-name entry. 239 * Conditions: 240 * Nothing locked. 241 * Returns: 242 * KERN_SUCCESS The dead name is allocated. 243 * KERN_INVALID_TASK The space is dead. 244 * KERN_NO_SPACE No room for an entry in the space. 245 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 246 */ 247 248kern_return_t 249ipc_object_alloc_dead( 250 ipc_space_t space, 251 mach_port_name_t *namep) 252{ 253 ipc_entry_t entry; 254 kern_return_t kr; 255 256 kr = ipc_entry_alloc(space, namep, &entry); 257 if (kr != KERN_SUCCESS) 258 return kr; 259 /* space is write-locked */ 260 261 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ 262 263 assert(entry->ie_object == IO_NULL); 264 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; 265 266 is_write_unlock(space); 267 return KERN_SUCCESS; 268} 269 270/* 271 * Routine: ipc_object_alloc_dead_name 272 * Purpose: 273 * Allocate a dead-name entry, with a specific name. 274 * Conditions: 275 * Nothing locked. 276 * Returns: 277 * KERN_SUCCESS The dead name is allocated. 278 * KERN_INVALID_TASK The space is dead. 279 * KERN_NAME_EXISTS The name already denotes a right. 280 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 281 */ 282 283kern_return_t 284ipc_object_alloc_dead_name( 285 ipc_space_t space, 286 mach_port_name_t name) 287{ 288 ipc_entry_t entry; 289 kern_return_t kr; 290 291 kr = ipc_entry_alloc_name(space, name, &entry); 292 if (kr != KERN_SUCCESS) 293 return kr; 294 /* space is write-locked */ 295 296 if (ipc_right_inuse(space, name, entry)) 297 return KERN_NAME_EXISTS; 298 299 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ 300 301 assert(entry->ie_object == IO_NULL); 302 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; 303 304 is_write_unlock(space); 305 return KERN_SUCCESS; 306} 307 308/* 309 * Routine: ipc_object_alloc 310 * Purpose: 311 * Allocate an object. 312 * Conditions: 313 * Nothing locked. If successful, the object is returned locked. 314 * The caller doesn't get a reference for the object. 315 * Returns: 316 * KERN_SUCCESS The object is allocated. 317 * KERN_INVALID_TASK The space is dead. 318 * KERN_NO_SPACE No room for an entry in the space. 319 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 320 */ 321 322kern_return_t 323ipc_object_alloc( 324 ipc_space_t space, 325 ipc_object_type_t otype, 326 mach_port_type_t type, 327 mach_port_urefs_t urefs, 328 mach_port_name_t *namep, 329 ipc_object_t *objectp) 330{ 331 ipc_object_t object; 332 ipc_entry_t entry; 333 kern_return_t kr; 334 335 assert(otype < IOT_NUMBER); 336 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); 337 assert(type != MACH_PORT_TYPE_NONE); 338 assert(urefs <= MACH_PORT_UREFS_MAX); 339 340 object = io_alloc(otype); 341 if (object == IO_NULL) 342 return KERN_RESOURCE_SHORTAGE; 343 344 if (otype == IOT_PORT) { 345 ipc_port_t port = (ipc_port_t)object; 346 347 bzero((char *)port, sizeof(*port)); 348#if CONFIG_MACF_MACH 349 mac_port_label_init(&port->ip_label); 350#endif 351 } else if (otype == IOT_PORT_SET) { 352 ipc_pset_t pset = (ipc_pset_t)object; 353 354 bzero((char *)pset, sizeof(*pset)); 355 } 356 357 io_lock_init(object); 358 *namep = (mach_port_name_t)object; 359 kr = ipc_entry_alloc(space, namep, &entry); 360 if (kr != KERN_SUCCESS) { 361 io_free(otype, object); 362 return kr; 363 } 364 /* space is write-locked */ 365 366 entry->ie_bits |= type | urefs; 367 entry->ie_object = object; 368 369 io_lock(object); 370 is_write_unlock(space); 371 372 object->io_references = 1; /* for entry, not caller */ 373 object->io_bits = io_makebits(TRUE, otype, 0); 374 375 *objectp = object; 376 return KERN_SUCCESS; 377} 378 379/* 380 * Routine: ipc_object_alloc_name 381 * Purpose: 382 * Allocate an object, with a specific name. 383 * Conditions: 384 * Nothing locked. If successful, the object is returned locked. 385 * The caller doesn't get a reference for the object. 386 * Returns: 387 * KERN_SUCCESS The object is allocated. 388 * KERN_INVALID_TASK The space is dead. 389 * KERN_NAME_EXISTS The name already denotes a right. 390 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 391 */ 392 393kern_return_t 394ipc_object_alloc_name( 395 ipc_space_t space, 396 ipc_object_type_t otype, 397 mach_port_type_t type, 398 mach_port_urefs_t urefs, 399 mach_port_name_t name, 400 ipc_object_t *objectp) 401{ 402 ipc_object_t object; 403 ipc_entry_t entry; 404 kern_return_t kr; 405 406 assert(otype < IOT_NUMBER); 407 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); 408 assert(type != MACH_PORT_TYPE_NONE); 409 assert(urefs <= MACH_PORT_UREFS_MAX); 410 411 object = io_alloc(otype); 412 if (object == IO_NULL) 413 return KERN_RESOURCE_SHORTAGE; 414 415 if (otype == IOT_PORT) { 416 ipc_port_t port = (ipc_port_t)object; 417 418 bzero((char *)port, sizeof(*port)); 419#if CONFIG_MACF_MACH 420 mac_port_label_init(&port->ip_label); 421#endif 422 } else if (otype == IOT_PORT_SET) { 423 ipc_pset_t pset = (ipc_pset_t)object; 424 425 bzero((char *)pset, sizeof(*pset)); 426 } 427 428 io_lock_init(object); 429 kr = ipc_entry_alloc_name(space, name, &entry); 430 if (kr != KERN_SUCCESS) { 431 io_free(otype, object); 432 return kr; 433 } 434 /* space is write-locked */ 435 436 if (ipc_right_inuse(space, name, entry)) { 437 io_free(otype, object); 438 return KERN_NAME_EXISTS; 439 } 440 441 entry->ie_bits |= type | urefs; 442 entry->ie_object = object; 443 444 io_lock(object); 445 is_write_unlock(space); 446 447 object->io_references = 1; /* for entry, not caller */ 448 object->io_bits = io_makebits(TRUE, otype, 0); 449 450 *objectp = object; 451 return KERN_SUCCESS; 452} 453 454/* 455 * Routine: ipc_object_copyin_type 456 * Purpose: 457 * Convert a send type name to a received type name. 458 */ 459 460mach_msg_type_name_t 461ipc_object_copyin_type( 462 mach_msg_type_name_t msgt_name) 463{ 464 switch (msgt_name) { 465 466 case MACH_MSG_TYPE_MOVE_RECEIVE: 467 case MACH_MSG_TYPE_COPY_RECEIVE: 468 return MACH_MSG_TYPE_PORT_RECEIVE; 469 470 case MACH_MSG_TYPE_MOVE_SEND_ONCE: 471 case MACH_MSG_TYPE_MAKE_SEND_ONCE: 472 return MACH_MSG_TYPE_PORT_SEND_ONCE; 473 474 case MACH_MSG_TYPE_MOVE_SEND: 475 case MACH_MSG_TYPE_MAKE_SEND: 476 case MACH_MSG_TYPE_COPY_SEND: 477 return MACH_MSG_TYPE_PORT_SEND; 478 479 default: 480 return MACH_MSG_TYPE_PORT_NONE; 481 } 482} 483 484/* 485 * Routine: ipc_object_copyin 486 * Purpose: 487 * Copyin a capability from a space. 488 * If successful, the caller gets a ref 489 * for the resulting object, unless it is IO_DEAD. 490 * Conditions: 491 * Nothing locked. 492 * Returns: 493 * KERN_SUCCESS Acquired an object, possibly IO_DEAD. 494 * KERN_INVALID_TASK The space is dead. 495 * KERN_INVALID_NAME Name doesn't exist in space. 496 * KERN_INVALID_RIGHT Name doesn't denote correct right. 497 */ 498 499kern_return_t 500ipc_object_copyin( 501 ipc_space_t space, 502 mach_port_name_t name, 503 mach_msg_type_name_t msgt_name, 504 ipc_object_t *objectp) 505{ 506 ipc_entry_t entry; 507 ipc_port_t soright; 508 kern_return_t kr; 509 510 /* 511 * Could first try a read lock when doing 512 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND, 513 * and MACH_MSG_TYPE_MAKE_SEND_ONCE. 514 */ 515 516 kr = ipc_right_lookup_write(space, name, &entry); 517 if (kr != KERN_SUCCESS) 518 return kr; 519 /* space is write-locked and active */ 520 521 kr = ipc_right_copyin(space, name, entry, 522 msgt_name, TRUE, 523 objectp, &soright); 524 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) 525 ipc_entry_dealloc(space, name, entry); 526 is_write_unlock(space); 527 528 if ((kr == KERN_SUCCESS) && (soright != IP_NULL)) 529 ipc_notify_port_deleted(soright, name); 530 531 return kr; 532} 533 534/* 535 * Routine: ipc_object_copyin_from_kernel 536 * Purpose: 537 * Copyin a naked capability from the kernel. 538 * 539 * MACH_MSG_TYPE_MOVE_RECEIVE 540 * The receiver must be ipc_space_kernel 541 * or the receive right must already be in limbo. 542 * Consumes the naked receive right. 543 * MACH_MSG_TYPE_COPY_SEND 544 * A naked send right must be supplied. 545 * The port gains a reference, and a send right 546 * if the port is still active. 547 * MACH_MSG_TYPE_MAKE_SEND 548 * The receiver must be ipc_space_kernel. 549 * The port gains a reference and a send right. 550 * MACH_MSG_TYPE_MOVE_SEND 551 * Consumes a naked send right. 552 * MACH_MSG_TYPE_MAKE_SEND_ONCE 553 * The port gains a reference and a send-once right. 554 * Receiver also be the caller of device subsystem, 555 * so no assertion. 556 * MACH_MSG_TYPE_MOVE_SEND_ONCE 557 * Consumes a naked send-once right. 558 * Conditions: 559 * Nothing locked. 560 */ 561 562void 563ipc_object_copyin_from_kernel( 564 ipc_object_t object, 565 mach_msg_type_name_t msgt_name) 566{ 567 assert(IO_VALID(object)); 568 569 switch (msgt_name) { 570 case MACH_MSG_TYPE_MOVE_RECEIVE: { 571 ipc_port_t port = (ipc_port_t) object; 572 573 ip_lock(port); 574 assert(ip_active(port)); 575 if (port->ip_destination != IP_NULL) { 576 assert(port->ip_receiver == ipc_space_kernel); 577 578 /* relevant part of ipc_port_clear_receiver */ 579 ipc_port_set_mscount(port, 0); 580 581 port->ip_receiver_name = MACH_PORT_NULL; 582 port->ip_destination = IP_NULL; 583 } 584 ip_unlock(port); 585 break; 586 } 587 588 case MACH_MSG_TYPE_COPY_SEND: { 589 ipc_port_t port = (ipc_port_t) object; 590 591 ip_lock(port); 592 if (ip_active(port)) { 593 assert(port->ip_srights > 0); 594 port->ip_srights++; 595 } 596 ip_reference(port); 597 ip_unlock(port); 598 break; 599 } 600 601 case MACH_MSG_TYPE_MAKE_SEND: { 602 ipc_port_t port = (ipc_port_t) object; 603 604 ip_lock(port); 605 assert(ip_active(port)); 606 assert(port->ip_receiver_name != MACH_PORT_NULL); 607 assert(port->ip_receiver == ipc_space_kernel); 608 609 ip_reference(port); 610 port->ip_mscount++; 611 port->ip_srights++; 612 ip_unlock(port); 613 break; 614 } 615 616 case MACH_MSG_TYPE_MOVE_SEND: { 617 /* move naked send right into the message */ 618 assert(((ipc_port_t)object)->ip_srights); 619 break; 620 } 621 622 case MACH_MSG_TYPE_MAKE_SEND_ONCE: { 623 ipc_port_t port = (ipc_port_t) object; 624 625 ip_lock(port); 626 assert(ip_active(port)); 627 assert(port->ip_receiver_name != MACH_PORT_NULL); 628 629 ip_reference(port); 630 port->ip_sorights++; 631 ip_unlock(port); 632 break; 633 } 634 635 case MACH_MSG_TYPE_MOVE_SEND_ONCE: { 636 /* move naked send-once right into the message */ 637 assert(((ipc_port_t)object)->ip_sorights); 638 break; 639 } 640 641 default: 642 panic("ipc_object_copyin_from_kernel: strange rights"); 643 } 644} 645 646/* 647 * Routine: ipc_object_destroy 648 * Purpose: 649 * Destroys a naked capability. 650 * Consumes a ref for the object. 651 * 652 * A receive right should be in limbo or in transit. 653 * Conditions: 654 * Nothing locked. 655 */ 656 657void 658ipc_object_destroy( 659 ipc_object_t object, 660 mach_msg_type_name_t msgt_name) 661{ 662 assert(IO_VALID(object)); 663 assert(io_otype(object) == IOT_PORT); 664 665 switch (msgt_name) { 666 case MACH_MSG_TYPE_PORT_SEND: 667 ipc_port_release_send((ipc_port_t) object); 668 break; 669 670 case MACH_MSG_TYPE_PORT_SEND_ONCE: 671 ipc_notify_send_once((ipc_port_t) object); 672 break; 673 674 case MACH_MSG_TYPE_PORT_RECEIVE: 675 ipc_port_release_receive((ipc_port_t) object); 676 break; 677 678 default: 679 panic("ipc_object_destroy: strange rights"); 680 } 681} 682 683/* 684 * Routine: ipc_object_copyout 685 * Purpose: 686 * Copyout a capability, placing it into a space. 687 * If successful, consumes a ref for the object. 688 * Conditions: 689 * Nothing locked. 690 * Returns: 691 * KERN_SUCCESS Copied out object, consumed ref. 692 * KERN_INVALID_TASK The space is dead. 693 * KERN_INVALID_CAPABILITY The object is dead. 694 * KERN_NO_SPACE No room in space for another right. 695 * KERN_RESOURCE_SHORTAGE No memory available. 696 * KERN_UREFS_OVERFLOW Urefs limit exceeded 697 * and overflow wasn't specified. 698 */ 699 700kern_return_t 701ipc_object_copyout( 702 ipc_space_t space, 703 ipc_object_t object, 704 mach_msg_type_name_t msgt_name, 705 boolean_t overflow, 706 mach_port_name_t *namep) 707{ 708 mach_port_name_t name; 709 ipc_entry_t entry; 710 kern_return_t kr; 711 712 assert(IO_VALID(object)); 713 assert(io_otype(object) == IOT_PORT); 714 715 is_write_lock(space); 716 717 for (;;) { 718 if (!space->is_active) { 719 is_write_unlock(space); 720 return KERN_INVALID_TASK; 721 } 722 723 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 724 ipc_right_reverse(space, object, &name, &entry)) { 725 /* object is locked and active */ 726 727 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 728 break; 729 } 730 731 name = (mach_port_name_t)object; 732 kr = ipc_entry_get(space, &name, &entry); 733 if (kr != KERN_SUCCESS) { 734 /* unlocks/locks space, so must start again */ 735 736 kr = ipc_entry_grow_table(space, ITS_SIZE_NONE); 737 if (kr != KERN_SUCCESS) 738 return kr; /* space is unlocked */ 739 740 continue; 741 } 742 743 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 744 assert(entry->ie_object == IO_NULL); 745 746 io_lock(object); 747 if (!io_active(object)) { 748 io_unlock(object); 749 ipc_entry_dealloc(space, name, entry); 750 is_write_unlock(space); 751 return KERN_INVALID_CAPABILITY; 752 } 753 754 entry->ie_object = object; 755 break; 756 } 757 758 /* space is write-locked and active, object is locked and active */ 759 760 kr = ipc_right_copyout(space, name, entry, 761 msgt_name, overflow, object); 762 /* object is unlocked */ 763 is_write_unlock(space); 764 765 if (kr == KERN_SUCCESS) 766 *namep = name; 767 return kr; 768} 769 770/* 771 * Routine: ipc_object_copyout_name 772 * Purpose: 773 * Copyout a capability, placing it into a space. 774 * The specified name is used for the capability. 775 * If successful, consumes a ref for the object. 776 * Conditions: 777 * Nothing locked. 778 * Returns: 779 * KERN_SUCCESS Copied out object, consumed ref. 780 * KERN_INVALID_TASK The space is dead. 781 * KERN_INVALID_CAPABILITY The object is dead. 782 * KERN_RESOURCE_SHORTAGE No memory available. 783 * KERN_UREFS_OVERFLOW Urefs limit exceeded 784 * and overflow wasn't specified. 785 * KERN_RIGHT_EXISTS Space has rights under another name. 786 * KERN_NAME_EXISTS Name is already used. 787 */ 788 789kern_return_t 790ipc_object_copyout_name( 791 ipc_space_t space, 792 ipc_object_t object, 793 mach_msg_type_name_t msgt_name, 794 boolean_t overflow, 795 mach_port_name_t name) 796{ 797 mach_port_name_t oname; 798 ipc_entry_t oentry; 799 ipc_entry_t entry; 800 kern_return_t kr; 801 802 assert(IO_VALID(object)); 803 assert(io_otype(object) == IOT_PORT); 804 805 kr = ipc_entry_alloc_name(space, name, &entry); 806 if (kr != KERN_SUCCESS) 807 return kr; 808 /* space is write-locked and active */ 809 810 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 811 ipc_right_reverse(space, object, &oname, &oentry)) { 812 /* object is locked and active */ 813 814 if (name != oname) { 815 io_unlock(object); 816 817 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) 818 ipc_entry_dealloc(space, name, entry); 819 820 is_write_unlock(space); 821 return KERN_RIGHT_EXISTS; 822 } 823 824 assert(entry == oentry); 825 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 826 } else { 827 if (ipc_right_inuse(space, name, entry)) 828 return KERN_NAME_EXISTS; 829 830 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); 831 assert(entry->ie_object == IO_NULL); 832 833 io_lock(object); 834 if (!io_active(object)) { 835 io_unlock(object); 836 ipc_entry_dealloc(space, name, entry); 837 is_write_unlock(space); 838 return KERN_INVALID_CAPABILITY; 839 } 840 841 entry->ie_object = object; 842 } 843 844 /* space is write-locked and active, object is locked and active */ 845 846 kr = ipc_right_copyout(space, name, entry, 847 msgt_name, overflow, object); 848 /* object is unlocked */ 849 is_write_unlock(space); 850 return kr; 851} 852 853/* 854 * Routine: ipc_object_copyout_dest 855 * Purpose: 856 * Translates/consumes the destination right of a message. 857 * This is unlike normal copyout because the right is consumed 858 * in a funny way instead of being given to the receiving space. 859 * The receiver gets his name for the port, if he has receive 860 * rights, otherwise MACH_PORT_NULL. 861 * Conditions: 862 * The object is locked and active. Nothing else locked. 863 * The object is unlocked and loses a reference. 864 */ 865 866void 867ipc_object_copyout_dest( 868 ipc_space_t space, 869 ipc_object_t object, 870 mach_msg_type_name_t msgt_name, 871 mach_port_name_t *namep) 872{ 873 mach_port_name_t name; 874 875 assert(IO_VALID(object)); 876 assert(io_active(object)); 877 878 io_release(object); 879 880 /* 881 * If the space is the receiver/owner of the object, 882 * then we quietly consume the right and return 883 * the space's name for the object. Otherwise 884 * we destroy the right and return MACH_PORT_NULL. 885 */ 886 887 switch (msgt_name) { 888 case MACH_MSG_TYPE_PORT_SEND: { 889 ipc_port_t port = (ipc_port_t) object; 890 ipc_port_t nsrequest = IP_NULL; 891 mach_port_mscount_t mscount; 892 893 if (port->ip_receiver == space) 894 name = port->ip_receiver_name; 895 else 896 name = MACH_PORT_NULL; 897 898 assert(port->ip_srights > 0); 899 if (--port->ip_srights == 0 && 900 port->ip_nsrequest != IP_NULL) { 901 nsrequest = port->ip_nsrequest; 902 port->ip_nsrequest = IP_NULL; 903 mscount = port->ip_mscount; 904 ip_unlock(port); 905 ipc_notify_no_senders(nsrequest, mscount); 906 } else 907 ip_unlock(port); 908 break; 909 } 910 911 case MACH_MSG_TYPE_PORT_SEND_ONCE: { 912 ipc_port_t port = (ipc_port_t) object; 913 914 assert(port->ip_sorights > 0); 915 916 if (port->ip_receiver == space) { 917 /* quietly consume the send-once right */ 918 919 port->ip_sorights--; 920 name = port->ip_receiver_name; 921 ip_unlock(port); 922 } else { 923 /* 924 * A very bizarre case. The message 925 * was received, but before this copyout 926 * happened the space lost receive rights. 927 * We can't quietly consume the soright 928 * out from underneath some other task, 929 * so generate a send-once notification. 930 */ 931 932 ip_reference(port); /* restore ref */ 933 ip_unlock(port); 934 935 ipc_notify_send_once(port); 936 name = MACH_PORT_NULL; 937 } 938 939 break; 940 } 941 942 default: 943 panic("ipc_object_copyout_dest: strange rights"); 944 name = MACH_PORT_DEAD; 945 } 946 947 *namep = name; 948} 949 950/* 951 * Routine: ipc_object_rename 952 * Purpose: 953 * Rename an entry in a space. 954 * Conditions: 955 * Nothing locked. 956 * Returns: 957 * KERN_SUCCESS Renamed the entry. 958 * KERN_INVALID_TASK The space was dead. 959 * KERN_INVALID_NAME oname didn't denote an entry. 960 * KERN_NAME_EXISTS nname already denoted an entry. 961 * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry. 962 */ 963 964kern_return_t 965ipc_object_rename( 966 ipc_space_t space, 967 mach_port_name_t oname, 968 mach_port_name_t nname) 969{ 970 ipc_entry_t oentry, nentry; 971 kern_return_t kr; 972 973 kr = ipc_entry_alloc_name(space, nname, &nentry); 974 if (kr != KERN_SUCCESS) 975 return kr; 976 977 /* space is write-locked and active */ 978 979 if (ipc_right_inuse(space, nname, nentry)) { 980 /* space is unlocked */ 981 return KERN_NAME_EXISTS; 982 } 983 984 /* don't let ipc_entry_lookup see the uninitialized new entry */ 985 986 if ((oname == nname) || 987 ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) { 988 ipc_entry_dealloc(space, nname, nentry); 989 is_write_unlock(space); 990 return KERN_INVALID_NAME; 991 } 992 993 kr = ipc_right_rename(space, oname, oentry, nname, nentry); 994 /* space is unlocked */ 995 return kr; 996} 997 998/* 999 * Get a label out of a port, to be used by a kernel call 1000 * that takes a security label as a parameter. In this case, we want 1001 * to use the label stored in the label handle and not the label on its 1002 * port. 1003 * 1004 * The port should be locked for this call. The lock protecting 1005 * label handle contents should not be necessary, as they can only 1006 * be modified when a label handle with one reference is a task label. 1007 * User allocated label handles can never be modified. 1008 */ 1009#if CONFIG_MACF_MACH 1010struct label *io_getlabel (ipc_object_t objp) 1011{ 1012 ipc_port_t port = (ipc_port_t)objp; 1013 1014 assert(io_otype(objp) == IOT_PORT); 1015 1016 if (ip_kotype(port) == IKOT_LABELH) 1017 return &((ipc_labelh_t) port->ip_kobject)->lh_label; 1018 else 1019 return &port->ip_label; 1020} 1021#endif 1022#if MACH_ASSERT || CONFIG_MACF_MACH 1023/* 1024 * Check whether the object is a port if so, free it. But 1025 * keep track of that fact. 1026 */ 1027void 1028io_free( 1029 unsigned int otype, 1030 ipc_object_t object) 1031{ 1032 ipc_port_t port; 1033 1034 if (otype == IOT_PORT) { 1035 port = (ipc_port_t) object; 1036#if MACH_ASSERT 1037 ipc_port_track_dealloc(port); 1038#endif /* MACH_ASSERT */ 1039 1040#if CONFIG_MACF_MACH 1041 /* Port label should have been initialized after creation. */ 1042 mac_port_label_destroy(&port->ip_label); 1043#endif 1044 } 1045 zfree(ipc_object_zones[otype], object); 1046} 1047#endif /* MACH_ASSER || MAC */ 1048 1049#include <mach_kdb.h> 1050#if MACH_KDB 1051 1052#include <ddb/db_output.h> 1053 1054#define printf kdbprintf 1055 1056/* 1057 * Routine: ipc_object_print 1058 * Purpose: 1059 * Pretty-print an object for kdb. 1060 */ 1061 1062const char *ikot_print_array[IKOT_MAX_TYPE] = { 1063 "(NONE) ", 1064 "(THREAD) ", 1065 "(TASK) ", 1066 "(HOST) ", 1067 "(HOST_PRIV) ", 1068 "(PROCESSOR) ", 1069 "(PSET) ", 1070 "(PSET_NAME) ", 1071 "(TIMER) ", 1072 "(PAGER_REQUEST) ", 1073 "(DEVICE) ", /* 10 */ 1074 "(XMM_OBJECT) ", 1075 "(XMM_PAGER) ", 1076 "(XMM_KERNEL) ", 1077 "(XMM_REPLY) ", 1078 "(NOTDEF 15) ", 1079 "(NOTDEF 16) ", 1080 "(HOST_SECURITY) ", 1081 "(LEDGER) ", 1082 "(MASTER_DEVICE) ", 1083 "(ACTIVATION) ", /* 20 */ 1084 "(SUBSYSTEM) ", 1085 "(IO_DONE_QUEUE) ", 1086 "(SEMAPHORE) ", 1087 "(LOCK_SET) ", 1088 "(CLOCK) ", 1089 "(CLOCK_CTRL) ", /* 26 */ 1090 "(IOKIT_SPARE) ", /* 27 */ 1091 "(NAMED_MEM_ENTRY) ", /* 28 */ 1092 "(IOKIT_CONNECT) ", 1093 "(IOKIT_OBJECT) ", /* 30 */ 1094 "(UPL) ", 1095 "(MEM_OBJ_CONTROL) ", 1096#if CONFIG_MACF_MACH 1097 "(LABELH) ", 1098#endif 1099/* 1100 * Add new entries here. 1101 * Please keep in sync with kern/ipc_kobject.h 1102 */ 1103 "(UNKNOWN) " /* magic catchall */ 1104}; 1105 1106void 1107ipc_object_print( 1108 ipc_object_t object) 1109{ 1110 int kotype; 1111 1112 iprintf("%s", io_active(object) ? "active" : "dead"); 1113 printf(", refs=%d", object->io_references); 1114 printf(", otype=%d", io_otype(object)); 1115 kotype = io_kotype(object); 1116 if (kotype >= 0 && kotype < IKOT_MAX_TYPE) 1117 printf(", kotype=%d %s\n", io_kotype(object), 1118 ikot_print_array[kotype]); 1119 else 1120 printf(", kotype=0x%x %s\n", io_kotype(object), 1121 ikot_print_array[IKOT_UNKNOWN]); 1122} 1123 1124#endif /* MACH_KDB */ 1125