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 */
45extern lck_grp_t ipc_lck_grp;
46extern lck_attr_t ipc_lck_attr;
47
48/* some shorthand for longer types */
49typedef mach_voucher_attr_value_handle_t iv_value_handle_t __kernel_ptr_semantics;
50typedef mach_voucher_attr_value_reference_t iv_value_refs_t;
51
52typedef natural_t iv_index_t;
53#define IV_UNUSED_VALINDEX ((iv_index_t) 0)
54#define IV_UNUSED_KEYINDEX ((iv_index_t) ~0)
55
56typedef 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 */
73struct 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
115struct 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};
129typedef struct ivac_entry_s ivac_entry;
130typedef 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
142struct 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};
151typedef ipc_voucher_attr_control_t iv_attr_control_t;
152
153#define IVAC_NULL IPC_VOUCHER_ATTR_CONTROL_NULL
154
155extern void ipc_voucher_receive_postprocessing(ipc_kmsg_t kmsg, mach_msg_option_t option);
156extern void ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg);
157extern ipc_voucher_t ipc_voucher_get_default_voucher(void);
158extern void mach_init_activity_id(void);
159#if CONFIG_VOUCHER_DEPRECATED
160extern 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)
190typedef 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;
197typedef ipc_voucher_attr_recipe_data_t *ipc_voucher_attr_recipe_t;
198typedef mach_msg_type_number_t ipc_voucher_attr_recipe_size_t;
199
200typedef uint8_t *ipc_voucher_attr_raw_recipe_t;
201typedef ipc_voucher_attr_raw_recipe_t ipc_voucher_attr_raw_recipe_array_t;
202typedef mach_msg_type_number_t ipc_voucher_attr_raw_recipe_size_t;
203typedef 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
217typedef 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
222typedef 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
233typedef 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
241typedef 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
251typedef void (*ipc_voucher_attr_manager_release_t)(ipc_voucher_attr_manager_t);
252
253typedef uint32_t ipc_voucher_attr_manager_flags;
254
255struct 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 */
270extern uintptr_t unsafe_convert_port_to_voucher(
271 ipc_port_t port) __pure2;
272
273/* Convert from a port to a voucher */
274extern ipc_voucher_t convert_port_to_voucher(
275 ipc_port_t port);
276
277/* Convert from a port name to an ipc_voucher */
278extern ipc_voucher_t convert_port_name_to_voucher(
279 mach_port_name_t name);
280
281/* add a reference to the specified voucher */
282extern void ipc_voucher_reference(
283 ipc_voucher_t voucher);
284
285/* drop the voucher reference picked up above */
286extern void ipc_voucher_release(
287 ipc_voucher_t voucher);
288
289/* Convert from a voucher to a port */
290extern ipc_port_t convert_voucher_to_port(
291 ipc_voucher_t voucher);
292
293/*
294 * In-kernel equivalents to the user syscalls
295 */
296extern kern_return_t
297ipc_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
302extern kern_return_t
303ipc_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
309extern void
310ipc_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
316extern kern_return_t
317mach_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