1 | /* |
2 | * Copyright (c) 2000-2006 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 | /* |
29 | * @OSF_COPYRIGHT@ |
30 | */ |
31 | /* |
32 | * Mach Operating System |
33 | * Copyright (c) 1991,1990,1989 Carnegie Mellon University |
34 | * All Rights Reserved. |
35 | * |
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. |
41 | * |
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. |
45 | * |
46 | * Carnegie Mellon requests users of this software to return to |
47 | * |
48 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
49 | * School of Computer Science |
50 | * Carnegie Mellon University |
51 | * Pittsburgh PA 15213-3890 |
52 | * |
53 | * any improvements or extensions that they make and grant Carnegie Mellon |
54 | * the rights to redistribute these changes. |
55 | */ |
56 | /* |
57 | * NOTICE: This file was modified by SPARTA, Inc. in 2005 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, |
60 | * Version 2.0. |
61 | */ |
62 | /* |
63 | */ |
64 | /* |
65 | * File: kern/ipc_kobject.h |
66 | * Author: Rich Draves |
67 | * Date: 1989 |
68 | * |
69 | * Declarations for letting a port represent a kernel object. |
70 | */ |
71 | |
72 | #ifndef _KERN_IPC_KOBJECT_H_ |
73 | #define _KERN_IPC_KOBJECT_H_ |
74 | |
75 | #ifdef MACH_KERNEL_PRIVATE |
76 | #include <ipc/ipc_kmsg.h> |
77 | #include <ipc/ipc_port.h> |
78 | #include <kern/startup.h> |
79 | #endif /* MACH_KERNEL_PRIVATE */ |
80 | #include <mach/machine/vm_types.h> |
81 | #include <mach/mach_types.h> |
82 | |
83 | __BEGIN_DECLS |
84 | #pragma GCC visibility push(hidden) |
85 | |
86 | __enum_decl(ipc_kotype_t, natural_t, { |
87 | IKOT_NONE = 0, |
88 | IKOT_THREAD_CONTROL = 1, |
89 | IKOT_TASK_CONTROL = 2, |
90 | IKOT_HOST = 3, |
91 | IKOT_HOST_PRIV = 4, |
92 | IKOT_PROCESSOR = 5, |
93 | IKOT_PSET = 6, |
94 | IKOT_PSET_NAME = 7, |
95 | IKOT_TIMER = 8, |
96 | IKOT_PORT_SUBST_ONCE = 9, |
97 | // IKOT_MIG = 10, |
98 | IKOT_MEMORY_OBJECT = 11, |
99 | // IKOT_XMM_PAGER = 12, |
100 | // IKOT_XMM_KERNEL = 13, |
101 | // IKOT_XMM_REPLY = 14, |
102 | IKOT_UND_REPLY = 15, |
103 | // IKOT_HOST_NOTIFY = 16, |
104 | // IKOT_HOST_SECURITY = 17, |
105 | // IKOT_LEDGER = 18, |
106 | IKOT_MAIN_DEVICE = 19, |
107 | IKOT_TASK_NAME = 20, |
108 | // IKOT_SUBSYSTEM = 21, |
109 | // IKOT_IO_DONE_QUEUE = 22, |
110 | IKOT_SEMAPHORE = 23, |
111 | // IKOT_LOCK_SET = 24, |
112 | IKOT_CLOCK = 25, |
113 | // IKOT_CLOCK_CTRL = 26, |
114 | IKOT_IOKIT_IDENT = 27, |
115 | IKOT_NAMED_ENTRY = 28, |
116 | IKOT_IOKIT_CONNECT = 29, |
117 | IKOT_IOKIT_OBJECT = 30, |
118 | // IKOT_UPL = 31, |
119 | // IKOT_MEM_OBJ_CONTROL = 32, |
120 | #if CONFIG_AUDIT |
121 | IKOT_AU_SESSIONPORT = 33, |
122 | #endif |
123 | IKOT_FILEPORT = 34, |
124 | // IKOT_LABELH = 35, |
125 | IKOT_TASK_RESUME = 36, |
126 | IKOT_VOUCHER = 37, |
127 | // IKOT_VOUCHER_ATTR_CONTROL = 38, |
128 | IKOT_WORK_INTERVAL = 39, |
129 | IKOT_UX_HANDLER = 40, |
130 | IKOT_UEXT_OBJECT = 41, |
131 | IKOT_ARCADE_REG = 42, |
132 | IKOT_EVENTLINK = 43, |
133 | IKOT_TASK_INSPECT = 44, |
134 | IKOT_TASK_READ = 45, |
135 | IKOT_THREAD_INSPECT = 46, |
136 | IKOT_THREAD_READ = 47, |
137 | // IKOT_SUID_CRED = 48, |
138 | #if HYPERVISOR |
139 | IKOT_HYPERVISOR = 49, |
140 | #endif |
141 | IKOT_TASK_ID_TOKEN = 50, |
142 | #if CONFIG_PROC_RESOURCE_LIMITS |
143 | IKOT_TASK_FATAL = 51, |
144 | #endif |
145 | IKOT_KCDATA = 52, |
146 | #if CONFIG_EXCLAVES |
147 | IKOT_EXCLAVES_RESOURCE = 53, |
148 | #endif |
149 | /* magic catch-all; should be the last entry */ |
150 | IKOT_UNKNOWN, |
151 | }); |
152 | |
153 | #define IKOT_MAX_TYPE (IKOT_UNKNOWN+1) /* # of IKOT_ types */ |
154 | |
155 | #ifdef __cplusplus |
156 | /* preserve legacy ABI for c++ */ |
157 | typedef natural_t ipc_kobject_type_t; |
158 | #else |
159 | typedef ipc_kotype_t ipc_kobject_type_t; |
160 | #endif |
161 | |
162 | /* set the bitstring index for kobject */ |
163 | extern kern_return_t ipc_kobject_set_kobjidx( |
164 | int msgid, |
165 | int index); |
166 | |
167 | #ifdef MACH_KERNEL_PRIVATE |
168 | |
169 | /*! |
170 | * @typedef ipc_kobject_ops_t |
171 | * |
172 | * @brief |
173 | * Describes the operations for a given kobject. |
174 | * |
175 | * @field iko_ko_type |
176 | * An @c IKOT_* value. |
177 | * |
178 | * @field iko_op_stable |
179 | * The kobject/port association is stable: |
180 | * - ipc_kobject_dealloc_port() cannot be called |
181 | * while there are outstanding send rights, |
182 | * - ipc_kobject_enable() is never called. |
183 | * - ipc_kobject_disable() is never called. |
184 | * |
185 | * @field iko_op_permanent |
186 | * The port is never destroyed. |
187 | * This doesn't necessarily imply iko_op_stable. |
188 | * |
189 | * @field iko_op_no_senders |
190 | * A callback to run when a NO_SENDERS notification fires. |
191 | * |
192 | * Kobjects that destroy their port on no senders only are guaranteed |
193 | * to be called with an active port only. |
194 | * |
195 | * However kobject ports that can be destroyed concurrently need |
196 | * to be prepared for no senders to fail to acquire the kobject port. |
197 | * |
198 | * @field iko_op_destroy |
199 | * A callback to run as part of destroying the kobject port. |
200 | * |
201 | * When this callback is set, @c ipc_kobject_dealloc_port() |
202 | * will not implicitly call @c ipc_kobject_disable(). |
203 | * |
204 | * The callback runs after the port has been marked inactive, |
205 | * hence @c ipc_kobject_get_raw() needs to be used to get to the port. |
206 | */ |
207 | typedef const struct ipc_kobject_ops { |
208 | ipc_kobject_type_t iko_op_type; |
209 | unsigned long |
210 | iko_op_stable : 1, |
211 | iko_op_permanent : 1; |
212 | const char *iko_op_name; |
213 | void (*iko_op_no_senders)(ipc_port_t port, mach_port_mscount_t mscount); |
214 | void (*iko_op_destroy)(ipc_port_t port); |
215 | } *ipc_kobject_ops_t; |
216 | |
217 | #define IPC_KOBJECT_DEFINE(type, ...) \ |
218 | __startup_data \ |
219 | static struct ipc_kobject_ops ipc_kobject_ops_##type = { \ |
220 | .iko_op_type = type, \ |
221 | .iko_op_name = #type, \ |
222 | __VA_ARGS__ \ |
223 | }; \ |
224 | STARTUP_ARG(MACH_IPC, STARTUP_RANK_FIRST, ipc_kobject_register_startup, \ |
225 | &ipc_kobject_ops_##type) |
226 | |
227 | struct ipc_kobject_label { |
228 | ipc_label_t ikol_label; /* [private] mandatory access label */ |
229 | ipc_port_t XNU_PTRAUTH_SIGNED_PTR("ipc_kobject_label.ikol_alt_port" ) ikol_alt_port; |
230 | }; |
231 | |
232 | __options_decl(ipc_kobject_alloc_options_t, uint32_t, { |
233 | /* Just make the naked port */ |
234 | IPC_KOBJECT_ALLOC_NONE = 0x00000000, |
235 | /* Make a send right */ |
236 | IPC_KOBJECT_ALLOC_MAKE_SEND = 0x00000001, |
237 | /* Register for no-more-senders */ |
238 | IPC_KOBJECT_ALLOC_NSREQUEST = 0x00000002, |
239 | /* Make it no grant port */ |
240 | IPC_KOBJECT_ALLOC_NO_GRANT = 0x00000004, |
241 | /* Mark the port as immovable send right */ |
242 | IPC_KOBJECT_ALLOC_IMMOVABLE_SEND = 0x00000008, |
243 | /* Add a label structure to the port */ |
244 | IPC_KOBJECT_ALLOC_LABEL = 0x00000010, |
245 | /* Mark the port as pinned (non dealloc-able) in an ipc space */ |
246 | IPC_KOBJECT_ALLOC_PINNED = 0x00000020, |
247 | }); |
248 | |
249 | /* Allocates a kobject port, never fails */ |
250 | extern ipc_port_t ipc_kobject_alloc_port( |
251 | ipc_kobject_t kobject, |
252 | ipc_kobject_type_t type, |
253 | ipc_kobject_alloc_options_t options); |
254 | |
255 | /* Allocates a kobject port, never fails */ |
256 | extern ipc_port_t ipc_kobject_alloc_labeled_port( |
257 | ipc_kobject_t kobject, |
258 | ipc_kobject_type_t type, |
259 | ipc_label_t label, |
260 | ipc_kobject_alloc_options_t options); |
261 | |
262 | extern ipc_port_t ipc_kobject_alloc_subst_once( |
263 | ipc_port_t target); |
264 | |
265 | /* Makes a send right, lazily allocating a kobject port, arming for no-senders, never fails */ |
266 | extern bool ipc_kobject_make_send_lazy_alloc_port( |
267 | ipc_port_t *port_store, |
268 | ipc_kobject_t kobject, |
269 | ipc_kobject_type_t type, |
270 | ipc_kobject_alloc_options_t alloc_opts); |
271 | |
272 | /* Makes a send right, lazily allocating a kobject port, arming for no-senders, never fails */ |
273 | extern boolean_t ipc_kobject_make_send_lazy_alloc_labeled_port( |
274 | ipc_port_t *port_store, |
275 | ipc_kobject_t kobject, |
276 | ipc_kobject_type_t type, |
277 | ipc_label_t label) __result_use_check; |
278 | |
279 | extern kern_return_t ipc_kobject_nsrequest( |
280 | ipc_port_t port, |
281 | mach_port_mscount_t sync, |
282 | mach_port_mscount_t *mscount) __result_use_check; |
283 | |
284 | /*! |
285 | * @function ipc_kobject_copy_send() |
286 | * |
287 | * @brief |
288 | * Copies a naked send right for the specified kobject port. |
289 | * |
290 | * @decription |
291 | * This function will validate that the specified port is pointing |
292 | * to the expected kobject pointer and type (by calling ipc_kobject_require()). |
293 | * |
294 | * @param port The target port. |
295 | * @param kobject The kobject pointer this port should be associated to. |
296 | * @param kotype The kobject type this port should have. |
297 | * |
298 | * @returns |
299 | * - IP_DEAD if @c port was dead. |
300 | * - @c port if @c port was valid, in which case |
301 | * a naked send right was made. |
302 | */ |
303 | extern ipc_port_t ipc_kobject_copy_send( |
304 | ipc_port_t port, |
305 | ipc_kobject_t kobject, |
306 | ipc_kobject_type_t kotype) __result_use_check; |
307 | |
308 | /*! |
309 | * @function ipc_kobject_make_send() |
310 | * |
311 | * @brief |
312 | * Makes a naked send right for the specified kobject port. |
313 | * |
314 | * @decription |
315 | * @see ipc_port_make_send_any_locked() for a general warning about |
316 | * making send rights. |
317 | * |
318 | * This function will validate that the specified port is pointing |
319 | * to the expected kobject pointer and type (by calling ipc_kobject_require()). |
320 | * |
321 | * @param port The target port. |
322 | * @param kobject The kobject pointer this port should be associated to. |
323 | * @param kotype The kobject type this port should have. |
324 | * |
325 | * @returns |
326 | * - IP_DEAD if @c port was dead. |
327 | * - @c port if @c port was valid, in which case |
328 | * a naked send right was made. |
329 | */ |
330 | extern ipc_port_t ipc_kobject_make_send( |
331 | ipc_port_t port, |
332 | ipc_kobject_t kobject, |
333 | ipc_kobject_type_t kotype) __result_use_check; |
334 | |
335 | /*! |
336 | * @function ipc_kobject_make_send_nsrequest() |
337 | * |
338 | * @brief |
339 | * Makes a naked send right for the specified kobject port, |
340 | * and arms no-more-senders if it wasn't already. |
341 | * |
342 | * @decription |
343 | * @see ipc_port_make_send_any_locked() for a general warning about |
344 | * making send rights. |
345 | * |
346 | * This function will validate that the specified port is pointing |
347 | * to the expected kobject pointer and type (by calling ipc_kobject_require()). |
348 | * |
349 | * @param port The target port. |
350 | * @param kobject The kobject pointer this port should be associated to. |
351 | * @param kotype The kobject type this port should have. |
352 | * |
353 | * @returns |
354 | * - KERN_SUCCESS: the notification was armed |
355 | * - KERN_ALREADY_WAITING: the notification was already armed |
356 | * - KERN_INVALID_RIGHT: the port is dead |
357 | */ |
358 | extern kern_return_t ipc_kobject_make_send_nsrequest( |
359 | ipc_port_t port, |
360 | ipc_kobject_t kobject, |
361 | ipc_kobject_type_t kotype) __result_use_check; |
362 | |
363 | extern kern_return_t ipc_kobject_make_send_nsrequest_locked( |
364 | ipc_port_t port, |
365 | ipc_kobject_t kobject, |
366 | ipc_kobject_type_t kotype) __result_use_check; |
367 | |
368 | extern ipc_kobject_t ipc_kobject_dealloc_port_and_unlock( |
369 | ipc_port_t port, |
370 | mach_port_mscount_t mscount, |
371 | ipc_kobject_type_t type); |
372 | |
373 | extern ipc_kobject_t ipc_kobject_dealloc_port( |
374 | ipc_port_t port, |
375 | mach_port_mscount_t mscount, |
376 | ipc_kobject_type_t type); |
377 | |
378 | extern void ipc_kobject_enable( |
379 | ipc_port_t port, |
380 | ipc_kobject_t kobject, |
381 | ipc_kobject_type_t type); |
382 | |
383 | /*! |
384 | * @function ipc_kobject_require() |
385 | * |
386 | * @brief |
387 | * Asserts that a given port is of the specified type |
388 | * with the expected kobject pointer. |
389 | * |
390 | * @decription |
391 | * Port type confusion can lead to catastrophic system compromise, |
392 | * this function can be used in choke points to ensure ports are |
393 | * what they're expected to be before their use. |
394 | * |
395 | * @note It is allowed for the kobject pointer to be NULL, |
396 | * as in some cases ipc_kobject_disable() can be raced with this check. |
397 | * |
398 | * @param port The target port. |
399 | * @param kobject The kobject pointer this port should be associated to. |
400 | * @param kotype The kobject type this port should have. |
401 | */ |
402 | extern void ipc_kobject_require( |
403 | ipc_port_t port, |
404 | ipc_kobject_t kobject, |
405 | ipc_kobject_type_t kotype); |
406 | |
407 | extern ipc_kobject_t ipc_kobject_get_raw( |
408 | ipc_port_t port, |
409 | ipc_kobject_type_t type); |
410 | |
411 | extern ipc_kobject_t ipc_kobject_get_locked( |
412 | ipc_port_t port, |
413 | ipc_kobject_type_t type); |
414 | |
415 | extern ipc_kobject_t ipc_kobject_get_stable( |
416 | ipc_port_t port, |
417 | ipc_kobject_type_t type); |
418 | |
419 | extern ipc_kobject_t ipc_kobject_disable_locked( |
420 | ipc_port_t port, |
421 | ipc_kobject_type_t type); |
422 | |
423 | extern ipc_kobject_t ipc_kobject_disable( |
424 | ipc_port_t port, |
425 | ipc_kobject_type_t type); |
426 | |
427 | extern void ipc_kobject_upgrade_mktimer_locked( |
428 | ipc_port_t port, |
429 | ipc_kobject_t kobject); |
430 | |
431 | /* in mk_timer.c */ |
432 | extern void ipc_kobject_mktimer_require_locked( |
433 | ipc_port_t port); |
434 | |
435 | /* Check if a kobject can be copied out to a given space */ |
436 | extern bool ipc_kobject_label_check( |
437 | ipc_space_t space, |
438 | ipc_port_t port, |
439 | mach_msg_type_name_t msgt_name, |
440 | ipc_object_copyout_flags_t *flags, |
441 | ipc_port_t *subst_portp) __result_use_check; |
442 | |
443 | __result_use_check |
444 | static inline bool |
445 | ip_label_check( |
446 | ipc_space_t space, |
447 | ipc_port_t port, |
448 | mach_msg_type_name_t msgt_name, |
449 | ipc_object_copyout_flags_t *flags, |
450 | ipc_port_t *subst_portp) |
451 | { |
452 | if (!ip_is_kolabeled(port)) { |
453 | *subst_portp = IP_NULL; |
454 | return true; |
455 | } |
456 | return ipc_kobject_label_check(space, port, msgt_name, flags, subst_portp); |
457 | } |
458 | |
459 | /* implementation details */ |
460 | |
461 | __startup_func |
462 | extern void ipc_kobject_register_startup( |
463 | ipc_kobject_ops_t ops); |
464 | |
465 | /* initialization of kobject subsystem */ |
466 | extern void ipc_kobject_init(void); |
467 | |
468 | /* Dispatch a kernel server function */ |
469 | extern ipc_kmsg_t ipc_kobject_server( |
470 | ipc_port_t receiver, |
471 | ipc_kmsg_t request, |
472 | mach_msg_option_t option); |
473 | |
474 | /* Release any kernel object resources associated with a port */ |
475 | extern void ipc_kobject_destroy( |
476 | ipc_port_t port); |
477 | |
478 | #define null_conversion(port) (port) |
479 | |
480 | extern void ipc_kobject_notify_no_senders( |
481 | ipc_port_t port, |
482 | mach_port_mscount_t mscount); |
483 | |
484 | extern void ipc_kobject_notify_send_once_and_unlock( |
485 | ipc_port_t port); |
486 | |
487 | extern kern_return_t uext_server( |
488 | ipc_port_t receiver, |
489 | ipc_kmsg_t request, |
490 | ipc_kmsg_t *reply); |
491 | |
492 | #endif /* MACH_KERNEL_PRIVATE */ |
493 | |
494 | #pragma GCC visibility pop |
495 | __END_DECLS |
496 | |
497 | #endif /* _KERN_IPC_KOBJECT_H_ */ |
498 | |