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@ 
  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, 
  65  *      File:   ipc/ipc_object.h 
  69  *      Definitions for IPC objects, for which tasks have capabilities. 
  72 #ifndef _IPC_IPC_OBJECT_H_ 
  73 #define _IPC_IPC_OBJECT_H_ 
  75 #include <mach/kern_return.h> 
  76 #include <mach/message.h> 
  77 #include <kern/locks.h> 
  78 #include <kern/macro_help.h> 
  79 #include <kern/assert.h> 
  80 #include <kern/zalloc.h> 
  81 #include <ipc/ipc_types.h> 
  82 #include <libkern/OSAtomic.h> 
  84 typedef natural_t ipc_object_refs_t
;    /* for ipc/ipc_object.h         */ 
  85 typedef natural_t ipc_object_bits_t
; 
  86 typedef natural_t ipc_object_type_t
; 
  88 __options_closed_decl(ipc_object_copyout_flags_t
, uint32_t, { 
  89         IPC_OBJECT_COPYOUT_FLAGS_NONE                 
= 0x0, 
  90         IPC_OBJECT_COPYOUT_FLAGS_PINNED               
= 0x1, 
  91         IPC_OBJECT_COPYOUT_FLAGS_NO_LABEL_CHECK       
= 0x2, 
  94 __options_closed_decl(ipc_object_copyin_flags_t
, uint32_t, { 
  95         IPC_OBJECT_COPYIN_FLAGS_NONE                     
= 0x0, 
  96         IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND     
= 0x1, /* Dest port contains an immovable send right */ 
  97         IPC_OBJECT_COPYIN_FLAGS_SOFT_FAIL_IMMOVABLE_SEND 
= 0x2, /* Silently fail copyin without guard exception */ 
  98         IPC_OBJECT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE     
= 0x4, 
  99         IPC_OBJECT_COPYIN_FLAGS_DEADOK                   
= 0x8, 
 103  * The ipc_object is used to both tag and reference count these two data 
 104  * structures, and (Noto Bene!) pointers to either of these or the 
 105  * ipc_object at the head of these are freely cast back and forth; hence 
 106  * the ipc_object MUST BE FIRST in the ipc_common_data. 
 108  * If the RPC implementation enabled user-mode code to use kernel-level 
 109  * data structures (as ours used to), this peculiar structuring would 
 110  * avoid having anything in user code depend on the kernel configuration 
 111  * (with which lock size varies). 
 114         ipc_object_bits_t io_bits
; 
 115         ipc_object_refs_t io_references
; 
 116         lck_spin_t        io_lock_data
; 
 117 } __attribute__((aligned(8))); 
 120  * If another object type needs to participate in io_kotype()-based 
 121  * dispatching, it must include a stub structure as the first 
 124 struct ipc_object_header 
{ 
 125         ipc_object_bits_t io_bits
; 
 127         natural_t         io_padding
; /* pad to natural boundary */ 
 132  * Legacy defines.  Should use IPC_OBJECT_NULL, etc... 
 134 #define IO_NULL                 ((ipc_object_t) 0) 
 135 #define IO_DEAD                 ((ipc_object_t) ~0UL) 
 136 #define IO_VALID(io)            (((io) != IO_NULL) && ((io) != IO_DEAD)) 
 139  *      IPC steals the high-order bits from the kotype to use 
 140  *      for its own purposes.  This allows IPC to record facts 
 141  *      about ports that aren't otherwise obvious from the 
 142  *      existing port fields.  In particular, IPC can optionally 
 143  *      mark a port for no more senders detection.  Any change 
 144  *      to IO_BITS_PORT_INFO must be coordinated with bitfield 
 145  *      definitions in ipc_port.h. 
 147 #define IO_BITS_PORT_INFO       0x0000f000      /* stupid port tricks */ 
 148 #define IO_BITS_KOTYPE          0x000003ff      /* used by the object */ 
 149 #define IO_BITS_KOBJECT         0x00000800      /* port belongs to a kobject */ 
 150 #define IO_BITS_KOLABEL         0x00000400      /* The kobject has a label */ 
 151 #define IO_BITS_OTYPE           0x7fff0000      /* determines a zone */ 
 152 #define IO_BITS_ACTIVE          0x80000000      /* is object alive? */ 
 154 #define io_active(io)           (((io)->io_bits & IO_BITS_ACTIVE) != 0) 
 156 #define io_otype(io)            (((io)->io_bits & IO_BITS_OTYPE) >> 16) 
 157 #define io_kotype(io)           ((io)->io_bits & IO_BITS_KOTYPE) 
 158 #define io_is_kobject(io)       (((io)->io_bits & IO_BITS_KOBJECT) != IKOT_NONE) 
 159 #define io_is_kolabeled(io)     (((io)->io_bits & IO_BITS_KOLABEL) != 0) 
 160 #define io_makebits(active, otype, kotype)      \ 
 161         (((active) ? IO_BITS_ACTIVE : 0) | ((otype) << 16) | (kotype)) 
 164  * Object types: ports, port sets, kernel-loaded ports 
 167 #define IOT_PORT_SET            1 
 168 #define IOT_NUMBER              2               /* number of types used */ 
 170 extern zone_t ipc_object_zones
[IOT_NUMBER
]; 
 171 extern lck_grp_t        ipc_lck_grp
; 
 173 static inline ipc_object_t
 
 174 io_alloc(unsigned int otype
, zalloc_flags_t flags
) 
 176         return zalloc_flags(ipc_object_zones
[otype
], flags
); 
 181         ipc_object_t    object
); 
 184  * Here we depend on the ipc_object being first within the kernel struct 
 185  * (ipc_port and ipc_pset). 
 187 #define io_lock_init(io) \ 
 188         lck_spin_init(&(io)->io_lock_data, &ipc_lck_grp, &ipc_lck_attr) 
 189 #define io_lock_destroy(io) \ 
 190         lck_spin_destroy(&(io)->io_lock_data, &ipc_lck_grp) 
 191 #define io_lock_held(io) \ 
 192         LCK_SPIN_ASSERT(&(io)->io_lock_data, LCK_ASSERT_OWNED) 
 193 #define io_lock_held_kdp(io) \ 
 194         kdp_lck_spin_is_acquired(&(io)->io_lock_data) 
 195 #define io_unlock(io) \ 
 196         lck_spin_unlock(&(io)->io_lock_data) 
 200 extern boolean_t 
io_lock_try( 
 203 #define _VOLATILE_ volatile 
 205 /* Sanity check the ref count.  If it is 0, we may be doubly zfreeing. 
 206  * If it is larger than max int, it has been corrupted or leaked, 
 207  * probably by being modified into an address (this is architecture 
 208  * dependent, but it's safe to assume there cannot really be max int 
 209  * references unless some code is leaking the io_reference without leaking 
 210  * object). Saturate the io_reference on release kernel if it reaches 
 211  * max int to avoid use after free. 
 213  * NOTE: The 0 test alone will not catch double zfreeing of ipc_port 
 214  * structs, because the io_references field is the first word of the struct, 
 215  * and zfree modifies that to point to the next free zone element. 
 217 #define IO_MAX_REFERENCES                                               \ 
 218         (unsigned)(~0U ^ (1U << (sizeof(int)*BYTE_SIZE - 1))) 
 221 io_reference(ipc_object_t io
) 
 223         ipc_object_refs_t new_io_references
; 
 224         ipc_object_refs_t old_io_references
; 
 226         if ((io
)->io_references 
== 0 || 
 227             (io
)->io_references 
>= IO_MAX_REFERENCES
) { 
 228                 panic("%s: reference count %u is invalid\n", __func__
, (io
)->io_references
); 
 232                 old_io_references 
= (io
)->io_references
; 
 233                 new_io_references 
= old_io_references 
+ 1; 
 234                 if (old_io_references 
== IO_MAX_REFERENCES
) { 
 237         } while (OSCompareAndSwap(old_io_references
, new_io_references
, 
 238             &((io
)->io_references
)) == FALSE
); 
 243 io_release(ipc_object_t io
) 
 245         ipc_object_refs_t new_io_references
; 
 246         ipc_object_refs_t old_io_references
; 
 248         if ((io
)->io_references 
== 0 || 
 249             (io
)->io_references 
>= IO_MAX_REFERENCES
) { 
 250                 panic("%s: reference count %u is invalid\n", __func__
, (io
)->io_references
); 
 254                 old_io_references 
= (io
)->io_references
; 
 255                 new_io_references 
= old_io_references 
- 1; 
 256                 if (old_io_references 
== IO_MAX_REFERENCES
) { 
 259         } while (OSCompareAndSwap(old_io_references
, new_io_references
, 
 260             &((io
)->io_references
)) == FALSE
); 
 262         /* If we just removed the last reference count */ 
 263         if (1 == old_io_references
) { 
 264                 /* Free the object */ 
 265                 io_free(io_otype((io
)), (io
)); 
 270  * Retrieve a label for use in a kernel call that takes a security 
 271  * label as a parameter. If necessary, io_getlabel acquires internal 
 272  * (not io_lock) locks, and io_unlocklabel releases them. 
 276 extern struct label 
*io_getlabel(ipc_object_t obj
); 
 277 #define io_unlocklabel(obj) 
 280  * Exported interfaces 
 283 /* Take a reference to an object */ 
 284 extern void ipc_object_reference( 
 285         ipc_object_t    object
); 
 287 /* Release a reference to an object */ 
 288 extern void ipc_object_release( 
 289         ipc_object_t    object
); 
 291 /* Look up an object in a space */ 
 292 extern kern_return_t 
ipc_object_translate( 
 294         mach_port_name_t        name
, 
 295         mach_port_right_t       right
, 
 296         ipc_object_t            
*objectp
); 
 298 /* Look up two objects in a space, locking them in the order described */ 
 299 extern kern_return_t 
ipc_object_translate_two( 
 301         mach_port_name_t        name1
, 
 302         mach_port_right_t       right1
, 
 303         ipc_object_t            
*objectp1
, 
 304         mach_port_name_t        name2
, 
 305         mach_port_right_t       right2
, 
 306         ipc_object_t            
*objectp2
); 
 308 /* Validate an object as belonging to the correct zone */ 
 309 extern void ipc_object_validate( 
 310         ipc_object_t object
); 
 312 /* Allocate a dead-name entry */ 
 314 ipc_object_alloc_dead( 
 316         mach_port_name_t        
*namep
); 
 318 /*  Allocate a dead-name entry, with a specific name */ 
 319 extern kern_return_t 
ipc_object_alloc_dead_name( 
 321         mach_port_name_t        name
); 
 323 /* Allocate an object */ 
 324 extern kern_return_t 
ipc_object_alloc( 
 326         ipc_object_type_t       otype
, 
 327         mach_port_type_t        type
, 
 328         mach_port_urefs_t       urefs
, 
 329         mach_port_name_t        
*namep
, 
 330         ipc_object_t            
*objectp
); 
 332 /* Allocate an object, with a specific name */ 
 333 extern kern_return_t 
ipc_object_alloc_name( 
 335         ipc_object_type_t       otype
, 
 336         mach_port_type_t        type
, 
 337         mach_port_urefs_t       urefs
, 
 338         mach_port_name_t        name
, 
 339         ipc_object_t            
*objectp
); 
 341 /* Convert a send type name to a received type name */ 
 342 extern mach_msg_type_name_t 
ipc_object_copyin_type( 
 343         mach_msg_type_name_t    msgt_name
); 
 345 /* Copyin a capability from a space */ 
 346 extern kern_return_t 
ipc_object_copyin( 
 348         mach_port_name_t        name
, 
 349         mach_msg_type_name_t    msgt_name
, 
 350         ipc_object_t            
*objectp
, 
 351         mach_port_context_t     context
, 
 352         mach_msg_guard_flags_t  
*guard_flags
, 
 353         ipc_object_copyin_flags_t copyin_flags
); 
 355 /* Copyin a naked capability from the kernel */ 
 356 extern void ipc_object_copyin_from_kernel( 
 358         mach_msg_type_name_t    msgt_name
); 
 360 /* Destroy a naked capability */ 
 361 extern void ipc_object_destroy( 
 363         mach_msg_type_name_t    msgt_name
); 
 365 /* Destroy a naked destination capability */ 
 366 extern void ipc_object_destroy_dest( 
 368         mach_msg_type_name_t    msgt_name
); 
 370 /* Insert a send right into an object already in the current space */ 
 371 extern kern_return_t 
ipc_object_insert_send_right( 
 373         mach_port_name_t        name
, 
 374         mach_msg_type_name_t    msgt_name
); 
 376 /* Copyout a capability, placing it into a space */ 
 377 extern kern_return_t 
ipc_object_copyout( 
 380         mach_msg_type_name_t    msgt_name
, 
 381         ipc_object_copyout_flags_t flags
, 
 382         mach_port_context_t     
*context
, 
 383         mach_msg_guard_flags_t  
*guard_flags
, 
 384         mach_port_name_t        
*namep
); 
 386 /* Copyout a capability with a name, placing it into a space */ 
 387 extern kern_return_t 
ipc_object_copyout_name( 
 390         mach_msg_type_name_t    msgt_name
, 
 391         mach_port_name_t        name
); 
 393 /* Translate/consume the destination right of a message */ 
 394 extern void ipc_object_copyout_dest( 
 397         mach_msg_type_name_t    msgt_name
, 
 398         mach_port_name_t        
*namep
); 
 400 #endif  /* _IPC_IPC_OBJECT_H_ */