osfmk/ipc/ipc_right.c

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