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_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 ; |
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 | |