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 [email protected]
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 /* Check if a kobject can be copied out to a given space */
432 extern bool ipc_kobject_label_check(
433 ipc_space_t space,
434 ipc_port_t port,
435 mach_msg_type_name_t msgt_name,
436 ipc_object_copyout_flags_t *flags,
437 ipc_port_t *subst_portp) __result_use_check;
438
439 __result_use_check
440 static inline bool
ip_label_check(ipc_space_t space,ipc_port_t port,mach_msg_type_name_t msgt_name,ipc_object_copyout_flags_t * flags,ipc_port_t * subst_portp)441 ip_label_check(
442 ipc_space_t space,
443 ipc_port_t port,
444 mach_msg_type_name_t msgt_name,
445 ipc_object_copyout_flags_t *flags,
446 ipc_port_t *subst_portp)
447 {
448 if (!ip_is_kolabeled(port)) {
449 *subst_portp = IP_NULL;
450 return true;
451 }
452 return ipc_kobject_label_check(space, port, msgt_name, flags, subst_portp);
453 }
454
455 /* implementation details */
456
457 __startup_func
458 extern void ipc_kobject_register_startup(
459 ipc_kobject_ops_t ops);
460
461 /* initialization of kobject subsystem */
462 extern void ipc_kobject_init(void);
463
464 /* Dispatch a kernel server function */
465 extern ipc_kmsg_t ipc_kobject_server(
466 ipc_port_t receiver,
467 ipc_kmsg_t request,
468 mach_msg_option64_t option);
469
470 /* Release any kernel object resources associated with a port */
471 extern void ipc_kobject_destroy(
472 ipc_port_t port);
473
474 #define null_conversion(port) (port)
475
476 extern void ipc_kobject_notify_no_senders(
477 ipc_port_t port,
478 mach_port_mscount_t mscount);
479
480 extern void ipc_kobject_notify_send_once_and_unlock(
481 ipc_port_t port);
482
483 extern kern_return_t uext_server(
484 ipc_port_t receiver,
485 ipc_kmsg_t request,
486 ipc_kmsg_t *reply);
487
488 #endif /* MACH_KERNEL_PRIVATE */
489
490 #pragma GCC visibility pop
491 __END_DECLS
492
493 #endif /* _KERN_IPC_KOBJECT_H_ */
494