xref: /xnu-8020.140.41/osfmk/kern/ipc_kobject.h (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
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 #ifdef MACH_KERNEL_PRIVATE
73 #include <ipc/ipc_kmsg.h>
74 #include <ipc/ipc_port.h>
75 #include <kern/startup.h>
76 #endif /* MACH_KERNEL_PRIVATE */
77 
78 #ifndef _KERN_IPC_KOBJECT_H_
79 #define _KERN_IPC_KOBJECT_H_
80 
81 __BEGIN_DECLS
82 
83 #ifdef KERNEL_PRIVATE
84 /*
85  * This is the legacy in-kernel ipc-object mechanism.  Over the next
86  * several months, this will be phased out in favor of a mechanism that
87  * is less Mach IPC specific, and common across in-mach, in-kernel-component,
88  * and user-level-component (Plugin) models.
89  */
90 #include <mach/machine/vm_types.h>
91 #include <mach/mach_types.h>
92 
93 __enum_decl(ipc_kotype_t, natural_t, {
94 	IKOT_NONE                     = 0,
95 	IKOT_THREAD_CONTROL           = 1,
96 	IKOT_TASK_CONTROL             = 2,
97 	IKOT_HOST                     = 3,
98 	IKOT_HOST_PRIV                = 4,
99 	IKOT_PROCESSOR                = 5,
100 	IKOT_PSET                     = 6,
101 	IKOT_PSET_NAME                = 7,
102 	IKOT_TIMER                    = 8,
103 	IKOT_PORT_SUBST_ONCE          = 9,
104 	// IKOT_MIG                   = 10,
105 	IKOT_MEMORY_OBJECT            = 11,
106 	// IKOT_XMM_PAGER             = 12,
107 	// IKOT_XMM_KERNEL            = 13,
108 	// IKOT_XMM_REPLY             = 14,
109 	IKOT_UND_REPLY                = 15,
110 	IKOT_HOST_NOTIFY              = 16,
111 	// IKOT_HOST_SECURITY         = 17,
112 	// IKOT_LEDGER                = 18,
113 	IKOT_MASTER_DEVICE            = 19,
114 	IKOT_TASK_NAME                = 20,
115 	// IKOT_SUBSYSTEM             = 21,
116 	// IKOT_IO_DONE_QUEUE         = 22,
117 	IKOT_SEMAPHORE                = 23,
118 	// IKOT_LOCK_SET              = 24,
119 	IKOT_CLOCK                    = 25,
120 	IKOT_CLOCK_CTRL               = 26,
121 	IKOT_IOKIT_IDENT              = 27,
122 	IKOT_NAMED_ENTRY              = 28,
123 	IKOT_IOKIT_CONNECT            = 29,
124 	IKOT_IOKIT_OBJECT             = 30,
125 	// IKOT_UPL                   = 31,
126 	IKOT_MEM_OBJ_CONTROL          = 32,
127 #if CONFIG_AUDIT
128 	IKOT_AU_SESSIONPORT           = 33,
129 #endif
130 	IKOT_FILEPORT                 = 34,
131 	// IKOT_LABELH                = 35,
132 	IKOT_TASK_RESUME              = 36,
133 	IKOT_VOUCHER                  = 37,
134 	IKOT_VOUCHER_ATTR_CONTROL     = 38,
135 	IKOT_WORK_INTERVAL            = 39,
136 	IKOT_UX_HANDLER               = 40,
137 	IKOT_UEXT_OBJECT              = 41,
138 	IKOT_ARCADE_REG               = 42,
139 	IKOT_EVENTLINK                = 43,
140 	IKOT_TASK_INSPECT             = 44,
141 	IKOT_TASK_READ                = 45,
142 	IKOT_THREAD_INSPECT           = 46,
143 	IKOT_THREAD_READ              = 47,
144 	// IKOT_SUID_CRED             = 48,
145 #if HYPERVISOR
146 	IKOT_HYPERVISOR               = 49,
147 #endif
148 	IKOT_TASK_ID_TOKEN            = 50,
149 #if CONFIG_PROC_RESOURCE_LIMITS
150 	IKOT_TASK_FATAL               = 51,
151 #endif
152 	/* magic catch-all; should be the last entry */
153 	IKOT_UNKNOWN,
154 });
155 
156 #define IKOT_MAX_TYPE   (IKOT_UNKNOWN+1)        /* # of IKOT_ types	*/
157 
158 #ifdef __cplusplus
159 /* preserve legacy ABI for c++ */
160 typedef natural_t ipc_kobject_type_t;
161 #else
162 typedef ipc_kotype_t ipc_kobject_type_t;
163 #endif
164 
165 /* set the bitstring index for kobject */
166 extern kern_return_t ipc_kobject_set_kobjidx(
167 	int                         msgid,
168 	int                         index);
169 
170 #endif /* KERNEL_PRIVATE */
171 #ifdef MACH_KERNEL_PRIVATE
172 #pragma GCC visibility push(hidden)
173 
174 /*!
175  * @typedef ipc_kobject_ops_t
176  *
177  * @brief
178  * Describes the operations for a given kobject.
179  *
180  * @field iko_ko_type
181  * An @c IKOT_* value.
182  *
183  * @field iko_op_allow_upgrade
184  * Whether this kobject type is made (upgraded) rather than born.
185  *
186  * @field iko_op_stable
187  * The kobject/port association is stable:
188  * - ipc_kobject_dealloc_port() cannot be called
189  *   while there are outstanding send rights,
190  * - ipc_kobject_enable() is never called.
191  * - ipc_kobject_disable() is never called.
192  *
193  * @field iko_op_permanent
194  * The port is never destroyed.
195  * This doesn't necessarily imply iko_op_stable.
196  *
197  * @field iko_op_no_senders
198  * A callback to run when a NO_SENDERS notification fires.
199  *
200  * Kobjects that destroy their port on no senders only are guaranteed
201  * to be called with an active port only.
202  *
203  * However kobject ports that can be destroyed concurrently need
204  * to be prepared for no senders to fail to acquire the kobject port.
205  *
206  * @field iko_op_destroy
207  * A callback to run as part of destroying the kobject port.
208  *
209  * When this callback is set, @c ipc_kobject_dealloc_port()
210  * will not implicitly call @c ipc_kobject_disable().
211  *
212  * The callback runs after the port has been marked inactive,
213  * hence @c ipc_kobject_get_raw() needs to be used to get to the port.
214  */
215 typedef const struct ipc_kobject_ops {
216 	ipc_kobject_type_t iko_op_type;
217 	unsigned long
218 	    iko_op_allow_upgrade : 1,
219 	    iko_op_stable        : 1,
220 	    iko_op_permanent     : 1;
221 	const char        *iko_op_name;
222 	void (*iko_op_no_senders)(ipc_port_t port, mach_port_mscount_t mscount);
223 	void (*iko_op_destroy)(ipc_port_t port);
224 } *ipc_kobject_ops_t;
225 
226 #define IPC_KOBJECT_DEFINE(type, ...) \
227 	__startup_data \
228 	static struct ipc_kobject_ops ipc_kobject_ops_##type = { \
229 	    .iko_op_type = type, \
230 	    .iko_op_name = #type, \
231 	    __VA_ARGS__ \
232 	}; \
233 	STARTUP_ARG(MACH_IPC, STARTUP_RANK_FIRST, ipc_kobject_register_startup, \
234 	    &ipc_kobject_ops_##type)
235 
236 struct ipc_kobject_label {
237 	ipc_label_t   ikol_label;       /* [private] mandatory access label */
238 	ipc_port_t XNU_PTRAUTH_SIGNED_PTR("ipc_kobject_label.ikol_alt_port") ikol_alt_port;
239 };
240 
241 __options_decl(ipc_kobject_alloc_options_t, uint32_t, {
242 	/* Just make the naked port */
243 	IPC_KOBJECT_ALLOC_NONE      = 0x00000000,
244 	/* Make a send right */
245 	IPC_KOBJECT_ALLOC_MAKE_SEND = 0x00000001,
246 	/* Register for no-more-senders */
247 	IPC_KOBJECT_ALLOC_NSREQUEST = 0x00000002,
248 	/* Make it no grant port */
249 	IPC_KOBJECT_ALLOC_NO_GRANT  = 0x00000004,
250 	/* Mark the port as immovable send right */
251 	IPC_KOBJECT_ALLOC_IMMOVABLE_SEND = 0x00000008,
252 	/* Add a label structure to the port */
253 	IPC_KOBJECT_ALLOC_LABEL     = 0x00000010,
254 	/* Mark the port as pinned (non dealloc-able) in an ipc space */
255 	IPC_KOBJECT_ALLOC_PINNED    = 0x00000020,
256 	/* Use ptrauth_discriminator in ipc_kobject_make_send_lazy_alloc_port */
257 	IPC_KOBJECT_PTRAUTH_STORE   = 0x00000040,
258 });
259 
260 /* Allocates a kobject port, never fails */
261 extern ipc_port_t ipc_kobject_alloc_port(
262 	ipc_kobject_t               kobject,
263 	ipc_kobject_type_t          type,
264 	ipc_kobject_alloc_options_t options);
265 
266 /* Allocates a kobject port, never fails */
267 extern ipc_port_t ipc_kobject_alloc_labeled_port(
268 	ipc_kobject_t               kobject,
269 	ipc_kobject_type_t          type,
270 	ipc_label_t                 label,
271 	ipc_kobject_alloc_options_t options);
272 
273 extern ipc_port_t ipc_kobject_alloc_subst_once(
274 	ipc_port_t                  target);
275 
276 /* Makes a send right, lazily allocating a kobject port, arming for no-senders, never fails */
277 extern boolean_t ipc_kobject_make_send_lazy_alloc_port(
278 	ipc_port_t                 *port_store,
279 	ipc_kobject_t               kobject,
280 	ipc_kobject_type_t          type,
281 	ipc_kobject_alloc_options_t alloc_opts,
282 	uint64_t                    ptrauth_discriminator) __result_use_check;
283 
284 /* Makes a send right, lazily allocating a kobject port, arming for no-senders, never fails */
285 extern boolean_t ipc_kobject_make_send_lazy_alloc_labeled_port(
286 	ipc_port_t                 *port_store,
287 	ipc_kobject_t               kobject,
288 	ipc_kobject_type_t          type,
289 	ipc_label_t                 label) __result_use_check;
290 
291 extern kern_return_t ipc_kobject_nsrequest(
292 	ipc_port_t                  port,
293 	mach_port_mscount_t         sync,
294 	mach_port_mscount_t        *mscount) __result_use_check;
295 
296 /* Makes a send right, and arms no-senders */
297 extern kern_return_t ipc_kobject_make_send_nsrequest(
298 	ipc_port_t                  port) __result_use_check;
299 
300 extern ipc_kobject_t ipc_kobject_dealloc_port_and_unlock(
301 	ipc_port_t                  port,
302 	mach_port_mscount_t         mscount,
303 	ipc_kobject_type_t          type);
304 
305 extern ipc_kobject_t ipc_kobject_dealloc_port(
306 	ipc_port_t                  port,
307 	mach_port_mscount_t         mscount,
308 	ipc_kobject_type_t          type);
309 
310 extern void         ipc_kobject_enable(
311 	ipc_port_t                  port,
312 	ipc_kobject_t               kobject,
313 	ipc_kobject_type_t          type);
314 
315 extern ipc_kobject_t ipc_kobject_get_raw(
316 	ipc_port_t                  port,
317 	ipc_kobject_type_t          type);
318 
319 extern ipc_kobject_t ipc_kobject_get_locked(
320 	ipc_port_t                  port,
321 	ipc_kobject_type_t          type);
322 
323 extern ipc_kobject_t ipc_kobject_get_stable(
324 	ipc_port_t                  port,
325 	ipc_kobject_type_t          type);
326 
327 extern ipc_kobject_t ipc_kobject_disable_locked(
328 	ipc_port_t                  port,
329 	ipc_kobject_type_t          type);
330 
331 extern ipc_kobject_t ipc_kobject_disable(
332 	ipc_port_t                  port,
333 	ipc_kobject_type_t          type);
334 
335 extern void         ipc_kobject_upgrade_locked(
336 	ipc_port_t                  port,
337 	ipc_kobject_t               kobject,
338 	ipc_kobject_type_t          type);
339 
340 extern kern_return_t ipc_kobject_upgrade(
341 	ipc_port_t                  port,
342 	ipc_kobject_t               kobject,
343 	ipc_kobject_type_t          type) __result_use_check;
344 
345 extern ipc_kobject_t ipc_kobject_downgrade_host_notify(
346 	ipc_port_t                  port);
347 
348 /* Check if a kobject can be copied out to a given space */
349 extern bool     ipc_kobject_label_check(
350 	ipc_space_t                 space,
351 	ipc_port_t                  port,
352 	mach_msg_type_name_t        msgt_name,
353 	ipc_object_copyout_flags_t *flags,
354 	ipc_port_t                 *subst_portp) __result_use_check;
355 
356 __result_use_check
357 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)358 ip_label_check(
359 	ipc_space_t                 space,
360 	ipc_port_t                  port,
361 	mach_msg_type_name_t        msgt_name,
362 	ipc_object_copyout_flags_t *flags,
363 	ipc_port_t                 *subst_portp)
364 {
365 	if (!ip_is_kolabeled(port)) {
366 		*subst_portp = IP_NULL;
367 		return true;
368 	}
369 	return ipc_kobject_label_check(space, port, msgt_name, flags, subst_portp);
370 }
371 
372 /* implementation details */
373 
374 __startup_func
375 extern void ipc_kobject_register_startup(
376 	ipc_kobject_ops_t           ops);
377 
378 /* initialization of kobject subsystem */
379 extern void ipc_kobject_init(void);
380 
381 /* Dispatch a kernel server function */
382 extern ipc_kmsg_t ipc_kobject_server(
383 	ipc_port_t                  receiver,
384 	ipc_kmsg_t                  request,
385 	mach_msg_option_t           option);
386 
387 /* Release any kernel object resources associated with a port */
388 extern void ipc_kobject_destroy(
389 	ipc_port_t                  port);
390 
391 #define null_conversion(port)   (port)
392 
393 extern void ipc_kobject_notify_no_senders(
394 	ipc_port_t                  port,
395 	mach_port_mscount_t         mscount);
396 
397 extern void ipc_kobject_notify_send_once_and_unlock(
398 	ipc_port_t                  port);
399 
400 extern kern_return_t uext_server(
401 	ipc_port_t                  receiver,
402 	ipc_kmsg_t                  request,
403 	ipc_kmsg_t                  *reply);
404 
405 #pragma GCC visibility pop
406 #endif /* MACH_KERNEL_PRIVATE */
407 
408 __END_DECLS
409 
410 #endif /* _KERN_IPC_KOBJECT_H_ */
411