xref: /xnu-11215.41.3/osfmk/kern/ipc_kobject.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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