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 */ 62/* 63 */ 64/* 65 * File: ipc/ipc_port.c 66 * Author: Rich Draves 67 * Date: 1989 68 * 69 * Functions to manipulate IPC ports. 70 */ 71 72#include <norma_vm.h> 73#include <zone_debug.h> 74#include <mach_assert.h> 75 76#include <mach/port.h> 77#include <mach/kern_return.h> 78#include <kern/lock.h> 79#include <kern/ipc_kobject.h> 80#include <kern/thread.h> 81#include <kern/misc_protos.h> 82#include <kern/wait_queue.h> 83#include <ipc/ipc_entry.h> 84#include <ipc/ipc_space.h> 85#include <ipc/ipc_object.h> 86#include <ipc/ipc_port.h> 87#include <ipc/ipc_pset.h> 88#include <ipc/ipc_kmsg.h> 89#include <ipc/ipc_mqueue.h> 90#include <ipc/ipc_notify.h> 91#include <ipc/ipc_table.h> 92 93#include <security/mac_mach_internal.h> 94 95#include <string.h> 96 97decl_lck_mtx_data(, ipc_port_multiple_lock_data) 98lck_mtx_ext_t ipc_port_multiple_lock_data_ext; 99ipc_port_timestamp_t ipc_port_timestamp_data; 100int ipc_portbt; 101 102#if MACH_ASSERT 103void ipc_port_init_debug( 104 ipc_port_t port, 105 natural_t *callstack, 106 unsigned int callstack_max); 107 108void ipc_port_callstack_init_debug( 109 natural_t *callstack, 110 unsigned int callstack_max); 111 112#endif /* MACH_ASSERT */ 113 114void 115ipc_port_release(ipc_port_t port) 116{ 117 ip_release(port); 118} 119 120void 121ipc_port_reference(ipc_port_t port) 122{ 123 ip_reference(port); 124} 125 126/* 127 * Routine: ipc_port_timestamp 128 * Purpose: 129 * Retrieve a timestamp value. 130 */ 131 132ipc_port_timestamp_t 133ipc_port_timestamp(void) 134{ 135 return OSIncrementAtomic(&ipc_port_timestamp_data); 136} 137 138/* 139 * Routine: ipc_port_request_alloc 140 * Purpose: 141 * Try to allocate a request slot. 142 * If successful, returns the request index. 143 * Otherwise returns zero. 144 * Conditions: 145 * The port is locked and active. 146 * Returns: 147 * KERN_SUCCESS A request index was found. 148 * KERN_NO_SPACE No index allocated. 149 */ 150 151kern_return_t 152ipc_port_request_alloc( 153 ipc_port_t port, 154 mach_port_name_t name, 155 ipc_port_t soright, 156 boolean_t send_possible, 157 boolean_t immediate, 158 ipc_port_request_index_t *indexp) 159{ 160 ipc_port_request_t ipr, table; 161 ipc_port_request_index_t index; 162 uintptr_t mask = 0; 163 164 assert(ip_active(port)); 165 assert(name != MACH_PORT_NULL); 166 assert(soright != IP_NULL); 167 168 table = port->ip_requests; 169 170 if (table == IPR_NULL) 171 return KERN_NO_SPACE; 172 173 index = table->ipr_next; 174 if (index == 0) 175 return KERN_NO_SPACE; 176 177 ipr = &table[index]; 178 assert(ipr->ipr_name == MACH_PORT_NULL); 179 180 table->ipr_next = ipr->ipr_next; 181 ipr->ipr_name = name; 182 183 if (send_possible) { 184 mask |= IPR_SOR_SPREQ_MASK; 185 if (immediate) { 186 mask |= IPR_SOR_SPARM_MASK; 187 port->ip_sprequests = TRUE; 188 } 189 } 190 ipr->ipr_soright = IPR_SOR_MAKE(soright, mask); 191 192 *indexp = index; 193 194 return KERN_SUCCESS; 195} 196 197/* 198 * Routine: ipc_port_request_grow 199 * Purpose: 200 * Grow a port's table of requests. 201 * Conditions: 202 * The port must be locked and active. 203 * Nothing else locked; will allocate memory. 204 * Upon return the port is unlocked. 205 * Returns: 206 * KERN_SUCCESS Grew the table. 207 * KERN_SUCCESS Somebody else grew the table. 208 * KERN_SUCCESS The port died. 209 * KERN_RESOURCE_SHORTAGE Couldn't allocate new table. 210 * KERN_NO_SPACE Couldn't grow to desired size 211 */ 212 213kern_return_t 214ipc_port_request_grow( 215 ipc_port_t port, 216 ipc_table_elems_t target_size) 217{ 218 ipc_table_size_t its; 219 ipc_port_request_t otable, ntable; 220 221 assert(ip_active(port)); 222 223 otable = port->ip_requests; 224 if (otable == IPR_NULL) 225 its = &ipc_table_requests[0]; 226 else 227 its = otable->ipr_size + 1; 228 229 if (target_size != ITS_SIZE_NONE) { 230 if ((otable != IPR_NULL) && 231 (target_size <= otable->ipr_size->its_size)) { 232 ip_unlock(port); 233 return KERN_SUCCESS; 234 } 235 while ((its->its_size) && (its->its_size < target_size)) { 236 its++; 237 } 238 if (its->its_size == 0) { 239 ip_unlock(port); 240 return KERN_NO_SPACE; 241 } 242 } 243 244 ip_reference(port); 245 ip_unlock(port); 246 247 if ((its->its_size == 0) || 248 ((ntable = it_requests_alloc(its)) == IPR_NULL)) { 249 ip_release(port); 250 return KERN_RESOURCE_SHORTAGE; 251 } 252 253 ip_lock(port); 254 255 /* 256 * Check that port is still active and that nobody else 257 * has slipped in and grown the table on us. Note that 258 * just checking if the current table pointer == otable 259 * isn't sufficient; must check ipr_size. 260 */ 261 262 if (ip_active(port) && (port->ip_requests == otable) && 263 ((otable == IPR_NULL) || (otable->ipr_size+1 == its))) { 264 ipc_table_size_t oits; 265 ipc_table_elems_t osize, nsize; 266 ipc_port_request_index_t free, i; 267 268 /* copy old table to new table */ 269 270 if (otable != IPR_NULL) { 271 oits = otable->ipr_size; 272 osize = oits->its_size; 273 free = otable->ipr_next; 274 275 (void) memcpy((void *)(ntable + 1), 276 (const void *)(otable + 1), 277 (osize - 1) * sizeof(struct ipc_port_request)); 278 } else { 279 osize = 1; 280 oits = 0; 281 free = 0; 282 } 283 284 nsize = its->its_size; 285 assert(nsize > osize); 286 287 /* add new elements to the new table's free list */ 288 289 for (i = osize; i < nsize; i++) { 290 ipc_port_request_t ipr = &ntable[i]; 291 292 ipr->ipr_name = MACH_PORT_NULL; 293 ipr->ipr_next = free; 294 free = i; 295 } 296 297 ntable->ipr_next = free; 298 ntable->ipr_size = its; 299 port->ip_requests = ntable; 300 ip_unlock(port); 301 ip_release(port); 302 303 if (otable != IPR_NULL) { 304 it_requests_free(oits, otable); 305 } 306 } else { 307 ip_unlock(port); 308 ip_release(port); 309 it_requests_free(its, ntable); 310 } 311 312 return KERN_SUCCESS; 313} 314 315/* 316 * Routine: ipc_port_request_sparm 317 * Purpose: 318 * Arm delayed send-possible request. 319 * Conditions: 320 * The port must be locked and active. 321 */ 322 323void 324ipc_port_request_sparm( 325 ipc_port_t port, 326 __assert_only mach_port_name_t name, 327 ipc_port_request_index_t index) 328{ 329 if (index != IE_REQ_NONE) { 330 ipc_port_request_t ipr, table; 331 332 assert(ip_active(port)); 333 334 table = port->ip_requests; 335 assert(table != IPR_NULL); 336 337 ipr = &table[index]; 338 assert(ipr->ipr_name == name); 339 340 if (IPR_SOR_SPREQ(ipr->ipr_soright)) { 341 ipr->ipr_soright = IPR_SOR_MAKE(ipr->ipr_soright, IPR_SOR_SPARM_MASK); 342 port->ip_sprequests = TRUE; 343 } 344 } 345} 346 347/* 348 * Routine: ipc_port_request_type 349 * Purpose: 350 * Determine the type(s) of port requests enabled for a name. 351 * Conditions: 352 * The port must be locked or inactive (to avoid table growth). 353 * The index must not be IE_REQ_NONE and for the name in question. 354 */ 355mach_port_type_t 356ipc_port_request_type( 357 ipc_port_t port, 358 __assert_only mach_port_name_t name, 359 ipc_port_request_index_t index) 360{ 361 ipc_port_request_t ipr, table; 362 mach_port_type_t type = 0; 363 364 table = port->ip_requests; 365 assert (table != IPR_NULL); 366 367 assert(index != IE_REQ_NONE); 368 ipr = &table[index]; 369 assert(ipr->ipr_name == name); 370 371 if (IP_VALID(IPR_SOR_PORT(ipr->ipr_soright))) { 372 type |= MACH_PORT_TYPE_DNREQUEST; 373 374 if (IPR_SOR_SPREQ(ipr->ipr_soright)) { 375 type |= MACH_PORT_TYPE_SPREQUEST; 376 377 if (!IPR_SOR_SPARMED(ipr->ipr_soright)) { 378 type |= MACH_PORT_TYPE_SPREQUEST_DELAYED; 379 } 380 } 381 } 382 return type; 383} 384 385/* 386 * Routine: ipc_port_request_cancel 387 * Purpose: 388 * Cancel a dead-name/send-possible request and return the send-once right. 389 * Conditions: 390 * The port must be locked and active. 391 * The index must not be IPR_REQ_NONE and must correspond with name. 392 */ 393 394ipc_port_t 395ipc_port_request_cancel( 396 ipc_port_t port, 397 __assert_only mach_port_name_t name, 398 ipc_port_request_index_t index) 399{ 400 ipc_port_request_t ipr, table; 401 ipc_port_t request = IP_NULL; 402 403 assert(ip_active(port)); 404 table = port->ip_requests; 405 assert(table != IPR_NULL); 406 407 assert (index != IE_REQ_NONE); 408 ipr = &table[index]; 409 assert(ipr->ipr_name == name); 410 request = IPR_SOR_PORT(ipr->ipr_soright); 411 412 /* return ipr to the free list inside the table */ 413 ipr->ipr_name = MACH_PORT_NULL; 414 ipr->ipr_next = table->ipr_next; 415 table->ipr_next = index; 416 417 return request; 418} 419 420/* 421 * Routine: ipc_port_pdrequest 422 * Purpose: 423 * Make a port-deleted request, returning the 424 * previously registered send-once right. 425 * Just cancels the previous request if notify is IP_NULL. 426 * Conditions: 427 * The port is locked and active. It is unlocked. 428 * Consumes a ref for notify (if non-null), and 429 * returns previous with a ref (if non-null). 430 */ 431 432void 433ipc_port_pdrequest( 434 ipc_port_t port, 435 ipc_port_t notify, 436 ipc_port_t *previousp) 437{ 438 ipc_port_t previous; 439 440 assert(ip_active(port)); 441 442 previous = port->ip_pdrequest; 443 port->ip_pdrequest = notify; 444 ip_unlock(port); 445 446 *previousp = previous; 447} 448 449/* 450 * Routine: ipc_port_nsrequest 451 * Purpose: 452 * Make a no-senders request, returning the 453 * previously registered send-once right. 454 * Just cancels the previous request if notify is IP_NULL. 455 * Conditions: 456 * The port is locked and active. It is unlocked. 457 * Consumes a ref for notify (if non-null), and 458 * returns previous with a ref (if non-null). 459 */ 460 461void 462ipc_port_nsrequest( 463 ipc_port_t port, 464 mach_port_mscount_t sync, 465 ipc_port_t notify, 466 ipc_port_t *previousp) 467{ 468 ipc_port_t previous; 469 mach_port_mscount_t mscount; 470 471 assert(ip_active(port)); 472 473 previous = port->ip_nsrequest; 474 mscount = port->ip_mscount; 475 476 if ((port->ip_srights == 0) && (sync <= mscount) && 477 (notify != IP_NULL)) { 478 port->ip_nsrequest = IP_NULL; 479 ip_unlock(port); 480 ipc_notify_no_senders(notify, mscount); 481 } else { 482 port->ip_nsrequest = notify; 483 ip_unlock(port); 484 } 485 486 *previousp = previous; 487} 488 489 490/* 491 * Routine: ipc_port_clear_receiver 492 * Purpose: 493 * Prepares a receive right for transmission/destruction. 494 * Conditions: 495 * The port is locked and active. 496 */ 497 498void 499ipc_port_clear_receiver( 500 ipc_port_t port, 501 queue_t links) 502{ 503 spl_t s; 504 505 assert(ip_active(port)); 506 507 /* 508 * pull ourselves from any sets. 509 */ 510 if (port->ip_pset_count != 0) { 511 ipc_pset_remove_from_all(port, links); 512 assert(port->ip_pset_count == 0); 513 } 514 515 /* 516 * Send anyone waiting on the port's queue directly away. 517 * Also clear the mscount and seqno. 518 */ 519 s = splsched(); 520 imq_lock(&port->ip_messages); 521 ipc_mqueue_changed(&port->ip_messages); 522 ipc_port_set_mscount(port, 0); 523 port->ip_messages.imq_seqno = 0; 524 imq_unlock(&port->ip_messages); 525 splx(s); 526} 527 528/* 529 * Routine: ipc_port_init 530 * Purpose: 531 * Initializes a newly-allocated port. 532 * Doesn't touch the ip_object fields. 533 */ 534 535void 536ipc_port_init( 537 ipc_port_t port, 538 ipc_space_t space, 539 mach_port_name_t name) 540{ 541 /* port->ip_kobject doesn't have to be initialized */ 542 543 port->ip_receiver = space; 544 port->ip_receiver_name = name; 545 546 port->ip_mscount = 0; 547 port->ip_srights = 0; 548 port->ip_sorights = 0; 549 550 port->ip_nsrequest = IP_NULL; 551 port->ip_pdrequest = IP_NULL; 552 port->ip_requests = IPR_NULL; 553 554 port->ip_pset_count = 0; 555 port->ip_premsg = IKM_NULL; 556 port->ip_context = 0; 557 558 ipc_mqueue_init(&port->ip_messages, FALSE /* set */); 559} 560 561/* 562 * Routine: ipc_port_alloc 563 * Purpose: 564 * Allocate a port. 565 * Conditions: 566 * Nothing locked. If successful, the port is returned 567 * locked. (The caller doesn't have a reference.) 568 * Returns: 569 * KERN_SUCCESS The port is allocated. 570 * KERN_INVALID_TASK The space is dead. 571 * KERN_NO_SPACE No room for an entry in the space. 572 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 573 */ 574 575kern_return_t 576ipc_port_alloc( 577 ipc_space_t space, 578 mach_port_name_t *namep, 579 ipc_port_t *portp) 580{ 581 ipc_port_t port; 582 mach_port_name_t name; 583 kern_return_t kr; 584 585#if MACH_ASSERT 586 natural_t buf[IP_CALLSTACK_MAX]; 587 ipc_port_callstack_init_debug(&buf[0], IP_CALLSTACK_MAX); 588#endif /* MACH_ASSERT */ 589 590 kr = ipc_object_alloc(space, IOT_PORT, 591 MACH_PORT_TYPE_RECEIVE, 0, 592 &name, (ipc_object_t *) &port); 593 if (kr != KERN_SUCCESS) 594 return kr; 595 596 /* port and space are locked */ 597 ipc_port_init(port, space, name); 598 599#if MACH_ASSERT 600 ipc_port_init_debug(port, &buf[0], IP_CALLSTACK_MAX); 601#endif /* MACH_ASSERT */ 602 603 /* unlock space after init */ 604 is_write_unlock(space); 605 606#if CONFIG_MACF_MACH 607 task_t issuer = current_task(); 608 tasklabel_lock2 (issuer, space->is_task); 609 mac_port_label_associate(&issuer->maclabel, &space->is_task->maclabel, 610 &port->ip_label); 611 tasklabel_unlock2 (issuer, space->is_task); 612#endif 613 614 *namep = name; 615 *portp = port; 616 617 return KERN_SUCCESS; 618} 619 620/* 621 * Routine: ipc_port_alloc_name 622 * Purpose: 623 * Allocate a port, with a specific name. 624 * Conditions: 625 * Nothing locked. If successful, the port is returned 626 * locked. (The caller doesn't have a reference.) 627 * Returns: 628 * KERN_SUCCESS The port is allocated. 629 * KERN_INVALID_TASK The space is dead. 630 * KERN_NAME_EXISTS The name already denotes a right. 631 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 632 */ 633 634kern_return_t 635ipc_port_alloc_name( 636 ipc_space_t space, 637 mach_port_name_t name, 638 ipc_port_t *portp) 639{ 640 ipc_port_t port; 641 kern_return_t kr; 642 643#if MACH_ASSERT 644 natural_t buf[IP_CALLSTACK_MAX]; 645 ipc_port_callstack_init_debug(&buf[0], IP_CALLSTACK_MAX); 646#endif /* MACH_ASSERT */ 647 648 kr = ipc_object_alloc_name(space, IOT_PORT, 649 MACH_PORT_TYPE_RECEIVE, 0, 650 name, (ipc_object_t *) &port); 651 if (kr != KERN_SUCCESS) 652 return kr; 653 654 /* port is locked */ 655 656 ipc_port_init(port, space, name); 657 658#if MACH_ASSERT 659 ipc_port_init_debug(port, &buf[0], IP_CALLSTACK_MAX); 660#endif /* MACH_ASSERT */ 661 662#if CONFIG_MACF_MACH 663 task_t issuer = current_task(); 664 tasklabel_lock2 (issuer, space->is_task); 665 mac_port_label_associate(&issuer->maclabel, &space->is_task->maclabel, 666 &port->ip_label); 667 tasklabel_unlock2 (issuer, space->is_task); 668#endif 669 670 *portp = port; 671 672 return KERN_SUCCESS; 673} 674 675/* 676 * Routine: ipc_port_spnotify 677 * Purpose: 678 * Generate send-possible port notifications. 679 * Conditions: 680 * Nothing locked, reference held on port. 681 */ 682void 683ipc_port_spnotify( 684 ipc_port_t port) 685{ 686 ipc_port_request_index_t index = 0; 687 ipc_table_elems_t size = 0; 688 689 /* 690 * If the port has no send-possible request 691 * armed, don't bother to lock the port. 692 */ 693 if (!port->ip_sprequests) 694 return; 695 696 ip_lock(port); 697 if (!port->ip_sprequests) { 698 ip_unlock(port); 699 return; 700 } 701 port->ip_sprequests = FALSE; 702 703 revalidate: 704 if (ip_active(port)) { 705 ipc_port_request_t requests; 706 707 /* table may change each time port unlocked (reload) */ 708 requests = port->ip_requests; 709 assert(requests != IPR_NULL); 710 711 /* 712 * no need to go beyond table size when first 713 * we entered - those are future notifications. 714 */ 715 if (size == 0) 716 size = requests->ipr_size->its_size; 717 718 /* no need to backtrack either */ 719 while (++index < size) { 720 ipc_port_request_t ipr = &requests[index]; 721 mach_port_name_t name = ipr->ipr_name; 722 ipc_port_t soright = IPR_SOR_PORT(ipr->ipr_soright); 723 boolean_t armed = IPR_SOR_SPARMED(ipr->ipr_soright); 724 725 if (MACH_PORT_VALID(name) && armed && IP_VALID(soright)) { 726 /* claim send-once right - slot still inuse */ 727 ipr->ipr_soright = IP_NULL; 728 ip_unlock(port); 729 730 ipc_notify_send_possible(soright, name); 731 732 ip_lock(port); 733 goto revalidate; 734 } 735 } 736 } 737 ip_unlock(port); 738} 739 740/* 741 * Routine: ipc_port_dnnotify 742 * Purpose: 743 * Generate dead name notifications for 744 * all outstanding dead-name and send- 745 * possible requests. 746 * Conditions: 747 * Nothing locked. 748 * Port must be inactive. 749 * Reference held on port. 750 */ 751void 752ipc_port_dnnotify( 753 ipc_port_t port) 754{ 755 ipc_port_request_t requests = port->ip_requests; 756 757 assert(!ip_active(port)); 758 if (requests != IPR_NULL) { 759 ipc_table_size_t its = requests->ipr_size; 760 ipc_table_elems_t size = its->its_size; 761 ipc_port_request_index_t index; 762 for (index = 1; index < size; index++) { 763 ipc_port_request_t ipr = &requests[index]; 764 mach_port_name_t name = ipr->ipr_name; 765 ipc_port_t soright = IPR_SOR_PORT(ipr->ipr_soright); 766 767 if (MACH_PORT_VALID(name) && IP_VALID(soright)) { 768 ipc_notify_dead_name(soright, name); 769 } 770 } 771 } 772} 773 774 775/* 776 * Routine: ipc_port_destroy 777 * Purpose: 778 * Destroys a port. Cleans up queued messages. 779 * 780 * If the port has a backup, it doesn't get destroyed, 781 * but is sent in a port-destroyed notification to the backup. 782 * Conditions: 783 * The port is locked and alive; nothing else locked. 784 * The caller has a reference, which is consumed. 785 * Afterwards, the port is unlocked and dead. 786 */ 787 788void 789ipc_port_destroy( 790 ipc_port_t port) 791{ 792 ipc_port_t pdrequest, nsrequest; 793 ipc_mqueue_t mqueue; 794 ipc_kmsg_t kmsg; 795 796 assert(ip_active(port)); 797 /* port->ip_receiver_name is garbage */ 798 /* port->ip_receiver/port->ip_destination is garbage */ 799 assert(port->ip_pset_count == 0); 800 assert(port->ip_mscount == 0); 801 802 /* first check for a backup port */ 803 804 pdrequest = port->ip_pdrequest; 805 if (pdrequest != IP_NULL) { 806 /* we assume the ref for pdrequest */ 807 port->ip_pdrequest = IP_NULL; 808 809 /* make port be in limbo */ 810 port->ip_receiver_name = MACH_PORT_NULL; 811 port->ip_destination = IP_NULL; 812 ip_unlock(port); 813 814 /* consumes our refs for port and pdrequest */ 815 ipc_notify_port_destroyed(pdrequest, port); 816 return; 817 } 818 819 /* once port is dead, we don't need to keep it locked */ 820 821 port->ip_object.io_bits &= ~IO_BITS_ACTIVE; 822 port->ip_timestamp = ipc_port_timestamp(); 823 824 /* 825 * If the port has a preallocated message buffer and that buffer 826 * is not inuse, free it. If it has an inuse one, then the kmsg 827 * free will detect that we freed the association and it can free it 828 * like a normal buffer. 829 */ 830 if (IP_PREALLOC(port)) { 831 ipc_port_t inuse_port; 832 833 kmsg = port->ip_premsg; 834 assert(kmsg != IKM_NULL); 835 inuse_port = ikm_prealloc_inuse_port(kmsg); 836 IP_CLEAR_PREALLOC(port, kmsg); 837 ip_unlock(port); 838 if (inuse_port != IP_NULL) { 839 assert(inuse_port == port); 840 } else { 841 ipc_kmsg_free(kmsg); 842 } 843 } else { 844 ip_unlock(port); 845 } 846 847 /* throw away no-senders request */ 848 nsrequest = port->ip_nsrequest; 849 if (nsrequest != IP_NULL) 850 ipc_notify_send_once(nsrequest); /* consumes ref */ 851 852 /* destroy any queued messages */ 853 mqueue = &port->ip_messages; 854 ipc_mqueue_destroy(mqueue); 855 856 /* generate dead-name notifications */ 857 ipc_port_dnnotify(port); 858 859 ipc_kobject_destroy(port); 860 861 ip_release(port); /* consume caller's ref */ 862} 863 864/* 865 * Routine: ipc_port_check_circularity 866 * Purpose: 867 * Check if queueing "port" in a message for "dest" 868 * would create a circular group of ports and messages. 869 * 870 * If no circularity (FALSE returned), then "port" 871 * is changed from "in limbo" to "in transit". 872 * 873 * That is, we want to set port->ip_destination == dest, 874 * but guaranteeing that this doesn't create a circle 875 * port->ip_destination->ip_destination->... == port 876 * Conditions: 877 * No ports locked. References held for "port" and "dest". 878 */ 879 880boolean_t 881ipc_port_check_circularity( 882 ipc_port_t port, 883 ipc_port_t dest) 884{ 885 ipc_port_t base; 886 887 assert(port != IP_NULL); 888 assert(dest != IP_NULL); 889 890 if (port == dest) 891 return TRUE; 892 base = dest; 893 894 /* 895 * First try a quick check that can run in parallel. 896 * No circularity if dest is not in transit. 897 */ 898 899 ip_lock(port); 900 if (ip_lock_try(dest)) { 901 if (!ip_active(dest) || 902 (dest->ip_receiver_name != MACH_PORT_NULL) || 903 (dest->ip_destination == IP_NULL)) 904 goto not_circular; 905 906 /* dest is in transit; further checking necessary */ 907 908 ip_unlock(dest); 909 } 910 ip_unlock(port); 911 912 ipc_port_multiple_lock(); /* massive serialization */ 913 914 /* 915 * Search for the end of the chain (a port not in transit), 916 * acquiring locks along the way. 917 */ 918 919 for (;;) { 920 ip_lock(base); 921 922 if (!ip_active(base) || 923 (base->ip_receiver_name != MACH_PORT_NULL) || 924 (base->ip_destination == IP_NULL)) 925 break; 926 927 base = base->ip_destination; 928 } 929 930 /* all ports in chain from dest to base, inclusive, are locked */ 931 932 if (port == base) { 933 /* circularity detected! */ 934 935 ipc_port_multiple_unlock(); 936 937 /* port (== base) is in limbo */ 938 939 assert(ip_active(port)); 940 assert(port->ip_receiver_name == MACH_PORT_NULL); 941 assert(port->ip_destination == IP_NULL); 942 943 while (dest != IP_NULL) { 944 ipc_port_t next; 945 946 /* dest is in transit or in limbo */ 947 948 assert(ip_active(dest)); 949 assert(dest->ip_receiver_name == MACH_PORT_NULL); 950 951 next = dest->ip_destination; 952 ip_unlock(dest); 953 dest = next; 954 } 955 956 return TRUE; 957 } 958 959 /* 960 * The guarantee: lock port while the entire chain is locked. 961 * Once port is locked, we can take a reference to dest, 962 * add port to the chain, and unlock everything. 963 */ 964 965 ip_lock(port); 966 ipc_port_multiple_unlock(); 967 968 not_circular: 969 970 /* port is in limbo */ 971 972 assert(ip_active(port)); 973 assert(port->ip_receiver_name == MACH_PORT_NULL); 974 assert(port->ip_destination == IP_NULL); 975 976 ip_reference(dest); 977 port->ip_destination = dest; 978 979 /* now unlock chain */ 980 981 while (port != base) { 982 ipc_port_t next; 983 984 /* port is in transit */ 985 986 assert(ip_active(port)); 987 assert(port->ip_receiver_name == MACH_PORT_NULL); 988 assert(port->ip_destination != IP_NULL); 989 990 next = port->ip_destination; 991 ip_unlock(port); 992 port = next; 993 } 994 995 /* base is not in transit */ 996 997 assert(!ip_active(base) || 998 (base->ip_receiver_name != MACH_PORT_NULL) || 999 (base->ip_destination == IP_NULL)); 1000 ip_unlock(base); 1001 1002 return FALSE; 1003} 1004 1005/* 1006 * Routine: ipc_port_lookup_notify 1007 * Purpose: 1008 * Make a send-once notify port from a receive right. 1009 * Returns IP_NULL if name doesn't denote a receive right. 1010 * Conditions: 1011 * The space must be locked (read or write) and active. 1012 * Being the active space, we can rely on thread server_id 1013 * context to give us the proper server level sub-order 1014 * within the space. 1015 */ 1016 1017ipc_port_t 1018ipc_port_lookup_notify( 1019 ipc_space_t space, 1020 mach_port_name_t name) 1021{ 1022 ipc_port_t port; 1023 ipc_entry_t entry; 1024 1025 assert(is_active(space)); 1026 1027 entry = ipc_entry_lookup(space, name); 1028 if (entry == IE_NULL) 1029 return IP_NULL; 1030 if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) 1031 return IP_NULL; 1032 1033 port = (ipc_port_t) entry->ie_object; 1034 assert(port != IP_NULL); 1035 1036 ip_lock(port); 1037 assert(ip_active(port)); 1038 assert(port->ip_receiver_name == name); 1039 assert(port->ip_receiver == space); 1040 1041 ip_reference(port); 1042 port->ip_sorights++; 1043 ip_unlock(port); 1044 1045 return port; 1046} 1047 1048/* 1049 * Routine: ipc_port_make_send_locked 1050 * Purpose: 1051 * Make a naked send right from a receive right. 1052 * 1053 * Conditions: 1054 * port locked and active. 1055 */ 1056ipc_port_t 1057ipc_port_make_send_locked( 1058 ipc_port_t port) 1059{ 1060 assert(ip_active(port)); 1061 port->ip_mscount++; 1062 port->ip_srights++; 1063 ip_reference(port); 1064 ip_unlock(port); 1065 return port; 1066} 1067 1068/* 1069 * Routine: ipc_port_make_send 1070 * Purpose: 1071 * Make a naked send right from a receive right. 1072 */ 1073 1074ipc_port_t 1075ipc_port_make_send( 1076 ipc_port_t port) 1077{ 1078 1079 if (!IP_VALID(port)) 1080 return port; 1081 1082 ip_lock(port); 1083 if (ip_active(port)) { 1084 port->ip_mscount++; 1085 port->ip_srights++; 1086 ip_reference(port); 1087 ip_unlock(port); 1088 return port; 1089 } 1090 ip_unlock(port); 1091 return IP_DEAD; 1092} 1093 1094/* 1095 * Routine: ipc_port_copy_send 1096 * Purpose: 1097 * Make a naked send right from another naked send right. 1098 * IP_NULL -> IP_NULL 1099 * IP_DEAD -> IP_DEAD 1100 * dead port -> IP_DEAD 1101 * live port -> port + ref 1102 * Conditions: 1103 * Nothing locked except possibly a space. 1104 */ 1105 1106ipc_port_t 1107ipc_port_copy_send( 1108 ipc_port_t port) 1109{ 1110 ipc_port_t sright; 1111 1112 if (!IP_VALID(port)) 1113 return port; 1114 1115 ip_lock(port); 1116 if (ip_active(port)) { 1117 assert(port->ip_srights > 0); 1118 1119 ip_reference(port); 1120 port->ip_srights++; 1121 sright = port; 1122 } else 1123 sright = IP_DEAD; 1124 ip_unlock(port); 1125 1126 return sright; 1127} 1128 1129/* 1130 * Routine: ipc_port_copyout_send 1131 * Purpose: 1132 * Copyout a naked send right (possibly null/dead), 1133 * or if that fails, destroy the right. 1134 * Conditions: 1135 * Nothing locked. 1136 */ 1137 1138mach_port_name_t 1139ipc_port_copyout_send( 1140 ipc_port_t sright, 1141 ipc_space_t space) 1142{ 1143 mach_port_name_t name; 1144 1145 if (IP_VALID(sright)) { 1146 kern_return_t kr; 1147 1148 kr = ipc_object_copyout(space, (ipc_object_t) sright, 1149 MACH_MSG_TYPE_PORT_SEND, TRUE, &name); 1150 if (kr != KERN_SUCCESS) { 1151 ipc_port_release_send(sright); 1152 1153 if (kr == KERN_INVALID_CAPABILITY) 1154 name = MACH_PORT_DEAD; 1155 else 1156 name = MACH_PORT_NULL; 1157 } 1158 } else 1159 name = CAST_MACH_PORT_TO_NAME(sright); 1160 1161 return name; 1162} 1163 1164/* 1165 * Routine: ipc_port_release_send 1166 * Purpose: 1167 * Release a naked send right. 1168 * Consumes a ref for the port. 1169 * Conditions: 1170 * Nothing locked. 1171 */ 1172 1173void 1174ipc_port_release_send( 1175 ipc_port_t port) 1176{ 1177 ipc_port_t nsrequest = IP_NULL; 1178 mach_port_mscount_t mscount; 1179 1180 if (!IP_VALID(port)) 1181 return; 1182 1183 ip_lock(port); 1184 1185 if (!ip_active(port)) { 1186 ip_unlock(port); 1187 ip_release(port); 1188 return; 1189 } 1190 1191 assert(port->ip_srights > 0); 1192 1193 if (--port->ip_srights == 0 && 1194 port->ip_nsrequest != IP_NULL) { 1195 nsrequest = port->ip_nsrequest; 1196 port->ip_nsrequest = IP_NULL; 1197 mscount = port->ip_mscount; 1198 ip_unlock(port); 1199 ip_release(port); 1200 ipc_notify_no_senders(nsrequest, mscount); 1201 } else { 1202 ip_unlock(port); 1203 ip_release(port); 1204 } 1205} 1206 1207/* 1208 * Routine: ipc_port_make_sonce_locked 1209 * Purpose: 1210 * Make a naked send-once right from a receive right. 1211 * Conditions: 1212 * The port is locked and active. 1213 */ 1214 1215ipc_port_t 1216ipc_port_make_sonce_locked( 1217 ipc_port_t port) 1218{ 1219 assert(ip_active(port)); 1220 port->ip_sorights++; 1221 ip_reference(port); 1222 return port; 1223} 1224 1225/* 1226 * Routine: ipc_port_make_sonce 1227 * Purpose: 1228 * Make a naked send-once right from a receive right. 1229 * Conditions: 1230 * The port is not locked. 1231 */ 1232 1233ipc_port_t 1234ipc_port_make_sonce( 1235 ipc_port_t port) 1236{ 1237 if (!IP_VALID(port)) 1238 return port; 1239 1240 ip_lock(port); 1241 if (ip_active(port)) { 1242 port->ip_sorights++; 1243 ip_reference(port); 1244 ip_unlock(port); 1245 return port; 1246 } 1247 ip_unlock(port); 1248 return IP_DEAD; 1249} 1250 1251/* 1252 * Routine: ipc_port_release_sonce 1253 * Purpose: 1254 * Release a naked send-once right. 1255 * Consumes a ref for the port. 1256 * 1257 * In normal situations, this is never used. 1258 * Send-once rights are only consumed when 1259 * a message (possibly a send-once notification) 1260 * is sent to them. 1261 * Conditions: 1262 * Nothing locked except possibly a space. 1263 */ 1264 1265void 1266ipc_port_release_sonce( 1267 ipc_port_t port) 1268{ 1269 if (!IP_VALID(port)) 1270 return; 1271 1272 ip_lock(port); 1273 1274 assert(port->ip_sorights > 0); 1275 1276 port->ip_sorights--; 1277 1278 ip_unlock(port); 1279 ip_release(port); 1280} 1281 1282/* 1283 * Routine: ipc_port_release_receive 1284 * Purpose: 1285 * Release a naked (in limbo or in transit) receive right. 1286 * Consumes a ref for the port; destroys the port. 1287 * Conditions: 1288 * Nothing locked. 1289 */ 1290 1291void 1292ipc_port_release_receive( 1293 ipc_port_t port) 1294{ 1295 ipc_port_t dest; 1296 1297 if (!IP_VALID(port)) 1298 return; 1299 1300 ip_lock(port); 1301 assert(ip_active(port)); 1302 assert(port->ip_receiver_name == MACH_PORT_NULL); 1303 dest = port->ip_destination; 1304 1305 ipc_port_destroy(port); /* consumes ref, unlocks */ 1306 1307 if (dest != IP_NULL) 1308 ip_release(dest); 1309} 1310 1311/* 1312 * Routine: ipc_port_alloc_special 1313 * Purpose: 1314 * Allocate a port in a special space. 1315 * The new port is returned with one ref. 1316 * If unsuccessful, IP_NULL is returned. 1317 * Conditions: 1318 * Nothing locked. 1319 */ 1320 1321ipc_port_t 1322ipc_port_alloc_special( 1323 ipc_space_t space) 1324{ 1325 ipc_port_t port; 1326 1327 port = (ipc_port_t) io_alloc(IOT_PORT); 1328 if (port == IP_NULL) 1329 return IP_NULL; 1330 1331#if MACH_ASSERT 1332 natural_t buf[IP_CALLSTACK_MAX]; 1333 ipc_port_callstack_init_debug(&buf[0], IP_CALLSTACK_MAX); 1334#endif /* MACH_ASSERT */ 1335 1336 bzero((char *)port, sizeof(*port)); 1337 io_lock_init(&port->ip_object); 1338 port->ip_references = 1; 1339 port->ip_object.io_bits = io_makebits(TRUE, IOT_PORT, 0); 1340 1341 ipc_port_init(port, space, 1); 1342 1343#if MACH_ASSERT 1344 ipc_port_init_debug(port, &buf[0], IP_CALLSTACK_MAX); 1345#endif /* MACH_ASSERT */ 1346 1347#if CONFIG_MACF_MACH 1348 /* Currently, ipc_port_alloc_special is used for two things: 1349 * - Reply ports for messages from the kernel 1350 * - Ports for communication with the kernel (e.g. task ports) 1351 * Since both of these would typically be labelled as kernel objects, 1352 * we will use a new entry point for this purpose, as current_task() 1353 * is often wrong (i.e. not kernel_task) or null. 1354 */ 1355 mac_port_label_init(&port->ip_label); 1356 mac_port_label_associate_kernel(&port->ip_label, space == ipc_space_reply); 1357#endif 1358 1359 return port; 1360} 1361 1362/* 1363 * Routine: ipc_port_dealloc_special 1364 * Purpose: 1365 * Deallocate a port in a special space. 1366 * Consumes one ref for the port. 1367 * Conditions: 1368 * Nothing locked. 1369 */ 1370 1371void 1372ipc_port_dealloc_special( 1373 ipc_port_t port, 1374 __assert_only ipc_space_t space) 1375{ 1376 ip_lock(port); 1377 assert(ip_active(port)); 1378// assert(port->ip_receiver_name != MACH_PORT_NULL); 1379 assert(port->ip_receiver == space); 1380 1381 /* 1382 * We clear ip_receiver_name and ip_receiver to simplify 1383 * the ipc_space_kernel check in ipc_mqueue_send. 1384 */ 1385 1386 port->ip_receiver_name = MACH_PORT_NULL; 1387 port->ip_receiver = IS_NULL; 1388 1389 /* relevant part of ipc_port_clear_receiver */ 1390 ipc_port_set_mscount(port, 0); 1391 port->ip_messages.imq_seqno = 0; 1392 1393 ipc_port_destroy(port); 1394} 1395 1396/* 1397 * Routine: ipc_port_finalize 1398 * Purpose: 1399 * Called on last reference deallocate to 1400 * free any remaining data associated with the 1401 * port. 1402 * Conditions: 1403 * Nothing locked. 1404 */ 1405void 1406ipc_port_finalize( 1407 ipc_port_t port) 1408{ 1409 ipc_port_request_t requests = port->ip_requests; 1410 1411 assert(!ip_active(port)); 1412 if (requests != IPR_NULL) { 1413 ipc_table_size_t its = requests->ipr_size; 1414 it_requests_free(its, requests); 1415 port->ip_requests = IPR_NULL; 1416 } 1417 1418#if MACH_ASSERT 1419 ipc_port_track_dealloc(port); 1420#endif /* MACH_ASSERT */ 1421 1422#if CONFIG_MACF_MACH 1423 /* Port label should have been initialized after creation. */ 1424 mac_port_label_destroy(&port->ip_label); 1425#endif 1426} 1427 1428#if MACH_ASSERT 1429#include <kern/machine.h> 1430 1431/* 1432 * Keep a list of all allocated ports. 1433 * Allocation is intercepted via ipc_port_init; 1434 * deallocation is intercepted via io_free. 1435 */ 1436queue_head_t port_alloc_queue; 1437lck_spin_t port_alloc_queue_lock; 1438 1439unsigned long port_count = 0; 1440unsigned long port_count_warning = 20000; 1441unsigned long port_timestamp = 0; 1442 1443void db_port_stack_trace( 1444 ipc_port_t port); 1445void db_ref( 1446 int refs); 1447int db_port_walk( 1448 unsigned int verbose, 1449 unsigned int display, 1450 unsigned int ref_search, 1451 unsigned int ref_target); 1452 1453/* 1454 * Initialize global state needed for run-time 1455 * port debugging. 1456 */ 1457void 1458ipc_port_debug_init(void) 1459{ 1460 queue_init(&port_alloc_queue); 1461 1462 lck_spin_init(&port_alloc_queue_lock, &ipc_lck_grp, &ipc_lck_attr); 1463 1464 if (!PE_parse_boot_argn("ipc_portbt", &ipc_portbt, sizeof (ipc_portbt))) 1465 ipc_portbt = 0; 1466} 1467 1468#ifdef MACH_BSD 1469extern int proc_pid(struct proc*); 1470#endif /* MACH_BSD */ 1471 1472/* 1473 * Initialize all of the debugging state in a port. 1474 * Insert the port into a global list of all allocated ports. 1475 */ 1476void 1477ipc_port_init_debug( 1478 ipc_port_t port, 1479 natural_t *callstack, 1480 unsigned int callstack_max) 1481{ 1482 unsigned int i; 1483 1484 port->ip_thread = current_thread(); 1485 port->ip_timetrack = port_timestamp++; 1486 for (i = 0; i < callstack_max; ++i) 1487 port->ip_callstack[i] = callstack[i]; 1488 for (i = 0; i < IP_NSPARES; ++i) 1489 port->ip_spares[i] = 0; 1490 1491#ifdef MACH_BSD 1492 task_t task = current_task(); 1493 if (task != TASK_NULL) { 1494 struct proc* proc = (struct proc*) get_bsdtask_info(task); 1495 if (proc) 1496 port->ip_spares[0] = proc_pid(proc); 1497 } 1498#endif /* MACH_BSD */ 1499 1500#if 0 1501 lck_spin_lock(&port_alloc_queue_lock); 1502 ++port_count; 1503 if (port_count_warning > 0 && port_count >= port_count_warning) 1504 assert(port_count < port_count_warning); 1505 queue_enter(&port_alloc_queue, port, ipc_port_t, ip_port_links); 1506 lck_spin_unlock(&port_alloc_queue_lock); 1507#endif 1508} 1509 1510/* 1511 * Routine: ipc_port_callstack_init_debug 1512 * Purpose: 1513 * Calls the machine-dependent routine to 1514 * fill in an array with up to IP_CALLSTACK_MAX 1515 * levels of return pc information 1516 * Conditions: 1517 * May block (via copyin) 1518 */ 1519void 1520ipc_port_callstack_init_debug( 1521 natural_t *callstack, 1522 unsigned int callstack_max) 1523{ 1524 unsigned int i; 1525 1526 /* guarantee the callstack is initialized */ 1527 for (i=0; i < callstack_max; i++) 1528 callstack[i] = 0; 1529 1530 if (ipc_portbt) 1531 machine_callstack(callstack, callstack_max); 1532} 1533 1534/* 1535 * Remove a port from the queue of allocated ports. 1536 * This routine should be invoked JUST prior to 1537 * deallocating the actual memory occupied by the port. 1538 */ 1539#if 1 1540void 1541ipc_port_track_dealloc( 1542 __unused ipc_port_t port) 1543{ 1544} 1545#else 1546void 1547ipc_port_track_dealloc( 1548 ipc_port_t port) 1549{ 1550 lck_spin_lock(&port_alloc_queue_lock); 1551 assert(port_count > 0); 1552 --port_count; 1553 queue_remove(&port_alloc_queue, port, ipc_port_t, ip_port_links); 1554 lck_spin_unlock(&port_alloc_queue_lock); 1555} 1556#endif 1557 1558 1559#endif /* MACH_ASSERT */ 1560