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 <ipc/ipc_importance.h> 90#include <security/mac_mach_internal.h> 91 92/* Allow IPC to generate mach port guard exceptions */ 93extern kern_return_t 94mach_port_guard_exception( 95 mach_port_name_t name, 96 uint64_t inguard, 97 uint64_t portguard, 98 unsigned reason); 99/* 100 * Routine: ipc_right_lookup_write 101 * Purpose: 102 * Finds an entry in a space, given the name. 103 * Conditions: 104 * Nothing locked. If successful, the space is write-locked. 105 * Returns: 106 * KERN_SUCCESS Found an entry. 107 * KERN_INVALID_TASK The space is dead. 108 * KERN_INVALID_NAME Name doesn't exist in space. 109 */ 110 111kern_return_t 112ipc_right_lookup_write( 113 ipc_space_t space, 114 mach_port_name_t name, 115 ipc_entry_t *entryp) 116{ 117 ipc_entry_t entry; 118 119 assert(space != IS_NULL); 120 121 is_write_lock(space); 122 123 if (!is_active(space)) { 124 is_write_unlock(space); 125 return KERN_INVALID_TASK; 126 } 127 128 if ((entry = ipc_entry_lookup(space, name)) == IE_NULL) { 129 is_write_unlock(space); 130 return KERN_INVALID_NAME; 131 } 132 133 *entryp = entry; 134 return KERN_SUCCESS; 135} 136 137/* 138 * Routine: ipc_right_lookup_two_write 139 * Purpose: 140 * Like ipc_right_lookup except that it returns two 141 * entries for two different names that were looked 142 * up under the same space lock. 143 * Conditions: 144 * Nothing locked. If successful, the space is write-locked. 145 * Returns: 146 * KERN_INVALID_TASK The space is dead. 147 * KERN_INVALID_NAME Name doesn't exist in space. 148 */ 149 150kern_return_t 151ipc_right_lookup_two_write( 152 ipc_space_t space, 153 mach_port_name_t name1, 154 ipc_entry_t *entryp1, 155 mach_port_name_t name2, 156 ipc_entry_t *entryp2) 157{ 158 ipc_entry_t entry1; 159 ipc_entry_t entry2; 160 161 assert(space != IS_NULL); 162 163 is_write_lock(space); 164 165 if (!is_active(space)) { 166 is_write_unlock(space); 167 return KERN_INVALID_TASK; 168 } 169 170 if ((entry1 = ipc_entry_lookup(space, name1)) == IE_NULL) { 171 is_write_unlock(space); 172 return KERN_INVALID_NAME; 173 } 174 if ((entry2 = ipc_entry_lookup(space, name2)) == IE_NULL) { 175 is_write_unlock(space); 176 return KERN_INVALID_NAME; 177 } 178 *entryp1 = entry1; 179 *entryp2 = entry2; 180 return KERN_SUCCESS; 181} 182 183/* 184 * Routine: ipc_right_reverse 185 * Purpose: 186 * Translate (space, object) -> (name, entry). 187 * Only finds send/receive rights. 188 * Returns TRUE if an entry is found; if so, 189 * the object is locked and active. 190 * Conditions: 191 * The space must be locked (read or write) and active. 192 * Nothing else locked. 193 */ 194 195boolean_t 196ipc_right_reverse( 197 ipc_space_t space, 198 ipc_object_t object, 199 mach_port_name_t *namep, 200 ipc_entry_t *entryp) 201{ 202 ipc_port_t port; 203 mach_port_name_t name; 204 ipc_entry_t entry; 205 206 /* would switch on io_otype to handle multiple types of object */ 207 208 assert(is_active(space)); 209 assert(io_otype(object) == IOT_PORT); 210 211 port = (ipc_port_t) object; 212 213 ip_lock(port); 214 if (!ip_active(port)) { 215 ip_unlock(port); 216 217 return FALSE; 218 } 219 220 if (port->ip_receiver == space) { 221 name = port->ip_receiver_name; 222 assert(name != MACH_PORT_NULL); 223 224 entry = ipc_entry_lookup(space, name); 225 226 assert(entry != IE_NULL); 227 assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE); 228 assert(port == (ipc_port_t) entry->ie_object); 229 230 *namep = name; 231 *entryp = entry; 232 return TRUE; 233 } 234 235 if (ipc_hash_lookup(space, (ipc_object_t) port, namep, entryp)) { 236 assert((entry = *entryp) != IE_NULL); 237 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_SEND); 238 assert(port == (ipc_port_t) entry->ie_object); 239 240 return TRUE; 241 } 242 243 ip_unlock(port); 244 return FALSE; 245} 246 247/* 248 * Routine: ipc_right_dnrequest 249 * Purpose: 250 * Make a dead-name request, returning the previously 251 * registered send-once right. If notify is IP_NULL, 252 * just cancels the previously registered request. 253 * 254 * Conditions: 255 * Nothing locked. May allocate memory. 256 * Only consumes/returns refs if successful. 257 * Returns: 258 * KERN_SUCCESS Made/canceled dead-name request. 259 * KERN_INVALID_TASK The space is dead. 260 * KERN_INVALID_NAME Name doesn't exist in space. 261 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights. 262 * KERN_INVALID_ARGUMENT Name denotes dead name, but 263 * immediate is FALSE or notify is IP_NULL. 264 * KERN_UREFS_OVERFLOW Name denotes dead name, but 265 * generating immediate notif. would overflow urefs. 266 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 267 */ 268 269kern_return_t 270ipc_right_request_alloc( 271 ipc_space_t space, 272 mach_port_name_t name, 273 boolean_t immediate, 274 boolean_t send_possible, 275 ipc_port_t notify, 276 ipc_port_t *previousp) 277{ 278 ipc_port_request_index_t prev_request; 279 ipc_port_t previous = IP_NULL; 280 ipc_entry_t entry; 281 kern_return_t kr; 282 283#if IMPORTANCE_INHERITANCE 284 boolean_t needboost = FALSE; 285#endif /* IMPORTANCE_INHERITANCE */ 286 287 for (;;) { 288 ipc_port_t port = IP_NULL; 289 290 kr = ipc_right_lookup_write(space, name, &entry); 291 if (kr != KERN_SUCCESS) 292 return kr; 293 294 /* space is write-locked and active */ 295 296 prev_request = entry->ie_request; 297 298 /* if nothing to do or undo, we're done */ 299 if (notify == IP_NULL && prev_request == IE_REQ_NONE) { 300 is_write_unlock(space); 301 *previousp = IP_NULL; 302 return KERN_SUCCESS; 303 } 304 305 /* see if the entry is of proper type for requests */ 306 if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) { 307 ipc_port_request_index_t new_request; 308 309 port = (ipc_port_t) entry->ie_object; 310 assert(port != IP_NULL); 311 312 if (!ipc_right_check(space, port, name, entry)) { 313 /* port is locked and active */ 314 315 /* if no new request, just cancel previous */ 316 if (notify == IP_NULL) { 317 if (prev_request != IE_REQ_NONE) 318 previous = ipc_port_request_cancel(port, name, prev_request); 319 ip_unlock(port); 320 entry->ie_request = IE_REQ_NONE; 321 ipc_entry_modified(space, name, entry); 322 is_write_unlock(space); 323 break; 324 } 325 326 /* 327 * send-once rights, kernel objects, and non-full other queues 328 * fire immediately (if immediate specified). 329 */ 330 if (send_possible && immediate && 331 ((entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE) || 332 port->ip_receiver == ipc_space_kernel || !ip_full(port))) { 333 if (prev_request != IE_REQ_NONE) 334 previous = ipc_port_request_cancel(port, name, prev_request); 335 ip_unlock(port); 336 entry->ie_request = IE_REQ_NONE; 337 ipc_entry_modified(space, name, entry); 338 is_write_unlock(space); 339 340 ipc_notify_send_possible(notify, name); 341 break; 342 } 343 344 /* 345 * If there is a previous request, free it. Any subsequent 346 * allocation cannot fail, thus assuring an atomic swap. 347 */ 348 if (prev_request != IE_REQ_NONE) 349 previous = ipc_port_request_cancel(port, name, prev_request); 350 351#if IMPORTANCE_INHERITANCE 352 kr = ipc_port_request_alloc(port, name, notify, 353 send_possible, immediate, 354 &new_request, &needboost); 355#else 356 kr = ipc_port_request_alloc(port, name, notify, 357 send_possible, immediate, 358 &new_request); 359#endif /* IMPORTANCE_INHERITANCE */ 360 if (kr != KERN_SUCCESS) { 361 assert(previous == IP_NULL); 362 is_write_unlock(space); 363 364 kr = ipc_port_request_grow(port, ITS_SIZE_NONE); 365 /* port is unlocked */ 366 367 if (kr != KERN_SUCCESS) 368 return kr; 369 370 continue; 371 } 372 373 374 assert(new_request != IE_REQ_NONE); 375 entry->ie_request = new_request; 376 ipc_entry_modified(space, name, entry); 377 is_write_unlock(space); 378 379#if IMPORTANCE_INHERITANCE 380 if (needboost == TRUE) { 381 if (ipc_port_importance_delta(port, 1) == FALSE) 382 ip_unlock(port); 383 } else 384#endif /* IMPORTANCE_INHERITANCE */ 385 ip_unlock(port); 386 387 break; 388 } 389 /* entry may have changed to dead-name by ipc_right_check() */ 390 391 } 392 393 /* treat send_possible requests as immediate w.r.t. dead-name */ 394 if ((send_possible || immediate) && notify != IP_NULL && 395 (entry->ie_bits & MACH_PORT_TYPE_DEAD_NAME)) { 396 mach_port_urefs_t urefs = IE_BITS_UREFS(entry->ie_bits); 397 398 assert(urefs > 0); 399 400 if (MACH_PORT_UREFS_OVERFLOW(urefs, 1)) { 401 is_write_unlock(space); 402 if (port != IP_NULL) 403 ip_release(port); 404 return KERN_UREFS_OVERFLOW; 405 } 406 407 (entry->ie_bits)++; /* increment urefs */ 408 ipc_entry_modified(space, name, entry); 409 is_write_unlock(space); 410 411 if (port != IP_NULL) 412 ip_release(port); 413 414 ipc_notify_dead_name(notify, name); 415 previous = IP_NULL; 416 break; 417 } 418 419 is_write_unlock(space); 420 421 if (port != IP_NULL) 422 ip_release(port); 423 424 if (entry->ie_bits & MACH_PORT_TYPE_PORT_OR_DEAD) 425 return KERN_INVALID_ARGUMENT; 426 else 427 return KERN_INVALID_RIGHT; 428 } 429 430 *previousp = previous; 431 return KERN_SUCCESS; 432} 433 434/* 435 * Routine: ipc_right_request_cancel 436 * Purpose: 437 * Cancel a notification request and return the send-once right. 438 * Afterwards, entry->ie_request == 0. 439 * Conditions: 440 * The space must be write-locked; the port must be locked. 441 * The port must be active; the space doesn't have to be. 442 */ 443 444ipc_port_t 445ipc_right_request_cancel( 446 __unused ipc_space_t space, 447 ipc_port_t port, 448 mach_port_name_t name, 449 ipc_entry_t entry) 450{ 451 ipc_port_t previous; 452 453 assert(ip_active(port)); 454 assert(port == (ipc_port_t) entry->ie_object); 455 456 if (entry->ie_request == IE_REQ_NONE) 457 return IP_NULL; 458 459 previous = ipc_port_request_cancel(port, name, entry->ie_request); 460 entry->ie_request = IE_REQ_NONE; 461 ipc_entry_modified(space, name, entry); 462 return previous; 463} 464 465/* 466 * Routine: ipc_right_inuse 467 * Purpose: 468 * Check if an entry is being used. 469 * Returns TRUE if it is. 470 * Conditions: 471 * The space is write-locked and active. 472 * It is unlocked if the entry is inuse. 473 */ 474 475boolean_t 476ipc_right_inuse( 477 ipc_space_t space, 478 __unused mach_port_name_t name, 479 ipc_entry_t entry) 480{ 481 if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_NONE) { 482 is_write_unlock(space); 483 return TRUE; 484 } 485 return FALSE; 486} 487 488/* 489 * Routine: ipc_right_check 490 * Purpose: 491 * Check if the port has died. If it has, 492 * clean up the entry and return TRUE. 493 * Conditions: 494 * The space is write-locked; the port is not locked. 495 * If returns FALSE, the port is also locked and active. 496 * Otherwise, entry is converted to a dead name. 497 * 498 * Caller is responsible for a reference to port if it 499 * had died (returns TRUE). 500 */ 501 502boolean_t 503ipc_right_check( 504 ipc_space_t space, 505 ipc_port_t port, 506 mach_port_name_t name, 507 ipc_entry_t entry) 508{ 509 ipc_entry_bits_t bits; 510 511 assert(is_active(space)); 512 assert(port == (ipc_port_t) entry->ie_object); 513 514 ip_lock(port); 515 if (ip_active(port)) 516 return FALSE; 517 518 /* this was either a pure send right or a send-once right */ 519 520 bits = entry->ie_bits; 521 assert((bits & MACH_PORT_TYPE_RECEIVE) == 0); 522 assert(IE_BITS_UREFS(bits) > 0); 523 524 if (bits & MACH_PORT_TYPE_SEND) { 525 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 526 assert(IE_BITS_UREFS(bits) > 0); 527 assert(port->ip_srights > 0); 528 port->ip_srights--; 529 } else { 530 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 531 assert(IE_BITS_UREFS(bits) == 1); 532 assert(port->ip_sorights > 0); 533 port->ip_sorights--; 534 } 535 ip_unlock(port); 536 537 /* 538 * delete SEND rights from ipc hash. 539 */ 540 541 if ((bits & MACH_PORT_TYPE_SEND) != 0) { 542 ipc_hash_delete(space, (ipc_object_t)port, name, entry); 543 } 544 545 /* convert entry to dead name */ 546 bits = (bits &~ IE_BITS_TYPE_MASK) | MACH_PORT_TYPE_DEAD_NAME; 547 548 /* 549 * If there was a notification request outstanding on this 550 * name, and the port went dead, that notification 551 * must already be on its way up from the port layer. 552 * 553 * Add the reference that the notification carries. It 554 * is done here, and not in the notification delivery, 555 * because the latter doesn't have a space reference and 556 * trying to actually move a send-right reference would 557 * get short-circuited into a MACH_PORT_DEAD by IPC. Since 558 * all calls that deal with the right eventually come 559 * through here, it has the same result. 560 * 561 * Once done, clear the request index so we only account 562 * for it once. 563 */ 564 if (entry->ie_request != IE_REQ_NONE) { 565 if (ipc_port_request_type(port, name, entry->ie_request) != 0) { 566 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX); 567 bits++; 568 } 569 entry->ie_request = IE_REQ_NONE; 570 } 571 entry->ie_bits = bits; 572 entry->ie_object = IO_NULL; 573 ipc_entry_modified(space, name, entry); 574 return TRUE; 575} 576 577/* 578 * Routine: ipc_right_terminate 579 * Purpose: 580 * Cleans up an entry in a terminated space. 581 * The entry isn't deallocated or removed 582 * from reverse hash tables. 583 * Conditions: 584 * The space is dead and unlocked. 585 */ 586 587void 588ipc_right_terminate( 589 ipc_space_t space, 590 mach_port_name_t name, 591 ipc_entry_t entry) 592{ 593 ipc_entry_bits_t bits; 594 mach_port_type_t type; 595 596 bits = entry->ie_bits; 597 type = IE_BITS_TYPE(bits); 598 599 assert(!is_active(space)); 600 601 /* 602 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this 603 * problem, because we check that the port is active. If 604 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy 605 * would still work, but dead space refs would accumulate 606 * in ip_dnrequests. They would use up slots in 607 * ip_dnrequests and keep the spaces from being freed. 608 */ 609 610 switch (type) { 611 case MACH_PORT_TYPE_DEAD_NAME: 612 assert(entry->ie_request == IE_REQ_NONE); 613 assert(entry->ie_object == IO_NULL); 614 break; 615 616 case MACH_PORT_TYPE_PORT_SET: { 617 ipc_pset_t pset = (ipc_pset_t) entry->ie_object; 618 619 assert(entry->ie_request == IE_REQ_NONE); 620 assert(pset != IPS_NULL); 621 622 ips_lock(pset); 623 assert(ips_active(pset)); 624 ipc_pset_destroy(pset); /* consumes ref, unlocks */ 625 break; 626 } 627 628 case MACH_PORT_TYPE_SEND: 629 case MACH_PORT_TYPE_RECEIVE: 630 case MACH_PORT_TYPE_SEND_RECEIVE: 631 case MACH_PORT_TYPE_SEND_ONCE: { 632 ipc_port_t port = (ipc_port_t) entry->ie_object; 633 ipc_port_t request; 634 ipc_port_t nsrequest = IP_NULL; 635 mach_port_mscount_t mscount = 0; 636 637 assert(port != IP_NULL); 638 ip_lock(port); 639 640 if (!ip_active(port)) { 641 ip_unlock(port); 642 ip_release(port); 643 break; 644 } 645 646 request = ipc_right_request_cancel_macro(space, port, 647 name, entry); 648 649 if (type & MACH_PORT_TYPE_SEND) { 650 assert(port->ip_srights > 0); 651 if (--port->ip_srights == 0 652 ) { 653 nsrequest = port->ip_nsrequest; 654 if (nsrequest != IP_NULL) { 655 port->ip_nsrequest = IP_NULL; 656 mscount = port->ip_mscount; 657 } 658 } 659 } 660 661 if (type & MACH_PORT_TYPE_RECEIVE) { 662 wait_queue_link_t wql; 663 queue_head_t links_data; 664 queue_t links = &links_data; 665 666 assert(port->ip_receiver_name == name); 667 assert(port->ip_receiver == space); 668 669 queue_init(links); 670 ipc_port_clear_receiver(port, links); 671 ipc_port_destroy(port); /* consumes our ref, unlocks */ 672 while(!queue_empty(links)) { 673 wql = (wait_queue_link_t) dequeue(links); 674 wait_queue_link_free(wql); 675 } 676 677 } else if (type & MACH_PORT_TYPE_SEND_ONCE) { 678 assert(port->ip_sorights > 0); 679 ip_unlock(port); 680 681 ipc_notify_send_once(port); /* consumes our ref */ 682 } else { 683 assert(port->ip_receiver != space); 684 685 ip_unlock(port); 686 ip_release(port); 687 } 688 689 if (nsrequest != IP_NULL) 690 ipc_notify_no_senders(nsrequest, mscount); 691 692 if (request != IP_NULL) 693 ipc_notify_port_deleted(request, name); 694 break; 695 } 696 697 default: 698 panic("ipc_right_terminate: strange type - 0x%x", type); 699 } 700} 701 702/* 703 * Routine: ipc_right_destroy 704 * Purpose: 705 * Destroys an entry in a space. 706 * Conditions: 707 * The space is write-locked (returns unlocked). 708 * The space must be active. 709 * Returns: 710 * KERN_SUCCESS The entry was destroyed. 711 */ 712 713kern_return_t 714ipc_right_destroy( 715 ipc_space_t space, 716 mach_port_name_t name, 717 ipc_entry_t entry, 718 boolean_t check_guard, 719 uint64_t guard) 720{ 721 ipc_entry_bits_t bits; 722 mach_port_type_t type; 723 724 bits = entry->ie_bits; 725 entry->ie_bits &= ~IE_BITS_TYPE_MASK; 726 type = IE_BITS_TYPE(bits); 727 728 assert(is_active(space)); 729 730 switch (type) { 731 case MACH_PORT_TYPE_DEAD_NAME: 732 assert(entry->ie_request == IE_REQ_NONE); 733 assert(entry->ie_object == IO_NULL); 734 735 ipc_entry_dealloc(space, name, entry); 736 is_write_unlock(space); 737 break; 738 739 case MACH_PORT_TYPE_PORT_SET: { 740 ipc_pset_t pset = (ipc_pset_t) entry->ie_object; 741 742 assert(entry->ie_request == IE_REQ_NONE); 743 assert(pset != IPS_NULL); 744 745 entry->ie_object = IO_NULL; 746 ipc_entry_dealloc(space, name, entry); 747 748 ips_lock(pset); 749 is_write_unlock(space); 750 751 assert(ips_active(pset)); 752 ipc_pset_destroy(pset); /* consumes ref, unlocks */ 753 break; 754 } 755 756 case MACH_PORT_TYPE_SEND: 757 case MACH_PORT_TYPE_RECEIVE: 758 case MACH_PORT_TYPE_SEND_RECEIVE: 759 case MACH_PORT_TYPE_SEND_ONCE: { 760 ipc_port_t port = (ipc_port_t) entry->ie_object; 761 ipc_port_t nsrequest = IP_NULL; 762 mach_port_mscount_t mscount = 0; 763 ipc_port_t request; 764 765 assert(port != IP_NULL); 766 767 if (type == MACH_PORT_TYPE_SEND) 768 ipc_hash_delete(space, (ipc_object_t) port, 769 name, entry); 770 771 ip_lock(port); 772 773 if (!ip_active(port)) { 774 assert((type & MACH_PORT_TYPE_RECEIVE) == 0); 775 ip_unlock(port); 776 entry->ie_request = IE_REQ_NONE; 777 entry->ie_object = IO_NULL; 778 ipc_entry_dealloc(space, name, entry); 779 is_write_unlock(space); 780 ip_release(port); 781 break; 782 } 783 784 /* For receive rights, check for guarding */ 785 if ((type & MACH_PORT_TYPE_RECEIVE) && 786 (check_guard) && (port->ip_guarded) && 787 (guard != port->ip_context)) { 788 /* Guard Violation */ 789 uint64_t portguard = port->ip_context; 790 ip_unlock(port); 791 is_write_unlock(space); 792 /* Raise mach port guard exception */ 793 mach_port_guard_exception(name, 0, portguard, kGUARD_EXC_DESTROY); 794 return KERN_INVALID_RIGHT; 795 } 796 797 798 request = ipc_right_request_cancel_macro(space, port, name, entry); 799 800 entry->ie_object = IO_NULL; 801 ipc_entry_dealloc(space, name, entry); 802 is_write_unlock(space); 803 804 if (type & MACH_PORT_TYPE_SEND) { 805 assert(port->ip_srights > 0); 806 if (--port->ip_srights == 0) { 807 nsrequest = port->ip_nsrequest; 808 if (nsrequest != IP_NULL) { 809 port->ip_nsrequest = IP_NULL; 810 mscount = port->ip_mscount; 811 } 812 } 813 } 814 815 if (type & MACH_PORT_TYPE_RECEIVE) { 816 queue_head_t links_data; 817 queue_t links = &links_data; 818 wait_queue_link_t wql; 819 820 assert(ip_active(port)); 821 assert(port->ip_receiver == space); 822 823 queue_init(links); 824 825 ipc_port_clear_receiver(port, links); 826 ipc_port_destroy(port); /* consumes our ref, unlocks */ 827 828 while(!queue_empty(links)) { 829 wql = (wait_queue_link_t) dequeue(links); 830 wait_queue_link_free(wql); 831 } 832 833 } else if (type & MACH_PORT_TYPE_SEND_ONCE) { 834 assert(port->ip_sorights > 0); 835 ip_unlock(port); 836 837 ipc_notify_send_once(port); /* consumes our ref */ 838 } else { 839 assert(port->ip_receiver != space); 840 841 ip_unlock(port); 842 ip_release(port); 843 } 844 845 if (nsrequest != IP_NULL) 846 ipc_notify_no_senders(nsrequest, mscount); 847 848 if (request != IP_NULL) 849 ipc_notify_port_deleted(request, name); 850 851 852 break; 853 } 854 855 default: 856 panic("ipc_right_destroy: strange type"); 857 } 858 859 return KERN_SUCCESS; 860} 861 862/* 863 * Routine: ipc_right_dealloc 864 * Purpose: 865 * Releases a send/send-once/dead-name user ref. 866 * Like ipc_right_delta with a delta of -1, 867 * but looks at the entry to determine the right. 868 * Conditions: 869 * The space is write-locked, and is unlocked upon return. 870 * The space must be active. 871 * Returns: 872 * KERN_SUCCESS A user ref was released. 873 * KERN_INVALID_RIGHT Entry has wrong type. 874 */ 875 876kern_return_t 877ipc_right_dealloc( 878 ipc_space_t space, 879 mach_port_name_t name, 880 ipc_entry_t entry) 881{ 882 ipc_port_t port = IP_NULL; 883 ipc_entry_bits_t bits; 884 mach_port_type_t type; 885 886 bits = entry->ie_bits; 887 type = IE_BITS_TYPE(bits); 888 889 890 assert(is_active(space)); 891 892 switch (type) { 893 case MACH_PORT_TYPE_DEAD_NAME: { 894 dead_name: 895 896 assert(IE_BITS_UREFS(bits) > 0); 897 assert(entry->ie_request == IE_REQ_NONE); 898 assert(entry->ie_object == IO_NULL); 899 900 if (IE_BITS_UREFS(bits) == 1) { 901 ipc_entry_dealloc(space, name, entry); 902 } else { 903 entry->ie_bits = bits-1; /* decrement urefs */ 904 ipc_entry_modified(space, name, entry); 905 } 906 is_write_unlock(space); 907 908 /* release any port that got converted to dead name below */ 909 if (port != IP_NULL) 910 ip_release(port); 911 break; 912 } 913 914 case MACH_PORT_TYPE_SEND_ONCE: { 915 ipc_port_t request; 916 917 assert(IE_BITS_UREFS(bits) == 1); 918 919 port = (ipc_port_t) entry->ie_object; 920 assert(port != IP_NULL); 921 922 if (ipc_right_check(space, port, name, entry)) { 923 924 bits = entry->ie_bits; 925 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 926 goto dead_name; /* it will release port */ 927 } 928 /* port is locked and active */ 929 930 assert(port->ip_sorights > 0); 931 932 request = ipc_right_request_cancel_macro(space, port, name, entry); 933 ip_unlock(port); 934 935 entry->ie_object = IO_NULL; 936 ipc_entry_dealloc(space, name, entry); 937 938 is_write_unlock(space); 939 940 ipc_notify_send_once(port); 941 942 if (request != IP_NULL) 943 ipc_notify_port_deleted(request, name); 944 break; 945 } 946 947 case MACH_PORT_TYPE_SEND: { 948 ipc_port_t request = IP_NULL; 949 ipc_port_t nsrequest = IP_NULL; 950 mach_port_mscount_t mscount = 0; 951 952 953 assert(IE_BITS_UREFS(bits) > 0); 954 955 port = (ipc_port_t) entry->ie_object; 956 assert(port != IP_NULL); 957 958 if (ipc_right_check(space, port, name, entry)) { 959 bits = entry->ie_bits; 960 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 961 goto dead_name; /* it will release port */ 962 } 963 /* port is locked and active */ 964 965 assert(port->ip_srights > 0); 966 967 if (IE_BITS_UREFS(bits) == 1) { 968 if (--port->ip_srights == 0) { 969 nsrequest = port->ip_nsrequest; 970 if (nsrequest != IP_NULL) { 971 port->ip_nsrequest = IP_NULL; 972 mscount = port->ip_mscount; 973 } 974 } 975 976 request = ipc_right_request_cancel_macro(space, port, 977 name, entry); 978 ipc_hash_delete(space, (ipc_object_t) port, 979 name, entry); 980 981 ip_unlock(port); 982 entry->ie_object = IO_NULL; 983 ipc_entry_dealloc(space, name, entry); 984 is_write_unlock(space); 985 ip_release(port); 986 987 } else { 988 ip_unlock(port); 989 entry->ie_bits = bits-1; /* decrement urefs */ 990 ipc_entry_modified(space, name, entry); 991 is_write_unlock(space); 992 } 993 994 995 if (nsrequest != IP_NULL) 996 ipc_notify_no_senders(nsrequest, mscount); 997 998 if (request != IP_NULL) 999 ipc_notify_port_deleted(request, name); 1000 break; 1001 } 1002 1003 case MACH_PORT_TYPE_SEND_RECEIVE: { 1004 ipc_port_t nsrequest = IP_NULL; 1005 mach_port_mscount_t mscount = 0; 1006 1007 assert(IE_BITS_UREFS(bits) > 0); 1008 1009 port = (ipc_port_t) entry->ie_object; 1010 assert(port != IP_NULL); 1011 1012 ip_lock(port); 1013 assert(ip_active(port)); 1014 assert(port->ip_receiver_name == name); 1015 assert(port->ip_receiver == space); 1016 assert(port->ip_srights > 0); 1017 1018 if (IE_BITS_UREFS(bits) == 1) { 1019 if (--port->ip_srights == 0) { 1020 nsrequest = port->ip_nsrequest; 1021 if (nsrequest != IP_NULL) { 1022 port->ip_nsrequest = IP_NULL; 1023 mscount = port->ip_mscount; 1024 } 1025 } 1026 1027 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK | 1028 MACH_PORT_TYPE_SEND); 1029 } else 1030 entry->ie_bits = bits-1; /* decrement urefs */ 1031 1032 ip_unlock(port); 1033 1034 ipc_entry_modified(space, name, entry); 1035 is_write_unlock(space); 1036 1037 if (nsrequest != IP_NULL) 1038 ipc_notify_no_senders(nsrequest, mscount); 1039 break; 1040 } 1041 1042 default: 1043 is_write_unlock(space); 1044 return KERN_INVALID_RIGHT; 1045 } 1046 1047 return KERN_SUCCESS; 1048} 1049 1050/* 1051 * Routine: ipc_right_delta 1052 * Purpose: 1053 * Modifies the user-reference count for a right. 1054 * May deallocate the right, if the count goes to zero. 1055 * Conditions: 1056 * The space is write-locked, and is unlocked upon return. 1057 * The space must be active. 1058 * Returns: 1059 * KERN_SUCCESS Count was modified. 1060 * KERN_INVALID_RIGHT Entry has wrong type. 1061 * KERN_INVALID_VALUE Bad delta for the right. 1062 * KERN_UREFS_OVERFLOW OK delta, except would overflow. 1063 */ 1064 1065kern_return_t 1066ipc_right_delta( 1067 ipc_space_t space, 1068 mach_port_name_t name, 1069 ipc_entry_t entry, 1070 mach_port_right_t right, 1071 mach_port_delta_t delta) 1072{ 1073 ipc_port_t port = IP_NULL; 1074 ipc_entry_bits_t bits; 1075 1076 bits = entry->ie_bits; 1077 1078 1079/* 1080 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the 1081 * switch below. It is used to keep track of those cases (in DIPC) 1082 * where we have postponed the dropping of a port reference. Since 1083 * the dropping of the reference could cause the port to disappear 1084 * we postpone doing so when we are holding the space lock. 1085 */ 1086 1087 assert(is_active(space)); 1088 assert(right < MACH_PORT_RIGHT_NUMBER); 1089 1090 /* Rights-specific restrictions and operations. */ 1091 1092 switch (right) { 1093 case MACH_PORT_RIGHT_PORT_SET: { 1094 ipc_pset_t pset; 1095 1096 if ((bits & MACH_PORT_TYPE_PORT_SET) == 0) 1097 goto invalid_right; 1098 1099 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_PORT_SET); 1100 assert(IE_BITS_UREFS(bits) == 0); 1101 assert(entry->ie_request == IE_REQ_NONE); 1102 1103 if (delta == 0) 1104 goto success; 1105 1106 if (delta != -1) 1107 goto invalid_value; 1108 1109 pset = (ipc_pset_t) entry->ie_object; 1110 assert(pset != IPS_NULL); 1111 1112 entry->ie_object = IO_NULL; 1113 ipc_entry_dealloc(space, name, entry); 1114 1115 ips_lock(pset); 1116 assert(ips_active(pset)); 1117 is_write_unlock(space); 1118 1119 ipc_pset_destroy(pset); /* consumes ref, unlocks */ 1120 break; 1121 } 1122 1123 case MACH_PORT_RIGHT_RECEIVE: { 1124 ipc_port_t request = IP_NULL; 1125 queue_head_t links_data; 1126 queue_t links = &links_data; 1127 wait_queue_link_t wql; 1128 1129 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1130 goto invalid_right; 1131 1132 if (delta == 0) 1133 goto success; 1134 1135 if (delta != -1) 1136 goto invalid_value; 1137 1138 port = (ipc_port_t) entry->ie_object; 1139 assert(port != IP_NULL); 1140 1141 /* 1142 * The port lock is needed for ipc_right_dncancel; 1143 * otherwise, we wouldn't have to take the lock 1144 * until just before dropping the space lock. 1145 */ 1146 1147 ip_lock(port); 1148 assert(ip_active(port)); 1149 assert(port->ip_receiver_name == name); 1150 assert(port->ip_receiver == space); 1151 1152 /* Mach Port Guard Checking */ 1153 if(port->ip_guarded) { 1154 uint64_t portguard = port->ip_context; 1155 ip_unlock(port); 1156 is_write_unlock(space); 1157 /* Raise mach port guard exception */ 1158 mach_port_guard_exception(name, 0, portguard, kGUARD_EXC_MOD_REFS); 1159 goto guard_failure; 1160 } 1161 1162 if (bits & MACH_PORT_TYPE_SEND) { 1163 assert(IE_BITS_TYPE(bits) == 1164 MACH_PORT_TYPE_SEND_RECEIVE); 1165 assert(IE_BITS_UREFS(bits) > 0); 1166 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX); 1167 assert(port->ip_srights > 0); 1168 1169 if (port->ip_pdrequest != NULL) { 1170 /* 1171 * Since another task has requested a 1172 * destroy notification for this port, it 1173 * isn't actually being destroyed - the receive 1174 * right is just being moved to another task. 1175 * Since we still have one or more send rights, 1176 * we need to record the loss of the receive 1177 * right and enter the remaining send right 1178 * into the hash table. 1179 */ 1180 ipc_entry_modified(space, name, entry); 1181 entry->ie_bits &= ~MACH_PORT_TYPE_RECEIVE; 1182 ipc_hash_insert(space, (ipc_object_t) port, 1183 name, entry); 1184 ip_reference(port); 1185 } else { 1186 /* 1187 * The remaining send right turns into a 1188 * dead name. Notice we don't decrement 1189 * ip_srights, generate a no-senders notif, 1190 * or use ipc_right_dncancel, because the 1191 * port is destroyed "first". 1192 */ 1193 bits &= ~IE_BITS_TYPE_MASK; 1194 bits |= MACH_PORT_TYPE_DEAD_NAME; 1195 if (entry->ie_request) { 1196 entry->ie_request = IE_REQ_NONE; 1197 bits++; 1198 } 1199 entry->ie_bits = bits; 1200 entry->ie_object = IO_NULL; 1201 ipc_entry_modified(space, name, entry); 1202 } 1203 } else { 1204 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE); 1205 assert(IE_BITS_UREFS(bits) == 0); 1206 1207 request = ipc_right_request_cancel_macro(space, port, 1208 name, entry); 1209 entry->ie_object = IO_NULL; 1210 ipc_entry_dealloc(space, name, entry); 1211 } 1212 is_write_unlock(space); 1213 1214 queue_init(links); 1215 ipc_port_clear_receiver(port, links); 1216 ipc_port_destroy(port); /* consumes ref, unlocks */ 1217 1218 while(!queue_empty(links)) { 1219 wql = (wait_queue_link_t) dequeue(links); 1220 wait_queue_link_free(wql); 1221 } 1222 1223 if (request != IP_NULL) 1224 ipc_notify_port_deleted(request, name); 1225 break; 1226 } 1227 1228 case MACH_PORT_RIGHT_SEND_ONCE: { 1229 ipc_port_t request; 1230 1231 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) 1232 goto invalid_right; 1233 1234 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 1235 assert(IE_BITS_UREFS(bits) == 1); 1236 1237 port = (ipc_port_t) entry->ie_object; 1238 assert(port != IP_NULL); 1239 1240 if (ipc_right_check(space, port, name, entry)) { 1241 assert(!(entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE)); 1242 goto invalid_right; 1243 } 1244 /* port is locked and active */ 1245 1246 assert(port->ip_sorights > 0); 1247 1248 if ((delta > 0) || (delta < -1)) { 1249 ip_unlock(port); 1250 goto invalid_value; 1251 } 1252 1253 if (delta == 0) { 1254 ip_unlock(port); 1255 goto success; 1256 } 1257 1258 request = ipc_right_request_cancel_macro(space, port, name, entry); 1259 ip_unlock(port); 1260 1261 entry->ie_object = IO_NULL; 1262 ipc_entry_dealloc(space, name, entry); 1263 1264 is_write_unlock(space); 1265 1266 ipc_notify_send_once(port); 1267 1268 if (request != IP_NULL) 1269 ipc_notify_port_deleted(request, name); 1270 break; 1271 } 1272 1273 case MACH_PORT_RIGHT_DEAD_NAME: { 1274 ipc_port_t relport = IP_NULL; 1275 mach_port_urefs_t urefs; 1276 1277 if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { 1278 1279 port = (ipc_port_t) entry->ie_object; 1280 assert(port != IP_NULL); 1281 1282 if (!ipc_right_check(space, port, name, entry)) { 1283 /* port is locked and active */ 1284 ip_unlock(port); 1285 port = IP_NULL; 1286 goto invalid_right; 1287 } 1288 bits = entry->ie_bits; 1289 relport = port; 1290 port = IP_NULL; 1291 } else if ((bits & MACH_PORT_TYPE_DEAD_NAME) == 0) 1292 goto invalid_right; 1293 1294 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 1295 assert(IE_BITS_UREFS(bits) > 0); 1296 assert(entry->ie_object == IO_NULL); 1297 assert(entry->ie_request == IE_REQ_NONE); 1298 1299 urefs = IE_BITS_UREFS(bits); 1300 if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta)) 1301 goto invalid_value; 1302 if (MACH_PORT_UREFS_OVERFLOW(urefs, delta)) 1303 goto urefs_overflow; 1304 1305 if ((urefs + delta) == 0) { 1306 ipc_entry_dealloc(space, name, entry); 1307 } else { 1308 entry->ie_bits = bits + delta; 1309 ipc_entry_modified(space, name, entry); 1310 } 1311 is_write_unlock(space); 1312 1313 if (relport != IP_NULL) 1314 ip_release(relport); 1315 1316 break; 1317 } 1318 1319 case MACH_PORT_RIGHT_SEND: { 1320 mach_port_urefs_t urefs; 1321 ipc_port_t request = IP_NULL; 1322 ipc_port_t nsrequest = IP_NULL; 1323 mach_port_mscount_t mscount = 0; 1324 1325 if ((bits & MACH_PORT_TYPE_SEND) == 0) 1326 goto invalid_right; 1327 1328 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */ 1329 1330 port = (ipc_port_t) entry->ie_object; 1331 assert(port != IP_NULL); 1332 1333 if (ipc_right_check(space, port, name, entry)) { 1334 assert((entry->ie_bits & MACH_PORT_TYPE_SEND) == 0); 1335 goto invalid_right; 1336 } 1337 /* port is locked and active */ 1338 1339 assert(port->ip_srights > 0); 1340 1341 urefs = IE_BITS_UREFS(bits); 1342 if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta)) { 1343 ip_unlock(port); 1344 goto invalid_value; 1345 } 1346 if (MACH_PORT_UREFS_OVERFLOW(urefs+1, delta)) { 1347 ip_unlock(port); 1348 goto urefs_overflow; 1349 } 1350 1351 if ((urefs + delta) == 0) { 1352 if (--port->ip_srights == 0) { 1353 nsrequest = port->ip_nsrequest; 1354 if (nsrequest != IP_NULL) { 1355 port->ip_nsrequest = IP_NULL; 1356 mscount = port->ip_mscount; 1357 } 1358 } 1359 1360 if (bits & MACH_PORT_TYPE_RECEIVE) { 1361 assert(port->ip_receiver_name == name); 1362 assert(port->ip_receiver == space); 1363 ip_unlock(port); 1364 assert(IE_BITS_TYPE(bits) == 1365 MACH_PORT_TYPE_SEND_RECEIVE); 1366 1367 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK| 1368 MACH_PORT_TYPE_SEND); 1369 ipc_entry_modified(space, name, entry); 1370 } else { 1371 assert(IE_BITS_TYPE(bits) == 1372 MACH_PORT_TYPE_SEND); 1373 1374 request = ipc_right_request_cancel_macro(space, port, 1375 name, entry); 1376 ipc_hash_delete(space, (ipc_object_t) port, 1377 name, entry); 1378 1379 ip_unlock(port); 1380 ip_release(port); 1381 1382 entry->ie_object = IO_NULL; 1383 ipc_entry_dealloc(space, name, entry); 1384 } 1385 } else { 1386 ip_unlock(port); 1387 entry->ie_bits = bits + delta; 1388 ipc_entry_modified(space, name, entry); 1389 } 1390 1391 is_write_unlock(space); 1392 1393 if (nsrequest != IP_NULL) 1394 ipc_notify_no_senders(nsrequest, mscount); 1395 1396 if (request != IP_NULL) 1397 ipc_notify_port_deleted(request, name); 1398 break; 1399 } 1400 1401 default: 1402 panic("ipc_right_delta: strange right"); 1403 } 1404 1405 return KERN_SUCCESS; 1406 1407 success: 1408 is_write_unlock(space); 1409 return KERN_SUCCESS; 1410 1411 invalid_right: 1412 is_write_unlock(space); 1413 if (port != IP_NULL) 1414 ip_release(port); 1415 return KERN_INVALID_RIGHT; 1416 1417 invalid_value: 1418 is_write_unlock(space); 1419 return KERN_INVALID_VALUE; 1420 1421 urefs_overflow: 1422 is_write_unlock(space); 1423 return KERN_UREFS_OVERFLOW; 1424 1425 guard_failure: 1426 return KERN_INVALID_RIGHT; 1427} 1428 1429/* 1430 * Routine: ipc_right_destruct 1431 * Purpose: 1432 * Deallocates the receive right and modifies the 1433 * user-reference count for the send rights as requested. 1434 * Conditions: 1435 * The space is write-locked, and is unlocked upon return. 1436 * The space must be active. 1437 * Returns: 1438 * KERN_SUCCESS Count was modified. 1439 * KERN_INVALID_RIGHT Entry has wrong type. 1440 * KERN_INVALID_VALUE Bad delta for the right. 1441 */ 1442 1443kern_return_t 1444ipc_right_destruct( 1445 ipc_space_t space, 1446 mach_port_name_t name, 1447 ipc_entry_t entry, 1448 mach_port_delta_t srdelta, 1449 uint64_t guard) 1450{ 1451 ipc_port_t port = IP_NULL; 1452 ipc_entry_bits_t bits; 1453 1454 queue_head_t links_data; 1455 queue_t links = &links_data; 1456 wait_queue_link_t wql; 1457 1458 mach_port_urefs_t urefs; 1459 ipc_port_t request = IP_NULL; 1460 ipc_port_t nsrequest = IP_NULL; 1461 mach_port_mscount_t mscount = 0; 1462 1463 bits = entry->ie_bits; 1464 1465 assert(is_active(space)); 1466 1467 if (((bits & MACH_PORT_TYPE_RECEIVE) == 0) || 1468 (srdelta && ((bits & MACH_PORT_TYPE_SEND) == 0))) { 1469 is_write_unlock(space); 1470 return KERN_INVALID_RIGHT; 1471 } 1472 1473 if (srdelta > 0) 1474 goto invalid_value; 1475 1476 port = (ipc_port_t) entry->ie_object; 1477 assert(port != IP_NULL); 1478 1479 ip_lock(port); 1480 assert(ip_active(port)); 1481 assert(port->ip_receiver_name == name); 1482 assert(port->ip_receiver == space); 1483 1484 /* Mach Port Guard Checking */ 1485 if(port->ip_guarded && (guard != port->ip_context)) { 1486 uint64_t portguard = port->ip_context; 1487 ip_unlock(port); 1488 is_write_unlock(space); 1489 mach_port_guard_exception(name, 0, portguard, kGUARD_EXC_DESTROY); 1490 return KERN_INVALID_ARGUMENT; 1491 } 1492 1493 /* 1494 * First reduce the send rights as requested and 1495 * adjust the entry->ie_bits accordingly. The 1496 * ipc_entry_modified() call is made once the receive 1497 * right is destroyed too. 1498 */ 1499 1500 if (srdelta) { 1501 1502 assert(port->ip_srights > 0); 1503 1504 urefs = IE_BITS_UREFS(bits); 1505 /* 1506 * Since we made sure that srdelta is negative, 1507 * the check for urefs overflow is not required. 1508 */ 1509 if (MACH_PORT_UREFS_UNDERFLOW(urefs, srdelta)) { 1510 ip_unlock(port); 1511 goto invalid_value; 1512 } 1513 if ((urefs + srdelta) == 0) { 1514 if (--port->ip_srights == 0) { 1515 nsrequest = port->ip_nsrequest; 1516 if (nsrequest != IP_NULL) { 1517 port->ip_nsrequest = IP_NULL; 1518 mscount = port->ip_mscount; 1519 } 1520 } 1521 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_RECEIVE); 1522 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK| 1523 MACH_PORT_TYPE_SEND); 1524 } else { 1525 entry->ie_bits = bits + srdelta; 1526 } 1527 } 1528 1529 /* 1530 * Now destroy the receive right. Update space and 1531 * entry accordingly. 1532 */ 1533 1534 bits = entry->ie_bits; 1535 if (bits & MACH_PORT_TYPE_SEND) { 1536 assert(IE_BITS_UREFS(bits) > 0); 1537 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX); 1538 1539 if (port->ip_pdrequest != NULL) { 1540 /* 1541 * Since another task has requested a 1542 * destroy notification for this port, it 1543 * isn't actually being destroyed - the receive 1544 * right is just being moved to another task. 1545 * Since we still have one or more send rights, 1546 * we need to record the loss of the receive 1547 * right and enter the remaining send right 1548 * into the hash table. 1549 */ 1550 ipc_entry_modified(space, name, entry); 1551 entry->ie_bits &= ~MACH_PORT_TYPE_RECEIVE; 1552 ipc_hash_insert(space, (ipc_object_t) port, 1553 name, entry); 1554 ip_reference(port); 1555 } else { 1556 /* 1557 * The remaining send right turns into a 1558 * dead name. Notice we don't decrement 1559 * ip_srights, generate a no-senders notif, 1560 * or use ipc_right_dncancel, because the 1561 * port is destroyed "first". 1562 */ 1563 bits &= ~IE_BITS_TYPE_MASK; 1564 bits |= MACH_PORT_TYPE_DEAD_NAME; 1565 if (entry->ie_request) { 1566 entry->ie_request = IE_REQ_NONE; 1567 bits++; 1568 } 1569 entry->ie_bits = bits; 1570 entry->ie_object = IO_NULL; 1571 ipc_entry_modified(space, name, entry); 1572 } 1573 } else { 1574 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE); 1575 assert(IE_BITS_UREFS(bits) == 0); 1576 request = ipc_right_request_cancel_macro(space, port, 1577 name, entry); 1578 entry->ie_object = IO_NULL; 1579 ipc_entry_dealloc(space, name, entry); 1580 } 1581 1582 /* Unlock space */ 1583 is_write_unlock(space); 1584 1585 if (nsrequest != IP_NULL) 1586 ipc_notify_no_senders(nsrequest, mscount); 1587 1588 queue_init(links); 1589 ipc_port_clear_receiver(port, links); 1590 ipc_port_destroy(port); /* consumes ref, unlocks */ 1591 1592 while(!queue_empty(links)) { 1593 wql = (wait_queue_link_t) dequeue(links); 1594 wait_queue_link_free(wql); 1595 } 1596 1597 if (request != IP_NULL) 1598 ipc_notify_port_deleted(request, name); 1599 1600 return KERN_SUCCESS; 1601 1602 invalid_value: 1603 is_write_unlock(space); 1604 return KERN_INVALID_VALUE; 1605 1606} 1607 1608 1609/* 1610 * Routine: ipc_right_info 1611 * Purpose: 1612 * Retrieves information about the right. 1613 * Conditions: 1614 * The space is active and write-locked. 1615 * The space is unlocked upon return. 1616 * Returns: 1617 * KERN_SUCCESS Retrieved info 1618 */ 1619 1620kern_return_t 1621ipc_right_info( 1622 ipc_space_t space, 1623 mach_port_name_t name, 1624 ipc_entry_t entry, 1625 mach_port_type_t *typep, 1626 mach_port_urefs_t *urefsp) 1627{ 1628 ipc_port_t port; 1629 ipc_entry_bits_t bits; 1630 mach_port_type_t type = 0; 1631 ipc_port_request_index_t request; 1632 1633 bits = entry->ie_bits; 1634 request = entry->ie_request; 1635 port = (ipc_port_t) entry->ie_object; 1636 1637 if (bits & MACH_PORT_TYPE_RECEIVE) { 1638 assert(IP_VALID(port)); 1639 1640 if (request != IE_REQ_NONE) { 1641 ip_lock(port); 1642 assert(ip_active(port)); 1643 type |= ipc_port_request_type(port, name, request); 1644 ip_unlock(port); 1645 } 1646 is_write_unlock(space); 1647 1648 } else if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { 1649 /* 1650 * validate port is still alive - if so, get request 1651 * types while we still have it locked. Otherwise, 1652 * recapture the (now dead) bits. 1653 */ 1654 if (!ipc_right_check(space, port, name, entry)) { 1655 if (request != IE_REQ_NONE) 1656 type |= ipc_port_request_type(port, name, request); 1657 ip_unlock(port); 1658 is_write_unlock(space); 1659 } else { 1660 bits = entry->ie_bits; 1661 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 1662 is_write_unlock(space); 1663 ip_release(port); 1664 } 1665 } else { 1666 is_write_unlock(space); 1667 } 1668 1669 type |= IE_BITS_TYPE(bits); 1670 1671 *typep = type; 1672 *urefsp = IE_BITS_UREFS(bits); 1673 return KERN_SUCCESS; 1674} 1675 1676/* 1677 * Routine: ipc_right_copyin_check 1678 * Purpose: 1679 * Check if a subsequent ipc_right_copyin would succeed. 1680 * Conditions: 1681 * The space is locked (read or write) and active. 1682 */ 1683 1684boolean_t 1685ipc_right_copyin_check( 1686 __assert_only ipc_space_t space, 1687 __unused mach_port_name_t name, 1688 ipc_entry_t entry, 1689 mach_msg_type_name_t msgt_name) 1690{ 1691 ipc_entry_bits_t bits; 1692 ipc_port_t port; 1693 1694 bits= entry->ie_bits; 1695 assert(is_active(space)); 1696 1697 switch (msgt_name) { 1698 case MACH_MSG_TYPE_MAKE_SEND: 1699 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1700 return FALSE; 1701 break; 1702 1703 case MACH_MSG_TYPE_MAKE_SEND_ONCE: 1704 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1705 return FALSE; 1706 break; 1707 1708 case MACH_MSG_TYPE_MOVE_RECEIVE: 1709 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1710 return FALSE; 1711 break; 1712 1713 case MACH_MSG_TYPE_COPY_SEND: 1714 case MACH_MSG_TYPE_MOVE_SEND: 1715 case MACH_MSG_TYPE_MOVE_SEND_ONCE: { 1716 1717 if (bits & MACH_PORT_TYPE_DEAD_NAME) 1718 break; 1719 1720 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 1721 return FALSE; 1722 1723 port = (ipc_port_t) entry->ie_object; 1724 assert(port != IP_NULL); 1725 1726 /* 1727 * active status peek to avoid checks that will be skipped 1728 * on copyin for dead ports. Lock not held, so will not be 1729 * atomic (but once dead, there's no going back). 1730 */ 1731 if (!ip_active(port)) { 1732 break; 1733 } 1734 1735 if (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE) { 1736 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) 1737 return FALSE; 1738 } else { 1739 if ((bits & MACH_PORT_TYPE_SEND) == 0) 1740 return FALSE; 1741 } 1742 1743 break; 1744 } 1745 1746 default: 1747 panic("ipc_right_copyin_check: strange rights"); 1748 } 1749 1750 return TRUE; 1751} 1752 1753/* 1754 * Routine: ipc_right_copyin 1755 * Purpose: 1756 * Copyin a capability from a space. 1757 * If successful, the caller gets a ref 1758 * for the resulting object, unless it is IO_DEAD, 1759 * and possibly a send-once right which should 1760 * be used in a port-deleted notification. 1761 * 1762 * If deadok is not TRUE, the copyin operation 1763 * will fail instead of producing IO_DEAD. 1764 * 1765 * The entry is never deallocated (except 1766 * when KERN_INVALID_NAME), so the caller 1767 * should deallocate the entry if its type 1768 * is MACH_PORT_TYPE_NONE. 1769 * Conditions: 1770 * The space is write-locked and active. 1771 * Returns: 1772 * KERN_SUCCESS Acquired an object, possibly IO_DEAD. 1773 * KERN_INVALID_RIGHT Name doesn't denote correct right. 1774 */ 1775 1776kern_return_t 1777ipc_right_copyin( 1778 ipc_space_t space, 1779 mach_port_name_t name, 1780 ipc_entry_t entry, 1781 mach_msg_type_name_t msgt_name, 1782 boolean_t deadok, 1783 ipc_object_t *objectp, 1784 ipc_port_t *sorightp, 1785 ipc_port_t *releasep, 1786#if IMPORTANCE_INHERITANCE 1787 int *assertcntp, 1788#endif /* IMPORTANCE_INHERITANCE */ 1789 queue_t links) 1790{ 1791 ipc_entry_bits_t bits; 1792 ipc_port_t port; 1793 1794 *releasep = IP_NULL; 1795 1796#if IMPORTANCE_INHERITANCE 1797 *assertcntp = 0; 1798#endif 1799 1800 bits = entry->ie_bits; 1801 1802 assert(is_active(space)); 1803 1804 switch (msgt_name) { 1805 case MACH_MSG_TYPE_MAKE_SEND: { 1806 1807 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1808 goto invalid_right; 1809 1810 port = (ipc_port_t) entry->ie_object; 1811 assert(port != IP_NULL); 1812 1813 ip_lock(port); 1814 assert(ip_active(port)); 1815 assert(port->ip_receiver_name == name); 1816 assert(port->ip_receiver == space); 1817 1818 port->ip_mscount++; 1819 port->ip_srights++; 1820 ip_reference(port); 1821 ip_unlock(port); 1822 1823 *objectp = (ipc_object_t) port; 1824 *sorightp = IP_NULL; 1825 break; 1826 } 1827 1828 case MACH_MSG_TYPE_MAKE_SEND_ONCE: { 1829 1830 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1831 goto invalid_right; 1832 1833 port = (ipc_port_t) entry->ie_object; 1834 assert(port != IP_NULL); 1835 1836 ip_lock(port); 1837 assert(ip_active(port)); 1838 assert(port->ip_receiver_name == name); 1839 assert(port->ip_receiver == space); 1840 1841 port->ip_sorights++; 1842 ip_reference(port); 1843 ip_unlock(port); 1844 1845 *objectp = (ipc_object_t) port; 1846 *sorightp = IP_NULL; 1847 break; 1848 } 1849 1850 case MACH_MSG_TYPE_MOVE_RECEIVE: { 1851 ipc_port_t request = IP_NULL; 1852 1853 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) 1854 goto invalid_right; 1855 1856 port = (ipc_port_t) entry->ie_object; 1857 assert(port != IP_NULL); 1858 1859 ip_lock(port); 1860 assert(ip_active(port)); 1861 assert(port->ip_receiver_name == name); 1862 assert(port->ip_receiver == space); 1863 1864 if (bits & MACH_PORT_TYPE_SEND) { 1865 assert(IE_BITS_TYPE(bits) == 1866 MACH_PORT_TYPE_SEND_RECEIVE); 1867 assert(IE_BITS_UREFS(bits) > 0); 1868 assert(port->ip_srights > 0); 1869 1870 ipc_hash_insert(space, (ipc_object_t) port, 1871 name, entry); 1872 ip_reference(port); 1873 } else { 1874 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE); 1875 assert(IE_BITS_UREFS(bits) == 0); 1876 1877 request = ipc_right_request_cancel_macro(space, port, 1878 name, entry); 1879 entry->ie_object = IO_NULL; 1880 } 1881 entry->ie_bits = bits &~ MACH_PORT_TYPE_RECEIVE; 1882 ipc_entry_modified(space, name, entry); 1883 1884 ipc_port_clear_receiver(port, links); 1885 port->ip_receiver_name = MACH_PORT_NULL; 1886 port->ip_destination = IP_NULL; 1887 1888#if IMPORTANCE_INHERITANCE 1889 /* 1890 * Account for boosts the current task is going to lose when 1891 * copying this right in. Tempowner ports have either not 1892 * been accounting to any task (and therefore are already in 1893 * "limbo" state w.r.t. assertions) or to some other specific 1894 * task. As we have no way to drop the latter task's assertions 1895 * here, We'll deduct those when we enqueue it on its 1896 * destination port (see ipc_port_check_circularity()). 1897 */ 1898 if (port->ip_tempowner == 0) { 1899 assert(IIT_NULL == port->ip_imp_task); 1900 1901 /* ports in limbo have to be tempowner */ 1902 port->ip_tempowner = 1; 1903 *assertcntp = port->ip_impcount; 1904 } 1905#endif /* IMPORTANCE_INHERITANCE */ 1906 1907 ip_unlock(port); 1908 1909 *objectp = (ipc_object_t) port; 1910 *sorightp = request; 1911 break; 1912 } 1913 1914 case MACH_MSG_TYPE_COPY_SEND: { 1915 1916 if (bits & MACH_PORT_TYPE_DEAD_NAME) 1917 goto copy_dead; 1918 1919 /* allow for dead send-once rights */ 1920 1921 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 1922 goto invalid_right; 1923 1924 assert(IE_BITS_UREFS(bits) > 0); 1925 1926 port = (ipc_port_t) entry->ie_object; 1927 assert(port != IP_NULL); 1928 1929 if (ipc_right_check(space, port, name, entry)) { 1930 bits = entry->ie_bits; 1931 *releasep = port; 1932 goto copy_dead; 1933 } 1934 /* port is locked and active */ 1935 1936 if ((bits & MACH_PORT_TYPE_SEND) == 0) { 1937 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 1938 assert(port->ip_sorights > 0); 1939 1940 ip_unlock(port); 1941 goto invalid_right; 1942 } 1943 1944 assert(port->ip_srights > 0); 1945 1946 port->ip_srights++; 1947 ip_reference(port); 1948 ip_unlock(port); 1949 1950 *objectp = (ipc_object_t) port; 1951 *sorightp = IP_NULL; 1952 break; 1953 } 1954 1955 case MACH_MSG_TYPE_MOVE_SEND: { 1956 ipc_port_t request = IP_NULL; 1957 1958 if (bits & MACH_PORT_TYPE_DEAD_NAME) 1959 goto move_dead; 1960 1961 /* allow for dead send-once rights */ 1962 1963 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 1964 goto invalid_right; 1965 1966 assert(IE_BITS_UREFS(bits) > 0); 1967 1968 port = (ipc_port_t) entry->ie_object; 1969 assert(port != IP_NULL); 1970 1971 if (ipc_right_check(space, port, name, entry)) { 1972 bits = entry->ie_bits; 1973 *releasep = port; 1974 goto move_dead; 1975 } 1976 /* port is locked and active */ 1977 1978 if ((bits & MACH_PORT_TYPE_SEND) == 0) { 1979 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 1980 assert(port->ip_sorights > 0); 1981 1982 ip_unlock(port); 1983 goto invalid_right; 1984 } 1985 1986 assert(port->ip_srights > 0); 1987 1988 if (IE_BITS_UREFS(bits) == 1) { 1989 if (bits & MACH_PORT_TYPE_RECEIVE) { 1990 assert(port->ip_receiver_name == name); 1991 assert(port->ip_receiver == space); 1992 assert(IE_BITS_TYPE(bits) == 1993 MACH_PORT_TYPE_SEND_RECEIVE); 1994 1995 ip_reference(port); 1996 } else { 1997 assert(IE_BITS_TYPE(bits) == 1998 MACH_PORT_TYPE_SEND); 1999 2000 request = ipc_right_request_cancel_macro(space, port, 2001 name, entry); 2002 ipc_hash_delete(space, (ipc_object_t) port, 2003 name, entry); 2004 entry->ie_object = IO_NULL; 2005 } 2006 entry->ie_bits = bits &~ 2007 (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND); 2008 } else { 2009 port->ip_srights++; 2010 ip_reference(port); 2011 entry->ie_bits = bits-1; /* decrement urefs */ 2012 } 2013 ipc_entry_modified(space, name, entry); 2014 ip_unlock(port); 2015 2016 *objectp = (ipc_object_t) port; 2017 *sorightp = request; 2018 break; 2019 } 2020 2021 case MACH_MSG_TYPE_MOVE_SEND_ONCE: { 2022 ipc_port_t request; 2023 2024 if (bits & MACH_PORT_TYPE_DEAD_NAME) 2025 goto move_dead; 2026 2027 /* allow for dead send rights */ 2028 2029 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) 2030 goto invalid_right; 2031 2032 assert(IE_BITS_UREFS(bits) > 0); 2033 2034 port = (ipc_port_t) entry->ie_object; 2035 assert(port != IP_NULL); 2036 2037 if (ipc_right_check(space, port, name, entry)) { 2038 bits = entry->ie_bits; 2039 goto move_dead; 2040 } 2041 /* port is locked and active */ 2042 2043 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) { 2044 assert(bits & MACH_PORT_TYPE_SEND); 2045 assert(port->ip_srights > 0); 2046 2047 ip_unlock(port); 2048 goto invalid_right; 2049 } 2050 2051 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE); 2052 assert(IE_BITS_UREFS(bits) == 1); 2053 assert(port->ip_sorights > 0); 2054 2055 request = ipc_right_request_cancel_macro(space, port, name, entry); 2056 ip_unlock(port); 2057 2058 entry->ie_object = IO_NULL; 2059 entry->ie_bits = bits &~ 2060 (IE_BITS_UREFS_MASK | MACH_PORT_TYPE_SEND_ONCE); 2061 ipc_entry_modified(space, name, entry); 2062 *objectp = (ipc_object_t) port; 2063 *sorightp = request; 2064 break; 2065 } 2066 2067 default: 2068 invalid_right: 2069 return KERN_INVALID_RIGHT; 2070 } 2071 2072 return KERN_SUCCESS; 2073 2074 copy_dead: 2075 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 2076 assert(IE_BITS_UREFS(bits) > 0); 2077 assert(entry->ie_request == IE_REQ_NONE); 2078 assert(entry->ie_object == 0); 2079 2080 if (!deadok) 2081 goto invalid_right; 2082 2083 *objectp = IO_DEAD; 2084 *sorightp = IP_NULL; 2085 return KERN_SUCCESS; 2086 2087 move_dead: 2088 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 2089 assert(IE_BITS_UREFS(bits) > 0); 2090 assert(entry->ie_request == IE_REQ_NONE); 2091 assert(entry->ie_object == 0); 2092 2093 if (!deadok) 2094 goto invalid_right; 2095 2096 if (IE_BITS_UREFS(bits) == 1) { 2097 bits &= ~MACH_PORT_TYPE_DEAD_NAME; 2098 } 2099 entry->ie_bits = bits-1; /* decrement urefs */ 2100 ipc_entry_modified(space, name, entry); 2101 *objectp = IO_DEAD; 2102 *sorightp = IP_NULL; 2103 return KERN_SUCCESS; 2104 2105} 2106 2107/* 2108 * Routine: ipc_right_copyin_undo 2109 * Purpose: 2110 * Undoes the effects of an ipc_right_copyin 2111 * of a send/send-once right that is dead. 2112 * (Object is either IO_DEAD or a dead port.) 2113 * Conditions: 2114 * The space is write-locked and active. 2115 */ 2116 2117void 2118ipc_right_copyin_undo( 2119 ipc_space_t space, 2120 mach_port_name_t name, 2121 ipc_entry_t entry, 2122 mach_msg_type_name_t msgt_name, 2123 ipc_object_t object, 2124 ipc_port_t soright) 2125{ 2126 ipc_entry_bits_t bits; 2127 2128 bits = entry->ie_bits; 2129 2130 assert(is_active(space)); 2131 2132 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 2133 (msgt_name == MACH_MSG_TYPE_COPY_SEND) || 2134 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE)); 2135 2136 if (soright != IP_NULL) { 2137 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 2138 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE)); 2139 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 2140 assert(object != IO_DEAD); 2141 2142 entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) | 2143 MACH_PORT_TYPE_DEAD_NAME | 2); 2144 2145 } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE) { 2146 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 2147 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE)); 2148 2149 entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) | 2150 MACH_PORT_TYPE_DEAD_NAME | 1); 2151 } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME) { 2152 assert(object == IO_DEAD); 2153 assert(IE_BITS_UREFS(bits) > 0); 2154 2155 if (msgt_name != MACH_MSG_TYPE_COPY_SEND) { 2156 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX); 2157 entry->ie_bits = bits+1; /* increment urefs */ 2158 } 2159 } else { 2160 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) || 2161 (msgt_name == MACH_MSG_TYPE_COPY_SEND)); 2162 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 2163 assert(object != IO_DEAD); 2164 assert(entry->ie_object == object); 2165 assert(IE_BITS_UREFS(bits) > 0); 2166 2167 if (msgt_name != MACH_MSG_TYPE_COPY_SEND) { 2168 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX-1); 2169 entry->ie_bits = bits+1; /* increment urefs */ 2170 } 2171 2172 /* 2173 * May as well convert the entry to a dead name. 2174 * (Or if it is a compat entry, destroy it.) 2175 */ 2176 2177 (void) ipc_right_check(space, (ipc_port_t) object, 2178 name, entry); 2179 /* object is dead so it is not locked */ 2180 } 2181 ipc_entry_modified(space, name, entry); 2182 /* release the reference acquired by copyin */ 2183 2184 if (object != IO_DEAD) 2185 io_release(object); 2186} 2187 2188/* 2189 * Routine: ipc_right_copyin_two_move_sends 2190 * Purpose: 2191 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND 2192 * and deadok == FALSE, except that this moves two 2193 * send rights at once. 2194 * Conditions: 2195 * The space is write-locked and active. 2196 * The object is returned with two refs/send rights. 2197 * Returns: 2198 * KERN_SUCCESS Acquired an object. 2199 * KERN_INVALID_RIGHT Name doesn't denote correct right. 2200 */ 2201static 2202kern_return_t 2203ipc_right_copyin_two_move_sends( 2204 ipc_space_t space, 2205 mach_port_name_t name, 2206 ipc_entry_t entry, 2207 ipc_object_t *objectp, 2208 ipc_port_t *sorightp, 2209 ipc_port_t *releasep) 2210{ 2211 ipc_entry_bits_t bits; 2212 mach_port_urefs_t urefs; 2213 ipc_port_t port; 2214 ipc_port_t request = IP_NULL; 2215 2216 *releasep = IP_NULL; 2217 2218 assert(is_active(space)); 2219 2220 bits = entry->ie_bits; 2221 2222 if ((bits & MACH_PORT_TYPE_SEND) == 0) 2223 goto invalid_right; 2224 2225 urefs = IE_BITS_UREFS(bits); 2226 if (urefs < 2) 2227 goto invalid_right; 2228 2229 port = (ipc_port_t) entry->ie_object; 2230 assert(port != IP_NULL); 2231 2232 if (ipc_right_check(space, port, name, entry)) { 2233 *releasep = port; 2234 goto invalid_right; 2235 } 2236 /* port is locked and active */ 2237 2238 assert(port->ip_srights > 0); 2239 2240 if (urefs == 2) { 2241 if (bits & MACH_PORT_TYPE_RECEIVE) { 2242 assert(port->ip_receiver_name == name); 2243 assert(port->ip_receiver == space); 2244 assert(IE_BITS_TYPE(bits) == 2245 MACH_PORT_TYPE_SEND_RECEIVE); 2246 2247 port->ip_srights++; 2248 ip_reference(port); 2249 ip_reference(port); 2250 } else { 2251 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 2252 2253 request = ipc_right_request_cancel_macro(space, port, 2254 name, entry); 2255 2256 port->ip_srights++; 2257 ip_reference(port); 2258 ipc_hash_delete(space, (ipc_object_t) port, 2259 name, entry); 2260 entry->ie_object = IO_NULL; 2261 } 2262 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND); 2263 } else { 2264 port->ip_srights += 2; 2265 ip_reference(port); 2266 ip_reference(port); 2267 entry->ie_bits = bits-2; /* decrement urefs */ 2268 } 2269 ipc_entry_modified(space, name, entry); 2270 2271 ip_unlock(port); 2272 2273 *objectp = (ipc_object_t) port; 2274 *sorightp = request; 2275 return KERN_SUCCESS; 2276 2277 invalid_right: 2278 return KERN_INVALID_RIGHT; 2279} 2280 2281 2282/* 2283 * Routine: ipc_right_copyin_two 2284 * Purpose: 2285 * Like ipc_right_copyin with two dispositions, 2286 * each of which results in a send or send-once right, 2287 * and deadok = FALSE. 2288 * Conditions: 2289 * The space is write-locked and active. 2290 * The object is returned with two refs/rights. 2291 * Returns: 2292 * KERN_SUCCESS Acquired an object. 2293 * KERN_INVALID_RIGHT Name doesn't denote correct right(s). 2294 * KERN_INVALID_CAPABILITY Name doesn't denote correct right for msgt_two. 2295 */ 2296kern_return_t 2297ipc_right_copyin_two( 2298 ipc_space_t space, 2299 mach_port_name_t name, 2300 ipc_entry_t entry, 2301 mach_msg_type_name_t msgt_one, 2302 mach_msg_type_name_t msgt_two, 2303 ipc_object_t *objectp, 2304 ipc_port_t *sorightp, 2305 ipc_port_t *releasep) 2306{ 2307 queue_head_t links_data; 2308 queue_t links = &links_data; 2309 kern_return_t kr; 2310 2311#if IMPORTANCE_INHERITANCE 2312 int assertcnt = 0; 2313#endif 2314 2315 queue_init(links); 2316 2317 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one)); 2318 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two)); 2319 2320 2321 /* 2322 * Pre-validate the second disposition is possible all by itself. 2323 */ 2324 if (!ipc_right_copyin_check(space, name, entry, msgt_two)) { 2325 return KERN_INVALID_CAPABILITY; 2326 } 2327 2328 /* 2329 * This is a little tedious to make atomic, because 2330 * there are 25 combinations of valid dispositions. 2331 * However, most are easy. 2332 */ 2333 2334 /* 2335 * If either is move-sonce, then there must be an error. 2336 */ 2337 if (msgt_one == MACH_MSG_TYPE_MOVE_SEND_ONCE || 2338 msgt_two == MACH_MSG_TYPE_MOVE_SEND_ONCE) { 2339 return KERN_INVALID_RIGHT; 2340 } 2341 2342 if ((msgt_one == MACH_MSG_TYPE_MAKE_SEND) || 2343 (msgt_one == MACH_MSG_TYPE_MAKE_SEND_ONCE) || 2344 (msgt_two == MACH_MSG_TYPE_MAKE_SEND) || 2345 (msgt_two == MACH_MSG_TYPE_MAKE_SEND_ONCE)) { 2346 /* 2347 * One of the dispositions needs a receive right. 2348 * 2349 * If the copyin below succeeds, we know the receive 2350 * right is there (because the pre-validation of 2351 * the second disposition already succeeded in our 2352 * caller). 2353 * 2354 * Hence the port is not in danger of dying. 2355 */ 2356 ipc_object_t object_two; 2357 2358#if IMPORTANCE_INHERITANCE 2359 kr = ipc_right_copyin(space, name, entry, 2360 msgt_one, FALSE, 2361 objectp, sorightp, releasep, 2362 &assertcnt, links); 2363 assert(assertcnt == 0); 2364#else 2365 kr = ipc_right_copyin(space, name, entry, 2366 msgt_one, FALSE, 2367 objectp, sorightp, releasep, 2368 links); 2369#endif /* IMPORTANCE_INHERITANCE */ 2370 if (kr != KERN_SUCCESS) { 2371 return kr; 2372 } 2373 2374 assert(IO_VALID(*objectp)); 2375 assert(*sorightp == IP_NULL); 2376 assert(*releasep == IP_NULL); 2377 2378 /* 2379 * Now copyin the second (previously validated) 2380 * disposition. The result can't be a dead port, 2381 * as no valid disposition can make us lose our 2382 * receive right. 2383 */ 2384#if IMPORTANCE_INHERITANCE 2385 kr = ipc_right_copyin(space, name, entry, 2386 msgt_two, FALSE, 2387 &object_two, sorightp, releasep, 2388 &assertcnt, links); 2389 assert(assertcnt == 0); 2390#else 2391 kr = ipc_right_copyin(space, name, entry, 2392 msgt_two, FALSE, 2393 &object_two, sorightp, releasep, 2394 links); 2395#endif /* IMPORTANCE_INHERITANCE */ 2396 assert(kr == KERN_SUCCESS); 2397 assert(*sorightp == IP_NULL); 2398 assert(*releasep == IP_NULL); 2399 assert(object_two == *objectp); 2400 assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE); 2401 2402 } else if ((msgt_one == MACH_MSG_TYPE_MOVE_SEND) && 2403 (msgt_two == MACH_MSG_TYPE_MOVE_SEND)) { 2404 /* 2405 * This is an easy case. Just use our 2406 * handy-dandy special-purpose copyin call 2407 * to get two send rights for the price of one. 2408 */ 2409 kr = ipc_right_copyin_two_move_sends(space, name, entry, 2410 objectp, sorightp, 2411 releasep); 2412 if (kr != KERN_SUCCESS) { 2413 return kr; 2414 } 2415 2416 } else { 2417 mach_msg_type_name_t msgt_name; 2418 2419 /* 2420 * Must be either a single move-send and a 2421 * copy-send, or two copy-send dispositions. 2422 * Use the disposition with the greatest side 2423 * effects for the actual copyin - then just 2424 * duplicate the send right you get back. 2425 */ 2426 if (msgt_one == MACH_MSG_TYPE_MOVE_SEND || 2427 msgt_two == MACH_MSG_TYPE_MOVE_SEND) { 2428 msgt_name = MACH_MSG_TYPE_MOVE_SEND; 2429 } else { 2430 msgt_name = MACH_MSG_TYPE_COPY_SEND; 2431 } 2432 2433#if IMPORTANCE_INHERITANCE 2434 kr = ipc_right_copyin(space, name, entry, 2435 msgt_name, FALSE, 2436 objectp, sorightp, releasep, 2437 &assertcnt, links); 2438 assert(assertcnt == 0); 2439#else 2440 kr = ipc_right_copyin(space, name, entry, 2441 msgt_name, FALSE, 2442 objectp, sorightp, releasep, 2443 links); 2444#endif /* IMPORTANCE_INHERITANCE */ 2445 if (kr != KERN_SUCCESS) { 2446 return kr; 2447 } 2448 2449 /* 2450 * Copy the right we got back. If it is dead now, 2451 * that's OK. Neither right will be usable to send 2452 * a message anyway. 2453 */ 2454 (void)ipc_port_copy_send((ipc_port_t)*objectp); 2455 } 2456 2457 assert(queue_empty(links)); 2458 2459 return KERN_SUCCESS; 2460} 2461 2462 2463/* 2464 * Routine: ipc_right_copyout 2465 * Purpose: 2466 * Copyout a capability to a space. 2467 * If successful, consumes a ref for the object. 2468 * 2469 * Always succeeds when given a newly-allocated entry, 2470 * because user-reference overflow isn't a possibility. 2471 * 2472 * If copying out the object would cause the user-reference 2473 * count in the entry to overflow, and overflow is TRUE, 2474 * then instead the user-reference count is left pegged 2475 * to its maximum value and the copyout succeeds anyway. 2476 * Conditions: 2477 * The space is write-locked and active. 2478 * The object is locked and active. 2479 * The object is unlocked; the space isn't. 2480 * Returns: 2481 * KERN_SUCCESS Copied out capability. 2482 * KERN_UREFS_OVERFLOW User-refs would overflow; 2483 * guaranteed not to happen with a fresh entry 2484 * or if overflow=TRUE was specified. 2485 */ 2486 2487kern_return_t 2488ipc_right_copyout( 2489 ipc_space_t space, 2490 mach_port_name_t name, 2491 ipc_entry_t entry, 2492 mach_msg_type_name_t msgt_name, 2493 boolean_t overflow, 2494 ipc_object_t object) 2495{ 2496 ipc_entry_bits_t bits; 2497 ipc_port_t port; 2498 2499 bits = entry->ie_bits; 2500 2501 assert(IO_VALID(object)); 2502 assert(io_otype(object) == IOT_PORT); 2503 assert(io_active(object)); 2504 assert(entry->ie_object == object); 2505 2506 port = (ipc_port_t) object; 2507 2508 switch (msgt_name) { 2509 case MACH_MSG_TYPE_PORT_SEND_ONCE: 2510 2511 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 2512 assert(port->ip_sorights > 0); 2513 2514 /* transfer send-once right and ref to entry */ 2515 ip_unlock(port); 2516 2517 entry->ie_bits = bits | (MACH_PORT_TYPE_SEND_ONCE | 1); 2518 ipc_entry_modified(space, name, entry); 2519 break; 2520 2521 case MACH_MSG_TYPE_PORT_SEND: 2522 assert(port->ip_srights > 0); 2523 2524 if (bits & MACH_PORT_TYPE_SEND) { 2525 mach_port_urefs_t urefs = IE_BITS_UREFS(bits); 2526 2527 assert(port->ip_srights > 1); 2528 assert(urefs > 0); 2529 assert(urefs < MACH_PORT_UREFS_MAX); 2530 2531 if (urefs+1 == MACH_PORT_UREFS_MAX) { 2532 if (overflow) { 2533 /* leave urefs pegged to maximum */ 2534 2535 port->ip_srights--; 2536 ip_unlock(port); 2537 ip_release(port); 2538 return KERN_SUCCESS; 2539 } 2540 2541 ip_unlock(port); 2542 return KERN_UREFS_OVERFLOW; 2543 } 2544 port->ip_srights--; 2545 ip_unlock(port); 2546 ip_release(port); 2547 2548 } else if (bits & MACH_PORT_TYPE_RECEIVE) { 2549 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE); 2550 assert(IE_BITS_UREFS(bits) == 0); 2551 2552 /* transfer send right to entry */ 2553 ip_unlock(port); 2554 ip_release(port); 2555 2556 } else { 2557 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 2558 assert(IE_BITS_UREFS(bits) == 0); 2559 2560 /* transfer send right and ref to entry */ 2561 ip_unlock(port); 2562 2563 /* entry is locked holding ref, so can use port */ 2564 2565 ipc_hash_insert(space, (ipc_object_t) port, 2566 name, entry); 2567 } 2568 2569 entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1; 2570 ipc_entry_modified(space, name, entry); 2571 break; 2572 2573 case MACH_MSG_TYPE_PORT_RECEIVE: { 2574 ipc_port_t dest; 2575 2576#if IMPORTANCE_INHERITANCE 2577 natural_t assertcnt = port->ip_impcount; 2578#endif /* IMPORTANCE_INHERITANCE */ 2579 2580 assert(port->ip_mscount == 0); 2581 assert(port->ip_receiver_name == MACH_PORT_NULL); 2582 dest = port->ip_destination; 2583 2584 port->ip_receiver_name = name; 2585 port->ip_receiver = space; 2586 2587 assert((bits & MACH_PORT_TYPE_RECEIVE) == 0); 2588 2589 if (bits & MACH_PORT_TYPE_SEND) { 2590 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND); 2591 assert(IE_BITS_UREFS(bits) > 0); 2592 assert(port->ip_srights > 0); 2593 2594 ip_unlock(port); 2595 ip_release(port); 2596 2597 /* entry is locked holding ref, so can use port */ 2598 2599 ipc_hash_delete(space, (ipc_object_t) port, 2600 name, entry); 2601 } else { 2602 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE); 2603 assert(IE_BITS_UREFS(bits) == 0); 2604 2605 /* transfer ref to entry */ 2606 ip_unlock(port); 2607 } 2608 entry->ie_bits = bits | MACH_PORT_TYPE_RECEIVE; 2609 ipc_entry_modified(space, name, entry); 2610 2611 if (dest != IP_NULL) { 2612#if IMPORTANCE_INHERITANCE 2613 /* 2614 * Deduct the assertion counts we contributed to 2615 * the old destination port. They've already 2616 * been reflected into the task as a result of 2617 * getting enqueued. 2618 */ 2619 ip_lock(dest); 2620 ipc_port_impcount_delta(dest, 0 - assertcnt, IP_NULL); 2621 ip_unlock(dest); 2622#endif /* IMPORTANCE_INHERITANCE */ 2623 ip_release(dest); 2624 } 2625 break; 2626 } 2627 2628 default: 2629 panic("ipc_right_copyout: strange rights"); 2630 } 2631 return KERN_SUCCESS; 2632} 2633 2634/* 2635 * Routine: ipc_right_rename 2636 * Purpose: 2637 * Transfer an entry from one name to another. 2638 * The old entry is deallocated. 2639 * Conditions: 2640 * The space is write-locked and active. 2641 * The new entry is unused. Upon return, 2642 * the space is unlocked. 2643 * Returns: 2644 * KERN_SUCCESS Moved entry to new name. 2645 */ 2646 2647kern_return_t 2648ipc_right_rename( 2649 ipc_space_t space, 2650 mach_port_name_t oname, 2651 ipc_entry_t oentry, 2652 mach_port_name_t nname, 2653 ipc_entry_t nentry) 2654{ 2655 ipc_port_request_index_t request = oentry->ie_request; 2656 ipc_entry_bits_t bits = oentry->ie_bits; 2657 ipc_object_t object = oentry->ie_object; 2658 ipc_port_t release_port = IP_NULL; 2659 2660 assert(is_active(space)); 2661 assert(oname != nname); 2662 2663 /* 2664 * If IE_BITS_COMPAT, we can't allow the entry to be renamed 2665 * if the port is dead. (This would foil ipc_port_destroy.) 2666 * Instead we should fail because oentry shouldn't exist. 2667 * Note IE_BITS_COMPAT implies ie_request != 0. 2668 */ 2669 2670 if (request != IE_REQ_NONE) { 2671 ipc_port_t port; 2672 2673 assert(bits & MACH_PORT_TYPE_PORT_RIGHTS); 2674 port = (ipc_port_t) object; 2675 assert(port != IP_NULL); 2676 2677 if (ipc_right_check(space, port, oname, oentry)) { 2678 request = IE_REQ_NONE; 2679 object = IO_NULL; 2680 bits = oentry->ie_bits; 2681 release_port = port; 2682 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME); 2683 assert(oentry->ie_request == IE_REQ_NONE); 2684 } else { 2685 /* port is locked and active */ 2686 2687 ipc_port_request_rename(port, request, oname, nname); 2688 ip_unlock(port); 2689 oentry->ie_request = IE_REQ_NONE; 2690 } 2691 } 2692 2693 /* initialize nentry before letting ipc_hash_insert see it */ 2694 2695 assert((nentry->ie_bits & IE_BITS_RIGHT_MASK) == 0); 2696 nentry->ie_bits |= bits & IE_BITS_RIGHT_MASK; 2697 nentry->ie_request = request; 2698 nentry->ie_object = object; 2699 2700 switch (IE_BITS_TYPE(bits)) { 2701 case MACH_PORT_TYPE_SEND: { 2702 ipc_port_t port; 2703 2704 port = (ipc_port_t) object; 2705 assert(port != IP_NULL); 2706 2707 /* remember, there are no other share entries possible */ 2708 /* or we can't do the rename. Therefore we do not need */ 2709 /* to check the other subspaces */ 2710 ipc_hash_delete(space, (ipc_object_t) port, oname, oentry); 2711 ipc_hash_insert(space, (ipc_object_t) port, nname, nentry); 2712 break; 2713 } 2714 2715 case MACH_PORT_TYPE_RECEIVE: 2716 case MACH_PORT_TYPE_SEND_RECEIVE: { 2717 ipc_port_t port; 2718 2719 port = (ipc_port_t) object; 2720 assert(port != IP_NULL); 2721 2722 ip_lock(port); 2723 assert(ip_active(port)); 2724 assert(port->ip_receiver_name == oname); 2725 assert(port->ip_receiver == space); 2726 2727 port->ip_receiver_name = nname; 2728 ip_unlock(port); 2729 break; 2730 } 2731 2732 case MACH_PORT_TYPE_PORT_SET: { 2733 ipc_pset_t pset; 2734 2735 pset = (ipc_pset_t) object; 2736 assert(pset != IPS_NULL); 2737 2738 ips_lock(pset); 2739 assert(ips_active(pset)); 2740 assert(pset->ips_local_name == oname); 2741 2742 pset->ips_local_name = nname; 2743 ips_unlock(pset); 2744 break; 2745 } 2746 2747 case MACH_PORT_TYPE_SEND_ONCE: 2748 case MACH_PORT_TYPE_DEAD_NAME: 2749 break; 2750 2751 default: 2752 panic("ipc_right_rename: strange rights"); 2753 } 2754 2755 assert(oentry->ie_request == IE_REQ_NONE); 2756 oentry->ie_object = IO_NULL; 2757 ipc_entry_dealloc(space, oname, oentry); 2758 ipc_entry_modified(space, nname, nentry); 2759 is_write_unlock(space); 2760 2761 if (release_port != IP_NULL) 2762 ip_release(release_port); 2763 2764 return KERN_SUCCESS; 2765} 2766