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_FREE_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_right.c 67 * Author: Rich Draves 68 * Date: 1989 69 * 70 * Functions to manipulate IPC capabilities. 71 */ 72 73#include <mach/boolean.h> 74#include <mach/kern_return.h> 75#include <mach/port.h> 76#include <mach/message.h> 77#include <kern/assert.h> 78#include <kern/misc_protos.h> 79#include <ipc/port.h> 80#include <ipc/ipc_entry.h> 81#include <ipc/ipc_space.h> 82#include <ipc/ipc_object.h> 83#include <ipc/ipc_hash.h> 84#include <ipc/ipc_port.h> 85#include <ipc/ipc_pset.h> 86#include <ipc/ipc_right.h> 87#include <ipc/ipc_notify.h> 88#include <ipc/ipc_table.h> 89#include <security/mac_mach_internal.h> 90 91/* 92 * Routine: ipc_right_lookup_write 93 * Purpose: 94 * Finds an entry in a space, given the name. 95 * Conditions: 96 * Nothing locked. If successful, the space is write-locked. 97 * Returns: 98 * KERN_SUCCESS Found an entry. 99 * KERN_INVALID_TASK The space is dead. 100 * KERN_INVALID_NAME Name doesn't exist in space. 101 */ 102 103kern_return_t 104ipc_right_lookup_write( 105 ipc_space_t space, 106 mach_port_name_t name, 107 ipc_entry_t *entryp) 108{ 109 ipc_entry_t entry; 110 111 assert(space != IS_NULL); 112 113 is_write_lock(space); 114 115 if (!space->is_active) { 116 is_write_unlock(space); 117 return KERN_INVALID_TASK; 118 } 119 120 if ((entry = ipc_entry_lookup(space, name)) == IE_NULL) { 121 is_write_unlock(space); 122 return KERN_INVALID_NAME; 123 } 124 125 *entryp = entry; 126 return KERN_SUCCESS; 127} 128 129/* 130 * Routine: ipc_right_lookup_two_write 131 * Purpose: 132 * Like ipc_right_lookup except that it returns two 133 * entries for two different names that were looked 134 * up under the same space lock. 135 * Conditions: 136 * Nothing locked. If successful, the space is write-locked. 137 * Returns: 138 * KERN_INVALID_TASK The space is dead. 139 * KERN_INVALID_NAME Name doesn't exist in space. 140 */ 141 142kern_return_t 143ipc_right_lookup_two_write( 144 ipc_space_t space, 145 mach_port_name_t name1, 146 ipc_entry_t *entryp1, 147 mach_port_name_t name2, 148 ipc_entry_t *entryp2) 149{ 150 ipc_entry_t entry1; 151 ipc_entry_t entry2; 152 153 assert(space != IS_NULL); 154 155 is_write_lock(space); 156 157 if (!space->is_active) { 158 is_write_unlock(space); 159 return KERN_INVALID_TASK; 160 } 161 162 if ((entry1 = ipc_entry_lookup(space, name1)) == IE_NULL) { 163 is_write_unlock(space); 164 return KERN_INVALID_NAME; 165 } 166 if ((entry2 = ipc_entry_lookup(space, name2)) == IE_NULL) { 167 is_write_unlock(space); 168 return KERN_INVALID_NAME; 169 } 170 *entryp1 = entry1; 171 *entryp2 = entry2; 172 return KERN_SUCCESS; 173} 174 175/* 176 * Routine: ipc_right_reverse 177 * Purpose: 178 * Translate (space, object) -> (name, entry). 179 * Only finds send/receive rights. 180 * Returns TRUE if an entry is found; if so, 181 * the object is locked and active. 182 * Conditions: 183 * The space must be locked (read or write) and active. 184 * Nothing else locked. 185 */ 186 187boolean_t 188ipc_right_reverse( 189 ipc_space_t space, 190 ipc_object_t object, 191 mach_port_name_t *namep, 192 ipc_entry_t *entryp) 193{ 194 ipc_port_t port; 195 mach_port_name_t name; 196 ipc_entry_t entry; 197 198 /* would switch on io_otype to handle multiple types of object */ 199 200 assert(space->is_active); 201 assert(io_otype(object) == IOT_PORT); 202 203 port = (ipc_port_t) object; 204 205 ip_lock(port); 206 if (!ip_active(port)) { 207 ip_unlock(port); 208 209 return FALSE; 210 } 211 212 if (port->ip_receiver == space) { 213 name = port->ip_receiver_name; 214 assert(name != MACH_PORT_NULL); 215 216 entry = ipc_entry_lookup(space, name); 217 218 assert(entry != IE_NULL); 219 assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE); 220 assert(port == (ipc_port_t) entry->ie_object); 221 222 *namep = name; 223 *entryp = entry; 224 return TRUE; 225 } 226 227 if (ipc_hash_lookup(space, (ipc_object_t) port, namep, entryp)) { 228 assert((entry = *entryp) != IE_NULL); 229 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_SEND); 230 assert(port == (ipc_port_t) entry->ie_object); 231 232 return TRUE; 233 } 234 235 ip_unlock(port); 236 return FALSE; 237} 238 239/* 240 * Routine: ipc_right_dnrequest 241 * Purpose: 242 * Make a dead-name request, returning the previously 243 * registered send-once right. If notify is IP_NULL, 244 * just cancels the previously registered request. 245 * 246 * This interacts with the IE_BITS_COMPAT, because they 247 * both use ie_request. If this is a compat entry, then 248 * previous always gets IP_NULL. If notify is IP_NULL, 249 * then the entry remains a compat entry. Otherwise 250 * the real dead-name request is registered and the entry 251 * is no longer a compat entry. 252 * Conditions: 253 * Nothing locked. May allocate memory. 254 * Only consumes/returns refs if successful. 255 * Returns: 256 * KERN_SUCCESS Made/canceled dead-name request. 257 * KERN_INVALID_TASK The space is dead. 258 * KERN_INVALID_NAME Name doesn't exist in space. 259 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights. 260 * KERN_INVALID_ARGUMENT Name denotes dead name, but 261 * immediate is FALSE or notify is IP_NULL. 262 * KERN_UREFS_OVERFLOW Name denotes dead name, but 263 * generating immediate notif. would overflow urefs. 264 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 265 */ 266 267kern_return_t 268ipc_right_dnrequest( 269 ipc_space_t space, 270 mach_port_name_t name, 271 boolean_t immediate, 272 ipc_port_t notify, 273 ipc_port_t *previousp) 274{ 275 ipc_port_t previous; 276 277 for (;;) { 278 ipc_entry_t entry; 279 ipc_entry_bits_t bits; 280 kern_return_t kr; 281 282 kr = ipc_right_lookup_write(space, name, &entry); 283 if (kr != KERN_SUCCESS) 284 return kr; 285 /* space is write-locked and active */ 286 bits = entry->ie_bits; 287 if (bits & MACH_PORT_TYPE_PORT_RIGHTS) { 288 ipc_port_t port; 289 ipc_port_request_index_t request; 290 291 port = (ipc_port_t) entry->ie_object; 292 assert(port != IP_NULL); 293 294 if (!ipc_right_check(space, port, name, entry)) { 295 /* port is locked and active */ 296 297 if (notify == IP_NULL) { 298 previous = ipc_right_dncancel_macro( 299 space, port, name, entry); 300 301 ip_unlock(port); 302 is_write_unlock(space); 303 break; 304 } 305 306 /* 307 * If a registered soright exists, 308 * want to atomically switch with it. 309 * If ipc_port_dncancel finds us a 310 * soright, then the following 311 * ipc_port_dnrequest will reuse 312 * that slot, so we are guaranteed 313 * not to unlock and retry. 314 */ 315 316 previous = ipc_right_dncancel_macro(space, 317 port, name, entry); 318 319 kr = ipc_port_dnrequest(port, name, notify, 320 &request); 321 if (kr != KERN_SUCCESS) { 322 assert(previous == IP_NULL); 323 is_write_unlock(space); 324 325 kr = ipc_port_dngrow(port, 326 ITS_SIZE_NONE); 327 /* port is unlocked */ 328 if (kr != KERN_SUCCESS) 329 return kr; 330 331 continue; 332 } 333 334 assert(request != 0); 335 ip_unlock(port); 336 337 entry->ie_request = request; 338 is_write_unlock(space); 339 break; 340 } else { 341 342 /* 343 * Our capability bits were changed by ipc_right_check 344 * because it found an inactive port and removed our 345 * references to it (converting our entry into a dead 346 * one). Reload the bits (and obviously we can't use 347 * the port name anymore). 348 */ 349 bits = entry->ie_bits; 350 351 } 352 353 assert(bits & MACH_PORT_TYPE_DEAD_NAME); 354 } 355 356 if ((bits & MACH_PORT_TYPE_DEAD_NAME) && 357 immediate && (notify != IP_NULL)) { 358 mach_port_urefs_t urefs = IE_BITS_UREFS(bits); 359 360 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 361 assert(urefs > 0); 362 363 if (MACH_PORT_UREFS_OVERFLOW(urefs, 1)) { 364 is_write_unlock(space); 365 return KERN_UREFS_OVERFLOW; 366 } 367 368 (entry->ie_bits)++; /* increment urefs */ 369 is_write_unlock(space); 370 371 ipc_notify_dead_name(notify, name); 372 previous = IP_NULL; 373 break; 374 } 375 376 is_write_unlock(space); 377 if (bits & MACH_PORT_TYPE_PORT_OR_DEAD) 378 return KERN_INVALID_ARGUMENT; 379 else 380 return KERN_INVALID_RIGHT; 381 } 382 383 *previousp = previous; 384 return KERN_SUCCESS; 385} 386 387/* 388 * Routine: ipc_right_dncancel 389 * Purpose: 390 * Cancel a dead-name request and return the send-once right. 391 * Afterwards, entry->ie_request == 0. 392 * Conditions: 393 * The space must be write-locked; the port must be locked. 394 * The port must be active; the space doesn't have to be. 395 */ 396 397ipc_port_t 398ipc_right_dncancel( 399 __unused ipc_space_t space, 400 ipc_port_t port, 401 mach_port_name_t name, 402 ipc_entry_t entry) 403{ 404 ipc_port_t dnrequest; 405 406 assert(ip_active(port)); 407 assert(port == (ipc_port_t) entry->ie_object); 408 409 dnrequest = ipc_port_dncancel(port, name, entry->ie_request); 410 entry->ie_request = 0; 411 412 return dnrequest; 413} 414 415/* 416 * Routine: ipc_right_inuse 417 * Purpose: 418 * Check if an entry is being used. 419 * Returns TRUE if it is. 420 * Conditions: 421 * The space is write-locked and active. 422 * It is unlocked if the entry is inuse. 423 */ 424 425boolean_t 426ipc_right_inuse( 427 ipc_space_t space, 428 __unused mach_port_name_t name, 429 ipc_entry_t entry) 430{ 431 if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_NONE) { 432 is_write_unlock(space); 433 return TRUE; 434 } 435 return FALSE; 436} 437 438/* 439 * Routine: ipc_right_check 440 * Purpose: 441 * Check if the port has died. If it has, 442 * clean up the entry and return TRUE. 443 * Conditions: 444 * The space is write-locked; the port is not locked. 445 * If returns FALSE, the port is also locked and active. 446 * Otherwise, entry is converted to a dead name, freeing 447 * a reference to port. 448 */ 449 450boolean_t 451ipc_right_check( 452 ipc_space_t space, 453 ipc_port_t port, 454 mach_port_name_t name, 455 ipc_entry_t entry) 456{ 457 ipc_entry_bits_t bits; 458 459 assert(space->is_active); 460 assert(port == (ipc_port_t) entry->ie_object); 461 462 ip_lock(port); 463 if (ip_active(port)) 464 return FALSE; 465 ip_unlock(port); 466 467 /* this was either a pure send right or a send-once right */ 468 469 bits = entry->ie_bits; 470 assert((bits & MACH_PORT_TYPE_RECEIVE) == 0); 471 assert(IE_BITS_UREFS(bits) > 0); 472 473 if (bits & MACH_PORT_TYPE_SEND) { 474 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 475 } else { 476 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 477 assert(IE_BITS_UREFS(bits) == 1); 478 } 479 480 481 ipc_port_release(port); 482 483 /* convert entry to dead name */ 484 485 if ((bits & MACH_PORT_TYPE_SEND) && !(bits & MACH_PORT_TYPE_RECEIVE)) 486 ipc_hash_delete(space, (ipc_object_t)port, name, entry); 487 488 bits = (bits &~ IE_BITS_TYPE_MASK) | MACH_PORT_TYPE_DEAD_NAME; 489 490 /* 491 * If there was a notification request outstanding on this 492 * name, and since the port went dead, that notification 493 * must already be on its way up from the port layer. We 494 * don't need the index of the notification port anymore. 495 * 496 * JMM - We also add a reference to the entry since the 497 * notification only carries the name and NOT a reference 498 * (or right). This makes for pretty loose reference 499 * counting, since it is only happenstance that we 500 * detected the notification in progress like this. 501 * But most (all?) calls that try to deal with this entry 502 * will also come through here, so the reference gets added 503 * before the entry gets used eventually (I would rather it 504 * be explicit in the notification generation, though) 505 */ 506 if (entry->ie_request != 0) { 507 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX); 508 entry->ie_request = 0; 509 bits++; 510 } 511 entry->ie_bits = bits; 512 entry->ie_object = IO_NULL; 513 return TRUE; 514} 515 516/* 517 * Routine: ipc_right_clean 518 * Purpose: 519 * Cleans up an entry in a dead space. 520 * The entry isn't deallocated or removed 521 * from reverse hash tables. 522 * Conditions: 523 * The space is dead and unlocked. 524 */ 525 526void 527ipc_right_clean( 528 ipc_space_t space, 529 mach_port_name_t name, 530 ipc_entry_t entry) 531{ 532 ipc_entry_bits_t bits; 533 mach_port_type_t type; 534 535 bits = entry->ie_bits; 536 type = IE_BITS_TYPE(bits); 537 538 assert(!space->is_active); 539 540 /* 541 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this 542 * problem, because we check that the port is active. If 543 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy 544 * would still work, but dead space refs would accumulate 545 * in ip_dnrequests. They would use up slots in 546 * ip_dnrequests and keep the spaces from being freed. 547 */ 548 549 switch (type) { 550 case MACH_PORT_TYPE_DEAD_NAME: 551 assert(entry->ie_request == 0); 552 assert(entry->ie_object == IO_NULL); 553 break; 554 555 case MACH_PORT_TYPE_PORT_SET: { 556 ipc_pset_t pset = (ipc_pset_t) entry->ie_object; 557 558 assert(entry->ie_request == 0); 559 assert(pset != IPS_NULL); 560 561 ips_lock(pset); 562 assert(ips_active(pset)); 563 564 ipc_pset_destroy(pset); /* consumes ref, unlocks */ 565 break; 566 } 567 568 case MACH_PORT_TYPE_SEND: 569 case MACH_PORT_TYPE_RECEIVE: 570 case MACH_PORT_TYPE_SEND_RECEIVE: 571 case MACH_PORT_TYPE_SEND_ONCE: { 572 ipc_port_t port = (ipc_port_t) entry->ie_object; 573 ipc_port_t dnrequest; 574 ipc_port_t nsrequest = IP_NULL; 575 mach_port_mscount_t mscount = 0; 576 577 assert(port != IP_NULL); 578 ip_lock(port); 579 580 if (!ip_active(port)) { 581 ip_release(port); 582 ip_check_unlock(port); 583 break; 584 } 585 586 dnrequest = ipc_right_dncancel_macro(space, port, 587 name, entry); 588 589 if (type & MACH_PORT_TYPE_SEND) { 590 assert(port->ip_srights > 0); 591 if (--port->ip_srights == 0 592 ) { 593 nsrequest = port->ip_nsrequest; 594 if (nsrequest != IP_NULL) { 595 port->ip_nsrequest = IP_NULL; 596 mscount = port->ip_mscount; 597 } 598 } 599 } 600 601 if (type & MACH_PORT_TYPE_RECEIVE) { 602 assert(port->ip_receiver_name == name); 603 assert(port->ip_receiver == space); 604 605 ipc_port_clear_receiver(port); 606 ipc_port_destroy(port); /* consumes our ref, unlocks */ 607 } else if (type & MACH_PORT_TYPE_SEND_ONCE) { 608 assert(port->ip_sorights > 0); 609 ip_unlock(port); 610 611 ipc_notify_send_once(port); /* consumes our ref */ 612 } else { 613 assert(port->ip_receiver != space); 614 615 ip_release(port); 616 ip_unlock(port); /* port is active */ 617 } 618 619 if (nsrequest != IP_NULL) 620 ipc_notify_no_senders(nsrequest, mscount); 621 622 if (dnrequest != IP_NULL) 623 ipc_notify_port_deleted(dnrequest, name); 624 break; 625 } 626 627 default: 628 panic("ipc_right_clean: strange type - 0x%x", type); 629 } 630} 631 632/* 633 * Routine: ipc_right_destroy 634 * Purpose: 635 * Destroys an entry in a space. 636 * Conditions: 637 * The space is write-locked. 638 * The space must be active. 639 * Returns: 640 * KERN_SUCCESS The entry was destroyed. 641 */ 642 643kern_return_t 644ipc_right_destroy( 645 ipc_space_t space, 646 mach_port_name_t name, 647 ipc_entry_t entry) 648{ 649 ipc_entry_bits_t bits; 650 mach_port_type_t type; 651 652 bits = entry->ie_bits; 653 entry->ie_bits &= ~IE_BITS_TYPE_MASK; 654 type = IE_BITS_TYPE(bits); 655 656 assert(space->is_active); 657 658 switch (type) { 659 case MACH_PORT_TYPE_DEAD_NAME: 660 assert(entry->ie_request == 0); 661 assert(entry->ie_object == IO_NULL); 662 663 ipc_entry_dealloc(space, name, entry); 664 break; 665 666 case MACH_PORT_TYPE_PORT_SET: { 667 ipc_pset_t pset = (ipc_pset_t) entry->ie_object; 668 669 assert(entry->ie_request == 0); 670 assert(pset != IPS_NULL); 671 672 entry->ie_object = IO_NULL; 673 ipc_entry_dealloc(space, name, entry); 674 675 ips_lock(pset); 676 assert(ips_active(pset)); 677 678 ipc_pset_destroy(pset); /* consumes ref, unlocks */ 679 break; 680 } 681 682 case MACH_PORT_TYPE_SEND: 683 case MACH_PORT_TYPE_RECEIVE: 684 case MACH_PORT_TYPE_SEND_RECEIVE: 685 case MACH_PORT_TYPE_SEND_ONCE: { 686 ipc_port_t port = (ipc_port_t) entry->ie_object; 687 ipc_port_t nsrequest = IP_NULL; 688 mach_port_mscount_t mscount = 0; 689 ipc_port_t dnrequest; 690 691 assert(port != IP_NULL); 692 693 if (type == MACH_PORT_TYPE_SEND) 694 ipc_hash_delete(space, (ipc_object_t) port, 695 name, entry); 696 697 ip_lock(port); 698 699 if (!ip_active(port)) { 700 assert((type & MACH_PORT_TYPE_RECEIVE) == 0); 701 ip_release(port); 702 ip_check_unlock(port); 703 704 entry->ie_request = 0; 705 entry->ie_object = IO_NULL; 706 ipc_entry_dealloc(space, name, entry); 707 708 break; 709 } 710 711 dnrequest = ipc_right_dncancel_macro(space, port, name, entry); 712 713 entry->ie_object = IO_NULL; 714 ipc_entry_dealloc(space, name, entry); 715 716 if (type & MACH_PORT_TYPE_SEND) { 717 assert(port->ip_srights > 0); 718 if (--port->ip_srights == 0) { 719 nsrequest = port->ip_nsrequest; 720 if (nsrequest != IP_NULL) { 721 port->ip_nsrequest = IP_NULL; 722 mscount = port->ip_mscount; 723 } 724 } 725 } 726 727 if (type & MACH_PORT_TYPE_RECEIVE) { 728 assert(ip_active(port)); 729 assert(port->ip_receiver == space); 730 731 ipc_port_clear_receiver(port); 732 ipc_port_destroy(port); /* consumes our ref, unlocks */ 733 } else if (type & MACH_PORT_TYPE_SEND_ONCE) { 734 assert(port->ip_sorights > 0); 735 ip_unlock(port); 736 737 ipc_notify_send_once(port); /* consumes our ref */ 738 } else { 739 assert(port->ip_receiver != space); 740 741 ip_release(port); 742 ip_unlock(port); 743 } 744 745 if (nsrequest != IP_NULL) 746 ipc_notify_no_senders(nsrequest, mscount); 747 748 if (dnrequest != IP_NULL) 749 ipc_notify_port_deleted(dnrequest, name); 750 break; 751 } 752 753 default: 754 panic("ipc_right_destroy: strange type"); 755 } 756 757 return KERN_SUCCESS; 758} 759 760/* 761 * Routine: ipc_right_dealloc 762 * Purpose: 763 * Releases a send/send-once/dead-name user ref. 764 * Like ipc_right_delta with a delta of -1, 765 * but looks at the entry to determine the right. 766 * Conditions: 767 * The space is write-locked, and is unlocked upon return. 768 * The space must be active. 769 * Returns: 770 * KERN_SUCCESS A user ref was released. 771 * KERN_INVALID_RIGHT Entry has wrong type. 772 */ 773 774kern_return_t 775ipc_right_dealloc( 776 ipc_space_t space, 777 mach_port_name_t name, 778 ipc_entry_t entry) 779{ 780 781 ipc_entry_bits_t bits; 782 mach_port_type_t type; 783 784 bits = entry->ie_bits; 785 type = IE_BITS_TYPE(bits); 786 787 788 assert(space->is_active); 789 790 switch (type) { 791 case MACH_PORT_TYPE_DEAD_NAME: { 792 dead_name: 793 794 assert(IE_BITS_UREFS(bits) > 0); 795 assert(entry->ie_request == 0); 796 assert(entry->ie_object == IO_NULL); 797 798 if (IE_BITS_UREFS(bits) == 1) { 799 ipc_entry_dealloc(space, name, entry); 800 } 801 else 802 entry->ie_bits = bits-1; /* decrement urefs */ 803 804 is_write_unlock(space); 805 break; 806 } 807 808 case MACH_PORT_TYPE_SEND_ONCE: { 809 ipc_port_t port, dnrequest; 810 811 assert(IE_BITS_UREFS(bits) == 1); 812 813 port = (ipc_port_t) entry->ie_object; 814 assert(port != IP_NULL); 815 816 if (ipc_right_check(space, port, name, entry)) { 817 818 bits = entry->ie_bits; 819 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 820 goto dead_name; 821 } 822 /* port is locked and active */ 823 824 assert(port->ip_sorights > 0); 825 826 dnrequest = ipc_right_dncancel_macro(space, port, name, entry); 827 ip_unlock(port); 828 829 entry->ie_object = IO_NULL; 830 ipc_entry_dealloc(space, name, entry); 831 832 is_write_unlock(space); 833 834 ipc_notify_send_once(port); 835 836 if (dnrequest != IP_NULL) 837 ipc_notify_port_deleted(dnrequest, name); 838 break; 839 } 840 841 case MACH_PORT_TYPE_SEND: { 842 ipc_port_t port; 843 ipc_port_t dnrequest = IP_NULL; 844 ipc_port_t nsrequest = IP_NULL; 845 mach_port_mscount_t mscount = 0; 846 847 848 assert(IE_BITS_UREFS(bits) > 0); 849 850 port = (ipc_port_t) entry->ie_object; 851 assert(port != IP_NULL); 852 853 if (ipc_right_check(space, port, name, entry)) { 854 bits = entry->ie_bits; 855 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 856 goto dead_name; 857 } 858 /* port is locked and active */ 859 860 assert(port->ip_srights > 0); 861 862 if (IE_BITS_UREFS(bits) == 1) { 863 if (--port->ip_srights == 0) { 864 nsrequest = port->ip_nsrequest; 865 if (nsrequest != IP_NULL) { 866 port->ip_nsrequest = IP_NULL; 867 mscount = port->ip_mscount; 868 } 869 } 870 871 dnrequest = ipc_right_dncancel_macro(space, port, 872 name, entry); 873 ipc_hash_delete(space, (ipc_object_t) port, 874 name, entry); 875 876 ip_release(port); 877 entry->ie_object = IO_NULL; 878 ipc_entry_dealloc(space, name, entry); 879 880 } else 881 entry->ie_bits = bits-1; /* decrement urefs */ 882 883 /* even if dropped a ref, port is active */ 884 ip_unlock(port); 885 is_write_unlock(space); 886 887 if (nsrequest != IP_NULL) 888 ipc_notify_no_senders(nsrequest, mscount); 889 890 if (dnrequest != IP_NULL) 891 ipc_notify_port_deleted(dnrequest, name); 892 break; 893 } 894 895 case MACH_PORT_TYPE_SEND_RECEIVE: { 896 ipc_port_t port; 897 ipc_port_t nsrequest = IP_NULL; 898 mach_port_mscount_t mscount = 0; 899 900 assert(IE_BITS_UREFS(bits) > 0); 901 902 port = (ipc_port_t) entry->ie_object; 903 assert(port != IP_NULL); 904 905 ip_lock(port); 906 assert(ip_active(port)); 907 assert(port->ip_receiver_name == name); 908 assert(port->ip_receiver == space); 909 assert(port->ip_srights > 0); 910 911 if (IE_BITS_UREFS(bits) == 1) { 912 if (--port->ip_srights == 0) { 913 nsrequest = port->ip_nsrequest; 914 if (nsrequest != IP_NULL) { 915 port->ip_nsrequest = IP_NULL; 916 mscount = port->ip_mscount; 917 } 918 } 919 920 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK | 921 MACH_PORT_TYPE_SEND); 922 } else 923 entry->ie_bits = bits-1; /* decrement urefs */ 924 925 ip_unlock(port); 926 is_write_unlock(space); 927 928 if (nsrequest != IP_NULL) 929 ipc_notify_no_senders(nsrequest, mscount); 930 break; 931 } 932 933 default: 934 is_write_unlock(space); 935 return KERN_INVALID_RIGHT; 936 } 937 938 return KERN_SUCCESS; 939} 940 941/* 942 * Routine: ipc_right_delta 943 * Purpose: 944 * Modifies the user-reference count for a right. 945 * May deallocate the right, if the count goes to zero. 946 * Conditions: 947 * The space is write-locked, and is unlocked upon return. 948 * The space must be active. 949 * Returns: 950 * KERN_SUCCESS Count was modified. 951 * KERN_INVALID_RIGHT Entry has wrong type. 952 * KERN_INVALID_VALUE Bad delta for the right. 953 * KERN_UREFS_OVERFLOW OK delta, except would overflow. 954 */ 955 956kern_return_t 957ipc_right_delta( 958 ipc_space_t space, 959 mach_port_name_t name, 960 ipc_entry_t entry, 961 mach_port_right_t right, 962 mach_port_delta_t delta) 963{ 964 ipc_entry_bits_t bits; 965 966 bits = entry->ie_bits; 967 968 969/* 970 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the 971 * switch below. It is used to keep track of those cases (in DIPC) 972 * where we have postponed the dropping of a port reference. Since 973 * the dropping of the reference could cause the port to disappear 974 * we postpone doing so when we are holding the space lock. 975 */ 976 977 assert(space->is_active); 978 assert(right < MACH_PORT_RIGHT_NUMBER); 979 980 /* Rights-specific restrictions and operations. */ 981 982 switch (right) { 983 case MACH_PORT_RIGHT_PORT_SET: { 984 ipc_pset_t pset; 985 986 if ((bits & MACH_PORT_TYPE_PORT_SET) == 0) 987 goto invalid_right; 988 989 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_PORT_SET); 990 assert(IE_BITS_UREFS(bits) == 0); 991 assert(entry->ie_request == 0); 992 993 if (delta == 0) 994 goto success; 995 996 if (delta != -1) 997 goto invalid_value; 998 999 pset = (ipc_pset_t) entry->ie_object; 1000 assert(pset != IPS_NULL); 1001 1002 1003 1004 entry->ie_object = IO_NULL; 1005 ipc_entry_dealloc(space, name, entry); 1006 1007 1008 ips_lock(pset); 1009 assert(ips_active(pset)); 1010 is_write_unlock(space); 1011 1012 ipc_pset_destroy(pset); /* consumes ref, unlocks */ 1013 break; 1014 } 1015 1016 case MACH_PORT_RIGHT_RECEIVE: { 1017 ipc_port_t port; 1018 ipc_port_t dnrequest = IP_NULL; 1019 1020 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1021 goto invalid_right; 1022 1023 if (delta == 0) 1024 goto success; 1025 1026 if (delta != -1) 1027 goto invalid_value; 1028 1029 port = (ipc_port_t) entry->ie_object; 1030 assert(port != IP_NULL); 1031 1032 /* 1033 * The port lock is needed for ipc_right_dncancel; 1034 * otherwise, we wouldn't have to take the lock 1035 * until just before dropping the space lock. 1036 */ 1037 1038 ip_lock(port); 1039 assert(ip_active(port)); 1040 assert(port->ip_receiver_name == name); 1041 assert(port->ip_receiver == space); 1042 1043 if (bits & MACH_PORT_TYPE_SEND) { 1044 assert(IE_BITS_TYPE(bits) == 1045 MACH_PORT_TYPE_SEND_RECEIVE); 1046 assert(IE_BITS_UREFS(bits) > 0); 1047 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX); 1048 assert(port->ip_srights > 0); 1049 1050 /* 1051 * The remaining send right turns into a 1052 * dead name. Notice we don't decrement 1053 * ip_srights, generate a no-senders notif, 1054 * or use ipc_right_dncancel, because the 1055 * port is destroyed "first". 1056 */ 1057 bits &= ~IE_BITS_TYPE_MASK; 1058 bits |= MACH_PORT_TYPE_DEAD_NAME; 1059 if (entry->ie_request) { 1060 entry->ie_request = 0; 1061 bits++; 1062 } 1063 entry->ie_bits = bits; 1064 entry->ie_object = IO_NULL; 1065 } else { 1066 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE); 1067 assert(IE_BITS_UREFS(bits) == 0); 1068 1069 dnrequest = ipc_right_dncancel_macro(space, port, 1070 name, entry); 1071 entry->ie_object = IO_NULL; 1072 ipc_entry_dealloc(space, name, entry); 1073 } 1074 is_write_unlock(space); 1075 1076 ipc_port_clear_receiver(port); 1077 ipc_port_destroy(port); /* consumes ref, unlocks */ 1078 1079 if (dnrequest != IP_NULL) 1080 ipc_notify_port_deleted(dnrequest, name); 1081 break; 1082 } 1083 1084 case MACH_PORT_RIGHT_SEND_ONCE: { 1085 ipc_port_t port, dnrequest; 1086 1087 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) 1088 goto invalid_right; 1089 1090 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 1091 assert(IE_BITS_UREFS(bits) == 1); 1092 1093 port = (ipc_port_t) entry->ie_object; 1094 assert(port != IP_NULL); 1095 1096 if (ipc_right_check(space, port, name, entry)) { 1097 assert(!(entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE)); 1098 goto invalid_right; 1099 } 1100 /* port is locked and active */ 1101 1102 assert(port->ip_sorights > 0); 1103 1104 if ((delta > 0) || (delta < -1)) { 1105 ip_unlock(port); 1106 goto invalid_value; 1107 } 1108 1109 if (delta == 0) { 1110 ip_unlock(port); 1111 goto success; 1112 } 1113 1114 dnrequest = ipc_right_dncancel_macro(space, port, name, entry); 1115 ip_unlock(port); 1116 1117 entry->ie_object = IO_NULL; 1118 ipc_entry_dealloc(space, name, entry); 1119 1120 is_write_unlock(space); 1121 1122 ipc_notify_send_once(port); 1123 1124 if (dnrequest != IP_NULL) 1125 ipc_notify_port_deleted(dnrequest, name); 1126 break; 1127 } 1128 1129 case MACH_PORT_RIGHT_DEAD_NAME: { 1130 mach_port_urefs_t urefs; 1131 1132 if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { 1133 ipc_port_t port; 1134 1135 port = (ipc_port_t) entry->ie_object; 1136 assert(port != IP_NULL); 1137 1138 if (!ipc_right_check(space, port, name, entry)) { 1139 /* port is locked and active */ 1140 ip_unlock(port); 1141 goto invalid_right; 1142 } 1143 bits = entry->ie_bits; 1144 } else if ((bits & MACH_PORT_TYPE_DEAD_NAME) == 0) 1145 goto invalid_right; 1146 1147 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 1148 assert(IE_BITS_UREFS(bits) > 0); 1149 assert(entry->ie_object == IO_NULL); 1150 assert(entry->ie_request == 0); 1151 1152 urefs = IE_BITS_UREFS(bits); 1153 if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta)) 1154 goto invalid_value; 1155 if (MACH_PORT_UREFS_OVERFLOW(urefs, delta)) 1156 goto urefs_overflow; 1157 1158 if ((urefs + delta) == 0) { 1159 ipc_entry_dealloc(space, name, entry); 1160 } 1161 else 1162 entry->ie_bits = bits + delta; 1163 1164 is_write_unlock(space); 1165 1166 break; 1167 } 1168 1169 case MACH_PORT_RIGHT_SEND: { 1170 mach_port_urefs_t urefs; 1171 ipc_port_t port; 1172 ipc_port_t dnrequest = IP_NULL; 1173 ipc_port_t nsrequest = IP_NULL; 1174 mach_port_mscount_t mscount = 0; 1175 1176 if ((bits & MACH_PORT_TYPE_SEND) == 0) 1177 goto invalid_right; 1178 1179 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */ 1180 1181 port = (ipc_port_t) entry->ie_object; 1182 assert(port != IP_NULL); 1183 1184 if (ipc_right_check(space, port, name, entry)) { 1185 assert((entry->ie_bits & MACH_PORT_TYPE_SEND) == 0); 1186 goto invalid_right; 1187 } 1188 /* port is locked and active */ 1189 1190 assert(port->ip_srights > 0); 1191 1192 urefs = IE_BITS_UREFS(bits); 1193 if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta)) { 1194 ip_unlock(port); 1195 goto invalid_value; 1196 } 1197 if (MACH_PORT_UREFS_OVERFLOW(urefs+1, delta)) { 1198 ip_unlock(port); 1199 goto urefs_overflow; 1200 } 1201 1202 if ((urefs + delta) == 0) { 1203 if (--port->ip_srights == 0) { 1204 nsrequest = port->ip_nsrequest; 1205 if (nsrequest != IP_NULL) { 1206 port->ip_nsrequest = IP_NULL; 1207 mscount = port->ip_mscount; 1208 } 1209 } 1210 1211 if (bits & MACH_PORT_TYPE_RECEIVE) { 1212 assert(port->ip_receiver_name == name); 1213 assert(port->ip_receiver == space); 1214 assert(IE_BITS_TYPE(bits) == 1215 MACH_PORT_TYPE_SEND_RECEIVE); 1216 1217 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK| 1218 MACH_PORT_TYPE_SEND); 1219 } else { 1220 assert(IE_BITS_TYPE(bits) == 1221 MACH_PORT_TYPE_SEND); 1222 1223 dnrequest = ipc_right_dncancel_macro(space, port, 1224 name, entry); 1225 ipc_hash_delete(space, (ipc_object_t) port, 1226 name, entry); 1227 1228 ip_release(port); 1229 1230 entry->ie_object = IO_NULL; 1231 ipc_entry_dealloc(space, name, entry); 1232 } 1233 } else 1234 entry->ie_bits = bits + delta; 1235 1236 /* even if dropped a ref, port is active */ 1237 ip_unlock(port); 1238 is_write_unlock(space); 1239 1240 if (nsrequest != IP_NULL) 1241 ipc_notify_no_senders(nsrequest, mscount); 1242 1243 if (dnrequest != IP_NULL) 1244 ipc_notify_port_deleted(dnrequest, name); 1245 break; 1246 } 1247 1248 default: 1249 panic("ipc_right_delta: strange right"); 1250 } 1251 1252 return KERN_SUCCESS; 1253 1254 success: 1255 is_write_unlock(space); 1256 return KERN_SUCCESS; 1257 1258 invalid_right: 1259 is_write_unlock(space); 1260 return KERN_INVALID_RIGHT; 1261 1262 invalid_value: 1263 is_write_unlock(space); 1264 return KERN_INVALID_VALUE; 1265 1266 urefs_overflow: 1267 is_write_unlock(space); 1268 return KERN_UREFS_OVERFLOW; 1269} 1270 1271/* 1272 * Routine: ipc_right_info 1273 * Purpose: 1274 * Retrieves information about the right. 1275 * Conditions: 1276 * The space is write-locked, and is unlocked upon return 1277 * if the call is unsuccessful. The space must be active. 1278 * Returns: 1279 * KERN_SUCCESS Retrieved info; space still locked. 1280 */ 1281 1282kern_return_t 1283ipc_right_info( 1284 ipc_space_t space, 1285 mach_port_name_t name, 1286 ipc_entry_t entry, 1287 mach_port_type_t *typep, 1288 mach_port_urefs_t *urefsp) 1289{ 1290 ipc_entry_bits_t bits; 1291 mach_port_type_t type; 1292 ipc_port_request_index_t request; 1293 1294 bits = entry->ie_bits; 1295 1296 if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { 1297 ipc_port_t port = (ipc_port_t) entry->ie_object; 1298 1299 if (ipc_right_check(space, port, name, entry)) { 1300 bits = entry->ie_bits; 1301 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 1302 } else 1303 ip_unlock(port); 1304 } 1305 1306 type = IE_BITS_TYPE(bits); 1307 request = entry->ie_request; 1308 1309 if (request != 0) 1310 type |= MACH_PORT_TYPE_DNREQUEST; 1311 1312 *typep = type; 1313 *urefsp = IE_BITS_UREFS(bits); 1314 return KERN_SUCCESS; 1315} 1316 1317/* 1318 * Routine: ipc_right_copyin_check 1319 * Purpose: 1320 * Check if a subsequent ipc_right_copyin would succeed. 1321 * Conditions: 1322 * The space is locked (read or write) and active. 1323 */ 1324 1325boolean_t 1326ipc_right_copyin_check( 1327 __assert_only ipc_space_t space, 1328 __unused mach_port_name_t name, 1329 ipc_entry_t entry, 1330 mach_msg_type_name_t msgt_name) 1331{ 1332 ipc_entry_bits_t bits; 1333 ipc_port_t port; 1334#if CONFIG_MACF_MACH 1335 task_t self = current_task(); 1336 int rc = 0; 1337#endif 1338 1339 bits= entry->ie_bits; 1340 assert(space->is_active); 1341 1342 switch (msgt_name) { 1343 case MACH_MSG_TYPE_MAKE_SEND: 1344 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1345 return FALSE; 1346 1347#if CONFIG_MACF_MACH 1348 port = (ipc_port_t) entry->ie_object; 1349 ip_lock(port); 1350 tasklabel_lock(self); 1351 rc = mac_port_check_make_send(&self->maclabel, &port->ip_label); tasklabel_unlock(self); 1352 ip_unlock(port); 1353 if (rc) 1354 return FALSE; 1355#endif 1356 break; 1357 1358 case MACH_MSG_TYPE_MAKE_SEND_ONCE: 1359 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1360 return FALSE; 1361 1362#if CONFIG_MACF_MACH 1363 port = (ipc_port_t) entry->ie_object; 1364 ip_lock(port); 1365 tasklabel_lock(self); 1366 rc = mac_port_check_make_send_once(&self->maclabel, &port->ip_label); 1367 tasklabel_unlock(self); 1368 ip_unlock(port); 1369 if (rc) 1370 return FALSE; 1371#endif 1372 break; 1373 1374 case MACH_MSG_TYPE_MOVE_RECEIVE: 1375 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1376 return FALSE; 1377 1378#if CONFIG_MACF_MACH 1379 port = (ipc_port_t) entry->ie_object; 1380 ip_lock(port); 1381 tasklabel_lock(self); 1382 rc = mac_port_check_move_receive(&self->maclabel, &port->ip_label); 1383 tasklabel_unlock(self); 1384 ip_unlock(port); 1385 if (rc) 1386 return FALSE; 1387#endif 1388 break; 1389 1390 case MACH_MSG_TYPE_COPY_SEND: 1391 case MACH_MSG_TYPE_MOVE_SEND: 1392 case MACH_MSG_TYPE_MOVE_SEND_ONCE: { 1393 boolean_t active; 1394 1395 if (bits & MACH_PORT_TYPE_DEAD_NAME) 1396 break; 1397 1398 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 1399 return FALSE; 1400 1401 port = (ipc_port_t) entry->ie_object; 1402 assert(port != IP_NULL); 1403 1404 ip_lock(port); 1405 active = ip_active(port); 1406#if CONFIG_MACF_MACH 1407 tasklabel_lock(self); 1408 switch (msgt_name) { 1409 case MACH_MSG_TYPE_COPY_SEND: 1410 rc = mac_port_check_copy_send(&self->maclabel, 1411 &port->ip_label); 1412 break; 1413 case MACH_MSG_TYPE_MOVE_SEND: 1414 rc = mac_port_check_move_send(&self->maclabel, 1415 &port->ip_label); 1416 break; 1417 case MACH_MSG_TYPE_MOVE_SEND_ONCE: 1418 rc = mac_port_check_move_send_once(&self->maclabel, 1419 &port->ip_label); 1420 break; 1421 default: 1422 panic("ipc_right_copyin_check: strange rights"); 1423 } 1424 tasklabel_unlock(self); 1425 if (rc) { 1426 ip_unlock(port); 1427 return FALSE; 1428 } 1429#endif 1430 ip_unlock(port); 1431 1432 if (!active) { 1433 break; 1434 } 1435 1436 if (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE) { 1437 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) 1438 return FALSE; 1439 } else { 1440 if ((bits & MACH_PORT_TYPE_SEND) == 0) 1441 return FALSE; 1442 } 1443 1444 break; 1445 } 1446 1447 default: 1448 panic("ipc_right_copyin_check: strange rights"); 1449 } 1450 1451 return TRUE; 1452} 1453 1454/* 1455 * Routine: ipc_right_copyin 1456 * Purpose: 1457 * Copyin a capability from a space. 1458 * If successful, the caller gets a ref 1459 * for the resulting object, unless it is IO_DEAD, 1460 * and possibly a send-once right which should 1461 * be used in a port-deleted notification. 1462 * 1463 * If deadok is not TRUE, the copyin operation 1464 * will fail instead of producing IO_DEAD. 1465 * 1466 * The entry is never deallocated (except 1467 * when KERN_INVALID_NAME), so the caller 1468 * should deallocate the entry if its type 1469 * is MACH_PORT_TYPE_NONE. 1470 * Conditions: 1471 * The space is write-locked and active. 1472 * Returns: 1473 * KERN_SUCCESS Acquired an object, possibly IO_DEAD. 1474 * KERN_INVALID_RIGHT Name doesn't denote correct right. 1475 */ 1476 1477kern_return_t 1478ipc_right_copyin( 1479 ipc_space_t space, 1480 mach_port_name_t name, 1481 ipc_entry_t entry, 1482 mach_msg_type_name_t msgt_name, 1483 boolean_t deadok, 1484 ipc_object_t *objectp, 1485 ipc_port_t *sorightp) 1486{ 1487 ipc_entry_bits_t bits; 1488#if CONFIG_MACF_MACH 1489 task_t self = current_task(); 1490 int rc; 1491#endif 1492 1493 bits = entry->ie_bits; 1494 1495 assert(space->is_active); 1496 1497 switch (msgt_name) { 1498 case MACH_MSG_TYPE_MAKE_SEND: { 1499 ipc_port_t port; 1500 1501 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1502 goto invalid_right; 1503 1504 port = (ipc_port_t) entry->ie_object; 1505 assert(port != IP_NULL); 1506 1507 ip_lock(port); 1508 assert(ip_active(port)); 1509 assert(port->ip_receiver_name == name); 1510 assert(port->ip_receiver == space); 1511 1512#if CONFIG_MACF_MACH 1513 tasklabel_lock(self); 1514 rc = mac_port_check_make_send(&self->maclabel, &port->ip_label); 1515 tasklabel_unlock(self); 1516 if (rc) { 1517 ip_unlock(port); 1518 return KERN_NO_ACCESS; 1519 } 1520#endif 1521 1522 port->ip_mscount++; 1523 port->ip_srights++; 1524 ip_reference(port); 1525 ip_unlock(port); 1526 1527 *objectp = (ipc_object_t) port; 1528 *sorightp = IP_NULL; 1529 break; 1530 } 1531 1532 case MACH_MSG_TYPE_MAKE_SEND_ONCE: { 1533 ipc_port_t port; 1534 1535 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1536 goto invalid_right; 1537 1538 port = (ipc_port_t) entry->ie_object; 1539 assert(port != IP_NULL); 1540 1541 ip_lock(port); 1542 assert(ip_active(port)); 1543 assert(port->ip_receiver_name == name); 1544 assert(port->ip_receiver == space); 1545 1546#if CONFIG_MACF_MACH 1547 tasklabel_lock(self); 1548 rc = mac_port_check_make_send_once(&self->maclabel, &port->ip_label); 1549 tasklabel_unlock(self); 1550 if (rc) { 1551 ip_unlock(port); 1552 return KERN_NO_ACCESS; 1553 } 1554#endif 1555 1556 port->ip_sorights++; 1557 ip_reference(port); 1558 ip_unlock(port); 1559 1560 *objectp = (ipc_object_t) port; 1561 *sorightp = IP_NULL; 1562 break; 1563 } 1564 1565 case MACH_MSG_TYPE_MOVE_RECEIVE: { 1566 ipc_port_t port; 1567 ipc_port_t dnrequest = IP_NULL; 1568 1569 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1570 goto invalid_right; 1571 1572 port = (ipc_port_t) entry->ie_object; 1573 assert(port != IP_NULL); 1574 1575 ip_lock(port); 1576 assert(ip_active(port)); 1577 assert(port->ip_receiver_name == name); 1578 assert(port->ip_receiver == space); 1579 1580#if CONFIG_MACF_MACH 1581 tasklabel_lock(self); 1582 rc = mac_port_check_move_receive(&self->maclabel, 1583 &port->ip_label); 1584 tasklabel_unlock(self); 1585 if (rc) { 1586 ip_unlock(port); 1587 return KERN_NO_ACCESS; 1588 } 1589#endif 1590 1591 if (bits & MACH_PORT_TYPE_SEND) { 1592 assert(IE_BITS_TYPE(bits) == 1593 MACH_PORT_TYPE_SEND_RECEIVE); 1594 assert(IE_BITS_UREFS(bits) > 0); 1595 assert(port->ip_srights > 0); 1596 1597 ipc_hash_insert(space, (ipc_object_t) port, 1598 name, entry); 1599 ip_reference(port); 1600 } else { 1601 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE); 1602 assert(IE_BITS_UREFS(bits) == 0); 1603 1604 dnrequest = ipc_right_dncancel_macro(space, port, 1605 name, entry); 1606 entry->ie_object = IO_NULL; 1607 } 1608 entry->ie_bits = bits &~ MACH_PORT_TYPE_RECEIVE; 1609 1610 ipc_port_clear_receiver(port); 1611 1612 port->ip_receiver_name = MACH_PORT_NULL; 1613 port->ip_destination = IP_NULL; 1614 ip_unlock(port); 1615 1616 *objectp = (ipc_object_t) port; 1617 *sorightp = dnrequest; 1618 break; 1619 } 1620 1621 case MACH_MSG_TYPE_COPY_SEND: { 1622 ipc_port_t port; 1623 1624 if (bits & MACH_PORT_TYPE_DEAD_NAME) 1625 goto copy_dead; 1626 1627 /* allow for dead send-once rights */ 1628 1629 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 1630 goto invalid_right; 1631 1632 assert(IE_BITS_UREFS(bits) > 0); 1633 1634 port = (ipc_port_t) entry->ie_object; 1635 assert(port != IP_NULL); 1636 1637 if (ipc_right_check(space, port, name, entry)) { 1638 bits = entry->ie_bits; 1639 goto copy_dead; 1640 } 1641 /* port is locked and active */ 1642 1643#if CONFIG_MACF_MACH 1644 tasklabel_lock(self); 1645 rc = mac_port_check_copy_send(&self->maclabel, &port->ip_label); 1646 tasklabel_unlock(self); 1647 if (rc) { 1648 ip_unlock(port); 1649 return KERN_NO_ACCESS; 1650 } 1651#endif 1652 1653 if ((bits & MACH_PORT_TYPE_SEND) == 0) { 1654 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 1655 assert(port->ip_sorights > 0); 1656 1657 ip_unlock(port); 1658 goto invalid_right; 1659 } 1660 1661 assert(port->ip_srights > 0); 1662 1663 port->ip_srights++; 1664 ip_reference(port); 1665 ip_unlock(port); 1666 1667 *objectp = (ipc_object_t) port; 1668 *sorightp = IP_NULL; 1669 break; 1670 } 1671 1672 case MACH_MSG_TYPE_MOVE_SEND: { 1673 ipc_port_t port; 1674 ipc_port_t dnrequest = IP_NULL; 1675 1676 if (bits & MACH_PORT_TYPE_DEAD_NAME) 1677 goto move_dead; 1678 1679 /* allow for dead send-once rights */ 1680 1681 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 1682 goto invalid_right; 1683 1684 assert(IE_BITS_UREFS(bits) > 0); 1685 1686 port = (ipc_port_t) entry->ie_object; 1687 assert(port != IP_NULL); 1688 1689 if (ipc_right_check(space, port, name, entry)) { 1690 bits = entry->ie_bits; 1691 goto move_dead; 1692 } 1693 /* port is locked and active */ 1694 1695#if CONFIG_MACF_MACH 1696 tasklabel_lock (self); 1697 rc = mac_port_check_copy_send (&self->maclabel, &port->ip_label); 1698 tasklabel_unlock (self); 1699 if (rc) 1700 { 1701 ip_unlock (port); 1702 return KERN_NO_ACCESS; 1703 } 1704#endif 1705 1706 if ((bits & MACH_PORT_TYPE_SEND) == 0) { 1707 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 1708 assert(port->ip_sorights > 0); 1709 1710 ip_unlock(port); 1711 goto invalid_right; 1712 } 1713 1714 assert(port->ip_srights > 0); 1715 1716 if (IE_BITS_UREFS(bits) == 1) { 1717 if (bits & MACH_PORT_TYPE_RECEIVE) { 1718 assert(port->ip_receiver_name == name); 1719 assert(port->ip_receiver == space); 1720 assert(IE_BITS_TYPE(bits) == 1721 MACH_PORT_TYPE_SEND_RECEIVE); 1722 1723 ip_reference(port); 1724 } else { 1725 assert(IE_BITS_TYPE(bits) == 1726 MACH_PORT_TYPE_SEND); 1727 1728 dnrequest = ipc_right_dncancel_macro(space, port, 1729 name, entry); 1730 ipc_hash_delete(space, (ipc_object_t) port, 1731 name, entry); 1732 entry->ie_object = IO_NULL; 1733 } 1734 entry->ie_bits = bits &~ 1735 (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND); 1736 } else { 1737 port->ip_srights++; 1738 ip_reference(port); 1739 entry->ie_bits = bits-1; /* decrement urefs */ 1740 } 1741 1742 ip_unlock(port); 1743 1744 *objectp = (ipc_object_t) port; 1745 *sorightp = dnrequest; 1746 break; 1747 } 1748 1749 case MACH_MSG_TYPE_MOVE_SEND_ONCE: { 1750 ipc_port_t port; 1751 ipc_port_t dnrequest; 1752 1753 if (bits & MACH_PORT_TYPE_DEAD_NAME) 1754 goto move_dead; 1755 1756 /* allow for dead send rights */ 1757 1758 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 1759 goto invalid_right; 1760 1761 assert(IE_BITS_UREFS(bits) > 0); 1762 1763 port = (ipc_port_t) entry->ie_object; 1764 assert(port != IP_NULL); 1765 1766 if (ipc_right_check(space, port, name, entry)) { 1767 bits = entry->ie_bits; 1768 goto move_dead; 1769 } 1770 /* port is locked and active */ 1771 1772#if CONFIG_MACF_MACH 1773 tasklabel_lock (self); 1774 rc = mac_port_check_copy_send (&self->maclabel, &port->ip_label); 1775 tasklabel_unlock (self); 1776 if (rc) 1777 { 1778 ip_unlock (port); 1779 return KERN_NO_ACCESS; 1780 } 1781#endif 1782 1783 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) { 1784 assert(bits & MACH_PORT_TYPE_SEND); 1785 assert(port->ip_srights > 0); 1786 1787 ip_unlock(port); 1788 goto invalid_right; 1789 } 1790 1791 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 1792 assert(IE_BITS_UREFS(bits) == 1); 1793 assert(port->ip_sorights > 0); 1794 1795 dnrequest = ipc_right_dncancel_macro(space, port, name, entry); 1796 ip_unlock(port); 1797 1798 entry->ie_object = IO_NULL; 1799 entry->ie_bits = bits &~ 1800 (IE_BITS_UREFS_MASK | MACH_PORT_TYPE_SEND_ONCE); 1801 1802 *objectp = (ipc_object_t) port; 1803 *sorightp = dnrequest; 1804 break; 1805 } 1806 1807 default: 1808 invalid_right: 1809 return KERN_INVALID_RIGHT; 1810 } 1811 1812 return KERN_SUCCESS; 1813 1814 copy_dead: 1815 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 1816 assert(IE_BITS_UREFS(bits) > 0); 1817 assert(entry->ie_request == 0); 1818 assert(entry->ie_object == 0); 1819 1820 if (!deadok) 1821 goto invalid_right; 1822 1823 *objectp = IO_DEAD; 1824 *sorightp = IP_NULL; 1825 return KERN_SUCCESS; 1826 1827 move_dead: 1828 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 1829 assert(IE_BITS_UREFS(bits) > 0); 1830 assert(entry->ie_request == 0); 1831 assert(entry->ie_object == 0); 1832 1833 if (!deadok) 1834 goto invalid_right; 1835 1836 if (IE_BITS_UREFS(bits) == 1) { 1837 bits &= ~MACH_PORT_TYPE_DEAD_NAME; 1838 } 1839 entry->ie_bits = bits-1; /* decrement urefs */ 1840 1841 *objectp = IO_DEAD; 1842 *sorightp = IP_NULL; 1843 return KERN_SUCCESS; 1844 1845} 1846 1847/* 1848 * Routine: ipc_right_copyin_undo 1849 * Purpose: 1850 * Undoes the effects of an ipc_right_copyin 1851 * of a send/send-once right that is dead. 1852 * (Object is either IO_DEAD or a dead port.) 1853 * Conditions: 1854 * The space is write-locked and active. 1855 */ 1856 1857void 1858ipc_right_copyin_undo( 1859 ipc_space_t space, 1860 mach_port_name_t name, 1861 ipc_entry_t entry, 1862 mach_msg_type_name_t msgt_name, 1863 ipc_object_t object, 1864 ipc_port_t soright) 1865{ 1866 ipc_entry_bits_t bits; 1867 1868 bits = entry->ie_bits; 1869 1870 assert(space->is_active); 1871 1872 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 1873 (msgt_name == MACH_MSG_TYPE_COPY_SEND) || 1874 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE)); 1875 1876 if (soright != IP_NULL) { 1877 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 1878 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE)); 1879 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 1880 assert(object != IO_DEAD); 1881 1882 entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) | 1883 MACH_PORT_TYPE_DEAD_NAME | 2); 1884 1885 } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE) { 1886 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 1887 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE)); 1888 1889 entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) | 1890 MACH_PORT_TYPE_DEAD_NAME | 1); 1891 } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME) { 1892 assert(object == IO_DEAD); 1893 assert(IE_BITS_UREFS(bits) > 0); 1894 1895 if (msgt_name != MACH_MSG_TYPE_COPY_SEND) { 1896 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX); 1897 entry->ie_bits = bits+1; /* increment urefs */ 1898 } 1899 } else { 1900 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 1901 (msgt_name == MACH_MSG_TYPE_COPY_SEND)); 1902 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 1903 assert(object != IO_DEAD); 1904 assert(entry->ie_object == object); 1905 assert(IE_BITS_UREFS(bits) > 0); 1906 1907 if (msgt_name != MACH_MSG_TYPE_COPY_SEND) { 1908 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX-1); 1909 entry->ie_bits = bits+1; /* increment urefs */ 1910 } 1911 1912 /* 1913 * May as well convert the entry to a dead name. 1914 * (Or if it is a compat entry, destroy it.) 1915 */ 1916 1917 (void) ipc_right_check(space, (ipc_port_t) object, 1918 name, entry); 1919 /* object is dead so it is not locked */ 1920 } 1921 1922 /* release the reference acquired by copyin */ 1923 1924 if (object != IO_DEAD) 1925 ipc_object_release(object); 1926} 1927 1928/* 1929 * Routine: ipc_right_copyin_two 1930 * Purpose: 1931 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND 1932 * and deadok == FALSE, except that this moves two 1933 * send rights at once. 1934 * Conditions: 1935 * The space is write-locked and active. 1936 * The object is returned with two refs/send rights. 1937 * Returns: 1938 * KERN_SUCCESS Acquired an object. 1939 * KERN_INVALID_RIGHT Name doesn't denote correct right. 1940 */ 1941 1942kern_return_t 1943ipc_right_copyin_two( 1944 ipc_space_t space, 1945 mach_port_name_t name, 1946 ipc_entry_t entry, 1947 ipc_object_t *objectp, 1948 ipc_port_t *sorightp) 1949{ 1950 ipc_entry_bits_t bits; 1951 mach_port_urefs_t urefs; 1952 ipc_port_t port; 1953 ipc_port_t dnrequest = IP_NULL; 1954#if CONFIG_MACF_MACH 1955 task_t self = current_task(); 1956 int rc; 1957#endif 1958 1959 assert(space->is_active); 1960 1961 bits = entry->ie_bits; 1962 1963 if ((bits & MACH_PORT_TYPE_SEND) == 0) 1964 goto invalid_right; 1965 1966 urefs = IE_BITS_UREFS(bits); 1967 if (urefs < 2) 1968 goto invalid_right; 1969 1970 port = (ipc_port_t) entry->ie_object; 1971 assert(port != IP_NULL); 1972 1973 if (ipc_right_check(space, port, name, entry)) { 1974 goto invalid_right; 1975 } 1976 /* port is locked and active */ 1977 1978#if CONFIG_MACF_MACH 1979 tasklabel_lock(self); 1980 rc = mac_port_check_copy_send(&self->maclabel, &port->ip_label); 1981 tasklabel_unlock(self); 1982 if (rc) { 1983 ip_unlock(port); 1984 return KERN_NO_ACCESS; 1985 } 1986#endif 1987 1988 assert(port->ip_srights > 0); 1989 1990 if (urefs == 2) { 1991 if (bits & MACH_PORT_TYPE_RECEIVE) { 1992 assert(port->ip_receiver_name == name); 1993 assert(port->ip_receiver == space); 1994 assert(IE_BITS_TYPE(bits) == 1995 MACH_PORT_TYPE_SEND_RECEIVE); 1996 1997 port->ip_srights++; 1998 ip_reference(port); 1999 ip_reference(port); 2000 } else { 2001 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 2002 2003 dnrequest = ipc_right_dncancel_macro(space, port, 2004 name, entry); 2005 2006 port->ip_srights++; 2007 ip_reference(port); 2008 ipc_hash_delete(space, (ipc_object_t) port, 2009 name, entry); 2010 entry->ie_object = IO_NULL; 2011 } 2012 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND); 2013 } else { 2014 port->ip_srights += 2; 2015 ip_reference(port); 2016 ip_reference(port); 2017 entry->ie_bits = bits-2; /* decrement urefs */ 2018 } 2019 ip_unlock(port); 2020 2021 *objectp = (ipc_object_t) port; 2022 *sorightp = dnrequest; 2023 return KERN_SUCCESS; 2024 2025 invalid_right: 2026 return KERN_INVALID_RIGHT; 2027} 2028 2029/* 2030 * Routine: ipc_right_copyout 2031 * Purpose: 2032 * Copyout a capability to a space. 2033 * If successful, consumes a ref for the object. 2034 * 2035 * Always succeeds when given a newly-allocated entry, 2036 * because user-reference overflow isn't a possibility. 2037 * 2038 * If copying out the object would cause the user-reference 2039 * count in the entry to overflow, and overflow is TRUE, 2040 * then instead the user-reference count is left pegged 2041 * to its maximum value and the copyout succeeds anyway. 2042 * Conditions: 2043 * The space is write-locked and active. 2044 * The object is locked and active. 2045 * The object is unlocked; the space isn't. 2046 * Returns: 2047 * KERN_SUCCESS Copied out capability. 2048 * KERN_UREFS_OVERFLOW User-refs would overflow; 2049 * guaranteed not to happen with a fresh entry 2050 * or if overflow=TRUE was specified. 2051 */ 2052 2053kern_return_t 2054ipc_right_copyout( 2055 ipc_space_t space, 2056 mach_port_name_t name, 2057 ipc_entry_t entry, 2058 mach_msg_type_name_t msgt_name, 2059 boolean_t overflow, 2060 ipc_object_t object) 2061{ 2062 ipc_entry_bits_t bits; 2063 ipc_port_t port; 2064#if CONFIG_MACF_MACH 2065 int rc; 2066#endif 2067 2068 bits = entry->ie_bits; 2069 2070 assert(IO_VALID(object)); 2071 assert(io_otype(object) == IOT_PORT); 2072 assert(io_active(object)); 2073 assert(entry->ie_object == object); 2074 2075 port = (ipc_port_t) object; 2076 2077 switch (msgt_name) { 2078 case MACH_MSG_TYPE_PORT_SEND_ONCE: 2079 2080 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 2081 assert(port->ip_sorights > 0); 2082 2083#if CONFIG_MACF_MACH 2084 if (space->is_task) { 2085 tasklabel_lock(space->is_task); 2086 rc = mac_port_check_hold_send_once(&space->is_task->maclabel, 2087 &port->ip_label); 2088 tasklabel_unlock(space->is_task); 2089 2090 if (rc) { 2091 ip_unlock(port); 2092 return KERN_NO_ACCESS; 2093 } 2094 } 2095#endif 2096 /* transfer send-once right and ref to entry */ 2097 ip_unlock(port); 2098 2099 entry->ie_bits = bits | (MACH_PORT_TYPE_SEND_ONCE | 1); 2100 break; 2101 2102 case MACH_MSG_TYPE_PORT_SEND: 2103 assert(port->ip_srights > 0); 2104 2105#if CONFIG_MACF_MACH 2106 if (space->is_task) { 2107 tasklabel_lock(space->is_task); 2108 rc = mac_port_check_hold_send(&space->is_task->maclabel, 2109 &port->ip_label); 2110 tasklabel_unlock(space->is_task); 2111 2112 if (rc) { 2113 ip_unlock(port); 2114 return KERN_NO_ACCESS; 2115 } 2116 } 2117#endif 2118 2119 if (bits & MACH_PORT_TYPE_SEND) { 2120 mach_port_urefs_t urefs = IE_BITS_UREFS(bits); 2121 2122 assert(port->ip_srights > 1); 2123 assert(urefs > 0); 2124 assert(urefs < MACH_PORT_UREFS_MAX); 2125 2126 if (urefs+1 == MACH_PORT_UREFS_MAX) { 2127 if (overflow) { 2128 /* leave urefs pegged to maximum */ 2129 2130 port->ip_srights--; 2131 ip_release(port); 2132 ip_unlock(port); 2133 return KERN_SUCCESS; 2134 } 2135 2136 ip_unlock(port); 2137 return KERN_UREFS_OVERFLOW; 2138 } 2139 2140 port->ip_srights--; 2141 ip_release(port); 2142 ip_unlock(port); 2143 } else if (bits & MACH_PORT_TYPE_RECEIVE) { 2144 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE); 2145 assert(IE_BITS_UREFS(bits) == 0); 2146 2147 /* transfer send right to entry */ 2148 ip_release(port); 2149 ip_unlock(port); 2150 } else { 2151 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 2152 assert(IE_BITS_UREFS(bits) == 0); 2153 2154 /* transfer send right and ref to entry */ 2155 ip_unlock(port); 2156 2157 /* entry is locked holding ref, so can use port */ 2158 2159 ipc_hash_insert(space, (ipc_object_t) port, 2160 name, entry); 2161 } 2162 2163 entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1; 2164 break; 2165 2166 case MACH_MSG_TYPE_PORT_RECEIVE: { 2167 ipc_port_t dest; 2168 2169 assert(port->ip_mscount == 0); 2170 assert(port->ip_receiver_name == MACH_PORT_NULL); 2171 dest = port->ip_destination; 2172 2173#if CONFIG_MACF_MACH 2174 if (space->is_task) { 2175 tasklabel_lock(space->is_task); 2176 rc = mac_port_check_hold_receive(&space->is_task->maclabel, 2177 &port->ip_label); 2178 tasklabel_unlock(space->is_task); 2179 2180 if (rc) { 2181 ip_unlock(port); 2182 return KERN_NO_ACCESS; 2183 } 2184 } 2185#endif 2186 2187 port->ip_receiver_name = name; 2188 port->ip_receiver = space; 2189 2190 assert((bits & MACH_PORT_TYPE_RECEIVE) == 0); 2191 2192 if (bits & MACH_PORT_TYPE_SEND) { 2193 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 2194 assert(IE_BITS_UREFS(bits) > 0); 2195 assert(port->ip_srights > 0); 2196 2197 ip_release(port); 2198 ip_unlock(port); 2199 2200 /* entry is locked holding ref, so can use port */ 2201 2202 ipc_hash_delete(space, (ipc_object_t) port, 2203 name, entry); 2204 } else { 2205 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 2206 assert(IE_BITS_UREFS(bits) == 0); 2207 2208 /* transfer ref to entry */ 2209 ip_unlock(port); 2210 } 2211 entry->ie_bits = bits | MACH_PORT_TYPE_RECEIVE; 2212 2213 if (dest != IP_NULL) 2214 ipc_port_release(dest); 2215 break; 2216 } 2217 2218 default: 2219 panic("ipc_right_copyout: strange rights"); 2220 } 2221 2222 return KERN_SUCCESS; 2223} 2224 2225/* 2226 * Routine: ipc_right_rename 2227 * Purpose: 2228 * Transfer an entry from one name to another. 2229 * The old entry is deallocated. 2230 * Conditions: 2231 * The space is write-locked and active. 2232 * The new entry is unused. Upon return, 2233 * the space is unlocked. 2234 * Returns: 2235 * KERN_SUCCESS Moved entry to new name. 2236 */ 2237 2238kern_return_t 2239ipc_right_rename( 2240 ipc_space_t space, 2241 mach_port_name_t oname, 2242 ipc_entry_t oentry, 2243 mach_port_name_t nname, 2244 ipc_entry_t nentry) 2245{ 2246 ipc_port_request_index_t request = oentry->ie_request; 2247 ipc_entry_bits_t bits = oentry->ie_bits; 2248 ipc_object_t object = oentry->ie_object; 2249 2250 assert(space->is_active); 2251 assert(oname != nname); 2252 2253 /* 2254 * If IE_BITS_COMPAT, we can't allow the entry to be renamed 2255 * if the port is dead. (This would foil ipc_port_destroy.) 2256 * Instead we should fail because oentry shouldn't exist. 2257 * Note IE_BITS_COMPAT implies ie_request != 0. 2258 */ 2259 2260 if (request != 0) { 2261 ipc_port_t port; 2262 2263 assert(bits & MACH_PORT_TYPE_PORT_RIGHTS); 2264 port = (ipc_port_t) object; 2265 assert(port != IP_NULL); 2266 2267 if (ipc_right_check(space, port, oname, oentry)) { 2268 request = 0; 2269 object = IO_NULL; 2270 bits = oentry->ie_bits; 2271 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 2272 assert(oentry->ie_request == 0); 2273 } else { 2274 /* port is locked and active */ 2275 2276 ipc_port_dnrename(port, request, oname, nname); 2277 ip_unlock(port); 2278 oentry->ie_request = 0; 2279 } 2280 } 2281 2282 /* initialize nentry before letting ipc_hash_insert see it */ 2283 2284 assert((nentry->ie_bits & IE_BITS_RIGHT_MASK) == 0); 2285 nentry->ie_bits |= bits & IE_BITS_RIGHT_MASK; 2286 nentry->ie_request = request; 2287 nentry->ie_object = object; 2288 2289 switch (IE_BITS_TYPE(bits)) { 2290 case MACH_PORT_TYPE_SEND: { 2291 ipc_port_t port; 2292 2293 port = (ipc_port_t) object; 2294 assert(port != IP_NULL); 2295 2296 /* remember, there are no other share entries possible */ 2297 /* or we can't do the rename. Therefore we do not need */ 2298 /* to check the other subspaces */ 2299 ipc_hash_delete(space, (ipc_object_t) port, oname, oentry); 2300 ipc_hash_insert(space, (ipc_object_t) port, nname, nentry); 2301 break; 2302 } 2303 2304 case MACH_PORT_TYPE_RECEIVE: 2305 case MACH_PORT_TYPE_SEND_RECEIVE: { 2306 ipc_port_t port; 2307 2308 port = (ipc_port_t) object; 2309 assert(port != IP_NULL); 2310 2311 ip_lock(port); 2312 assert(ip_active(port)); 2313 assert(port->ip_receiver_name == oname); 2314 assert(port->ip_receiver == space); 2315 2316 port->ip_receiver_name = nname; 2317 ip_unlock(port); 2318 break; 2319 } 2320 2321 case MACH_PORT_TYPE_PORT_SET: { 2322 ipc_pset_t pset; 2323 2324 pset = (ipc_pset_t) object; 2325 assert(pset != IPS_NULL); 2326 2327 ips_lock(pset); 2328 assert(ips_active(pset)); 2329 assert(pset->ips_local_name == oname); 2330 2331 pset->ips_local_name = nname; 2332 ips_unlock(pset); 2333 break; 2334 } 2335 2336 case MACH_PORT_TYPE_SEND_ONCE: 2337 case MACH_PORT_TYPE_DEAD_NAME: 2338 break; 2339 2340 default: 2341 panic("ipc_right_rename: strange rights"); 2342 } 2343 2344 assert(oentry->ie_request == 0); 2345 oentry->ie_object = IO_NULL; 2346 ipc_entry_dealloc(space, oname, oentry); 2347 is_write_unlock(space); 2348 2349 return KERN_SUCCESS; 2350} 2351