ipc_object.c
1 /* 2 * Copyright (c) 2000-2020 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* 29 * @OSF_COPYRIGHT@ 30 */ 31 /* 32 * Mach Operating System 33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56 /* 57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce 58 * support for mandatory and extensible security protections. This notice 59 * is included in support of clause 2.2 (b) of the Apple Public License, 60 * Version 2.0. 61 * Copyright (c) 2005-2006 SPARTA, Inc. 62 */ 63 /* 64 */ 65 /* 66 * File: ipc/ipc_object.c 67 * Author: Rich Draves 68 * Date: 1989 69 * 70 * Functions to manipulate IPC objects. 71 */ 72 73 #include <mach/mach_types.h> 74 #include <mach/boolean.h> 75 #include <mach/kern_return.h> 76 #include <mach/port.h> 77 #include <mach/message.h> 78 79 #include <kern/kern_types.h> 80 #include <kern/misc_protos.h> 81 #include <kern/ipc_kobject.h> 82 83 #include <ipc/ipc_types.h> 84 #include <ipc/ipc_importance.h> 85 #include <ipc/port.h> 86 #include <ipc/ipc_space.h> 87 #include <ipc/ipc_entry.h> 88 #include <ipc/ipc_object.h> 89 #include <ipc/ipc_hash.h> 90 #include <ipc/ipc_right.h> 91 #include <ipc/ipc_notify.h> 92 #include <ipc/ipc_port.h> 93 #include <ipc/ipc_pset.h> 94 95 #include <security/mac_mach_internal.h> 96 97 #if DSERVER_EXTENDED_DEBUG 98 #include <darlingserver/duct-tape/hooks.internal.h> 99 #include <darlingserver/duct-tape/task.h> 100 #endif 101 102 SECURITY_READ_ONLY_LATE(zone_t) ipc_object_zones[IOT_NUMBER]; 103 104 ZONE_INIT(&ipc_object_zones[IOT_PORT], "ipc ports", sizeof(struct ipc_port), 105 ZC_NOENCRYPT | ZC_CACHING | ZC_ZFREE_CLEARMEM | ZC_NOSEQUESTER, 106 ZONE_ID_IPC_PORT, NULL); 107 108 ZONE_INIT(&ipc_object_zones[IOT_PORT_SET], "ipc port sets", 109 sizeof(struct ipc_pset), 110 ZC_NOENCRYPT | ZC_ZFREE_CLEARMEM | ZC_NOSEQUESTER, 111 ZONE_ID_IPC_PORT_SET, NULL); 112 113 /* 114 * Routine: ipc_object_reference 115 * Purpose: 116 * Take a reference to an object. 117 */ 118 119 void 120 ipc_object_reference( 121 ipc_object_t object) 122 { 123 io_reference(object); 124 } 125 126 /* 127 * Routine: ipc_object_release 128 * Purpose: 129 * Release a reference to an object. 130 */ 131 132 void 133 ipc_object_release( 134 ipc_object_t object) 135 { 136 io_release(object); 137 } 138 139 /* 140 * Routine: ipc_object_translate 141 * Purpose: 142 * Look up an object in a space. 143 * Conditions: 144 * Nothing locked before. If successful, the object 145 * is returned active and locked. The caller doesn't get a ref. 146 * Returns: 147 * KERN_SUCCESS Object returned locked. 148 * KERN_INVALID_TASK The space is dead. 149 * KERN_INVALID_NAME The name doesn't denote a right 150 * KERN_INVALID_RIGHT Name doesn't denote the correct right 151 */ 152 kern_return_t 153 ipc_object_translate( 154 ipc_space_t space, 155 mach_port_name_t name, 156 mach_port_right_t right, 157 ipc_object_t *objectp) 158 { 159 ipc_entry_t entry; 160 ipc_object_t object; 161 kern_return_t kr; 162 163 if (!MACH_PORT_RIGHT_VALID_TRANSLATE(right)) { 164 return KERN_INVALID_RIGHT; 165 } 166 167 kr = ipc_right_lookup_read(space, name, &entry); 168 if (kr != KERN_SUCCESS) { 169 return kr; 170 } 171 /* space is read-locked and active */ 172 173 if ((entry->ie_bits & MACH_PORT_TYPE(right)) == MACH_PORT_TYPE_NONE) { 174 is_read_unlock(space); 175 return KERN_INVALID_RIGHT; 176 } 177 178 object = entry->ie_object; 179 assert(object != IO_NULL); 180 181 io_lock(object); 182 is_read_unlock(space); 183 184 if (!io_active(object)) { 185 io_unlock(object); 186 return KERN_INVALID_NAME; 187 } 188 189 *objectp = object; 190 return KERN_SUCCESS; 191 } 192 193 /* 194 * Routine: ipc_object_translate_two 195 * Purpose: 196 * Look up two objects in a space. 197 * Conditions: 198 * Nothing locked before. If successful, the objects 199 * are returned locked. The caller doesn't get a ref. 200 * Returns: 201 * KERN_SUCCESS Objects returned locked. 202 * KERN_INVALID_TASK The space is dead. 203 * KERN_INVALID_NAME A name doesn't denote a right. 204 * KERN_INVALID_RIGHT A name doesn't denote the correct right. 205 */ 206 207 kern_return_t 208 ipc_object_translate_two( 209 ipc_space_t space, 210 mach_port_name_t name1, 211 mach_port_right_t right1, 212 ipc_object_t *objectp1, 213 mach_port_name_t name2, 214 mach_port_right_t right2, 215 ipc_object_t *objectp2) 216 { 217 ipc_entry_t entry1; 218 ipc_entry_t entry2; 219 ipc_object_t object1, object2; 220 kern_return_t kr; 221 boolean_t doguard = TRUE; 222 223 kr = ipc_right_lookup_two_read(space, name1, &entry1, name2, &entry2); 224 if (kr != KERN_SUCCESS) { 225 return kr; 226 } 227 /* space is read-locked and active */ 228 229 if ((entry1->ie_bits & MACH_PORT_TYPE(right1)) == MACH_PORT_TYPE_NONE) { 230 /* If looking for receive, and the entry used to hold one, give a pass on EXC_GUARD */ 231 if ((right1 & MACH_PORT_RIGHT_RECEIVE) == MACH_PORT_RIGHT_RECEIVE && 232 (entry1->ie_bits & MACH_PORT_TYPE_EX_RECEIVE) == MACH_PORT_TYPE_EX_RECEIVE) { 233 doguard = FALSE; 234 } 235 is_read_unlock(space); 236 if (doguard) { 237 mach_port_guard_exception(name1, 0, 0, kGUARD_EXC_INVALID_RIGHT); 238 } 239 return KERN_INVALID_RIGHT; 240 } 241 242 if ((entry2->ie_bits & MACH_PORT_TYPE(right2)) == MACH_PORT_TYPE_NONE) { 243 /* If looking for receive, and the entry used to hold one, give a pass on EXC_GUARD */ 244 if ((right2 & MACH_PORT_RIGHT_RECEIVE) == MACH_PORT_RIGHT_RECEIVE && 245 (entry2->ie_bits & MACH_PORT_TYPE_EX_RECEIVE) == MACH_PORT_TYPE_EX_RECEIVE) { 246 doguard = FALSE; 247 } 248 is_read_unlock(space); 249 if (doguard) { 250 mach_port_guard_exception(name2, 0, 0, kGUARD_EXC_INVALID_RIGHT); 251 } 252 return KERN_INVALID_RIGHT; 253 } 254 255 object1 = entry1->ie_object; 256 assert(object1 != IO_NULL); 257 io_lock(object1); 258 if (!io_active(object1)) { 259 io_unlock(object1); 260 is_read_unlock(space); 261 return KERN_INVALID_NAME; 262 } 263 264 object2 = entry2->ie_object; 265 assert(object2 != IO_NULL); 266 io_lock(object2); 267 if (!io_active(object2)) { 268 io_unlock(object1); 269 io_unlock(object2); 270 is_read_unlock(space); 271 return KERN_INVALID_NAME; 272 } 273 274 *objectp1 = object1; 275 *objectp2 = object2; 276 277 is_read_unlock(space); 278 return KERN_SUCCESS; 279 } 280 281 /* 282 * Routine: ipc_object_alloc_dead 283 * Purpose: 284 * Allocate a dead-name entry. 285 * Conditions: 286 * Nothing locked. 287 * Returns: 288 * KERN_SUCCESS The dead name is allocated. 289 * KERN_INVALID_TASK The space is dead. 290 * KERN_NO_SPACE No room for an entry in the space. 291 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 292 */ 293 294 kern_return_t 295 ipc_object_alloc_dead( 296 ipc_space_t space, 297 mach_port_name_t *namep) 298 { 299 ipc_entry_t entry; 300 kern_return_t kr; 301 302 kr = ipc_entry_alloc(space, namep, &entry); 303 if (kr != KERN_SUCCESS) { 304 return kr; 305 } 306 /* space is write-locked */ 307 308 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ 309 310 assert(entry->ie_object == IO_NULL); 311 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; 312 ipc_entry_modified(space, *namep, entry); 313 is_write_unlock(space); 314 return KERN_SUCCESS; 315 } 316 317 /* 318 * Routine: ipc_object_alloc_dead_name 319 * Purpose: 320 * Allocate a dead-name entry, with a specific name. 321 * Conditions: 322 * Nothing locked. 323 * Returns: 324 * KERN_SUCCESS The dead name is allocated. 325 * KERN_INVALID_TASK The space is dead. 326 * KERN_NAME_EXISTS The name already denotes a right. 327 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 328 */ 329 330 kern_return_t 331 ipc_object_alloc_dead_name( 332 ipc_space_t space, 333 mach_port_name_t name) 334 { 335 ipc_entry_t entry; 336 kern_return_t kr; 337 338 kr = ipc_entry_alloc_name(space, name, &entry); 339 if (kr != KERN_SUCCESS) { 340 return kr; 341 } 342 /* space is write-locked */ 343 344 if (ipc_right_inuse(entry)) { 345 is_write_unlock(space); 346 return KERN_NAME_EXISTS; 347 } 348 349 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ 350 351 assert(entry->ie_object == IO_NULL); 352 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; 353 ipc_entry_modified(space, name, entry); 354 is_write_unlock(space); 355 return KERN_SUCCESS; 356 } 357 358 /* 359 * Routine: ipc_object_alloc 360 * Purpose: 361 * Allocate an object. 362 * Conditions: 363 * Nothing locked. If successful, the object is returned locked. 364 * The space is write locked on successful return. 365 * The caller doesn't get a reference for the object. 366 * Returns: 367 * KERN_SUCCESS The object is allocated. 368 * KERN_INVALID_TASK The space is dead. 369 * KERN_NO_SPACE No room for an entry in the space. 370 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 371 */ 372 373 kern_return_t 374 ipc_object_alloc( 375 ipc_space_t space, 376 ipc_object_type_t otype, 377 mach_port_type_t type, 378 mach_port_urefs_t urefs, 379 mach_port_name_t *namep, 380 ipc_object_t *objectp) 381 { 382 ipc_object_t object; 383 ipc_entry_t entry; 384 kern_return_t kr; 385 386 assert(otype < IOT_NUMBER); 387 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); 388 assert(type != MACH_PORT_TYPE_NONE); 389 assert(urefs <= MACH_PORT_UREFS_MAX); 390 391 object = io_alloc(otype, Z_WAITOK | Z_ZERO); 392 if (object == IO_NULL) { 393 return KERN_RESOURCE_SHORTAGE; 394 } 395 396 io_lock_init(object); 397 *namep = CAST_MACH_PORT_TO_NAME(object); 398 kr = ipc_entry_alloc(space, namep, &entry); 399 if (kr != KERN_SUCCESS) { 400 io_free(otype, object); 401 return kr; 402 } 403 /* space is write-locked */ 404 405 entry->ie_bits |= type | urefs; 406 entry->ie_object = object; 407 ipc_entry_modified(space, *namep, entry); 408 409 object->io_bits = io_makebits(TRUE, otype, 0); 410 io_lock(object); 411 412 object->io_references = 1; /* for entry, not caller */ 413 414 #if DSERVER_EXTENDED_DEBUG 415 dtape_hooks->task_register_name(dtape_task_for_xnu_task(current_task())->context, *namep, (uintptr_t)object); 416 #endif 417 418 *objectp = object; 419 return KERN_SUCCESS; 420 } 421 422 /* 423 * Routine: ipc_object_alloc_name 424 * Purpose: 425 * Allocate an object, with a specific name. 426 * Conditions: 427 * Nothing locked. If successful, the object is returned locked. 428 * The caller doesn't get a reference for the object. 429 * Returns: 430 * KERN_SUCCESS The object is allocated. 431 * KERN_INVALID_TASK The space is dead. 432 * KERN_NAME_EXISTS The name already denotes a right. 433 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 434 */ 435 436 kern_return_t 437 ipc_object_alloc_name( 438 ipc_space_t space, 439 ipc_object_type_t otype, 440 mach_port_type_t type, 441 mach_port_urefs_t urefs, 442 mach_port_name_t name, 443 ipc_object_t *objectp) 444 { 445 ipc_object_t object; 446 ipc_entry_t entry; 447 kern_return_t kr; 448 449 assert(otype < IOT_NUMBER); 450 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); 451 assert(type != MACH_PORT_TYPE_NONE); 452 assert(urefs <= MACH_PORT_UREFS_MAX); 453 454 object = io_alloc(otype, Z_WAITOK | Z_ZERO); 455 if (object == IO_NULL) { 456 return KERN_RESOURCE_SHORTAGE; 457 } 458 459 io_lock_init(object); 460 kr = ipc_entry_alloc_name(space, name, &entry); 461 if (kr != KERN_SUCCESS) { 462 io_free(otype, object); 463 return kr; 464 } 465 /* space is write-locked */ 466 467 if (ipc_right_inuse(entry)) { 468 is_write_unlock(space); 469 io_free(otype, object); 470 return KERN_NAME_EXISTS; 471 } 472 473 entry->ie_bits |= type | urefs; 474 entry->ie_object = object; 475 ipc_entry_modified(space, name, entry); 476 477 object->io_bits = io_makebits(TRUE, otype, 0); 478 479 io_lock(object); 480 is_write_unlock(space); 481 482 object->io_references = 1; /* for entry, not caller */ 483 484 *objectp = object; 485 return KERN_SUCCESS; 486 } 487 488 /* Routine: ipc_object_validate 489 * Purpose: 490 * Validates an ipc port or port set as belonging to the correct 491 * zone. 492 */ 493 494 void 495 ipc_object_validate( 496 ipc_object_t object) 497 { 498 if (io_otype(object) != IOT_PORT_SET) { 499 zone_id_require(ZONE_ID_IPC_PORT, 500 sizeof(struct ipc_port), object); 501 } else { 502 zone_id_require(ZONE_ID_IPC_PORT_SET, 503 sizeof(struct ipc_pset), object); 504 } 505 } 506 507 /* 508 * Routine: ipc_object_copyin_type 509 * Purpose: 510 * Convert a send type name to a received type name. 511 */ 512 513 mach_msg_type_name_t 514 ipc_object_copyin_type( 515 mach_msg_type_name_t msgt_name) 516 { 517 switch (msgt_name) { 518 case MACH_MSG_TYPE_MOVE_RECEIVE: 519 return MACH_MSG_TYPE_PORT_RECEIVE; 520 521 case MACH_MSG_TYPE_MOVE_SEND_ONCE: 522 case MACH_MSG_TYPE_MAKE_SEND_ONCE: 523 return MACH_MSG_TYPE_PORT_SEND_ONCE; 524 525 case MACH_MSG_TYPE_MOVE_SEND: 526 case MACH_MSG_TYPE_MAKE_SEND: 527 case MACH_MSG_TYPE_COPY_SEND: 528 return MACH_MSG_TYPE_PORT_SEND; 529 530 case MACH_MSG_TYPE_DISPOSE_RECEIVE: 531 case MACH_MSG_TYPE_DISPOSE_SEND: 532 case MACH_MSG_TYPE_DISPOSE_SEND_ONCE: 533 /* fall thru */ 534 default: 535 return MACH_MSG_TYPE_PORT_NONE; 536 } 537 } 538 539 /* 540 * Routine: ipc_object_copyin 541 * Purpose: 542 * Copyin a capability from a space. 543 * If successful, the caller gets a ref 544 * for the resulting object, unless it is IO_DEAD. 545 * Conditions: 546 * Nothing locked. 547 * Returns: 548 * KERN_SUCCESS Acquired an object, possibly IO_DEAD. 549 * KERN_INVALID_TASK The space is dead. 550 * KERN_INVALID_NAME Name doesn't exist in space. 551 * KERN_INVALID_RIGHT Name doesn't denote correct right. 552 */ 553 554 kern_return_t 555 ipc_object_copyin( 556 ipc_space_t space, 557 mach_port_name_t name, 558 mach_msg_type_name_t msgt_name, 559 ipc_object_t *objectp, 560 mach_port_context_t context, 561 mach_msg_guard_flags_t *guard_flags, 562 ipc_object_copyin_flags_t copyin_flags) 563 { 564 ipc_entry_t entry; 565 ipc_port_t soright; 566 ipc_port_t release_port; 567 kern_return_t kr; 568 int assertcnt = 0; 569 570 ipc_object_copyin_flags_t irc_flags = IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND | 571 IPC_OBJECT_COPYIN_FLAGS_SOFT_FAIL_IMMOVABLE_SEND; 572 irc_flags = (copyin_flags & irc_flags) | IPC_OBJECT_COPYIN_FLAGS_DEADOK; 573 /* 574 * Could first try a read lock when doing 575 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND, 576 * and MACH_MSG_TYPE_MAKE_SEND_ONCE. 577 */ 578 579 kr = ipc_right_lookup_write(space, name, &entry); 580 if (kr != KERN_SUCCESS) { 581 return kr; 582 } 583 /* space is write-locked and active */ 584 585 release_port = IP_NULL; 586 kr = ipc_right_copyin(space, name, entry, 587 msgt_name, irc_flags, 588 objectp, &soright, 589 &release_port, 590 &assertcnt, 591 context, 592 guard_flags); 593 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) { 594 ipc_entry_dealloc(space, name, entry); 595 } 596 is_write_unlock(space); 597 598 #if IMPORTANCE_INHERITANCE 599 if (0 < assertcnt && ipc_importance_task_is_any_receiver_type(current_task()->task_imp_base)) { 600 ipc_importance_task_drop_internal_assertion(current_task()->task_imp_base, assertcnt); 601 } 602 #endif /* IMPORTANCE_INHERITANCE */ 603 604 if (release_port != IP_NULL) { 605 ip_release(release_port); 606 } 607 608 if ((kr == KERN_SUCCESS) && (soright != IP_NULL)) { 609 ipc_notify_port_deleted(soright, name); 610 } 611 612 return kr; 613 } 614 615 /* 616 * Routine: ipc_object_copyin_from_kernel 617 * Purpose: 618 * Copyin a naked capability from the kernel. 619 * 620 * MACH_MSG_TYPE_MOVE_RECEIVE 621 * The receiver must be ipc_space_kernel 622 * or the receive right must already be in limbo. 623 * Consumes the naked receive right. 624 * MACH_MSG_TYPE_COPY_SEND 625 * A naked send right must be supplied. 626 * The port gains a reference, and a send right 627 * if the port is still active. 628 * MACH_MSG_TYPE_MAKE_SEND 629 * The receiver must be ipc_space_kernel. 630 * The port gains a reference and a send right. 631 * MACH_MSG_TYPE_MOVE_SEND 632 * Consumes a naked send right. 633 * MACH_MSG_TYPE_MAKE_SEND_ONCE 634 * The port gains a reference and a send-once right. 635 * Receiver also be the caller of device subsystem, 636 * so no assertion. 637 * MACH_MSG_TYPE_MOVE_SEND_ONCE 638 * Consumes a naked send-once right. 639 * Conditions: 640 * Nothing locked. 641 */ 642 643 void 644 ipc_object_copyin_from_kernel( 645 ipc_object_t object, 646 mach_msg_type_name_t msgt_name) 647 { 648 assert(IO_VALID(object)); 649 650 switch (msgt_name) { 651 case MACH_MSG_TYPE_MOVE_RECEIVE: { 652 ipc_port_t port = ip_object_to_port(object); 653 654 ip_lock(port); 655 imq_lock(&port->ip_messages); 656 require_ip_active(port); 657 if (port->ip_destination != IP_NULL) { 658 assert(port->ip_receiver == ipc_space_kernel); 659 assert(port->ip_immovable_receive == 0); 660 661 /* relevant part of ipc_port_clear_receiver */ 662 port->ip_mscount = 0; 663 port->ip_receiver_name = MACH_PORT_NULL; 664 port->ip_destination = IP_NULL; 665 } 666 imq_unlock(&port->ip_messages); 667 ip_unlock(port); 668 break; 669 } 670 671 case MACH_MSG_TYPE_COPY_SEND: { 672 ipc_port_t port = ip_object_to_port(object); 673 674 ip_lock(port); 675 if (ip_active(port)) { 676 assert(port->ip_srights > 0); 677 } 678 port->ip_srights++; 679 ip_reference(port); 680 ip_unlock(port); 681 break; 682 } 683 684 case MACH_MSG_TYPE_MAKE_SEND: { 685 ipc_port_t port = ip_object_to_port(object); 686 687 ip_lock(port); 688 if (ip_active(port)) { 689 assert(port->ip_receiver_name != MACH_PORT_NULL); 690 assert((port->ip_receiver == ipc_space_kernel) || 691 (port->ip_receiver->is_node_id != HOST_LOCAL_NODE)); 692 port->ip_mscount++; 693 } 694 695 port->ip_srights++; 696 ip_reference(port); 697 ip_unlock(port); 698 break; 699 } 700 701 case MACH_MSG_TYPE_MOVE_SEND: { 702 /* move naked send right into the message */ 703 assert(ip_object_to_port(object)->ip_srights); 704 break; 705 } 706 707 case MACH_MSG_TYPE_MAKE_SEND_ONCE: { 708 ipc_port_t port = ip_object_to_port(object); 709 710 ip_lock(port); 711 if (ip_active(port)) { 712 assert(port->ip_receiver_name != MACH_PORT_NULL); 713 } 714 ipc_port_make_sonce_locked(port); 715 ip_unlock(port); 716 break; 717 } 718 719 case MACH_MSG_TYPE_MOVE_SEND_ONCE: { 720 /* move naked send-once right into the message */ 721 assert(ip_object_to_port(object)->ip_sorights); 722 break; 723 } 724 725 default: 726 panic("ipc_object_copyin_from_kernel: strange rights"); 727 } 728 } 729 730 /* 731 * Routine: ipc_object_destroy 732 * Purpose: 733 * Destroys a naked capability. 734 * Consumes a ref for the object. 735 * 736 * A receive right should be in limbo or in transit. 737 * Conditions: 738 * Nothing locked. 739 */ 740 741 void 742 ipc_object_destroy( 743 ipc_object_t object, 744 mach_msg_type_name_t msgt_name) 745 { 746 assert(IO_VALID(object)); 747 assert(io_otype(object) == IOT_PORT); 748 749 switch (msgt_name) { 750 case MACH_MSG_TYPE_PORT_SEND: 751 ipc_port_release_send(ip_object_to_port(object)); 752 break; 753 754 case MACH_MSG_TYPE_PORT_SEND_ONCE: 755 ipc_notify_send_once(ip_object_to_port(object)); 756 break; 757 758 case MACH_MSG_TYPE_PORT_RECEIVE: 759 ipc_port_release_receive(ip_object_to_port(object)); 760 break; 761 762 default: 763 panic("ipc_object_destroy: strange rights"); 764 } 765 } 766 767 /* 768 * Routine: ipc_object_destroy_dest 769 * Purpose: 770 * Destroys a naked capability for the destination of 771 * of a message. Consumes a ref for the object. 772 * 773 * Conditions: 774 * Nothing locked. 775 */ 776 777 void 778 ipc_object_destroy_dest( 779 ipc_object_t object, 780 mach_msg_type_name_t msgt_name) 781 { 782 assert(IO_VALID(object)); 783 assert(io_otype(object) == IOT_PORT); 784 785 switch (msgt_name) { 786 case MACH_MSG_TYPE_PORT_SEND: 787 ipc_port_release_send(ip_object_to_port(object)); 788 break; 789 790 case MACH_MSG_TYPE_PORT_SEND_ONCE: 791 if (io_active(object) && 792 !ip_full_kernel(ip_object_to_port(object))) { 793 ipc_notify_send_once(ip_object_to_port(object)); 794 } else { 795 ipc_port_release_sonce(ip_object_to_port(object)); 796 } 797 break; 798 799 default: 800 panic("ipc_object_destroy_dest: strange rights"); 801 } 802 } 803 804 /* 805 * Routine: ipc_object_insert_send_right 806 * Purpose: 807 * Insert a send right into an object already in the space. 808 * The specified name must already point to a valid object. 809 * 810 * Note: This really is a combined copyin()/copyout(), 811 * that avoids most of the overhead of being implemented that way. 812 * 813 * This is the fastpath for mach_port_insert_right. 814 * 815 * Conditions: 816 * Nothing locked. 817 * 818 * msgt_name must be MACH_MSG_TYPE_MAKE_SEND_ONCE or 819 * MACH_MSG_TYPE_MOVE_SEND_ONCE. 820 * 821 * Returns: 822 * KERN_SUCCESS Copied out object, consumed ref. 823 * KERN_INVALID_TASK The space is dead. 824 * KERN_INVALID_NAME Name doesn't exist in space. 825 * KERN_INVALID_CAPABILITY The object is dead. 826 * KERN_RIGHT_EXISTS Space has rights under another name. 827 */ 828 kern_return_t 829 ipc_object_insert_send_right( 830 ipc_space_t space, 831 mach_port_name_t name, 832 mach_msg_type_name_t msgt_name) 833 { 834 ipc_entry_bits_t bits; 835 ipc_object_t object; 836 ipc_entry_t entry; 837 kern_return_t kr; 838 839 assert(msgt_name == MACH_MSG_TYPE_MAKE_SEND || 840 msgt_name == MACH_MSG_TYPE_COPY_SEND); 841 842 kr = ipc_right_lookup_write(space, name, &entry); 843 if (kr != KERN_SUCCESS) { 844 return kr; 845 } 846 /* space is write-locked and active */ 847 848 if (!IO_VALID(entry->ie_object)) { 849 is_write_unlock(space); 850 return KERN_INVALID_CAPABILITY; 851 } 852 853 bits = entry->ie_bits; 854 object = entry->ie_object; 855 856 io_lock(object); 857 if (!io_active(object)) { 858 kr = KERN_INVALID_CAPABILITY; 859 } else if (msgt_name == MACH_MSG_TYPE_MAKE_SEND) { 860 if (bits & MACH_PORT_TYPE_RECEIVE) { 861 ipc_port_t port = ip_object_to_port(object); 862 port->ip_mscount++; 863 if ((bits & MACH_PORT_TYPE_SEND) == 0) { 864 port->ip_srights++; 865 bits |= MACH_PORT_TYPE_SEND; 866 } 867 /* leave urefs pegged to maximum if it overflowed */ 868 if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) { 869 bits += 1; /* increment urefs */ 870 } 871 entry->ie_bits = bits; 872 ipc_entry_modified(space, name, entry); 873 kr = KERN_SUCCESS; 874 } else { 875 kr = KERN_INVALID_RIGHT; 876 } 877 } else { // MACH_MSG_TYPE_COPY_SEND 878 if (bits & MACH_PORT_TYPE_SEND) { 879 /* leave urefs pegged to maximum if it overflowed */ 880 if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) { 881 entry->ie_bits = bits + 1; /* increment urefs */ 882 } 883 ipc_entry_modified(space, name, entry); 884 kr = KERN_SUCCESS; 885 } else { 886 kr = KERN_INVALID_RIGHT; 887 } 888 } 889 890 io_unlock(object); 891 is_write_unlock(space); 892 893 return kr; 894 } 895 896 /* 897 * Routine: ipc_object_copyout 898 * Purpose: 899 * Copyout a capability, placing it into a space. 900 * Always consumes a ref for the object. 901 * Conditions: 902 * Nothing locked. 903 * Returns: 904 * KERN_SUCCESS Copied out object, consumed ref. 905 * KERN_INVALID_TASK The space is dead. 906 * KERN_INVALID_CAPABILITY The object is dead. 907 * KERN_NO_SPACE No room in space for another right. 908 * KERN_RESOURCE_SHORTAGE No memory available. 909 * KERN_UREFS_OVERFLOW Urefs limit exceeded 910 * and overflow wasn't specified. 911 */ 912 913 kern_return_t 914 ipc_object_copyout( 915 ipc_space_t space, 916 ipc_object_t object, 917 mach_msg_type_name_t msgt_name, 918 ipc_object_copyout_flags_t flags, 919 mach_port_context_t *context, 920 mach_msg_guard_flags_t *guard_flags, 921 mach_port_name_t *namep) 922 { 923 struct knote *kn = current_thread()->ith_knote; 924 mach_port_name_t name; 925 ipc_port_t port = ip_object_to_port(object); 926 ipc_entry_t entry; 927 kern_return_t kr; 928 929 assert(IO_VALID(object)); 930 assert(io_otype(object) == IOT_PORT); 931 932 if (ITH_KNOTE_VALID(kn, msgt_name)) { 933 filt_machport_turnstile_prepare_lazily(kn, msgt_name, port); 934 } 935 936 is_write_lock(space); 937 938 for (;;) { 939 ipc_port_t port_subst = IP_NULL; 940 941 if (!is_active(space)) { 942 is_write_unlock(space); 943 kr = KERN_INVALID_TASK; 944 goto out; 945 } 946 947 kr = ipc_entries_hold(space, 1); 948 if (kr != KERN_SUCCESS) { 949 /* unlocks/locks space, so must start again */ 950 951 kr = ipc_entry_grow_table(space, ITS_SIZE_NONE); 952 if (kr != KERN_SUCCESS) { 953 /* space is unlocked */ 954 goto out; 955 } 956 continue; 957 } 958 959 io_lock(object); 960 if (!io_active(object)) { 961 io_unlock(object); 962 is_write_unlock(space); 963 kr = KERN_INVALID_CAPABILITY; 964 goto out; 965 } 966 967 /* Don't actually copyout rights we aren't allowed to */ 968 if (!ip_label_check(space, port, msgt_name, &flags, &port_subst)) { 969 io_unlock(object); 970 is_write_unlock(space); 971 assert(port_subst == IP_NULL); 972 kr = KERN_INVALID_CAPABILITY; 973 goto out; 974 } 975 976 /* is the kolabel requesting a substitution */ 977 if (port_subst != IP_NULL) { 978 /* 979 * port is unlocked, its right consumed 980 * space is unlocked 981 */ 982 assert(msgt_name == MACH_MSG_TYPE_PORT_SEND); 983 port = port_subst; 984 if (!IP_VALID(port)) { 985 object = IO_DEAD; 986 kr = KERN_INVALID_CAPABILITY; 987 goto out; 988 } 989 990 object = ip_to_object(port); 991 is_write_lock(space); 992 continue; 993 } 994 995 break; 996 } 997 998 /* space is write-locked and active, object is locked and active */ 999 1000 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 1001 ipc_right_reverse(space, object, &name, &entry)) { 1002 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 1003 } else { 1004 ipc_entry_claim(space, &name, &entry); 1005 1006 assert(!ipc_right_inuse(entry)); 1007 assert(entry->ie_object == IO_NULL); 1008 1009 entry->ie_object = object; 1010 } 1011 1012 kr = ipc_right_copyout(space, name, entry, 1013 msgt_name, flags, context, guard_flags, object); 1014 1015 /* object is unlocked */ 1016 is_write_unlock(space); 1017 1018 out: 1019 if (kr == KERN_SUCCESS) { 1020 *namep = name; 1021 } else if (IO_VALID(object)) { 1022 ipc_object_destroy(object, msgt_name); 1023 } 1024 1025 return kr; 1026 } 1027 1028 /* 1029 * Routine: ipc_object_copyout_name 1030 * Purpose: 1031 * Copyout a capability, placing it into a space. 1032 * The specified name is used for the capability. 1033 * If successful, consumes a ref for the object. 1034 * Conditions: 1035 * Nothing locked. 1036 * Returns: 1037 * KERN_SUCCESS Copied out object, consumed ref. 1038 * KERN_INVALID_TASK The space is dead. 1039 * KERN_INVALID_CAPABILITY The object is dead. 1040 * KERN_RESOURCE_SHORTAGE No memory available. 1041 * KERN_UREFS_OVERFLOW Urefs limit exceeded 1042 * and overflow wasn't specified. 1043 * KERN_RIGHT_EXISTS Space has rights under another name. 1044 * KERN_NAME_EXISTS Name is already used. 1045 */ 1046 1047 kern_return_t 1048 ipc_object_copyout_name( 1049 ipc_space_t space, 1050 ipc_object_t object, 1051 mach_msg_type_name_t msgt_name, 1052 mach_port_name_t name) 1053 { 1054 ipc_port_t port = ip_object_to_port(object); 1055 mach_port_name_t oname; 1056 ipc_entry_t oentry; 1057 ipc_entry_t entry; 1058 kern_return_t kr; 1059 1060 #if IMPORTANCE_INHERITANCE 1061 int assertcnt = 0; 1062 ipc_importance_task_t task_imp = IIT_NULL; 1063 #endif /* IMPORTANCE_INHERITANCE */ 1064 1065 assert(IO_VALID(object)); 1066 assert(io_otype(object) == IOT_PORT); 1067 1068 kr = ipc_entry_alloc_name(space, name, &entry); 1069 if (kr != KERN_SUCCESS) { 1070 return kr; 1071 } 1072 /* space is write-locked and active */ 1073 1074 io_lock(object); 1075 1076 /* 1077 * Don't actually copyout rights we aren't allowed to 1078 * 1079 * In particular, kolabel-ed objects do not allow callers 1080 * to pick the name they end up with. 1081 */ 1082 if (!io_active(object) || ip_is_kolabeled(port)) { 1083 io_unlock(object); 1084 if (!ipc_right_inuse(entry)) { 1085 ipc_entry_dealloc(space, name, entry); 1086 } 1087 is_write_unlock(space); 1088 return KERN_INVALID_CAPABILITY; 1089 } 1090 1091 /* space is write-locked and active, object is locked and active */ 1092 1093 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && 1094 ipc_right_reverse(space, object, &oname, &oentry)) { 1095 if (name != oname) { 1096 io_unlock(object); 1097 if (!ipc_right_inuse(entry)) { 1098 ipc_entry_dealloc(space, name, entry); 1099 } 1100 is_write_unlock(space); 1101 return KERN_RIGHT_EXISTS; 1102 } 1103 1104 assert(entry == oentry); 1105 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); 1106 } else if (ipc_right_inuse(entry)) { 1107 io_unlock(object); 1108 is_write_unlock(space); 1109 return KERN_NAME_EXISTS; 1110 } else { 1111 assert(entry->ie_object == IO_NULL); 1112 1113 entry->ie_object = object; 1114 } 1115 1116 #if IMPORTANCE_INHERITANCE 1117 /* 1118 * We are slamming a receive right into the space, without 1119 * first having been enqueued on a port destined there. So, 1120 * we have to arrange to boost the task appropriately if this 1121 * port has assertions (and the task wants them). 1122 */ 1123 if (msgt_name == MACH_MSG_TYPE_PORT_RECEIVE) { 1124 if (space->is_task != TASK_NULL) { 1125 task_imp = space->is_task->task_imp_base; 1126 if (ipc_importance_task_is_any_receiver_type(task_imp)) { 1127 assertcnt = port->ip_impcount; 1128 ipc_importance_task_reference(task_imp); 1129 } else { 1130 task_imp = IIT_NULL; 1131 } 1132 } 1133 1134 /* take port out of limbo */ 1135 assert(port->ip_tempowner != 0); 1136 port->ip_tempowner = 0; 1137 } 1138 1139 #endif /* IMPORTANCE_INHERITANCE */ 1140 1141 kr = ipc_right_copyout(space, name, entry, 1142 msgt_name, IPC_OBJECT_COPYOUT_FLAGS_NONE, NULL, NULL, object); 1143 1144 /* object is unlocked */ 1145 is_write_unlock(space); 1146 1147 #if IMPORTANCE_INHERITANCE 1148 /* 1149 * Add the assertions to the task that we captured before 1150 */ 1151 if (task_imp != IIT_NULL) { 1152 ipc_importance_task_hold_internal_assertion(task_imp, assertcnt); 1153 ipc_importance_task_release(task_imp); 1154 } 1155 #endif /* IMPORTANCE_INHERITANCE */ 1156 1157 return kr; 1158 } 1159 1160 /* 1161 * Routine: ipc_object_copyout_dest 1162 * Purpose: 1163 * Translates/consumes the destination right of a message. 1164 * This is unlike normal copyout because the right is consumed 1165 * in a funny way instead of being given to the receiving space. 1166 * The receiver gets his name for the port, if he has receive 1167 * rights, otherwise MACH_PORT_NULL. 1168 * Conditions: 1169 * The object is locked and active. Nothing else locked. 1170 * The object is unlocked and loses a reference. 1171 */ 1172 1173 void 1174 ipc_object_copyout_dest( 1175 ipc_space_t space, 1176 ipc_object_t object, 1177 mach_msg_type_name_t msgt_name, 1178 mach_port_name_t *namep) 1179 { 1180 mach_port_name_t name; 1181 1182 assert(IO_VALID(object)); 1183 assert(io_active(object)); 1184 1185 /* 1186 * If the space is the receiver/owner of the object, 1187 * then we quietly consume the right and return 1188 * the space's name for the object. Otherwise 1189 * we destroy the right and return MACH_PORT_NULL. 1190 */ 1191 1192 switch (msgt_name) { 1193 case MACH_MSG_TYPE_PORT_SEND: { 1194 ipc_port_t port = ip_object_to_port(object); 1195 ipc_port_t nsrequest = IP_NULL; 1196 mach_port_mscount_t mscount; 1197 1198 if (port->ip_receiver == space) { 1199 name = port->ip_receiver_name; 1200 } else { 1201 name = MACH_PORT_NULL; 1202 } 1203 1204 assert(port->ip_srights > 0); 1205 if (--port->ip_srights == 0 && 1206 port->ip_nsrequest != IP_NULL) { 1207 nsrequest = port->ip_nsrequest; 1208 port->ip_nsrequest = IP_NULL; 1209 mscount = port->ip_mscount; 1210 ipc_port_clear_sync_rcv_thread_boost_locked(port); 1211 /* port unlocked */ 1212 ipc_notify_no_senders(nsrequest, mscount); 1213 } else { 1214 ipc_port_clear_sync_rcv_thread_boost_locked(port); 1215 /* port unlocked */ 1216 } 1217 1218 ip_release(port); 1219 break; 1220 } 1221 1222 case MACH_MSG_TYPE_PORT_SEND_ONCE: { 1223 ipc_port_t port = ip_object_to_port(object); 1224 1225 assert(port->ip_sorights > 0); 1226 1227 if (port->ip_receiver == space) { 1228 /* quietly consume the send-once right */ 1229 1230 port->ip_sorights--; 1231 name = port->ip_receiver_name; 1232 ipc_port_clear_sync_rcv_thread_boost_locked(port); 1233 /* port unlocked */ 1234 ip_release(port); 1235 } else { 1236 /* 1237 * A very bizarre case. The message 1238 * was received, but before this copyout 1239 * happened the space lost receive rights. 1240 * We can't quietly consume the soright 1241 * out from underneath some other task, 1242 * so generate a send-once notification. 1243 */ 1244 1245 ip_unlock(port); 1246 1247 ipc_notify_send_once(port); 1248 name = MACH_PORT_NULL; 1249 } 1250 1251 break; 1252 } 1253 1254 default: 1255 panic("ipc_object_copyout_dest: strange rights"); 1256 name = MACH_PORT_DEAD; 1257 } 1258 1259 *namep = name; 1260 } 1261 1262 /* 1263 * Routine: io_lock 1264 * Purpose: 1265 * Validate, then acquire a lock on an ipc object 1266 */ 1267 1268 void 1269 io_lock(ipc_object_t io) 1270 { 1271 ipc_object_validate(io); 1272 lck_spin_lock_grp(&(io)->io_lock_data, &ipc_lck_grp); 1273 } 1274 1275 /* 1276 * Routine: io_lock_try 1277 * Purpose: 1278 * Validate, then try to acquire a lock on an object, 1279 * fail if there is an existing busy lock 1280 */ 1281 1282 boolean_t 1283 io_lock_try(ipc_object_t io) 1284 { 1285 ipc_object_validate(io); 1286 return lck_spin_try_lock_grp(&(io)->io_lock_data, &ipc_lck_grp); 1287 } 1288 1289 /* 1290 * Check whether the object is a port if so, free it. But 1291 * keep track of that fact. 1292 */ 1293 void 1294 io_free( 1295 unsigned int otype, 1296 ipc_object_t object) 1297 { 1298 if (otype == IOT_PORT) { 1299 ipc_port_finalize(ip_object_to_port(object)); 1300 } 1301 io_lock_destroy(object); 1302 zfree(ipc_object_zones[otype], object); 1303 }