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 #include <ipc/ipc_types.h>
83
84 __BEGIN_DECLS
85 #pragma GCC visibility push(hidden)
86
87 typedef ipc_object_type_t ipc_kobject_type_t;
88
89 /* set the bitstring index for kobject */
90 extern kern_return_t ipc_kobject_set_kobjidx(
91 int msgid,
92 int index);
93
94 #ifdef MACH_KERNEL_PRIVATE
95
96 /*!
97 * @typedef ipc_kobject_ops_t
98 *
99 * @brief
100 * Describes the operations for a given kobject.
101 *
102 * @field iko_ko_type
103 * An @c IOT_* value.
104 *
105 * @field iko_op_stable
106 * The kobject/port association is stable:
107 * - ipc_kobject_dealloc_port() cannot be called
108 * while there are outstanding send rights,
109 * - ipc_kobject_enable() is never called.
110 * - ipc_kobject_disable() is never called.
111 *
112 * @field iko_op_permanent
113 * The port is never destroyed.
114 * This doesn't necessarily imply iko_op_stable.
115 *
116 * @field iko_op_no_senders
117 * A callback to run when a NO_SENDERS notification fires.
118 *
119 * This callback is called each time a kobject port reaches 0 send rights
120 * (from a non 0 value). There is no need to actively arm no-senders.
121 *
122 * Kobjects that destroy their port on no senders only are guaranteed
123 * to be called with an active port only.
124 *
125 * However kobject ports that can be destroyed concurrently need
126 * to be prepared for no senders to fail to acquire the kobject port.
127 *
128 * When this callback is set, @c ipc_kobject_dealloc_port()
129 * will not implicitly call @c ipc_kobject_disable().
130 *
131 * The callback runs after the port has been marked inactive,
132 * hence @c ipc_kobject_get_raw() needs to be used to get to the port.
133 *
134 * @field iko_op_label_free
135 * How to free the label on this kobject port (if it supports one).
136 *
137 * @field iko_op_movable_send
138 * Whether send rights created to this kobject are movable
139 */
140 typedef const struct ipc_kobject_ops {
141 ipc_kobject_type_t iko_op_type;
142 unsigned long
143 iko_op_stable : 1,
144 iko_op_permanent : 1,
145 iko_op_movable_send : 1;
146 const char *iko_op_name;
147 void (*iko_op_no_senders)(ipc_port_t port, mach_port_mscount_t mscount);
148 void (*iko_op_label_free)(ipc_object_label_t label);
149 } *ipc_kobject_ops_t;
150
151 #define IPC_KOBJECT_DEFINE(type, ...) \
152 __startup_data \
153 static struct ipc_kobject_ops ipc_kobject_ops_##type = { \
154 .iko_op_type = type, \
155 .iko_op_name = #type, \
156 __VA_ARGS__ \
157 }; \
158 STARTUP_ARG(MACH_IPC, STARTUP_RANK_FIRST, ipc_kobject_register_startup, \
159 &ipc_kobject_ops_##type)
160
161 struct ipc_kobject_label {
162 ipc_label_t ikol_label; /* [private] mandatory access label */
163 ipc_port_t XNU_PTRAUTH_SIGNED_PTR("ipc_kobject_label.ikol_alt_port") ikol_alt_port;
164 };
165
166 extern ipc_object_label_t ipc_kobject_label_alloc(
167 ipc_object_type_t otype,
168 ipc_label_t label_tag,
169 ipc_port_t alt_port);
170
171 extern void ipc_kobject_label_free(
172 ipc_object_label_t label);
173
174 __options_decl(ipc_kobject_alloc_options_t, uint32_t, {
175 /* Just make the naked port */
176 IPC_KOBJECT_ALLOC_NONE = 0x00000000,
177 /* Make a send right */
178 IPC_KOBJECT_ALLOC_MAKE_SEND = 0x00000001,
179 });
180
181 /* Allocates a kobject port, never fails */
182 extern ipc_port_t ipc_kobject_alloc_port(
183 ipc_kobject_t kobject,
184 ipc_object_label_t label,
185 ipc_kobject_alloc_options_t options);
186
187 __attribute__((always_inline, overloadable))
188 static inline ipc_port_t
ipc_kobject_alloc_port(ipc_kobject_t kobject,ipc_object_type_t otype,ipc_kobject_alloc_options_t options)189 ipc_kobject_alloc_port(
190 ipc_kobject_t kobject,
191 ipc_object_type_t otype,
192 ipc_kobject_alloc_options_t options)
193 {
194 return ipc_kobject_alloc_port(kobject, IPC_OBJECT_LABEL(otype), options);
195 }
196
197 /*!
198 * @function ipc_kobject_make_send_lazy_alloc_port()
199 *
200 * @brief
201 * Make a send once for a kobject port, lazily allocating the port.
202 *
203 * @discussion
204 * A location owning this port is passed in port_store.
205 * If no port exists, a port is made lazily.
206 *
207 * A send right is made for the port, and if this is the first one
208 * (possibly not for the first time), then the no-more-senders
209 * notification is rearmed.
210 *
211 * When a notification is armed, the kobject must donate
212 * one of its references to the port. It is expected
213 * the no-more-senders notification will consume this reference.
214 *
215 * In order to use this function, the kobject type requested must:
216 * - be use stable objects (iko_op_stable is true),
217 * - have a no-senders callback (iko_op_no_senders is set).
218 *
219 * @returns
220 * - true, if this was the first send right made for this port,
221 * and an object reference must be donated to the port;
222 * - false otherwise.
223 */
224 extern bool ipc_kobject_make_send_lazy_alloc_port(
225 ipc_port_t *port_store,
226 ipc_kobject_t kobject,
227 ipc_kobject_type_t type);
228
229 /*!
230 * @function ipc_kobject_is_mscount_current()
231 *
232 * @brief
233 * Returns whether the current make-send count is the current one.
234 *
235 * @discussion
236 * This is meant to be called from the context of a no-senders notification
237 * callout to determine whether the object/port has since been rematerialized.
238 *
239 * Most kobjects are uniquely owned by their port, and the object is otherwise
240 * not reachable from any place in the system (see semaphores, eventlink, etc),
241 * and die when the port has no more senders.
242 *
243 * However some kobjects might still be reachable from other means,
244 * and can make new send rights in a way that isn't synchronized with Mach IPC.
245 * (See IKOT_TASK_RESUME for an example of that).
246 *
247 * This function allows for such kobject types to verify under the
248 * synchronization it uses whether this no-senders callout is the last one,
249 * or if there has been new send rights made concurrently.
250 *
251 * @param port The target port.
252 * @param mscount The make-send count for which the no-senders
253 * notification was issued.
254 */
255 extern bool ipc_kobject_is_mscount_current(
256 ipc_port_t port,
257 mach_port_mscount_t mscount);
258
259 extern bool ipc_kobject_is_mscount_current_locked(
260 ipc_port_t port,
261 mach_port_mscount_t mscount);
262
263 /*!
264 * @function ipc_kobject_copy_send()
265 *
266 * @brief
267 * Copies a naked send right for the specified kobject port.
268 *
269 * @decription
270 * This function will validate that the specified port is pointing
271 * to the expected kobject pointer and type (by calling ipc_kobject_require()).
272 *
273 * @param port The target port.
274 * @param kobject The kobject pointer this port should be associated to.
275 * @param kotype The kobject type this port should have.
276 *
277 * @returns
278 * - IP_DEAD if @c port was dead.
279 * - @c port if @c port was valid, in which case
280 * a naked send right was made.
281 */
282 extern ipc_port_t ipc_kobject_copy_send(
283 ipc_port_t port,
284 ipc_kobject_t kobject,
285 ipc_kobject_type_t kotype) __result_use_check;
286
287 /*!
288 * @function ipc_kobject_make_send()
289 *
290 * @brief
291 * Makes a naked send right for the specified kobject port.
292 *
293 * @decription
294 * @see ipc_port_make_send_any_locked() for a general warning about
295 * making send rights.
296 *
297 * This function will validate that the specified port is pointing
298 * to the expected kobject pointer and type (by calling ipc_kobject_require()).
299 *
300 * @param port The target port.
301 * @param kobject The kobject pointer this port should be associated to.
302 * @param kotype The kobject type this port should have.
303 *
304 * @returns
305 * - IP_DEAD if @c port was dead.
306 * - @c port if @c port was valid, in which case
307 * a naked send right was made.
308 */
309 extern ipc_port_t ipc_kobject_make_send(
310 ipc_port_t port,
311 ipc_kobject_t kobject,
312 ipc_kobject_type_t kotype) __result_use_check;
313
314 #define IPC_KOBJECT_NO_MSCOUNT (~0ull)
315
316 extern ipc_kobject_t ipc_kobject_dealloc_port_and_unlock(
317 ipc_port_t port,
318 uint64_t mscount,
319 ipc_kobject_type_t type);
320
321 extern ipc_kobject_t ipc_kobject_dealloc_port(
322 ipc_port_t port,
323 uint64_t mscount,
324 ipc_kobject_type_t type);
325
326 extern void ipc_kobject_enable(
327 ipc_port_t port,
328 ipc_kobject_t kobject,
329 ipc_kobject_type_t type);
330
331 /*!
332 * @function ipc_kobject_require()
333 *
334 * @brief
335 * Asserts that a given port is of the specified type
336 * with the expected kobject pointer.
337 *
338 * @decription
339 * Port type confusion can lead to catastrophic system compromise,
340 * this function can be used in choke points to ensure ports are
341 * what they're expected to be before their use.
342 *
343 * @note It is allowed for the kobject pointer to be NULL,
344 * as in some cases ipc_kobject_disable() can be raced with this check.
345 *
346 * @param port The target port.
347 * @param kobject The kobject pointer this port should be associated to.
348 * @param kotype The kobject type this port should have.
349 */
350 extern void ipc_kobject_require(
351 ipc_port_t port,
352 ipc_kobject_t kobject,
353 ipc_kobject_type_t kotype);
354
355 extern ipc_kobject_t ipc_kobject_get_raw(
356 ipc_port_t port,
357 ipc_kobject_type_t type);
358
359 extern ipc_kobject_t ipc_kobject_get_locked(
360 ipc_port_t port,
361 ipc_kobject_type_t type);
362
363 extern ipc_kobject_t ipc_kobject_get_stable(
364 ipc_port_t port,
365 ipc_kobject_type_t type);
366
367 extern ipc_kobject_t ipc_kobject_disable_locked(
368 ipc_port_t port,
369 ipc_kobject_type_t type);
370
371 extern ipc_kobject_t ipc_kobject_disable(
372 ipc_port_t port,
373 ipc_kobject_type_t type);
374
375 /* Check if a kobject can be copied out to a given space */
376 extern bool ipc_kobject_label_check_or_substitute(
377 ipc_space_t space,
378 ipc_port_t port,
379 ipc_object_label_t *label,
380 mach_msg_type_name_t msgt_name,
381 ipc_port_t *subst_portp) __result_use_check;
382
383 /*!
384 * @brief
385 * Evaluate a port for substitution and kobject label rules.
386 *
387 * @discussion
388 * This function has a really cumbersome calling convention.
389 *
390 * If it returns false, then it means that some policy was violated,
391 * in that case, @c port has been unlocked, and @c label put.
392 *
393 * If it returns true, and subst_portp is not IP_NULL, then @c port
394 * has been unlocked, and @c label put, and the caller is expected
395 * to redrive evaluation with that substitution port.
396 *
397 * If it returns true, and subst_port is IP_NULL, then @c port
398 * is still locked, and @c label still valid, and the caller is expected
399 * to proceed further.
400 *
401 * @param space The current space
402 * @param port The port to evaluate (must be locked and active)
403 * @param label (In/out) the label for @c port.
404 * @param msgt_name The disposition for @c port in the message.
405 * @param subst_portp (out) an optional substitution port,
406 * to replace @c port with.
407 */
408 __result_use_check
409 static inline bool
ip_label_check_or_substitute(ipc_space_t space,ipc_port_t port,ipc_object_label_t * label,mach_msg_type_name_t msgt_name,ipc_port_t * subst_portp)410 ip_label_check_or_substitute(
411 ipc_space_t space,
412 ipc_port_t port,
413 ipc_object_label_t *label,
414 mach_msg_type_name_t msgt_name,
415 ipc_port_t *subst_portp)
416 {
417 if (!io_is_kobject_type(label->io_type) || !label->iol_kobject) {
418 *subst_portp = IP_NULL;
419 return true;
420 }
421 return ipc_kobject_label_check_or_substitute(space, port, label, msgt_name, subst_portp);
422 }
423
424 /* implementation details */
425
426 __startup_func
427 extern void ipc_kobject_register_startup(
428 ipc_kobject_ops_t ops);
429
430 /* Dispatch a kernel server function */
431 extern ipc_kmsg_t ipc_kobject_server(
432 ipc_port_t receiver,
433 ipc_kmsg_t request,
434 mach_msg_option64_t option);
435
436 #define null_conversion(port) (port)
437
438 extern void ipc_kobject_notify_send_once_and_unlock(
439 ipc_port_t port);
440
441 extern kern_return_t uext_server(
442 ipc_port_t receiver,
443 ipc_kmsg_t request,
444 ipc_kmsg_t *reply);
445
446 #endif /* MACH_KERNEL_PRIVATE */
447 #if XNU_KERNEL_PRIVATE
448
449 /*!
450 * @function ipc_typed_port_copyin_send()
451 *
452 * @brief
453 * Copies in a naked send right for the specified typed port.
454 *
455 * @decription
456 * This function will validate that the specified port is pointing
457 * to the expected kobject type, unless @c kotype is IOT_ANY,
458 * in which case any right is accepted.
459 *
460 * @param space The space to copyin in from.
461 * @param name The name to copyin.
462 * @param kotype The kobject type this port should have.
463 * @param port The resulting port or IP_NULL.
464 *
465 * @returns
466 * - KERN_SUCCESS Acquired an object, possibly IP_DEAD.
467 * - KERN_INVALID_TASK The space is dead.
468 * - KERN_INVALID_NAME Name doesn't exist in space.
469 * - KERN_INVALID_RIGHT Name doesn't denote correct right.
470 * - KERN_INVALID_CAPABILITY
471 * The right isn't of the right kobject type.
472 */
473 extern kern_return_t ipc_typed_port_copyin_send(
474 ipc_space_t space,
475 mach_port_name_t name,
476 ipc_kobject_type_t kotype,
477 ipc_port_t *port);
478
479 /*!
480 * @function ipc_typed_port_release_send()
481 *
482 * @brief
483 * Release a send right for a typed port.
484 *
485 * @description
486 * This is an alias for ipc_port_release_send() that the BSD side can use.
487 * If @c kotype is IOT_ANY, any right is accepted.
488 */
489 extern void ipc_typed_port_release_send(
490 ipc_port_t port,
491 ipc_kobject_type_t kotype);
492
493 #endif /* XNU_KERNEL_PRIVATE */
494 #pragma GCC visibility pop
495 __END_DECLS
496
497 #endif /* _KERN_IPC_KOBJECT_H_ */
498