1 /* 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 #ifndef _IPC_IPC_VOUCHER_H_ 29 #define _IPC_IPC_VOUCHER_H_ 30 31 #include <mach/mach_types.h> 32 #include <mach/mach_voucher_types.h> 33 #include <mach/boolean.h> 34 #include <ipc/ipc_types.h> 35 #include <os/refcnt.h> 36 37 #ifdef MACH_KERNEL_PRIVATE 38 39 #include <kern/smr_types.h> 40 #include <kern/locks.h> 41 #include <kern/simple_lock.h> 42 #include <voucher/ipc_pthread_priority_types.h> 43 44 /* locking */ 45 extern lck_grp_t ipc_lck_grp; 46 extern lck_attr_t ipc_lck_attr; 47 48 /* some shorthand for longer types */ 49 typedef mach_voucher_attr_value_handle_t iv_value_handle_t __kernel_ptr_semantics; 50 typedef mach_voucher_attr_value_reference_t iv_value_refs_t; 51 52 typedef natural_t iv_index_t; 53 #define IV_UNUSED_VALINDEX ((iv_index_t) 0) 54 #define IV_UNUSED_KEYINDEX ((iv_index_t) ~0) 55 56 typedef iv_index_t *iv_entry_t; 57 #define IVE_NULL ((iv_entry_t) 0) 58 59 /* actual number of attribute managers supported by kernel */ 60 #if CONFIG_VOUCHER_DEPRECATED 61 #define MACH_VOUCHER_ATTR_KEY_NUM MACH_VOUCHER_ATTR_KEY_TEST 62 #else 63 #define MACH_VOUCHER_ATTR_KEY_NUM MACH_VOUCHER_ATTR_KEY_BANK 64 #endif /* CONFIG_VOUCHER_DEPRECATED */ 65 66 /* 67 * IPC Voucher 68 * 69 * Vouchers are a reference counted immutable (once-created) set of 70 * indexes to particular resource manager attribute values 71 * (which themselves are reference counted). 72 */ 73 struct ipc_voucher { 74 os_ref_atomic_t iv_refs; /* reference count */ 75 iv_index_t iv_table[MACH_VOUCHER_ATTR_KEY_NUM]; 76 ipc_port_t iv_port; /* port representing the voucher */ 77 struct smrq_slink iv_hash_link; /* link on hash chain */ 78 }; 79 80 #define IV_NULL IPC_VOUCHER_NULL 81 82 83 /* 84 * Voucher Attribute Cache Control Object 85 * 86 * This is where the Voucher system stores its caches/references to 87 * returned resource manager attribute values. Each value only appears 88 * once in the table. If a value is returned more than once by the 89 * resource manager, the voucher system will increase the reference 90 * on the previous value. 91 * 92 * The voucher itself contains one entry per key, that indexes into 93 * this table. 94 * 95 * A voucher that does not have an explicit index for a given key 96 * is assumed to have a reference on slot zero - which is where the 97 * voucher system stores the default value for the given attribute 98 * (specified at the time of resource manager registration). 99 * 100 * The ivace_releasing field limits the entry to a single concurrent 101 * return. Without it, a previous release's reply might still be 102 * working its way back to the voucher code, and a subsequent get- 103 * value could return the same value as was previously returned. If 104 * the resource manager already knew that, it would return a failure 105 * on the return, and all is well. We just treat the additional made 106 * references on the value as we normally would. However, if the resource 107 * manager accepted the return, and the get-value response raced the 108 * release's reply, the newly made references will look like an extension 109 * of the old value's cache lifetime, rather than a new one. Dropping 110 * that new lifetime's references to zero would result in a second 111 * release callback to the resource manager - this time with the wrong 112 * "made" reference count. We avoid the race with this flag. 113 */ 114 115 struct ivac_entry_s { 116 iv_value_handle_t ivace_value; 117 iv_value_refs_t ivace_layered:1, /* layered effective entry */ 118 ivace_releasing:1, /* release in progress */ 119 ivace_free:1, /* on freelist */ 120 ivace_persist:1, /* Persist the entry, don't count made refs */ 121 ivace_refs:28; /* reference count */ 122 union { 123 iv_value_refs_t ivaceu_made; /* made count (non-layered) */ 124 iv_index_t ivaceu_layer; /* next effective layer (layered) */ 125 } ivace_u; 126 iv_index_t ivace_next; /* hash or freelist */ 127 iv_index_t ivace_index; /* hash head (independent) */ 128 }; 129 typedef struct ivac_entry_s ivac_entry; 130 typedef ivac_entry *ivac_entry_t; 131 132 #define ivace_made ivace_u.ivaceu_made 133 #define ivace_layer ivace_u.ivaceu_layer 134 135 #define IVACE_NULL ((ivac_entry_t) 0); 136 137 #define IVACE_REFS_MAX ((1 << 28) - 1) 138 139 #define IVAC_ENTRIES_MIN 512 140 #define IVAC_ENTRIES_MAX 524288 141 142 struct ipc_voucher_attr_control { 143 boolean_t ivac_is_growing; /* is the table being grown */ 144 ivac_entry_t ivac_table; /* table of voucher attr value entries */ 145 iv_index_t ivac_table_size; /* size of the attr value table */ 146 iv_index_t ivac_init_table_size; /* size of the attr value table */ 147 iv_index_t ivac_freelist; /* index of the first free element */ 148 lck_spin_t ivac_lock_data; 149 iv_index_t ivac_key_index; 150 }; 151 typedef ipc_voucher_attr_control_t iv_attr_control_t; 152 153 #define IVAC_NULL IPC_VOUCHER_ATTR_CONTROL_NULL 154 155 extern void ipc_voucher_receive_postprocessing(ipc_kmsg_t kmsg, mach_msg_option_t option); 156 extern void ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg); 157 extern ipc_voucher_t ipc_voucher_get_default_voucher(void); 158 extern void mach_init_activity_id(void); 159 #if CONFIG_VOUCHER_DEPRECATED 160 extern kern_return_t ipc_get_pthpriority_from_kmsg_voucher(ipc_kmsg_t kmsg, ipc_pthread_priority_value_t *qos); 161 #endif /* CONFIG_VOUCHER_DEPRECATED */ 162 163 #define ivac_lock_init(ivac) \ 164 lck_spin_init(&(ivac)->ivac_lock_data, &ipc_lck_grp, &ipc_lck_attr) 165 #define ivac_lock_destroy(ivac) \ 166 lck_spin_destroy(&(ivac)->ivac_lock_data, &ipc_lck_grp) 167 #define ivac_lock(ivac) \ 168 lck_spin_lock_grp(&(ivac)->ivac_lock_data, &ipc_lck_grp) 169 #define ivac_lock_try(ivac) \ 170 lck_spin_try_lock_grp(&(ivac)->ivac_lock_data, &ipc_lck_grp) 171 #define ivac_unlock(ivac) \ 172 lck_spin_unlock(&(ivac)->ivac_lock_data) 173 #define ivac_sleep(ivac) lck_spin_sleep_grp(&(ivac)->ivac_lock_data, \ 174 LCK_SLEEP_DEFAULT, \ 175 (event_t)(ivac), \ 176 THREAD_UNINT, &ipc_lck_grp) 177 #define ivac_wakeup(ivac) thread_wakeup((event_t)(ivac)) 178 179 #define IVAM_NULL IPC_VOUCHER_ATTR_MANAGER_NULL 180 181 #endif /* MACH_KERNEL_PRIVATE */ 182 183 /* 184 * IPC voucher attribute recipe 185 * 186 * In-kernel recipe format with an ipc_voucher_t pointer for the previous 187 * voucher reference. 188 */ 189 #pragma pack(1) 190 typedef struct ipc_voucher_attr_recipe_data { 191 mach_voucher_attr_key_t key; 192 mach_voucher_attr_recipe_command_t command; 193 ipc_voucher_t previous_voucher; 194 mach_voucher_attr_content_size_t content_size; 195 uint8_t content[]; 196 } ipc_voucher_attr_recipe_data_t; 197 typedef ipc_voucher_attr_recipe_data_t *ipc_voucher_attr_recipe_t; 198 typedef mach_msg_type_number_t ipc_voucher_attr_recipe_size_t; 199 200 typedef uint8_t *ipc_voucher_attr_raw_recipe_t; 201 typedef ipc_voucher_attr_raw_recipe_t ipc_voucher_attr_raw_recipe_array_t; 202 typedef mach_msg_type_number_t ipc_voucher_attr_raw_recipe_size_t; 203 typedef mach_msg_type_number_t ipc_voucher_attr_raw_recipe_array_size_t; 204 205 #pragma pack() 206 207 /* 208 * In-kernel Resource Manager Definition 209 * 210 * In-kernel resource managers are defined by a v-table like structure for 211 * the three callouts supported by a resource manager (and release function). 212 * 213 * There is a single in-kernel resource manager that represents all the 214 * outside kernel managers (and reflects the calls through MIG to user-space). 215 */ 216 217 typedef kern_return_t (*ipc_voucher_attr_manager_release_value_t)(ipc_voucher_attr_manager_t, 218 mach_voucher_attr_key_t, 219 mach_voucher_attr_value_handle_t, 220 mach_voucher_attr_value_reference_t); 221 222 typedef kern_return_t (*ipc_voucher_attr_manager_get_value_t)(ipc_voucher_attr_manager_t, 223 mach_voucher_attr_key_t, 224 mach_voucher_attr_recipe_command_t, 225 mach_voucher_attr_value_handle_array_t, 226 mach_voucher_attr_value_handle_array_size_t, 227 mach_voucher_attr_content_t, 228 mach_voucher_attr_content_size_t, 229 mach_voucher_attr_value_handle_t *, 230 mach_voucher_attr_value_flags_t *, 231 ipc_voucher_t *); 232 233 typedef kern_return_t (*ipc_voucher_attr_manager_extract_content_t)(ipc_voucher_attr_manager_t, 234 mach_voucher_attr_key_t, 235 mach_voucher_attr_value_handle_array_t, 236 mach_voucher_attr_value_handle_array_size_t, 237 mach_voucher_attr_recipe_command_t *, 238 mach_voucher_attr_content_t, 239 mach_voucher_attr_content_size_t *); 240 241 typedef kern_return_t (*ipc_voucher_attr_manager_command_t)(ipc_voucher_attr_manager_t, 242 mach_voucher_attr_key_t, 243 mach_voucher_attr_value_handle_array_t, 244 mach_voucher_attr_value_handle_array_size_t, 245 mach_voucher_attr_command_t, 246 mach_voucher_attr_content_t, 247 mach_voucher_attr_content_size_t, 248 mach_voucher_attr_content_t, 249 mach_voucher_attr_content_size_t *); 250 251 typedef void (*ipc_voucher_attr_manager_release_t)(ipc_voucher_attr_manager_t); 252 253 typedef uint32_t ipc_voucher_attr_manager_flags; 254 255 struct ipc_voucher_attr_manager { 256 ipc_voucher_attr_manager_release_value_t ivam_release_value; 257 ipc_voucher_attr_manager_get_value_t ivam_get_value; 258 ipc_voucher_attr_manager_extract_content_t ivam_extract_content; 259 ipc_voucher_attr_manager_command_t ivam_command; 260 ipc_voucher_attr_manager_flags ivam_flags; 261 }; 262 263 #define IVAM_FLAGS_NONE 0 264 #define IVAM_FLAGS_SUPPORT_SEND_PREPROCESS 0x1 265 #define IVAM_FLAGS_SUPPORT_RECEIVE_POSTPROCESS 0x2 266 267 __BEGIN_DECLS 268 269 /* DEBUG/TRACE Convert from a port to a voucher */ 270 extern uintptr_t unsafe_convert_port_to_voucher( 271 ipc_port_t port) __pure2; 272 273 /* Convert from a port to a voucher */ 274 extern ipc_voucher_t convert_port_to_voucher( 275 ipc_port_t port); 276 277 /* Convert from a port name to an ipc_voucher */ 278 extern ipc_voucher_t convert_port_name_to_voucher( 279 mach_port_name_t name); 280 281 /* add a reference to the specified voucher */ 282 extern void ipc_voucher_reference( 283 ipc_voucher_t voucher); 284 285 /* drop the voucher reference picked up above */ 286 extern void ipc_voucher_release( 287 ipc_voucher_t voucher); 288 289 /* Convert from a voucher to a port */ 290 extern ipc_port_t convert_voucher_to_port( 291 ipc_voucher_t voucher); 292 293 /* 294 * In-kernel equivalents to the user syscalls 295 */ 296 extern kern_return_t 297 ipc_create_mach_voucher( 298 ipc_voucher_attr_raw_recipe_array_t recipes, 299 ipc_voucher_attr_raw_recipe_array_size_t recipe_size, 300 ipc_voucher_t *new_voucher); 301 302 extern kern_return_t 303 ipc_voucher_attr_control_create_mach_voucher( 304 ipc_voucher_attr_control_t control, 305 ipc_voucher_attr_raw_recipe_array_t recipes, 306 ipc_voucher_attr_raw_recipe_array_size_t recipe_size, 307 ipc_voucher_t *new_voucher); 308 309 extern void 310 ipc_register_well_known_mach_voucher_attr_manager( 311 ipc_voucher_attr_manager_t manager, 312 mach_voucher_attr_value_handle_t default_value, 313 mach_voucher_attr_key_t key, 314 ipc_voucher_attr_control_t *control); 315 316 extern kern_return_t 317 mach_voucher_attr_control_get_values( 318 ipc_voucher_attr_control_t control, 319 ipc_voucher_t voucher, 320 mach_voucher_attr_value_handle_t *out_values, 321 mach_msg_type_number_t *in_out_size); 322 323 __END_DECLS 324 325 #endif /* _IPC_IPC_VOUCHER_H_ */ 326