2  * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * @OSF_FREE_COPYRIGHT@ 
  32  * Mach Operating System 
  33  * Copyright (c) 1991,1990,1989 Carnegie Mellon University 
  34  * All Rights Reserved. 
  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. 
  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. 
  46  * Carnegie Mellon requests users of this software to return to 
  48  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU 
  49  *  School of Computer Science 
  50  *  Carnegie Mellon University 
  51  *  Pittsburgh PA 15213-3890 
  53  * any improvements or extensions that they make and grant Carnegie Mellon 
  54  * the rights to redistribute these changes. 
  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, 
  61  * Copyright (c) 2005-2006 SPARTA, Inc. 
  66  *      File:   ipc/ipc_right.c 
  70  *      Functions to manipulate IPC capabilities. 
  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> 
  81 #include <ipc/ipc_entry.h> 
  82 #include <ipc/ipc_space.h> 
  83 #include <ipc/ipc_object.h> 
  84 #include <ipc/ipc_hash.h> 
  85 #include <ipc/ipc_port.h> 
  86 #include <ipc/ipc_pset.h> 
  87 #include <ipc/ipc_right.h> 
  88 #include <ipc/ipc_notify.h> 
  89 #include <ipc/ipc_table.h> 
  90 #include <ipc/ipc_importance.h> 
  91 #include <security/mac_mach_internal.h> 
  94  *      Routine:        ipc_right_lookup_write 
  96  *              Finds an entry in a space, given the name. 
  98  *              Nothing locked.  If successful, the space is write-locked. 
 100  *              KERN_SUCCESS            Found an entry. 
 101  *              KERN_INVALID_TASK       The space is dead. 
 102  *              KERN_INVALID_NAME       Name doesn't exist in space. 
 106 ipc_right_lookup_write( 
 108         mach_port_name_t        name
, 
 113         assert(space 
!= IS_NULL
); 
 115         is_write_lock(space
); 
 117         if (!is_active(space
)) { 
 118                 is_write_unlock(space
); 
 119                 return KERN_INVALID_TASK
; 
 122         if ((entry 
= ipc_entry_lookup(space
, name
)) == IE_NULL
) { 
 123                 is_write_unlock(space
); 
 124                 return KERN_INVALID_NAME
; 
 132  *      Routine:        ipc_right_lookup_two_write 
 134  *              Like ipc_right_lookup except that it returns two 
 135  *              entries for two different names that were looked 
 136  *              up under the same space lock. 
 138  *              Nothing locked.  If successful, the space is write-locked. 
 140  *              KERN_INVALID_TASK       The space is dead. 
 141  *              KERN_INVALID_NAME       Name doesn't exist in space. 
 145 ipc_right_lookup_two_write( 
 147         mach_port_name_t        name1
, 
 148         ipc_entry_t             
*entryp1
, 
 149         mach_port_name_t        name2
, 
 150         ipc_entry_t             
*entryp2
) 
 155         assert(space 
!= IS_NULL
); 
 157         is_write_lock(space
); 
 159         if (!is_active(space
)) { 
 160                 is_write_unlock(space
); 
 161                 return KERN_INVALID_TASK
; 
 164         if ((entry1 
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) { 
 165                 is_write_unlock(space
); 
 166                 mach_port_guard_exception(name1
, 0, 0, kGUARD_EXC_INVALID_NAME
); 
 167                 return KERN_INVALID_NAME
; 
 169         if ((entry2 
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) { 
 170                 is_write_unlock(space
); 
 171                 mach_port_guard_exception(name2
, 0, 0, kGUARD_EXC_INVALID_NAME
); 
 172                 return KERN_INVALID_NAME
; 
 180  *      Routine:        ipc_right_reverse 
 182  *              Translate (space, object) -> (name, entry). 
 183  *              Only finds send/receive rights. 
 184  *              Returns TRUE if an entry is found; if so, 
 187  *              The space must be locked (read or write) and active. 
 188  *              The port is locked and active 
 195         mach_port_name_t        
*namep
, 
 199         mach_port_name_t name
; 
 202         /* would switch on io_otype to handle multiple types of object */ 
 204         assert(is_active(space
)); 
 205         assert(io_otype(object
) == IOT_PORT
); 
 207         port 
= ip_object_to_port(object
); 
 208         require_ip_active(port
); 
 212         if (port
->ip_receiver 
== space
) { 
 213                 name 
= port
->ip_receiver_name
; 
 214                 assert(name 
!= MACH_PORT_NULL
); 
 216                 entry 
= ipc_entry_lookup(space
, name
); 
 218                 assert(entry 
!= IE_NULL
); 
 219                 assert(entry
->ie_bits 
& MACH_PORT_TYPE_RECEIVE
); 
 220                 assert(port 
== ip_object_to_port(entry
->ie_object
)); 
 227         if (ipc_hash_lookup(space
, ip_to_object(port
), namep
, entryp
)) { 
 228                 assert((entry 
= *entryp
) != IE_NULL
); 
 229                 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
); 
 230                 assert(port 
== ip_object_to_port(entry
->ie_object
)); 
 239  *      Routine:        ipc_right_dnrequest 
 241  *              Make a dead-name request, returning the previously 
 242  *              registered send-once right.  If notify is IP_NULL, 
 243  *              just cancels the previously registered request. 
 246  *              Nothing locked.  May allocate memory. 
 247  *              Only consumes/returns refs if successful. 
 249  *              KERN_SUCCESS            Made/canceled dead-name request. 
 250  *              KERN_INVALID_TASK       The space is dead. 
 251  *              KERN_INVALID_NAME       Name doesn't exist in space. 
 252  *              KERN_INVALID_RIGHT      Name doesn't denote port/dead rights. 
 253  *              KERN_INVALID_ARGUMENT   Name denotes dead name, but 
 254  *                      immediate is FALSE or notify is IP_NULL. 
 255  *              KERN_RESOURCE_SHORTAGE  Couldn't allocate memory. 
 259 ipc_right_request_alloc( 
 261         mach_port_name_t        name
, 
 263         boolean_t               send_possible
, 
 265         ipc_port_t              
*previousp
) 
 267         ipc_port_request_index_t prev_request
; 
 268         ipc_port_t previous 
= IP_NULL
; 
 272 #if IMPORTANCE_INHERITANCE 
 273         boolean_t needboost 
= FALSE
; 
 274 #endif /* IMPORTANCE_INHERITANCE */ 
 277                 ipc_port_t port 
= IP_NULL
; 
 279                 kr 
= ipc_right_lookup_write(space
, name
, &entry
); 
 280                 if (kr 
!= KERN_SUCCESS
) { 
 284                 /* space is write-locked and active */ 
 286                 prev_request 
= entry
->ie_request
; 
 288                 /* if nothing to do or undo, we're done */ 
 289                 if (notify 
== IP_NULL 
&& prev_request 
== IE_REQ_NONE
) { 
 290                         is_write_unlock(space
); 
 291                         *previousp 
= IP_NULL
; 
 295                 /* see if the entry is of proper type for requests */ 
 296                 if (entry
->ie_bits 
& MACH_PORT_TYPE_PORT_RIGHTS
) { 
 297                         ipc_port_request_index_t new_request
; 
 299                         port 
= ip_object_to_port(entry
->ie_object
); 
 300                         assert(port 
!= IP_NULL
); 
 302                         if (!ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
 303                                 /* port is locked and active */ 
 305                                 /* if no new request, just cancel previous */ 
 306                                 if (notify 
== IP_NULL
) { 
 307                                         if (prev_request 
!= IE_REQ_NONE
) { 
 308                                                 previous 
= ipc_port_request_cancel(port
, name
, prev_request
); 
 311                                         entry
->ie_request 
= IE_REQ_NONE
; 
 312                                         ipc_entry_modified(space
, name
, entry
); 
 313                                         is_write_unlock(space
); 
 318                                  * send-once rights, kernel objects, and non-full other queues 
 319                                  * fire immediately (if immediate specified). 
 321                                 if (send_possible 
&& immediate 
&& 
 322                                     ((entry
->ie_bits 
& MACH_PORT_TYPE_SEND_ONCE
) || 
 323                                     port
->ip_receiver 
== ipc_space_kernel 
|| !ip_full(port
))) { 
 324                                         if (prev_request 
!= IE_REQ_NONE
) { 
 325                                                 previous 
= ipc_port_request_cancel(port
, name
, prev_request
); 
 328                                         entry
->ie_request 
= IE_REQ_NONE
; 
 329                                         ipc_entry_modified(space
, name
, entry
); 
 330                                         is_write_unlock(space
); 
 332                                         ipc_notify_send_possible(notify
, name
); 
 337                                  * If there is a previous request, free it.  Any subsequent 
 338                                  * allocation cannot fail, thus assuring an atomic swap. 
 340                                 if (prev_request 
!= IE_REQ_NONE
) { 
 341                                         previous 
= ipc_port_request_cancel(port
, name
, prev_request
); 
 344 #if IMPORTANCE_INHERITANCE 
 345                                 kr 
= ipc_port_request_alloc(port
, name
, notify
, 
 346                                     send_possible
, immediate
, 
 347                                     &new_request
, &needboost
); 
 349                                 kr 
= ipc_port_request_alloc(port
, name
, notify
, 
 350                                     send_possible
, immediate
, 
 352 #endif /* IMPORTANCE_INHERITANCE */ 
 353                                 if (kr 
!= KERN_SUCCESS
) { 
 354                                         assert(previous 
== IP_NULL
); 
 355                                         is_write_unlock(space
); 
 357                                         kr 
= ipc_port_request_grow(port
, ITS_SIZE_NONE
); 
 358                                         /* port is unlocked */ 
 360                                         if (kr 
!= KERN_SUCCESS
) { 
 368                                 assert(new_request 
!= IE_REQ_NONE
); 
 369                                 entry
->ie_request 
= new_request
; 
 370                                 ipc_entry_modified(space
, name
, entry
); 
 371                                 is_write_unlock(space
); 
 373 #if IMPORTANCE_INHERITANCE 
 374                                 if (needboost 
== TRUE
) { 
 375                                         if (ipc_port_importance_delta(port
, IPID_OPTION_SENDPOSSIBLE
, 1) == FALSE
) { 
 379 #endif /* IMPORTANCE_INHERITANCE */ 
 384                         /* entry may have changed to dead-name by ipc_right_check() */ 
 387                 /* treat send_possible requests as immediate w.r.t. dead-name */ 
 388                 if ((send_possible 
|| immediate
) && notify 
!= IP_NULL 
&& 
 389                     (entry
->ie_bits 
& MACH_PORT_TYPE_DEAD_NAME
)) { 
 390                         mach_port_urefs_t urefs 
= IE_BITS_UREFS(entry
->ie_bits
); 
 394                         /* leave urefs pegged to maximum if it overflowed */ 
 395                         if (urefs 
< MACH_PORT_UREFS_MAX
) { 
 396                                 (entry
->ie_bits
)++; /* increment urefs */ 
 398                         ipc_entry_modified(space
, name
, entry
); 
 400                         is_write_unlock(space
); 
 402                         if (port 
!= IP_NULL
) { 
 406                         ipc_notify_dead_name(notify
, name
); 
 411                 kr 
= (entry
->ie_bits 
& MACH_PORT_TYPE_PORT_OR_DEAD
) ? 
 412                     KERN_INVALID_ARGUMENT 
: KERN_INVALID_RIGHT
; 
 414                 is_write_unlock(space
); 
 416                 if (port 
!= IP_NULL
) { 
 423         *previousp 
= previous
; 
 428  *      Routine:        ipc_right_request_cancel 
 430  *              Cancel a notification request and return the send-once right. 
 431  *              Afterwards, entry->ie_request == 0. 
 433  *              The space must be write-locked; the port must be locked. 
 434  *              The port must be active; the space doesn't have to be. 
 438 ipc_right_request_cancel( 
 439         __unused ipc_space_t            space
, 
 441         mach_port_name_t                name
, 
 446         require_ip_active(port
); 
 447         assert(port 
== ip_object_to_port(entry
->ie_object
)); 
 449         if (entry
->ie_request 
== IE_REQ_NONE
) { 
 453         previous 
= ipc_port_request_cancel(port
, name
, entry
->ie_request
); 
 454         entry
->ie_request 
= IE_REQ_NONE
; 
 455         ipc_entry_modified(space
, name
, entry
); 
 460  *      Routine:        ipc_right_inuse 
 462  *              Check if an entry is being used. 
 463  *              Returns TRUE if it is. 
 465  *              The space is write-locked and active. 
 472         return IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
; 
 476  *      Routine:        ipc_right_check 
 478  *              Check if the port has died.  If it has, 
 479  *              and IPC_OBJECT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE is not 
 480  *              passed and it is not a send once right then 
 481  *              clean up the entry and return TRUE. 
 483  *              The space is write-locked; the port is not locked. 
 484  *              If returns FALSE, the port is also locked. 
 485  *              Otherwise, entry is converted to a dead name. 
 487  *              Caller is responsible for a reference to port if it 
 488  *              had died (returns TRUE). 
 495         mach_port_name_t         name
, 
 497         ipc_object_copyin_flags_t flags
) 
 499         ipc_entry_bits_t bits
; 
 501         assert(is_active(space
)); 
 502         assert(port 
== ip_object_to_port(entry
->ie_object
)); 
 505         if (ip_active(port
) || 
 506             ((flags 
& IPC_OBJECT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE
) && 
 507             entry
->ie_request 
== IE_REQ_NONE 
&& 
 508             (entry
->ie_bits 
& MACH_PORT_TYPE_SEND_ONCE
))) { 
 512         /* this was either a pure send right or a send-once right */ 
 514         bits 
= entry
->ie_bits
; 
 515         assert((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0); 
 516         assert(IE_BITS_UREFS(bits
) > 0); 
 518         if (bits 
& MACH_PORT_TYPE_SEND
) { 
 519                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
); 
 520                 assert(IE_BITS_UREFS(bits
) > 0); 
 521                 assert(port
->ip_srights 
> 0); 
 524                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
); 
 525                 assert(IE_BITS_UREFS(bits
) == 1); 
 526                 assert(port
->ip_sorights 
> 0); 
 532          * delete SEND rights from ipc hash. 
 535         if ((bits 
& MACH_PORT_TYPE_SEND
) != 0) { 
 536                 ipc_hash_delete(space
, ip_to_object(port
), name
, entry
); 
 539         /* convert entry to dead name */ 
 540         bits 
= (bits 
& ~IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
; 
 543          * If there was a notification request outstanding on this 
 544          * name, and the port went dead, that notification 
 545          * must already be on its way up from the port layer. 
 547          * Add the reference that the notification carries. It 
 548          * is done here, and not in the notification delivery, 
 549          * because the latter doesn't have a space reference and 
 550          * trying to actually move a send-right reference would 
 551          * get short-circuited into a MACH_PORT_DEAD by IPC. Since 
 552          * all calls that deal with the right eventually come 
 553          * through here, it has the same result. 
 555          * Once done, clear the request index so we only account 
 558         if (entry
->ie_request 
!= IE_REQ_NONE
) { 
 559                 if (ipc_port_request_type(port
, name
, entry
->ie_request
) != 0) { 
 560                         /* if urefs are pegged due to overflow, leave them pegged */ 
 561                         if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
 562                                 bits
++; /* increment urefs */ 
 565                 entry
->ie_request 
= IE_REQ_NONE
; 
 567         entry
->ie_bits 
= bits
; 
 568         entry
->ie_object 
= IO_NULL
; 
 569         ipc_entry_modified(space
, name
, entry
); 
 574  *      Routine:        ipc_right_terminate 
 576  *              Cleans up an entry in a terminated space. 
 577  *              The entry isn't deallocated or removed 
 578  *              from reverse hash tables. 
 580  *              The space is dead and unlocked. 
 586         mach_port_name_t        name
, 
 589         ipc_entry_bits_t bits
; 
 590         mach_port_type_t type
; 
 592         bits 
= entry
->ie_bits
; 
 593         type 
= IE_BITS_TYPE(bits
); 
 595         assert(!is_active(space
)); 
 598          *      IE_BITS_COMPAT/ipc_right_dncancel doesn't have this 
 599          *      problem, because we check that the port is active.  If 
 600          *      we didn't cancel IE_BITS_COMPAT, ipc_port_destroy 
 601          *      would still work, but dead space refs would accumulate 
 602          *      in ip_dnrequests.  They would use up slots in 
 603          *      ip_dnrequests and keep the spaces from being freed. 
 607         case MACH_PORT_TYPE_DEAD_NAME
: 
 608                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
 609                 assert(entry
->ie_object 
== IO_NULL
); 
 612         case MACH_PORT_TYPE_PORT_SET
: { 
 613                 ipc_pset_t pset 
= ips_object_to_pset(entry
->ie_object
); 
 615                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
 616                 assert(pset 
!= IPS_NULL
); 
 619                 assert(ips_active(pset
)); 
 620                 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */ 
 624         case MACH_PORT_TYPE_SEND
: 
 625         case MACH_PORT_TYPE_RECEIVE
: 
 626         case MACH_PORT_TYPE_SEND_RECEIVE
: 
 627         case MACH_PORT_TYPE_SEND_ONCE
: { 
 628                 ipc_port_t port 
= ip_object_to_port(entry
->ie_object
); 
 630                 ipc_port_t nsrequest 
= IP_NULL
; 
 631                 mach_port_mscount_t mscount 
= 0; 
 633                 assert(port 
!= IP_NULL
); 
 636                 if (!ip_active(port
)) { 
 642                 request 
= ipc_right_request_cancel_macro(space
, port
, 
 645                 if (type 
& MACH_PORT_TYPE_SEND
) { 
 646                         assert(port
->ip_srights 
> 0); 
 647                         if (--port
->ip_srights 
== 0 
 649                                 nsrequest 
= port
->ip_nsrequest
; 
 650                                 if (nsrequest 
!= IP_NULL
) { 
 651                                         port
->ip_nsrequest 
= IP_NULL
; 
 652                                         mscount 
= port
->ip_mscount
; 
 657                 if (type 
& MACH_PORT_TYPE_RECEIVE
) { 
 658                         assert(port
->ip_receiver_name 
== name
); 
 659                         assert(port
->ip_receiver 
== space
); 
 661                         ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */ 
 662                 } else if (type 
& MACH_PORT_TYPE_SEND_ONCE
) { 
 663                         assert(port
->ip_sorights 
> 0); 
 664                         port
->ip_reply_context 
= 0; 
 667                         ipc_notify_send_once(port
); /* consumes our ref */ 
 669                         assert(port
->ip_receiver 
!= space
); 
 675                 if (nsrequest 
!= IP_NULL
) { 
 676                         ipc_notify_no_senders(nsrequest
, mscount
); 
 679                 if (request 
!= IP_NULL
) { 
 680                         ipc_notify_port_deleted(request
, name
); 
 686                 panic("ipc_right_terminate: strange type - 0x%x", type
); 
 691  *      Routine:        ipc_right_destroy 
 693  *              Destroys an entry in a space. 
 695  *              The space is write-locked (returns unlocked). 
 696  *              The space must be active. 
 698  *              KERN_SUCCESS            The entry was destroyed. 
 704         mach_port_name_t        name
, 
 706         boolean_t               check_guard
, 
 709         ipc_entry_bits_t bits
; 
 710         mach_port_type_t type
; 
 712         bits 
= entry
->ie_bits
; 
 713         entry
->ie_bits 
&= ~IE_BITS_TYPE_MASK
; 
 714         type 
= IE_BITS_TYPE(bits
); 
 716         assert(is_active(space
)); 
 719         case MACH_PORT_TYPE_DEAD_NAME
: 
 720                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
 721                 assert(entry
->ie_object 
== IO_NULL
); 
 723                 ipc_entry_dealloc(space
, name
, entry
); 
 724                 is_write_unlock(space
); 
 727         case MACH_PORT_TYPE_PORT_SET
: { 
 728                 ipc_pset_t pset 
= ips_object_to_pset(entry
->ie_object
); 
 730                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
 731                 assert(pset 
!= IPS_NULL
); 
 733                 entry
->ie_object 
= IO_NULL
; 
 734                 ipc_entry_dealloc(space
, name
, entry
); 
 737                 is_write_unlock(space
); 
 739                 assert(ips_active(pset
)); 
 740                 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */ 
 744         case MACH_PORT_TYPE_SEND
: 
 745         case MACH_PORT_TYPE_RECEIVE
: 
 746         case MACH_PORT_TYPE_SEND_RECEIVE
: 
 747         case MACH_PORT_TYPE_SEND_ONCE
: { 
 748                 ipc_port_t port 
= ip_object_to_port(entry
->ie_object
); 
 749                 ipc_port_t nsrequest 
= IP_NULL
; 
 750                 mach_port_mscount_t mscount 
= 0; 
 753                 assert(port 
!= IP_NULL
); 
 755                 if (type 
== MACH_PORT_TYPE_SEND
) { 
 756                         ipc_hash_delete(space
, ip_to_object(port
), name
, entry
); 
 761                 if (!ip_active(port
)) { 
 762                         assert((type 
& MACH_PORT_TYPE_RECEIVE
) == 0); 
 764                         entry
->ie_request 
= IE_REQ_NONE
; 
 765                         entry
->ie_object 
= IO_NULL
; 
 766                         ipc_entry_dealloc(space
, name
, entry
); 
 767                         is_write_unlock(space
); 
 772                 /* For receive rights, check for guarding */ 
 773                 if ((type 
& MACH_PORT_TYPE_RECEIVE
) && 
 774                     (check_guard
) && (port
->ip_guarded
) && 
 775                     (guard 
!= port
->ip_context
)) { 
 776                         /* Guard Violation */ 
 777                         uint64_t portguard 
= port
->ip_context
; 
 779                         is_write_unlock(space
); 
 780                         /* Raise mach port guard exception */ 
 781                         mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
); 
 782                         return KERN_INVALID_RIGHT
; 
 786                 request 
= ipc_right_request_cancel_macro(space
, port
, name
, entry
); 
 788                 entry
->ie_object 
= IO_NULL
; 
 789                 ipc_entry_dealloc(space
, name
, entry
); 
 790                 is_write_unlock(space
); 
 792                 if (type 
& MACH_PORT_TYPE_SEND
) { 
 793                         assert(port
->ip_srights 
> 0); 
 794                         if (--port
->ip_srights 
== 0) { 
 795                                 nsrequest 
= port
->ip_nsrequest
; 
 796                                 if (nsrequest 
!= IP_NULL
) { 
 797                                         port
->ip_nsrequest 
= IP_NULL
; 
 798                                         mscount 
= port
->ip_mscount
; 
 803                 if (type 
& MACH_PORT_TYPE_RECEIVE
) { 
 804                         require_ip_active(port
); 
 805                         assert(port
->ip_receiver 
== space
); 
 807                         ipc_port_destroy(port
); /* clears receiver, consumes our ref, unlocks */ 
 808                 } else if (type 
& MACH_PORT_TYPE_SEND_ONCE
) { 
 809                         assert(port
->ip_sorights 
> 0); 
 810                         port
->ip_reply_context 
= 0; 
 813                         ipc_notify_send_once(port
); /* consumes our ref */ 
 815                         assert(port
->ip_receiver 
!= space
); 
 821                 if (nsrequest 
!= IP_NULL
) { 
 822                         ipc_notify_no_senders(nsrequest
, mscount
); 
 825                 if (request 
!= IP_NULL
) { 
 826                         ipc_notify_port_deleted(request
, name
); 
 834                 panic("ipc_right_destroy: strange type"); 
 841  *      Routine:        ipc_right_dealloc 
 843  *              Releases a send/send-once/dead-name/port_set user ref. 
 844  *              Like ipc_right_delta with a delta of -1, 
 845  *              but looks at the entry to determine the right. 
 847  *              The space is write-locked, and is unlocked upon return. 
 848  *              The space must be active. 
 850  *              KERN_SUCCESS            A user ref was released. 
 851  *              KERN_INVALID_RIGHT      Entry has wrong type. 
 852  *      KERN_INVALID_CAPABILITY  Deallocating a pinned right. 
 858         mach_port_name_t        name
, 
 861         ipc_port_t port 
= IP_NULL
; 
 862         ipc_entry_bits_t bits
; 
 863         mach_port_type_t type
; 
 865         bits 
= entry
->ie_bits
; 
 866         type 
= IE_BITS_TYPE(bits
); 
 869         assert(is_active(space
)); 
 872         case MACH_PORT_TYPE_PORT_SET
: { 
 875                 assert(IE_BITS_UREFS(bits
) == 0); 
 876                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
 878                 pset 
= ips_object_to_pset(entry
->ie_object
); 
 879                 assert(pset 
!= IPS_NULL
); 
 881                 entry
->ie_object 
= IO_NULL
; 
 882                 ipc_entry_dealloc(space
, name
, entry
); 
 885                 assert(ips_active(pset
)); 
 886                 is_write_unlock(space
); 
 888                 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */ 
 892         case MACH_PORT_TYPE_DEAD_NAME
: { 
 895                 assert(IE_BITS_UREFS(bits
) > 0); 
 896                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
 897                 assert(entry
->ie_object 
== IO_NULL
); 
 899                 if (IE_BITS_UREFS(bits
) == 1) { 
 900                         ipc_entry_dealloc(space
, name
, entry
); 
 902                         /* if urefs are pegged due to overflow, leave them pegged */ 
 903                         if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
 904                                 entry
->ie_bits 
= bits 
- 1; /* decrement urefs */ 
 906                         ipc_entry_modified(space
, name
, entry
); 
 908                 is_write_unlock(space
); 
 910                 /* release any port that got converted to dead name below */ 
 911                 if (port 
!= IP_NULL
) { 
 917         case MACH_PORT_TYPE_SEND_ONCE
: { 
 920                 assert(IE_BITS_UREFS(bits
) == 1); 
 922                 port 
= ip_object_to_port(entry
->ie_object
); 
 923                 assert(port 
!= IP_NULL
); 
 925                 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
 926                         bits 
= entry
->ie_bits
; 
 927                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
); 
 928                         goto dead_name
;     /* it will release port */ 
 930                 /* port is locked and active */ 
 932                 assert(port
->ip_sorights 
> 0); 
 935                  * clear any reply context: 
 936                  * no one will be sending the response b/c we are destroying 
 937                  * the single, outstanding send once right. 
 939                 port
->ip_reply_context 
= 0; 
 941                 request 
= ipc_right_request_cancel_macro(space
, port
, name
, entry
); 
 944                 entry
->ie_object 
= IO_NULL
; 
 945                 ipc_entry_dealloc(space
, name
, entry
); 
 947                 is_write_unlock(space
); 
 949                 ipc_notify_send_once(port
); 
 951                 if (request 
!= IP_NULL
) { 
 952                         ipc_notify_port_deleted(request
, name
); 
 957         case MACH_PORT_TYPE_SEND
: { 
 958                 ipc_port_t request 
= IP_NULL
; 
 959                 ipc_port_t nsrequest 
= IP_NULL
; 
 960                 mach_port_mscount_t mscount 
=  0; 
 963                 assert(IE_BITS_UREFS(bits
) > 0); 
 965                 port 
= ip_object_to_port(entry
->ie_object
); 
 966                 assert(port 
!= IP_NULL
); 
 968                 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
 969                         bits 
= entry
->ie_bits
; 
 970                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
); 
 971                         goto dead_name
;     /* it will release port */ 
 973                 /* port is locked and active */ 
 975                 assert(port
->ip_srights 
> 0); 
 977                 if (IE_BITS_UREFS(bits
) == 1) { 
 978                         if (pinned_control_port_enabled 
&& port
->ip_pinned 
!= 0) { 
 980                                 is_write_unlock(space
); 
 981                                 mach_port_guard_exception(name
, 0, MPG_FLAGS_MOD_REFS_PINNED_DEALLOC
, 
 982                                     ipc_control_port_options 
& IPC_CONTROL_PORT_OPTIONS_PINNED_HARD 
? 
 983                                     kGUARD_EXC_MOD_REFS 
: kGUARD_EXC_MOD_REFS_NON_FATAL
); 
 984                                 return KERN_INVALID_CAPABILITY
; 
 986                         if (--port
->ip_srights 
== 0) { 
 987                                 nsrequest 
= port
->ip_nsrequest
; 
 988                                 if (nsrequest 
!= IP_NULL
) { 
 989                                         port
->ip_nsrequest 
= IP_NULL
; 
 990                                         mscount 
= port
->ip_mscount
; 
 994                         request 
= ipc_right_request_cancel_macro(space
, port
, 
 996                         ipc_hash_delete(space
, ip_to_object(port
), name
, entry
); 
 999                         entry
->ie_object 
= IO_NULL
; 
1000                         ipc_entry_dealloc(space
, name
, entry
); 
1001                         is_write_unlock(space
); 
1005                         /* if urefs are pegged due to overflow, leave them pegged */ 
1006                         if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
1007                                 entry
->ie_bits 
= bits 
- 1; /* decrement urefs */ 
1009                         ipc_entry_modified(space
, name
, entry
); 
1010                         is_write_unlock(space
); 
1013                 if (nsrequest 
!= IP_NULL
) { 
1014                         ipc_notify_no_senders(nsrequest
, mscount
); 
1017                 if (request 
!= IP_NULL
) { 
1018                         ipc_notify_port_deleted(request
, name
); 
1023         case MACH_PORT_TYPE_SEND_RECEIVE
: { 
1024                 ipc_port_t nsrequest 
= IP_NULL
; 
1025                 mach_port_mscount_t mscount 
= 0; 
1027                 assert(IE_BITS_UREFS(bits
) > 0); 
1029                 port 
= ip_object_to_port(entry
->ie_object
); 
1030                 assert(port 
!= IP_NULL
); 
1033                 require_ip_active(port
); 
1034                 assert(port
->ip_receiver_name 
== name
); 
1035                 assert(port
->ip_receiver 
== space
); 
1036                 assert(port
->ip_srights 
> 0); 
1038                 if (IE_BITS_UREFS(bits
) == 1) { 
1039                         if (--port
->ip_srights 
== 0) { 
1040                                 nsrequest 
= port
->ip_nsrequest
; 
1041                                 if (nsrequest 
!= IP_NULL
) { 
1042                                         port
->ip_nsrequest 
= IP_NULL
; 
1043                                         mscount 
= port
->ip_mscount
; 
1047                         entry
->ie_bits 
= bits 
& ~(IE_BITS_UREFS_MASK 
| 
1048                             MACH_PORT_TYPE_SEND
); 
1050                         /* if urefs are pegged due to overflow, leave them pegged */ 
1051                         if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
1052                                 entry
->ie_bits 
= bits 
- 1; /* decrement urefs */ 
1057                 ipc_entry_modified(space
, name
, entry
); 
1058                 is_write_unlock(space
); 
1060                 if (nsrequest 
!= IP_NULL
) { 
1061                         ipc_notify_no_senders(nsrequest
, mscount
); 
1067                 is_write_unlock(space
); 
1068                 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1069                 return KERN_INVALID_RIGHT
; 
1072         return KERN_SUCCESS
; 
1076  *      Routine:        ipc_right_delta 
1078  *              Modifies the user-reference count for a right. 
1079  *              May deallocate the right, if the count goes to zero. 
1081  *              The space is write-locked, and is unlocked upon return. 
1082  *              The space must be active. 
1084  *              KERN_SUCCESS            Count was modified. 
1085  *              KERN_INVALID_RIGHT      Entry has wrong type. 
1086  *              KERN_INVALID_VALUE      Bad delta for the right. 
1087  *              KERN_INVALID_CAPABILITY Deallocating a pinned right. 
1093         mach_port_name_t        name
, 
1095         mach_port_right_t       right
, 
1096         mach_port_delta_t       delta
) 
1098         ipc_port_t port 
= IP_NULL
; 
1099         ipc_entry_bits_t bits
; 
1101         bits 
= entry
->ie_bits
; 
1104  *      The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the 
1105  *      switch below. It is used to keep track of those cases (in DIPC) 
1106  *      where we have postponed the dropping of a port reference. Since 
1107  *      the dropping of the reference could cause the port to disappear 
1108  *      we postpone doing so when we are holding the space lock. 
1111         assert(is_active(space
)); 
1112         assert(right 
< MACH_PORT_RIGHT_NUMBER
); 
1114         /* Rights-specific restrictions and operations. */ 
1117         case MACH_PORT_RIGHT_PORT_SET
: { 
1120                 if ((bits 
& MACH_PORT_TYPE_PORT_SET
) == 0) { 
1121                         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1125                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
); 
1126                 assert(IE_BITS_UREFS(bits
) == 0); 
1127                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
1137                 pset 
= ips_object_to_pset(entry
->ie_object
); 
1138                 assert(pset 
!= IPS_NULL
); 
1140                 entry
->ie_object 
= IO_NULL
; 
1141                 ipc_entry_dealloc(space
, name
, entry
); 
1144                 assert(ips_active(pset
)); 
1145                 is_write_unlock(space
); 
1147                 ipc_pset_destroy(space
, pset
); /* consumes ref, unlocks */ 
1151         case MACH_PORT_RIGHT_RECEIVE
: { 
1152                 ipc_port_t request 
= IP_NULL
; 
1154                 if ((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) { 
1155                         if ((bits 
& MACH_PORT_TYPE_EX_RECEIVE
) == 0) { 
1156                                 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1169                 port 
= ip_object_to_port(entry
->ie_object
); 
1170                 assert(port 
!= IP_NULL
); 
1173                  *      The port lock is needed for ipc_right_dncancel; 
1174                  *      otherwise, we wouldn't have to take the lock 
1175                  *      until just before dropping the space lock. 
1179                 require_ip_active(port
); 
1180                 assert(port
->ip_receiver_name 
== name
); 
1181                 assert(port
->ip_receiver 
== space
); 
1183                 /* Mach Port Guard Checking */ 
1184                 if (port
->ip_guarded
) { 
1185                         uint64_t portguard 
= port
->ip_context
; 
1187                         is_write_unlock(space
); 
1188                         /* Raise mach port guard exception */ 
1189                         mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_MOD_REFS
); 
1193                 if (bits 
& MACH_PORT_TYPE_SEND
) { 
1194                         assert(IE_BITS_TYPE(bits
) == 
1195                             MACH_PORT_TYPE_SEND_RECEIVE
); 
1196                         assert(IE_BITS_UREFS(bits
) > 0); 
1197                         assert(port
->ip_srights 
> 0); 
1199                         if (port
->ip_pdrequest 
!= NULL
) { 
1201                                  * Since another task has requested a 
1202                                  * destroy notification for this port, it 
1203                                  * isn't actually being destroyed - the receive 
1204                                  * right is just being moved to another task. 
1205                                  * Since we still have one or more send rights, 
1206                                  * we need to record the loss of the receive 
1207                                  * right and enter the remaining send right 
1208                                  * into the hash table. 
1210                                 ipc_entry_modified(space
, name
, entry
); 
1211                                 entry
->ie_bits 
&= ~MACH_PORT_TYPE_RECEIVE
; 
1212                                 entry
->ie_bits 
|= MACH_PORT_TYPE_EX_RECEIVE
; 
1213                                 ipc_hash_insert(space
, ip_to_object(port
), 
1218                                  *      The remaining send right turns into a 
1219                                  *      dead name.  Notice we don't decrement 
1220                                  *      ip_srights, generate a no-senders notif, 
1221                                  *      or use ipc_right_dncancel, because the 
1222                                  *      port is destroyed "first". 
1224                                 bits 
&= ~IE_BITS_TYPE_MASK
; 
1225                                 bits 
|= (MACH_PORT_TYPE_DEAD_NAME 
| MACH_PORT_TYPE_EX_RECEIVE
); 
1226                                 if (entry
->ie_request
) { 
1227                                         entry
->ie_request 
= IE_REQ_NONE
; 
1228                                         /* if urefs are pegged due to overflow, leave them pegged */ 
1229                                         if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
1230                                                 bits
++; /* increment urefs */ 
1233                                 entry
->ie_bits 
= bits
; 
1234                                 entry
->ie_object 
= IO_NULL
; 
1235                                 ipc_entry_modified(space
, name
, entry
); 
1238                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
); 
1239                         assert(IE_BITS_UREFS(bits
) == 0); 
1241                         request 
= ipc_right_request_cancel_macro(space
, port
, 
1243                         entry
->ie_object 
= IO_NULL
; 
1244                         ipc_entry_dealloc(space
, name
, entry
); 
1246                 is_write_unlock(space
); 
1248                 ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */ 
1250                 if (request 
!= IP_NULL
) { 
1251                         ipc_notify_port_deleted(request
, name
); 
1256         case MACH_PORT_RIGHT_SEND_ONCE
: { 
1259                 if ((bits 
& MACH_PORT_TYPE_SEND_ONCE
) == 0) { 
1263                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
); 
1264                 assert(IE_BITS_UREFS(bits
) == 1); 
1266                 port 
= ip_object_to_port(entry
->ie_object
); 
1267                 assert(port 
!= IP_NULL
); 
1269                 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
1270                         assert(!(entry
->ie_bits 
& MACH_PORT_TYPE_SEND_ONCE
)); 
1271                         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1274                 /* port is locked and active */ 
1276                 assert(port
->ip_sorights 
> 0); 
1278                 if ((delta 
> 0) || (delta 
< -1)) { 
1289                  * clear any reply context: 
1290                  * no one will be sending the response b/c we are destroying 
1291                  * the single, outstanding send once right. 
1293                 port
->ip_reply_context 
= 0; 
1295                 request 
= ipc_right_request_cancel_macro(space
, port
, name
, entry
); 
1298                 entry
->ie_object 
= IO_NULL
; 
1299                 ipc_entry_dealloc(space
, name
, entry
); 
1301                 is_write_unlock(space
); 
1303                 ipc_notify_send_once(port
); 
1305                 if (request 
!= IP_NULL
) { 
1306                         ipc_notify_port_deleted(request
, name
); 
1311         case MACH_PORT_RIGHT_DEAD_NAME
: { 
1312                 ipc_port_t relport 
= IP_NULL
; 
1313                 mach_port_urefs_t urefs
; 
1315                 if (bits 
& MACH_PORT_TYPE_SEND_RIGHTS
) { 
1316                         port 
= ip_object_to_port(entry
->ie_object
); 
1317                         assert(port 
!= IP_NULL
); 
1319                         if (!ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
1320                                 /* port is locked and active */ 
1323                                 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1326                         bits 
= entry
->ie_bits
; 
1329                 } else if ((bits 
& MACH_PORT_TYPE_DEAD_NAME
) == 0) { 
1330                         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1334                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
); 
1335                 assert(IE_BITS_UREFS(bits
) > 0); 
1336                 assert(entry
->ie_object 
== IO_NULL
); 
1337                 assert(entry
->ie_request 
== IE_REQ_NONE
); 
1339                 if (delta 
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) || 
1340                     delta 
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) { 
1344                 urefs 
= IE_BITS_UREFS(bits
); 
1346                 if (urefs 
== MACH_PORT_UREFS_MAX
) { 
1348                          * urefs are pegged due to an overflow 
1349                          * only a delta removing all refs at once can change it 
1352                         if (delta 
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) { 
1356                         if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) { 
1359                         if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) { 
1360                                 /* leave urefs pegged to maximum if it overflowed */ 
1361                                 delta 
= MACH_PORT_UREFS_MAX 
- urefs
; 
1365                 if ((urefs 
+ delta
) == 0) { 
1366                         ipc_entry_dealloc(space
, name
, entry
); 
1367                 } else if (delta 
!= 0) { 
1368                         entry
->ie_bits 
= bits 
+ delta
; 
1369                         ipc_entry_modified(space
, name
, entry
); 
1372                 is_write_unlock(space
); 
1374                 if (relport 
!= IP_NULL
) { 
1375                         ip_release(relport
); 
1381         case MACH_PORT_RIGHT_SEND
: { 
1382                 mach_port_urefs_t urefs
; 
1383                 ipc_port_t request 
= IP_NULL
; 
1384                 ipc_port_t nsrequest 
= IP_NULL
; 
1385                 ipc_port_t port_to_release 
= IP_NULL
; 
1386                 mach_port_mscount_t mscount 
= 0; 
1388                 if ((bits 
& MACH_PORT_TYPE_SEND
) == 0) { 
1389                         /* invalid right exception only when not live/dead confusion */ 
1390                         if ((bits 
& MACH_PORT_TYPE_DEAD_NAME
) == 0 
1391 #if !defined(AE_MAKESENDRIGHT_FIXED) 
1393                              * AE tries to add single send right without knowing if it already owns one. 
1394                              * But if it doesn't, it should own the receive right and delta should be 1. 
1396                             && (((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) || (delta 
!= 1)) 
1399                                 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1404                 /* maximum urefs for send is MACH_PORT_UREFS_MAX */ 
1406                 port 
= ip_object_to_port(entry
->ie_object
); 
1407                 assert(port 
!= IP_NULL
); 
1409                 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
1410                         assert((entry
->ie_bits 
& MACH_PORT_TYPE_SEND
) == 0); 
1413                 /* port is locked and active */ 
1415                 assert(port
->ip_srights 
> 0); 
1417                 if (delta 
> ((mach_port_delta_t
)MACH_PORT_UREFS_MAX
) || 
1418                     delta 
< (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) { 
1423                 urefs 
= IE_BITS_UREFS(bits
); 
1425                 if (urefs 
== MACH_PORT_UREFS_MAX
) { 
1427                          * urefs are pegged due to an overflow 
1428                          * only a delta removing all refs at once can change it 
1431                         if (delta 
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) { 
1435                         if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) { 
1439                         if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
)) { 
1440                                 /* leave urefs pegged to maximum if it overflowed */ 
1441                                 delta 
= MACH_PORT_UREFS_MAX 
- urefs
; 
1445                 if ((urefs 
+ delta
) == 0) { 
1446                         if (pinned_control_port_enabled 
&& port
->ip_pinned 
!= 0) { 
1451                         if (--port
->ip_srights 
== 0) { 
1452                                 nsrequest 
= port
->ip_nsrequest
; 
1453                                 if (nsrequest 
!= IP_NULL
) { 
1454                                         port
->ip_nsrequest 
= IP_NULL
; 
1455                                         mscount 
= port
->ip_mscount
; 
1459                         if (bits 
& MACH_PORT_TYPE_RECEIVE
) { 
1460                                 assert(port
->ip_receiver_name 
== name
); 
1461                                 assert(port
->ip_receiver 
== space
); 
1463                                 assert(IE_BITS_TYPE(bits
) == 
1464                                     MACH_PORT_TYPE_SEND_RECEIVE
); 
1466                                 entry
->ie_bits 
= bits 
& ~(IE_BITS_UREFS_MASK 
| 
1467                                     MACH_PORT_TYPE_SEND
); 
1468                                 ipc_entry_modified(space
, name
, entry
); 
1470                                 assert(IE_BITS_TYPE(bits
) == 
1471                                     MACH_PORT_TYPE_SEND
); 
1473                                 request 
= ipc_right_request_cancel_macro(space
, port
, 
1475                                 ipc_hash_delete(space
, ip_to_object(port
), 
1479                                 port_to_release 
= port
; 
1481                                 entry
->ie_object 
= IO_NULL
; 
1482                                 ipc_entry_dealloc(space
, name
, entry
); 
1484                 } else if (delta 
!= 0) { 
1486                         entry
->ie_bits 
= bits 
+ delta
; 
1487                         ipc_entry_modified(space
, name
, entry
); 
1492                 is_write_unlock(space
); 
1494                 if (port_to_release 
!= IP_NULL
) { 
1495                         ip_release(port_to_release
); 
1498                 if (nsrequest 
!= IP_NULL
) { 
1499                         ipc_notify_no_senders(nsrequest
, mscount
); 
1502                 if (request 
!= IP_NULL
) { 
1503                         ipc_notify_port_deleted(request
, name
); 
1508         case MACH_PORT_RIGHT_LABELH
: 
1512                 panic("ipc_right_delta: strange right %d for 0x%x (%p) in space:%p", 
1513                     right
, name
, (void *)entry
, (void *)space
); 
1516         return KERN_SUCCESS
; 
1519         is_write_unlock(space
); 
1520         return KERN_SUCCESS
; 
1523         is_write_unlock(space
); 
1524         if (port 
!= IP_NULL
) { 
1527         return KERN_INVALID_RIGHT
; 
1530         assert(pinned_control_port_enabled
); 
1532         is_write_unlock(space
); 
1533         mach_port_guard_exception(name
, 0, MPG_FLAGS_MOD_REFS_PINNED_DEALLOC
, 
1534             ipc_control_port_options 
& IPC_CONTROL_PORT_OPTIONS_PINNED_HARD 
? 
1535             kGUARD_EXC_MOD_REFS 
: kGUARD_EXC_MOD_REFS_NON_FATAL
); 
1536         return KERN_INVALID_CAPABILITY
; 
1539         is_write_unlock(space
); 
1540         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
); 
1541         return KERN_INVALID_VALUE
; 
1544         return KERN_INVALID_RIGHT
; 
1548  *      Routine:        ipc_right_destruct 
1550  *              Deallocates the receive right and modifies the 
1551  *              user-reference count for the send rights as requested. 
1553  *              The space is write-locked, and is unlocked upon return. 
1554  *              The space must be active. 
1556  *              KERN_SUCCESS            Count was modified. 
1557  *              KERN_INVALID_RIGHT      Entry has wrong type. 
1558  *              KERN_INVALID_VALUE      Bad delta for the right. 
1564         mach_port_name_t        name
, 
1566         mach_port_delta_t       srdelta
, 
1569         ipc_port_t port 
= IP_NULL
; 
1570         ipc_entry_bits_t bits
; 
1572         mach_port_urefs_t urefs
; 
1573         ipc_port_t request 
= IP_NULL
; 
1574         ipc_port_t nsrequest 
= IP_NULL
; 
1575         mach_port_mscount_t mscount 
= 0; 
1577         bits 
= entry
->ie_bits
; 
1579         assert(is_active(space
)); 
1581         if ((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) { 
1582                 is_write_unlock(space
); 
1584                 /* No exception if we used to have receive and held entry since */ 
1585                 if ((bits 
& MACH_PORT_TYPE_EX_RECEIVE
) == 0) { 
1586                         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1588                 return KERN_INVALID_RIGHT
; 
1591         if (srdelta 
&& (bits 
& MACH_PORT_TYPE_SEND
) == 0) { 
1592                 is_write_unlock(space
); 
1593                 mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_RIGHT
); 
1594                 return KERN_INVALID_RIGHT
; 
1601         port 
= ip_object_to_port(entry
->ie_object
); 
1602         assert(port 
!= IP_NULL
); 
1605         require_ip_active(port
); 
1606         assert(port
->ip_receiver_name 
== name
); 
1607         assert(port
->ip_receiver 
== space
); 
1609         /* Mach Port Guard Checking */ 
1610         if (port
->ip_guarded 
&& (guard 
!= port
->ip_context
)) { 
1611                 uint64_t portguard 
= port
->ip_context
; 
1613                 is_write_unlock(space
); 
1614                 mach_port_guard_exception(name
, 0, portguard
, kGUARD_EXC_DESTROY
); 
1615                 return KERN_INVALID_ARGUMENT
; 
1619          * First reduce the send rights as requested and 
1620          * adjust the entry->ie_bits accordingly. The 
1621          * ipc_entry_modified() call is made once the receive 
1622          * right is destroyed too. 
1626                 assert(port
->ip_srights 
> 0); 
1628                 urefs 
= IE_BITS_UREFS(bits
); 
1631                  * Since we made sure that srdelta is negative, 
1632                  * the check for urefs overflow is not required. 
1634                 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, srdelta
)) { 
1639                 if (urefs 
== MACH_PORT_UREFS_MAX
) { 
1641                          * urefs are pegged due to an overflow 
1642                          * only a delta removing all refs at once can change it 
1644                         if (srdelta 
!= (-((mach_port_delta_t
)MACH_PORT_UREFS_MAX
))) { 
1649                 if ((urefs 
+ srdelta
) == 0) { 
1650                         if (--port
->ip_srights 
== 0) { 
1651                                 nsrequest 
= port
->ip_nsrequest
; 
1652                                 if (nsrequest 
!= IP_NULL
) { 
1653                                         port
->ip_nsrequest 
= IP_NULL
; 
1654                                         mscount 
= port
->ip_mscount
; 
1657                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_RECEIVE
); 
1658                         entry
->ie_bits 
= bits 
& ~(IE_BITS_UREFS_MASK 
| 
1659                             MACH_PORT_TYPE_SEND
); 
1661                         entry
->ie_bits 
= bits 
+ srdelta
; 
1666          * Now destroy the receive right. Update space and 
1667          * entry accordingly. 
1670         bits 
= entry
->ie_bits
; 
1671         if (bits 
& MACH_PORT_TYPE_SEND
) { 
1672                 assert(IE_BITS_UREFS(bits
) > 0); 
1673                 assert(IE_BITS_UREFS(bits
) <= MACH_PORT_UREFS_MAX
); 
1675                 if (port
->ip_pdrequest 
!= NULL
) { 
1677                          * Since another task has requested a 
1678                          * destroy notification for this port, it 
1679                          * isn't actually being destroyed - the receive 
1680                          * right is just being moved to another task. 
1681                          * Since we still have one or more send rights, 
1682                          * we need to record the loss of the receive 
1683                          * right and enter the remaining send right 
1684                          * into the hash table. 
1686                         ipc_entry_modified(space
, name
, entry
); 
1687                         entry
->ie_bits 
&= ~MACH_PORT_TYPE_RECEIVE
; 
1688                         entry
->ie_bits 
|= MACH_PORT_TYPE_EX_RECEIVE
; 
1689                         ipc_hash_insert(space
, ip_to_object(port
), 
1694                          *      The remaining send right turns into a 
1695                          *      dead name.  Notice we don't decrement 
1696                          *      ip_srights, generate a no-senders notif, 
1697                          *      or use ipc_right_dncancel, because the 
1698                          *      port is destroyed "first". 
1700                         bits 
&= ~IE_BITS_TYPE_MASK
; 
1701                         bits 
|= (MACH_PORT_TYPE_DEAD_NAME 
| MACH_PORT_TYPE_EX_RECEIVE
); 
1702                         if (entry
->ie_request
) { 
1703                                 entry
->ie_request 
= IE_REQ_NONE
; 
1704                                 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
1705                                         bits
++; /* increment urefs */ 
1708                         entry
->ie_bits 
= bits
; 
1709                         entry
->ie_object 
= IO_NULL
; 
1710                         ipc_entry_modified(space
, name
, entry
); 
1713                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
); 
1714                 assert(IE_BITS_UREFS(bits
) == 0); 
1715                 request 
= ipc_right_request_cancel_macro(space
, port
, 
1717                 entry
->ie_object 
= IO_NULL
; 
1718                 ipc_entry_dealloc(space
, name
, entry
); 
1722         is_write_unlock(space
); 
1724         if (nsrequest 
!= IP_NULL
) { 
1725                 ipc_notify_no_senders(nsrequest
, mscount
); 
1728         ipc_port_destroy(port
); /* clears receiver, consumes ref, unlocks */ 
1730         if (request 
!= IP_NULL
) { 
1731                 ipc_notify_port_deleted(request
, name
); 
1734         return KERN_SUCCESS
; 
1737         is_write_unlock(space
); 
1738         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_INVALID_VALUE
); 
1739         return KERN_INVALID_VALUE
; 
1744  *      Routine:        ipc_right_info 
1746  *              Retrieves information about the right. 
1748  *              The space is active and write-locked. 
1749  *              The space is unlocked upon return. 
1751  *              KERN_SUCCESS            Retrieved info 
1757         mach_port_name_t        name
, 
1759         mach_port_type_t        
*typep
, 
1760         mach_port_urefs_t       
*urefsp
) 
1763         ipc_entry_bits_t bits
; 
1764         mach_port_type_t type 
= 0; 
1765         ipc_port_request_index_t request
; 
1767         bits 
= entry
->ie_bits
; 
1768         request 
= entry
->ie_request
; 
1769         port 
= ip_object_to_port(entry
->ie_object
); 
1771         if (bits 
& MACH_PORT_TYPE_RECEIVE
) { 
1772                 assert(IP_VALID(port
)); 
1774                 if (request 
!= IE_REQ_NONE
) { 
1776                         require_ip_active(port
); 
1777                         type 
|= ipc_port_request_type(port
, name
, request
); 
1780                 is_write_unlock(space
); 
1781         } else if (bits 
& MACH_PORT_TYPE_SEND_RIGHTS
) { 
1783                  * validate port is still alive - if so, get request 
1784                  * types while we still have it locked.  Otherwise, 
1785                  * recapture the (now dead) bits. 
1787                 if (!ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
1788                         if (request 
!= IE_REQ_NONE
) { 
1789                                 type 
|= ipc_port_request_type(port
, name
, request
); 
1792                         is_write_unlock(space
); 
1794                         bits 
= entry
->ie_bits
; 
1795                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
); 
1796                         is_write_unlock(space
); 
1800                 is_write_unlock(space
); 
1803         type 
|= IE_BITS_TYPE(bits
); 
1806         *urefsp 
= IE_BITS_UREFS(bits
); 
1807         return KERN_SUCCESS
; 
1811  *      Routine:        ipc_right_copyin_check_reply 
1813  *              Check if a subsequent ipc_right_copyin would succeed. Used only 
1814  *              by ipc_kmsg_copyin_header to check if reply_port can be copied in. 
1815  *              If the reply port is an immovable send right, it errors out. 
1817  *              The space is locked (read or write) and active. 
1821 ipc_right_copyin_check_reply( 
1822         __assert_only ipc_space_t       space
, 
1823         mach_port_name_t                reply_name
, 
1824         ipc_entry_t                     reply_entry
, 
1825         mach_msg_type_name_t            reply_type
) 
1827         ipc_entry_bits_t bits
; 
1828         ipc_port_t reply_port
; 
1830         bits 
= reply_entry
->ie_bits
; 
1831         assert(is_active(space
)); 
1833         switch (reply_type
) { 
1834         case MACH_MSG_TYPE_MAKE_SEND
: 
1835                 if ((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) { 
1840         case MACH_MSG_TYPE_MAKE_SEND_ONCE
: 
1841                 if ((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) { 
1846         case MACH_MSG_TYPE_MOVE_RECEIVE
: 
1847                 /* ipc_kmsg_copyin_header already filters it out */ 
1850         case MACH_MSG_TYPE_COPY_SEND
: 
1851         case MACH_MSG_TYPE_MOVE_SEND
: 
1852         case MACH_MSG_TYPE_MOVE_SEND_ONCE
: { 
1853                 if (bits 
& MACH_PORT_TYPE_DEAD_NAME
) { 
1857                 if ((bits 
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) { 
1861                 reply_port 
= ip_object_to_port(reply_entry
->ie_object
); 
1862                 assert(reply_port 
!= IP_NULL
); 
1865                  * active status peek to avoid checks that will be skipped 
1866                  * on copyin for dead ports.  Lock not held, so will not be 
1867                  * atomic (but once dead, there's no going back). 
1869                 if (!ip_active(reply_port
)) { 
1874                  * Can't copyin a send right that is marked immovable. This bit 
1875                  * is set only during port creation and never unset. So it can 
1876                  * be read without a lock. 
1878                 if (reply_port
->ip_immovable_send
) { 
1879                         if (!ip_is_control(reply_port
) || immovable_control_port_enabled
) { 
1880                                 mach_port_guard_exception_immovable(reply_name
, reply_port
, MPG_FLAGS_NONE
); 
1885                 if (reply_type 
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) { 
1886                         if ((bits 
& MACH_PORT_TYPE_SEND_ONCE
) == 0) { 
1890                         if ((bits 
& MACH_PORT_TYPE_SEND
) == 0) { 
1899                 panic("ipc_right_copyin_check: strange rights"); 
1906  *      Routine:        ipc_right_copyin_check_guard_locked 
1908  *              Check if the port is guarded and the guard 
1909  *              value matches the one passed in the arguments. 
1910  *              If MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND is set, 
1911  *              check if the port is unguarded. 
1913  *              The port is locked. 
1915  *              KERN_SUCCESS            Port is either unguarded 
1916  *                                      or guarded with expected value 
1917  *              KERN_INVALID_ARGUMENT   Port is either unguarded already or guard mismatch. 
1918  *                                      This also raises a EXC_GUARD exception. 
1920 static kern_return_t
 
1921 ipc_right_copyin_check_guard_locked( 
1922         mach_port_name_t name
, 
1924         mach_port_context_t context
, 
1925         mach_msg_guard_flags_t 
*guard_flags
) 
1927         mach_msg_guard_flags_t flags 
= *guard_flags
; 
1928         if ((flags 
& MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
) && !port
->ip_guarded 
&& !context
) { 
1929                 return KERN_SUCCESS
; 
1930         } else if (port
->ip_guarded 
&& (port
->ip_context 
== context
)) { 
1931                 return KERN_SUCCESS
; 
1934         /* Incorrect guard; Raise exception */ 
1935         mach_port_guard_exception(name
, context
, port
->ip_context
, kGUARD_EXC_INCORRECT_GUARD
); 
1936         return KERN_INVALID_ARGUMENT
; 
1940  *      Routine:        ipc_right_copyin 
1942  *              Copyin a capability from a space. 
1943  *              If successful, the caller gets a ref 
1944  *              for the resulting object, unless it is IO_DEAD, 
1945  *              and possibly a send-once right which should 
1946  *              be used in a port-deleted notification. 
1948  *              If deadok is not TRUE, the copyin operation 
1949  *              will fail instead of producing IO_DEAD. 
1951  *              The entry is never deallocated (except 
1952  *              when KERN_INVALID_NAME), so the caller 
1953  *              should deallocate the entry if its type 
1954  *              is MACH_PORT_TYPE_NONE. 
1956  *              The space is write-locked and active. 
1958  *              KERN_SUCCESS            Acquired an object, possibly IO_DEAD. 
1959  *              KERN_INVALID_RIGHT      Name doesn't denote correct right. 
1960  *              KERN_INVALID_CAPABILITY Trying to move an kobject port or an immovable right, 
1961  *                                                              or moving the last ref of pinned right 
1962  *              KERN_INVALID_ARGUMENT   Port is unguarded or guard mismatch 
1968         mach_port_name_t           name
, 
1970         mach_msg_type_name_t       msgt_name
, 
1971         ipc_object_copyin_flags_t   flags
, 
1972         ipc_object_t               
*objectp
, 
1973         ipc_port_t                 
*sorightp
, 
1974         ipc_port_t                 
*releasep
, 
1976         mach_port_context_t        context
, 
1977         mach_msg_guard_flags_t     
*guard_flags
) 
1979         ipc_entry_bits_t bits
; 
1982         boolean_t deadok 
= !!(flags 
& IPC_OBJECT_COPYIN_FLAGS_DEADOK
); 
1983         boolean_t allow_imm_send 
= !!(flags 
& IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
); 
1984         boolean_t soft_fail_imm_send 
= !!(flags 
& IPC_OBJECT_COPYIN_FLAGS_SOFT_FAIL_IMMOVABLE_SEND
); 
1986         *releasep 
= IP_NULL
; 
1989         bits 
= entry
->ie_bits
; 
1991         assert(is_active(space
)); 
1993         switch (msgt_name
) { 
1994         case MACH_MSG_TYPE_MAKE_SEND
: { 
1995                 if ((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) { 
1999                 port 
= ip_object_to_port(entry
->ie_object
); 
2000                 assert(port 
!= IP_NULL
); 
2003                 assert(port
->ip_receiver_name 
== name
); 
2004                 assert(port
->ip_receiver 
== space
); 
2006                 ipc_port_make_send_locked(port
); 
2009                 *objectp 
= ip_to_object(port
); 
2010                 *sorightp 
= IP_NULL
; 
2014         case MACH_MSG_TYPE_MAKE_SEND_ONCE
: { 
2015                 if ((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) { 
2019                 port 
= ip_object_to_port(entry
->ie_object
); 
2020                 assert(port 
!= IP_NULL
); 
2023                 require_ip_active(port
); 
2024                 assert(port
->ip_receiver_name 
== name
); 
2025                 assert(port
->ip_receiver 
== space
); 
2027                 ipc_port_make_sonce_locked(port
); 
2030                 *objectp 
= ip_to_object(port
); 
2031                 *sorightp 
= IP_NULL
; 
2035         case MACH_MSG_TYPE_MOVE_RECEIVE
: { 
2036                 ipc_port_t request 
= IP_NULL
; 
2038                 if ((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0) { 
2043                  * Disallow moving receive-right kobjects/kolabel, e.g. mk_timer ports 
2044                  * The ipc_port structure uses the kdata union of kobject and 
2045                  * imp_task exclusively. Thus, general use of a kobject port as 
2046                  * a receive right can cause type confusion in the importance 
2049                 if (io_is_kobject(entry
->ie_object
) || 
2050                     io_is_kolabeled(entry
->ie_object
)) { 
2052                          * Distinguish an invalid right, e.g., trying to move 
2053                          * a send right as a receive right, from this 
2054                          * situation which is, "This is a valid receive right, 
2055                          * but it's also a kobject and you can't move it." 
2057                         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
); 
2058                         return KERN_INVALID_CAPABILITY
; 
2061                 port 
= ip_object_to_port(entry
->ie_object
); 
2062                 assert(port 
!= IP_NULL
); 
2065                 require_ip_active(port
); 
2066                 assert(port
->ip_receiver_name 
== name
); 
2067                 assert(port
->ip_receiver 
== space
); 
2069                 if (port
->ip_immovable_receive 
|| port
->ip_specialreply
) { 
2070                         assert(port
->ip_receiver 
!= ipc_space_kernel
); 
2072                         assert(current_task() != kernel_task
); 
2073                         mach_port_guard_exception(name
, 0, 0, kGUARD_EXC_IMMOVABLE
); 
2074                         return KERN_INVALID_CAPABILITY
; 
2077                 if (guard_flags 
!= NULL
) { 
2078                         kr 
= ipc_right_copyin_check_guard_locked(name
, port
, context
, guard_flags
); 
2079                         if (kr 
!= KERN_SUCCESS
) { 
2085                 if (bits 
& MACH_PORT_TYPE_SEND
) { 
2086                         assert(IE_BITS_TYPE(bits
) == 
2087                             MACH_PORT_TYPE_SEND_RECEIVE
); 
2088                         assert(IE_BITS_UREFS(bits
) > 0); 
2089                         assert(port
->ip_srights 
> 0); 
2091                         ipc_hash_insert(space
, ip_to_object(port
), 
2095                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
); 
2096                         assert(IE_BITS_UREFS(bits
) == 0); 
2098                         request 
= ipc_right_request_cancel_macro(space
, port
, 
2100                         entry
->ie_object 
= IO_NULL
; 
2102                 entry
->ie_bits 
= bits 
& ~MACH_PORT_TYPE_RECEIVE
; 
2103                 entry
->ie_bits 
|= MACH_PORT_TYPE_EX_RECEIVE
; 
2104                 ipc_entry_modified(space
, name
, entry
); 
2106                 /* ipc_port_clear_receiver unguards the port and clears the ip_immovable_receive bit */ 
2107                 (void)ipc_port_clear_receiver(port
, FALSE
); /* don't destroy the port/mqueue */ 
2108                 if (guard_flags 
!= NULL
) { 
2109                         /* this flag will be cleared during copyout */ 
2110                         *guard_flags 
= *guard_flags 
| MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
; 
2113 #if IMPORTANCE_INHERITANCE 
2115                  * Account for boosts the current task is going to lose when 
2116                  * copying this right in.  Tempowner ports have either not 
2117                  * been accounting to any task (and therefore are already in 
2118                  * "limbo" state w.r.t. assertions) or to some other specific 
2119                  * task. As we have no way to drop the latter task's assertions 
2120                  * here, We'll deduct those when we enqueue it on its 
2121                  * destination port (see ipc_port_check_circularity()). 
2123                 if (port
->ip_tempowner 
== 0) { 
2124                         assert(IIT_NULL 
== port
->ip_imp_task
); 
2126                         /* ports in limbo have to be tempowner */ 
2127                         port
->ip_tempowner 
= 1; 
2128                         *assertcntp 
= port
->ip_impcount
; 
2130 #endif /* IMPORTANCE_INHERITANCE */ 
2134                 *objectp 
= ip_to_object(port
); 
2135                 *sorightp 
= request
; 
2139         case MACH_MSG_TYPE_COPY_SEND
: { 
2140                 if (bits 
& MACH_PORT_TYPE_DEAD_NAME
) { 
2144                 /* allow for dead send-once rights */ 
2146                 if ((bits 
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) { 
2150                 assert(IE_BITS_UREFS(bits
) > 0); 
2152                 port 
= ip_object_to_port(entry
->ie_object
); 
2153                 assert(port 
!= IP_NULL
); 
2155                 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
2156                         bits 
= entry
->ie_bits
; 
2160                 /* port is locked and active */ 
2162                 if ((bits 
& MACH_PORT_TYPE_SEND
) == 0) { 
2163                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
); 
2164                         assert(port
->ip_sorights 
> 0); 
2170                 if (!allow_imm_send 
&& port
->ip_immovable_send
) { 
2171                         if (!ip_is_control(port
) || immovable_control_port_enabled
) { 
2173                                 if (!soft_fail_imm_send
) { 
2174                                         mach_port_guard_exception_immovable(name
, port
, MPG_FLAGS_NONE
); 
2176                                 return KERN_INVALID_CAPABILITY
; 
2180                 ipc_port_copy_send_locked(port
); 
2183                 *objectp 
= ip_to_object(port
); 
2184                 *sorightp 
= IP_NULL
; 
2188         case MACH_MSG_TYPE_MOVE_SEND
: { 
2189                 ipc_port_t request 
= IP_NULL
; 
2191                 if (bits 
& MACH_PORT_TYPE_DEAD_NAME
) { 
2195                 /* allow for dead send-once rights */ 
2197                 if ((bits 
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) { 
2201                 assert(IE_BITS_UREFS(bits
) > 0); 
2203                 port 
= ip_object_to_port(entry
->ie_object
); 
2204                 assert(port 
!= IP_NULL
); 
2206                 if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
2207                         bits 
= entry
->ie_bits
; 
2211                 /* port is locked and active */ 
2213                 if ((bits 
& MACH_PORT_TYPE_SEND
) == 0) { 
2214                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
); 
2215                         assert(port
->ip_sorights 
> 0); 
2220                 if (!allow_imm_send 
&& port
->ip_immovable_send
) { 
2221                         if (!ip_is_control(port
) || immovable_control_port_enabled
) { 
2223                                 if (!soft_fail_imm_send
) { 
2224                                         mach_port_guard_exception_immovable(name
, port
, MPG_FLAGS_NONE
); 
2226                                 return KERN_INVALID_CAPABILITY
; 
2230                 if (IE_BITS_UREFS(bits
) == 1) { 
2231                         assert(port
->ip_srights 
> 0); 
2232                         if (bits 
& MACH_PORT_TYPE_RECEIVE
) { 
2233                                 assert(port
->ip_receiver_name 
== name
); 
2234                                 assert(port
->ip_receiver 
== space
); 
2235                                 assert(IE_BITS_TYPE(bits
) == 
2236                                     MACH_PORT_TYPE_SEND_RECEIVE
); 
2237                                 assert(port
->ip_pinned 
== 0); 
2241                                 assert(IE_BITS_TYPE(bits
) == 
2242                                     MACH_PORT_TYPE_SEND
); 
2244                                 request 
= ipc_right_request_cancel_macro(space
, port
, 
2246                                 ipc_hash_delete(space
, ip_to_object(port
), 
2248                                 entry
->ie_object 
= IO_NULL
; 
2249                                 /* transfer entry's reference to caller */ 
2251                         entry
->ie_bits 
= bits 
& ~ 
2252                             (IE_BITS_UREFS_MASK 
| MACH_PORT_TYPE_SEND
); 
2254                         ipc_port_copy_send_locked(port
); 
2255                         /* if urefs are pegged due to overflow, leave them pegged */ 
2256                         if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
2257                                 entry
->ie_bits 
= bits 
- 1; /* decrement urefs */ 
2261                 ipc_entry_modified(space
, name
, entry
); 
2264                 *objectp 
= ip_to_object(port
); 
2265                 *sorightp 
= request
; 
2269         case MACH_MSG_TYPE_MOVE_SEND_ONCE
: { 
2272                 if (bits 
& MACH_PORT_TYPE_DEAD_NAME
) { 
2276                 /* allow for dead send rights */ 
2278                 if ((bits 
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0) { 
2282                 assert(IE_BITS_UREFS(bits
) > 0); 
2284                 port 
= ip_object_to_port(entry
->ie_object
); 
2285                 assert(port 
!= IP_NULL
); 
2287                 if (ipc_right_check(space
, port
, name
, entry
, flags
)) { 
2288                         bits 
= entry
->ie_bits
; 
2293                  * port is locked, but may not be active: 
2294                  * Allow copyin of inactive ports with no dead name request and treat it 
2295                  * as if the copyin of the port was successful and port became inactive 
2299                 if ((bits 
& MACH_PORT_TYPE_SEND_ONCE
) == 0) { 
2300                         assert(bits 
& MACH_PORT_TYPE_SEND
); 
2301                         assert(port
->ip_srights 
> 0); 
2307                 if (!allow_imm_send 
&& port
->ip_immovable_send
) { 
2308                         if (!ip_is_control(port
) || immovable_control_port_enabled
) { 
2310                                 if (!soft_fail_imm_send
) { 
2311                                         mach_port_guard_exception_immovable(name
, port
, MPG_FLAGS_NONE
); 
2313                                 return KERN_INVALID_CAPABILITY
; 
2317                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
); 
2318                 assert(IE_BITS_UREFS(bits
) == 1); 
2319                 assert(port
->ip_sorights 
> 0); 
2321                 request 
= ipc_right_request_cancel_macro(space
, port
, name
, entry
); 
2324                 entry
->ie_object 
= IO_NULL
; 
2325                 entry
->ie_bits 
= bits 
& ~ 
2326                     (IE_BITS_UREFS_MASK 
| MACH_PORT_TYPE_SEND_ONCE
); 
2327                 ipc_entry_modified(space
, name
, entry
); 
2328                 *objectp 
= ip_to_object(port
); 
2329                 *sorightp 
= request
; 
2335                 return KERN_INVALID_RIGHT
; 
2338         return KERN_SUCCESS
; 
2341         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
); 
2342         assert(IE_BITS_UREFS(bits
) > 0); 
2343         assert(entry
->ie_request 
== IE_REQ_NONE
); 
2344         assert(entry
->ie_object 
== 0); 
2351         *sorightp 
= IP_NULL
; 
2352         return KERN_SUCCESS
; 
2355         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
); 
2356         assert(IE_BITS_UREFS(bits
) > 0); 
2357         assert(entry
->ie_request 
== IE_REQ_NONE
); 
2358         assert(entry
->ie_object 
== 0); 
2364         if (IE_BITS_UREFS(bits
) == 1) { 
2365                 bits 
&= ~MACH_PORT_TYPE_DEAD_NAME
; 
2367         /* if urefs are pegged due to overflow, leave them pegged */ 
2368         if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
2369                 entry
->ie_bits 
= bits 
- 1; /* decrement urefs */ 
2371         ipc_entry_modified(space
, name
, entry
); 
2373         *sorightp 
= IP_NULL
; 
2374         return KERN_SUCCESS
; 
2378  *      Routine:        ipc_right_copyin_two_move_sends 
2380  *              Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND 
2381  *              and deadok == FALSE, except that this moves two 
2382  *              send rights at once. 
2384  *              The space is write-locked and active. 
2385  *              The object is returned with two refs/send rights. 
2387  *              KERN_SUCCESS            Acquired an object. 
2388  *              KERN_INVALID_RIGHT      Name doesn't denote correct right. 
2392 ipc_right_copyin_two_move_sends( 
2394         mach_port_name_t        name
, 
2396         ipc_object_t            
*objectp
, 
2397         ipc_port_t              
*sorightp
, 
2398         ipc_port_t              
*releasep
) 
2400         ipc_entry_bits_t bits
; 
2401         mach_port_urefs_t urefs
; 
2403         ipc_port_t request 
= IP_NULL
; 
2405         *releasep 
= IP_NULL
; 
2407         assert(is_active(space
)); 
2409         bits 
= entry
->ie_bits
; 
2411         if ((bits 
& MACH_PORT_TYPE_SEND
) == 0) { 
2415         urefs 
= IE_BITS_UREFS(bits
); 
2420         port 
= ip_object_to_port(entry
->ie_object
); 
2421         assert(port 
!= IP_NULL
); 
2423         if (ipc_right_check(space
, port
, name
, entry
, IPC_OBJECT_COPYIN_FLAGS_NONE
)) { 
2427         /* port is locked and active */ 
2431                  * We are moving 2 urefs as naked send rights, which is decomposed as: 
2432                  * - two copy sends (which doesn't affect the make send count) 
2433                  * - decrementing the local urefs twice. 
2435                 ipc_port_copy_send_locked(port
); 
2436                 ipc_port_copy_send_locked(port
); 
2437                 /* if urefs are pegged due to overflow, leave them pegged */ 
2438                 if (IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
) { 
2439                         entry
->ie_bits 
= bits 
- 2; /* decrement urefs */ 
2443                  * We have exactly 2 send rights for this port in this space, 
2444                  * which means that we will liberate the naked send right held 
2447                  * However refcounting rules around entries are that naked send rights 
2448                  * on behalf of spaces do not have an associated port reference, 
2449                  * so we need to donate one ... 
2451                 ipc_port_copy_send_locked(port
); 
2453                 if (bits 
& MACH_PORT_TYPE_RECEIVE
) { 
2454                         assert(port
->ip_receiver_name 
== name
); 
2455                         assert(port
->ip_receiver 
== space
); 
2456                         assert(IE_BITS_TYPE(bits
) == 
2457                             MACH_PORT_TYPE_SEND_RECEIVE
); 
2459                         /* ... that we inject manually when the entry stays alive */ 
2462                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
); 
2464                         /* ... that we steal from the entry when it dies */ 
2465                         request 
= ipc_right_request_cancel_macro(space
, port
, 
2468                         ipc_hash_delete(space
, ip_to_object(port
), 
2470                         entry
->ie_object 
= IO_NULL
; 
2473                 entry
->ie_bits 
= bits 
& ~(IE_BITS_UREFS_MASK 
| MACH_PORT_TYPE_SEND
); 
2475         ipc_entry_modified(space
, name
, entry
); 
2479         *objectp 
= ip_to_object(port
); 
2480         *sorightp 
= request
; 
2481         return KERN_SUCCESS
; 
2484         return KERN_INVALID_RIGHT
; 
2489  *      Routine:        ipc_right_copyin_two 
2491  *              Like ipc_right_copyin with two dispositions, 
2492  *              each of which results in a send or send-once right, 
2493  *              and deadok = FALSE. 
2495  *              The space is write-locked and active. 
2496  *              The object is returned with two refs/rights. 
2497  *              Msgt_one refers to the dest_type 
2499  *              KERN_SUCCESS            Acquired an object. 
2500  *              KERN_INVALID_RIGHT      Name doesn't denote correct right(s). 
2501  *              KERN_INVALID_CAPABILITY Name doesn't denote correct right for msgt_two. 
2504 ipc_right_copyin_two( 
2506         mach_port_name_t          name
, 
2508         mach_msg_type_name_t      msgt_one
, 
2509         mach_msg_type_name_t      msgt_two
, 
2510         ipc_object_t              
*objectp
, 
2511         ipc_port_t                
*sorightp
, 
2512         ipc_port_t                
*releasep
) 
2517         assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one
)); 
2518         assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two
)); 
2521          *      This is a little tedious to make atomic, because 
2522          *      there are 25 combinations of valid dispositions. 
2523          *      However, most are easy. 
2527          *      If either is move-sonce, then there must be an error. 
2529         if (msgt_one 
== MACH_MSG_TYPE_MOVE_SEND_ONCE 
|| 
2530             msgt_two 
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) { 
2531                 return KERN_INVALID_RIGHT
; 
2534         if ((msgt_one 
== MACH_MSG_TYPE_MAKE_SEND
) || 
2535             (msgt_one 
== MACH_MSG_TYPE_MAKE_SEND_ONCE
) || 
2536             (msgt_two 
== MACH_MSG_TYPE_MAKE_SEND
) || 
2537             (msgt_two 
== MACH_MSG_TYPE_MAKE_SEND_ONCE
)) { 
2539                  *      One of the dispositions needs a receive right. 
2541                  *      If the copyin below succeeds, we know the receive 
2542                  *      right is there (because the pre-validation of 
2543                  *      the second disposition already succeeded in our 
2546                  *      Hence the port is not in danger of dying. 
2548                 ipc_object_t object_two
; 
2550                 kr 
= ipc_right_copyin(space
, name
, entry
, 
2551                     msgt_one
, IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
, 
2552                     objectp
, sorightp
, releasep
, 
2553                     &assertcnt
, 0, NULL
); 
2554                 assert(assertcnt 
== 0); 
2555                 if (kr 
!= KERN_SUCCESS
) { 
2559                 assert(IO_VALID(*objectp
)); 
2560                 assert(*sorightp 
== IP_NULL
); 
2561                 assert(*releasep 
== IP_NULL
); 
2564                  *      Now copyin the second (previously validated) 
2565                  *      disposition.  The result can't be a dead port, 
2566                  *      as no valid disposition can make us lose our 
2569                 kr 
= ipc_right_copyin(space
, name
, entry
, 
2570                     msgt_two
, IPC_OBJECT_COPYIN_FLAGS_NONE
, 
2571                     &object_two
, sorightp
, releasep
, 
2572                     &assertcnt
, 0, NULL
); 
2573                 assert(assertcnt 
== 0); 
2574                 assert(kr 
== KERN_SUCCESS
); 
2575                 assert(*sorightp 
== IP_NULL
); 
2576                 assert(*releasep 
== IP_NULL
); 
2577                 assert(object_two 
== *objectp
); 
2578                 assert(entry
->ie_bits 
& MACH_PORT_TYPE_RECEIVE
); 
2579         } else if ((msgt_one 
== MACH_MSG_TYPE_MOVE_SEND
) && 
2580             (msgt_two 
== MACH_MSG_TYPE_MOVE_SEND
)) { 
2582                  *      This is an easy case.  Just use our 
2583                  *      handy-dandy special-purpose copyin call 
2584                  *      to get two send rights for the price of one. 
2586                 kr 
= ipc_right_copyin_two_move_sends(space
, name
, entry
, 
2589                 if (kr 
!= KERN_SUCCESS
) { 
2593                 mach_msg_type_name_t msgt_name
; 
2596                  *      Must be either a single move-send and a 
2597                  *      copy-send, or two copy-send dispositions. 
2598                  *      Use the disposition with the greatest side 
2599                  *      effects for the actual copyin - then just 
2600                  *      duplicate the send right you get back. 
2602                 if (msgt_one 
== MACH_MSG_TYPE_MOVE_SEND 
|| 
2603                     msgt_two 
== MACH_MSG_TYPE_MOVE_SEND
) { 
2604                         msgt_name 
= MACH_MSG_TYPE_MOVE_SEND
; 
2606                         msgt_name 
= MACH_MSG_TYPE_COPY_SEND
; 
2609                 kr 
= ipc_right_copyin(space
, name
, entry
, 
2610                     msgt_name
, IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND
, 
2611                     objectp
, sorightp
, releasep
, 
2612                     &assertcnt
, 0, NULL
); 
2613                 assert(assertcnt 
== 0); 
2614                 if (kr 
!= KERN_SUCCESS
) { 
2619                  *      Copy the right we got back.  If it is dead now, 
2620                  *      that's OK.  Neither right will be usable to send 
2623                 (void)ipc_port_copy_send(ip_object_to_port(*objectp
)); 
2626         return KERN_SUCCESS
; 
2631  *      Routine:        ipc_right_copyout 
2633  *              Copyout a capability to a space. 
2634  *              If successful, consumes a ref for the object. 
2636  *              Always succeeds when given a newly-allocated entry, 
2637  *              because user-reference overflow isn't a possibility. 
2639  *              If copying out the object would cause the user-reference 
2640  *              count in the entry to overflow, then the user-reference 
2641  *              count is left pegged to its maximum value and the copyout 
2644  *              The space is write-locked and active. 
2645  *              The object is locked and active. 
2646  *              The object is unlocked; the space isn't. 
2648  *              KERN_SUCCESS            Copied out capability. 
2654         mach_port_name_t        name
, 
2656         mach_msg_type_name_t    msgt_name
, 
2657         ipc_object_copyout_flags_t flags
, 
2658         mach_port_context_t     
*context
, 
2659         mach_msg_guard_flags_t  
*guard_flags
, 
2660         ipc_object_t            object
) 
2662         ipc_entry_bits_t bits
; 
2665         bits 
= entry
->ie_bits
; 
2667         assert(IO_VALID(object
)); 
2668         assert(io_otype(object
) == IOT_PORT
); 
2669         assert(io_active(object
)); 
2670         assert(entry
->ie_object 
== object
); 
2672         port 
= ip_object_to_port(object
); 
2674         if (pinned_control_port_enabled 
&& (flags 
& IPC_OBJECT_COPYOUT_FLAGS_PINNED
)) { 
2675                 assert(!port
->ip_pinned
); 
2676                 assert(port
->ip_immovable_send
); 
2677                 port
->ip_pinned 
= 1; 
2680         switch (msgt_name
) { 
2681         case MACH_MSG_TYPE_PORT_SEND_ONCE
: 
2683                 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
); 
2684                 assert(IE_BITS_UREFS(bits
) == 0); 
2685                 assert(port
->ip_sorights 
> 0); 
2687                 if (port
->ip_specialreply
) { 
2688                         ipc_port_adjust_special_reply_port_locked(port
, 
2689                             current_thread()->ith_knote
, IPC_PORT_ADJUST_SR_LINK_WORKLOOP
, FALSE
); 
2690                         /* port unlocked on return */ 
2695                 entry
->ie_bits 
= bits 
| (MACH_PORT_TYPE_SEND_ONCE 
| 1); /* set urefs to 1 */ 
2696                 ipc_entry_modified(space
, name
, entry
); 
2699         case MACH_MSG_TYPE_PORT_SEND
: 
2700                 assert(port
->ip_srights 
> 0); 
2702                 if (bits 
& MACH_PORT_TYPE_SEND
) { 
2703                         mach_port_urefs_t urefs 
= IE_BITS_UREFS(bits
); 
2705                         assert(port
->ip_srights 
> 1); 
2707                         assert(urefs 
<= MACH_PORT_UREFS_MAX
); 
2709                         if (urefs 
== MACH_PORT_UREFS_MAX
) { 
2711                                  * leave urefs pegged to maximum, 
2712                                  * consume send right and ref 
2718                                 return KERN_SUCCESS
; 
2721                         /* consume send right and ref */ 
2725                 } else if (bits 
& MACH_PORT_TYPE_RECEIVE
) { 
2726                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
); 
2727                         assert(IE_BITS_UREFS(bits
) == 0); 
2729                         /* transfer send right to entry, consume ref */ 
2733                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
); 
2734                         assert(IE_BITS_UREFS(bits
) == 0); 
2736                         /* transfer send right and ref to entry */ 
2739                         /* entry is locked holding ref, so can use port */ 
2741                         ipc_hash_insert(space
, ip_to_object(port
), name
, entry
); 
2744                 entry
->ie_bits 
= (bits 
| MACH_PORT_TYPE_SEND
) + 1; /* increment urefs */ 
2745                 ipc_entry_modified(space
, name
, entry
); 
2748         case MACH_MSG_TYPE_PORT_RECEIVE
: { 
2750 #if IMPORTANCE_INHERITANCE 
2751                 natural_t assertcnt 
= port
->ip_impcount
; 
2752 #endif /* IMPORTANCE_INHERITANCE */ 
2754                 assert(port
->ip_mscount 
== 0); 
2755                 assert(port
->ip_receiver_name 
== MACH_PORT_NULL
); 
2758                  * Don't copyout kobjects or kolabels as receive right 
2760                 if (io_is_kobject(entry
->ie_object
) || 
2761                     io_is_kolabeled(entry
->ie_object
)) { 
2762                         panic("ipc_right_copyout: Copyout kobject/kolabel as receive right"); 
2765                 imq_lock(&port
->ip_messages
); 
2766                 dest 
= port
->ip_destination
; 
2768                 port
->ip_receiver_name 
= name
; 
2769                 port
->ip_receiver 
= space
; 
2771                 struct knote 
*kn 
= current_thread()->ith_knote
; 
2773                 if ((guard_flags 
!= NULL
) && ((*guard_flags 
& MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE
) != 0)) { 
2774                         assert(port
->ip_immovable_receive 
== 0); 
2775                         port
->ip_guarded 
= 1; 
2776                         port
->ip_strict_guard 
= 0; 
2777                         /* pseudo receive shouldn't set the receive right as immovable in the sender's space */ 
2778                         if (kn 
!= ITH_KNOTE_PSEUDO
) { 
2779                                 port
->ip_immovable_receive 
= 1; 
2781                         port
->ip_context 
= current_thread()->ith_msg_addr
; 
2782                         *context 
= port
->ip_context
; 
2783                         *guard_flags 
= *guard_flags 
& ~MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND
; 
2786                 assert((bits 
& MACH_PORT_TYPE_RECEIVE
) == 0); 
2787                 if (bits 
& MACH_PORT_TYPE_SEND
) { 
2788                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
); 
2789                         assert(IE_BITS_UREFS(bits
) > 0); 
2790                         assert(port
->ip_srights 
> 0); 
2792                         assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
); 
2793                         assert(IE_BITS_UREFS(bits
) == 0); 
2796                 boolean_t sync_bootstrap_checkin 
= FALSE
; 
2797                 if (kn 
!= ITH_KNOTE_PSEUDO 
&& port
->ip_sync_bootstrap_checkin
) { 
2798                         sync_bootstrap_checkin 
= TRUE
; 
2800                 if (!ITH_KNOTE_VALID(kn
, MACH_MSG_TYPE_PORT_RECEIVE
)) { 
2803                 ipc_port_adjust_port_locked(port
, kn
, sync_bootstrap_checkin
); 
2804                 /* port & message queue are unlocked */ 
2806                 if (bits 
& MACH_PORT_TYPE_SEND
) { 
2809                         /* entry is locked holding ref, so can use port */ 
2810                         ipc_hash_delete(space
, ip_to_object(port
), name
, entry
); 
2812                 entry
->ie_bits 
= bits 
| MACH_PORT_TYPE_RECEIVE
; 
2813                 ipc_entry_modified(space
, name
, entry
); 
2815                 if (dest 
!= IP_NULL
) { 
2816 #if IMPORTANCE_INHERITANCE 
2818                          * Deduct the assertion counts we contributed to 
2819                          * the old destination port.  They've already 
2820                          * been reflected into the task as a result of 
2824                         ipc_port_impcount_delta(dest
, 0 - assertcnt
, IP_NULL
); 
2826 #endif /* IMPORTANCE_INHERITANCE */ 
2828                         /* Drop turnstile ref on dest */ 
2829                         ipc_port_send_turnstile_complete(dest
); 
2836                 panic("ipc_right_copyout: strange rights"); 
2838         return KERN_SUCCESS
;