xref: /xnu-12377.1.9/osfmk/ipc/ipc_policy.h (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1 /*
2  * Copyright (c) 2023 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 #ifndef _IPC_IPC_POLICY_H_
30 #define _IPC_IPC_POLICY_H_
31 
32 #include <kern/assert.h>
33 #include <ipc/port.h>
34 #include <ipc/ipc_types.h>
35 #include <ipc/ipc_port.h>
36 
37 
38 __BEGIN_DECLS __ASSUME_PTR_ABI_SINGLE_BEGIN
39 #pragma GCC visibility push(hidden)
40 
41 /*!
42  * @file <ipc/ipc_policy.h>
43  *
44  * @description
45  * This file exports interfaces that implement various security policies
46  * for Mach IPC.
47  */
48 
49 
50 #pragma mark compile time globals and configurations
51 
52 /*!
53  * @const IPC_HAS_LEGACY_MACH_MSG_TRAP
54  * Whether the legacy mach_msg_trap() is (somewhat) supported
55  */
56 #if XNU_TARGET_OS_OSX
57 #define IPC_HAS_LEGACY_MACH_MSG_TRAP    1
58 #else
59 #define IPC_HAS_LEGACY_MACH_MSG_TRAP    0
60 #endif /* XNU_TARGET_OS_OSX */
61 
62 /*!
63  * @const IPC_KOBJECT_DESC_MAX
64  * The maximum number of inline descriptors
65  * allowed in an incoming MACH64_SEND_KOBJECT_CALL message.
66  */
67 #define IPC_KOBJECT_DESC_MAX          3
68 /*!
69  * @const IPC_KOBJECT_RDESC_MAX
70  * The maximum number of inline descriptors
71  * allowed in a reply to a MACH64_SEND_KOBJECT_CALL message.
72  */
73 #define IPC_KOBJECT_RDESC_MAX        32
74 
75 /*!
76  * @const IPC_KMSG_MAX_BODY_SPACE
77  * Maximum size of ipc kmsg body sizes (not including trailer or aux).
78  */
79 #define IPC_KMSG_MAX_BODY_SPACE ((64 * 1024 * 1024 * 3) / 4 - MAX_TRAILER_SIZE)
80 
81 /*!
82  * @const IPC_KMSG_MAX_AUX_DATA_SPACE
83  * Maximum size for the auxiliary data of an IPC kmsg.
84  */
85 #define IPC_KMSG_MAX_AUX_DATA_SPACE  1024
86 
87 /*!
88  * @const IPC_KMSG_MAX_OOL_PORT_COUNT
89  * The maximum number of ports that can be sent at once in a message.
90  */
91 #define IPC_KMSG_MAX_OOL_PORT_COUNT  16383
92 
93 /*!
94  * @const IPC_POLICY_ENHANCED_V0
95  * This policy represents platform binaries, hardened-runtime and
96  * everything below it.
97  */
98 #define IPC_POLICY_ENHANCED_V0 \
99 	(IPC_SPACE_POLICY_ENHANCED | IPC_SPACE_POLICY_ENHANCED_V0)
100 
101 /*!
102  * @const IPC_POLICY_ENHANCED_V1
103  * This policy represents ES features exposed to 3P in FY2024 release.
104  */
105 #define IPC_POLICY_ENHANCED_V1 \
106 	(IPC_SPACE_POLICY_ENHANCED | IPC_SPACE_POLICY_ENHANCED_V1)
107 
108 /*!
109  * @const IPC_POLICY_ENHANCED_V2
110  * This policy represents ES features exposed to 3P in FY2025 release.
111  */
112 #define IPC_POLICY_ENHANCED_V2 \
113 	(IPC_SPACE_POLICY_ENHANCED | IPC_SPACE_POLICY_ENHANCED_V2)
114 
115 #pragma mark policy tunables
116 
117 __options_decl(ipc_control_port_options_t, uint32_t, {
118 	ICP_OPTIONS_NONE                = 0x00,
119 
120 	/* policy for IPC_SPACE_POLICY_{PLATFORM,HARDENED} */
121 	ICP_OPTIONS_PINNED_1P_SOFT      = 0x01,
122 	ICP_OPTIONS_PINNED_1P_HARD      = 0x02,
123 	ICP_OPTIONS_IMMOVABLE_1P_SOFT   = 0x04,
124 	ICP_OPTIONS_IMMOVABLE_1P_HARD   = 0x08,
125 
126 	/* policy for other processes */
127 	ICP_OPTIONS_PINNED_3P_SOFT      = 0x10,
128 	ICP_OPTIONS_PINNED_3P_HARD      = 0x20,
129 	ICP_OPTIONS_IMMOVABLE_3P_SOFT   = 0x40,
130 	ICP_OPTIONS_IMMOVABLE_3P_HARD   = 0x80,
131 });
132 
133 /*!
134  * @brief
135  * Policy for task and thread control ports.
136  */
137 extern ipc_control_port_options_t ipc_control_port_options;
138 
139 /*!
140  * @brief
141  * Whether service port defense in depth is enabled.
142  */
143 extern bool service_port_defense_enabled;
144 
145 /*!
146  * @brief
147  * Whether out-of-line port array descriptor
148  * restrictions are enabled.
149  */
150 extern bool ool_port_array_enforced;
151 
152 #pragma mark policy utils
153 
154 /*!
155  * @brief
156  * Denote that a path is unreachable.
157  *
158  * @discussion
159  * If this codepath is ever reached, it will reliably panic,
160  * even on release kernels.
161  */
162 #define ipc_unreachable(reason)         mach_assert_abort(reason)
163 
164 /*!
165  * @brief
166  * Performs an invariant check that stays on release kernels.
167  */
168 #define ipc_release_assert(expr)        release_assert(expr)
169 
170 
171 #pragma mark policy options
172 
173 
174 /*!
175  * @brief
176  * Convert mach_msg policy options (originally derived from the current_task space) back into the space namespace
177  *
178  * @param opts      the options to convert
179  *
180  * @return          the options for the space
181  */
182 extern ipc_space_policy_t ipc_convert_msg_options_to_space(
183 	mach_msg_option64_t     opts);
184 
185 /*!
186  * @brief
187  * Computes the IPC policy for a given task.
188  *
189  * @param task          the current task
190  */
191 extern ipc_space_policy_t ipc_policy_for_task(
192 	task_t                  task);
193 
194 /*!
195  * @brief
196  * Derive the current policy flags for the current process.
197  *
198  * @discussion
199  * This function will derive the proper in-kernel mach_msg options
200  * from user specified flags and the current context.
201  *
202  * @param task          the current task
203  * @param user_flags    flags passed in from userspace
204  */
205 extern mach_msg_option64_t ipc_current_msg_options(
206 	task_t                  task,
207 	mach_msg_option64_t     user_flags);
208 
209 /*!
210  * @brief
211  * Preflight send options for invalid combinations
212  *
213  * @discussion
214  * If the send options have "obviously" incorrect parameters,
215  * then a mach port guard exception (@c kGUARD_EXC_INVALID_OPTIONS) is raised.
216  *
217  * @param opts          the mach_msg() options, after sanitization
218  *                      via @c ipc_current_msg_options().
219  * @returns
220  * - MACH_MSG_SUCCESS   success,
221  * - MACH_SEND_INVALID_OPTIONS
222  *                      for failure cases if MACH64_MACH_MSG2 is set
223  * - KERN_NOT_SUPPORTED for failure cases if MACH64_MACH_MSG2 is not set
224  */
225 extern mach_msg_return_t ipc_preflight_msg_option64(
226 	mach_msg_option64_t     opts);
227 
228 /*!
229  * @brief
230  * Determines whether ipc policies should be applied
231  *
232  * @discussion
233  * This checks whether the current policy level matches the policy level
234  * of this particular feature, but this helper also allows for various
235  * ways for a task to be opted out of ipc security policies, such as if
236  * they have the IPC_SPACE_POLICY_SIMULATED, *_TRANSLATED, or *_OPTED_OUT flags.
237  *
238  * @param current_policy        the policy level for the task/space that we are enforcing on
239  * @param requested_level       the policy level that is required to be opted into this enforcement
240  *
241  * @returns
242  * - true       if the current policy level matches the requested policy
243  *              level for this feature, and the task is not opted out
244  * - false      otherwise
245  */
246 extern bool ipc_should_apply_policy(
247 	const ipc_space_policy_t current_policy,
248 	const ipc_space_policy_t requested_level);
249 
250 
251 #pragma mark legacy trap policies
252 #if IPC_HAS_LEGACY_MACH_MSG_TRAP
253 
254 /*!
255  * @brief
256  * Whether the current task is allowed to use the legacy @c mach_msg_trap().
257  *
258  * @description
259  * If using the legacy mach_msg_trap() is disallowed, this will raise
260  * a mach port guard exception (@c kGUARD_EXC_INVALID_OPTIONS).
261  *
262  * @discussion
263  * Nothing should be locked.
264  *
265  * @param msgid         the message ID of the message being sent
266  *                      with the legacy interface.
267  * @param opts          the mach_msg() options passed to the legacy interface,
268  *                      after sanitization via @c ipc_current_msg_options().
269  * @returns
270  * - MACH_MSG_SUCCESS   success,
271  * - KERN_NOT_SUPPORTED for failure cases.
272  */
273 extern mach_msg_return_t ipc_policy_allow_legacy_send_trap(
274 	mach_msg_id_t           msgid,
275 	mach_msg_option64_t     opts);
276 
277 
278 #endif /* IPC_HAS_LEGACY_MACH_MSG_TRAP */
279 #pragma mark policy array
280 
281 /*!
282  * @brief
283  * Decides the policy around receive right movability.
284  *
285  * @const IPC_MOVE_POLICY_NEVER
286  * Such ports are born in the IO_STATE_IN_SPACE_IMMOVABLE state.
287  * Moving or arming port-destroyed notification on such rights
288  * is disallowed.
289  *
290  * @const IPC_MOVE_POLICY_ONCE
291  * Such ports are born in the IO_STATE_IN_SPACE state.
292  *
293  * Arming port destroyed notification on such ports is allowed,
294  * and they will move to IO_STATE_IN_SPACE_IMMOVABLE after their first move.
295  *
296  * Their state will remain IO_STATE_IN_SPACE_IMMOVABLE after a port-destroyed
297  * notification fires.
298  *
299  * @const IPC_MOVE_POLICY_ONCE_OR_AFTER_PD
300  * Such ports are born in the IO_STATE_IN_SPACE state.
301  *
302  * This behaves like @c IPC_MOVE_POLICY_ONCE, but resets to IO_STATE_IN_SPACE
303  * after a port-destroyed notification is delivered.
304  *
305  * @const IPC_MOVE_POLICY_ALWAYS
306  * The port is always movable.
307  */
308 __enum_decl(ipc_move_policy_t, uint32_t, {
309 	IPC_MOVE_POLICY_NEVER,
310 	IPC_MOVE_POLICY_ONCE,
311 	IPC_MOVE_POLICY_ONCE_OR_AFTER_PD,
312 	IPC_MOVE_POLICY_ALWAYS,
313 });
314 
315 /*!
316  * @brief
317  * Type for port policies
318  */
319 typedef const struct ipc_object_policy {
320 	const char             *pol_name;
321 
322 	/** see iko_op_stable */
323 	unsigned long           pol_kobject_stable : 1;
324 	/** see iko_op_permanent */
325 	unsigned long           pol_kobject_permanent : 1;
326 
327 	/** whether the port is movable */
328 	ipc_move_policy_t       pol_movability : 2;
329 
330 
331 	/** `mach_port_request_notification` protections */
332 
333 	/**
334 	 * allow arming a `MACH_NOTIFY_PORT_DESTROYED` notification
335 	 * on this receive right
336 	 */
337 	unsigned long           pol_notif_port_destroy  : 1;
338 	/**
339 	 * allow arming a `MACH_NOTIFY_NO_SENDERS` notification
340 	 * on this receive right
341 	 */
342 	unsigned long           pol_notif_no_senders    : 1;
343 	/**
344 	 * allow arming a `MACH_NOTIFY_DEAD_NAME/MACH_NOTIFY_SEND_POSSIBLE`
345 	 * notification on this receive right
346 	 */
347 	unsigned long           pol_notif_dead_name     : 1;
348 
349 
350 	/** whether the port requires incoming messages to use an IOT_REPLY_PORT properly */
351 	unsigned long           pol_enforce_reply_semantics : 1;
352 
353 	/**
354 	 * whether send rights created on this port are movable,
355 	 * immovable ports still allow "movement" via MAKE_SEND(_ONCE)
356 	 */
357 	unsigned long           pol_movable_send : 1;
358 
359 	/** required entitlement for platform restrictions binaries to create this port */
360 	const char *pol_construct_entitlement;
361 
362 	/** see iko_op_no_senders */
363 	void                  (*pol_kobject_no_senders)(
364 		ipc_port_t              port,
365 		mach_port_mscount_t     mscount);
366 
367 	/** destroys the label for this port */
368 	void                  (*pol_label_free)(
369 		ipc_object_label_t      label);
370 } *ipc_object_policy_t;
371 
372 /*!
373  * @brief
374  * Array of policies per port type.
375  */
376 extern struct ipc_object_policy ipc_policy_array[IOT_UNKNOWN];
377 
378 /*!
379  * @brief
380  * Returns the policy for a given type/object/port/...
381  */
382 __attribute__((overloadable, always_inline, const))
383 static inline ipc_object_policy_t
ipc_policy(ipc_object_type_t otype)384 ipc_policy(ipc_object_type_t otype)
385 {
386 	ipc_release_assert(otype < IOT_UNKNOWN);
387 	return &ipc_policy_array[otype];
388 }
389 
390 __attribute__((overloadable, always_inline, const))
391 static inline ipc_object_policy_t
ipc_policy(ipc_object_label_t label)392 ipc_policy(ipc_object_label_t label)
393 {
394 	return ipc_policy(label.io_type);
395 }
396 
397 __attribute__((overloadable, always_inline, const))
398 static inline ipc_object_policy_t
ipc_policy(ipc_object_t object)399 ipc_policy(ipc_object_t object)
400 {
401 	return ipc_policy(object->io_type);
402 }
403 
404 __attribute__((overloadable, always_inline, const))
405 static inline ipc_object_policy_t
ipc_policy(ipc_port_t port)406 ipc_policy(ipc_port_t port)
407 {
408 	return ipc_policy(ip_type(port));
409 }
410 
411 
412 #pragma mark ipc policy telemetry [temporary]
413 
414 /* The bootarg to disable ALL ipc policy violation telemetry */
415 extern bool ipcpv_telemetry_enabled;
416 
417 /* Enables reply port/voucher/persona debugging code */
418 extern bool enforce_strict_reply;
419 
420 extern bool prp_enforcement_enabled;
421 
422 extern bool bootstrap_port_telemetry_enabled;
423 
424 /*!
425  * @brief
426  * Identifier of the type of ipc policy violation in a CA telemetry event
427  *
428  * Currently we only send reply port related violations to CA. This enum can
429  * be extended to report more violations in the future.
430  */
431 __enum_closed_decl(ipc_policy_violation_id_t, uint8_t, {
432 	IPCPV_VIOLATION_NONE, /* 0, denote no violations */
433 
434 	/* Kobject Reply Port and Move Reply Port violators Start */
435 	IPCPV_REPLY_PORT_SEMANTICS, /* 1, normal reply port semantics violator */
436 	/* [2-5] were previously used; should be avoided to avoid telemetry confusion */
437 	__UNUSED2, /* previously used, should be avoided */
438 	__UNUSED3, /* previously used, should be avoided */
439 	__UNUSED4, /* previously used, should be avoided */
440 	__UNUSED5, /* previously used, should be avoided */
441 	/* services opted out of reply port semantics previously should have fixed their violations */
442 	IPCPV_REPLY_PORT_SEMANTICS_OPTOUT, /* 6 */
443 	/* Kobject Reply Port and Move Reply Port Violators End */
444 
445 	/* Service Port Defense Violators Start */
446 	IPCPV_MOVE_SERVICE_PORT, /* 7 */
447 	IPCPV_SERVICE_PORT_PD_NOTIFICATION, /* 8, for future telemetry */
448 	/* Service Port Defense Violators End */
449 
450 	/*
451 	 * [9-12] were previously used for OOL port array restrictions;
452 	 * these should be avoided to avoid telemetry confusion
453 	 */
454 	__UNUSED6, /* 9 previously used, should be avoided */
455 	__UNUSED7, /* 10 previously used, should be avoided */
456 	__UNUSED8, /* 11 previously used, should be avoided */
457 	__UNUSED9, /* 12 previously used, should be avoided */
458 	/* OOL ports array violators End */
459 
460 	/* Bootstrap port reply port semantics violators Start */
461 	IPCPV_BOOTSTRAP_PORT, /* 13 */
462 	/* Bootstrap port reply port semantics violators End */
463 
464 	_IPCPV_VIOLATION_COUNT,
465 });
466 
467 /*!
468  * @brief
469  * Record ipc policy violations into a buffer for sending to CA at a later time.
470  *
471  * @discussion
472  * The ipc telemetry lock is not locked.
473  *
474  * @param violation_id      type of ipc policy violation
475  * @param service_port      service port involved in violation, if any
476  * @param aux_data          additional data to include in the CA event:
477  *                          violator msgh_id for reply port defense
478  */
479 extern void ipc_stash_policy_violations_telemetry(
480 	ipc_policy_violation_id_t   violation_id,
481 	ipc_port_t                  service_port,
482 	int                         aux_data);
483 
484 #if DEBUG || DEVELOPMENT
485 /*!
486  * @brief
487  * Helper function to record the total number of ipcpv violation occured.
488  * Telemetry count should be 0 in presub testing as we shouldn't emit any
489  * telemetry for known issue.
490  */
491 extern void ipc_inc_telemetry_count(void);
492 #endif /* DEBUG || DEVELOPMENT */
493 
494 /*!
495  * @brief
496  * Check if the ipc space has emitted a certain type of telemetry.
497  *
498  * @param is      ipc space in question
499  * @param type    ipc policy violation type
500  */
501 __attribute__((always_inline))
502 static inline bool
ipc_space_has_telemetry_type(ipc_space_t is,uint8_t type)503 ipc_space_has_telemetry_type(ipc_space_t is, uint8_t type)
504 {
505 	if (!ipcpv_telemetry_enabled) {
506 		return true;
507 	}
508 
509 #if DEBUG || DEVELOPMENT
510 	ipc_inc_telemetry_count();
511 #endif
512 
513 	return (os_atomic_or_orig(&is->is_telemetry, type, relaxed) & type) != 0;
514 }
515 
516 #pragma mark MACH_SEND_MSG policies
517 
518 /*!
519  * @brief
520  * Validation function that runs after the message header bytes have been copied
521  * from user, but before any other content or right is copied in.
522  *
523  * @discussion
524  * Nothing should be locked.
525  *
526  * @param hdr           the user message header bytes, before anything
527  *                      else has been copied in.
528  * @param dsc_count     the number of inline descriptors for the user message.
529  * @param opts          the mach_msg() options, after sanitization
530  *                      via @c ipc_current_msg_options().
531  *
532  * @returns
533  * - MACH_MSG_SUCCESS   the message passed validation
534  * - MACH_SEND_TOO_LARGE
535  *                      a MACH64_SEND_KOBJECT_CALL had too many descriptors.
536  * - MACH_MSG_VM_KERNEL the message would use more than ipc_kmsg_max_vm_space
537  *                      of kernel wired memory.
538  */
539 extern mach_msg_return_t ipc_validate_kmsg_header_schema_from_user(
540 	mach_msg_user_header_t *hdr,
541 	mach_msg_size_t         dsc_count,
542 	mach_msg_option64_t     opts);
543 
544 /*!
545  * @brief
546  * Validation function that runs after the message bytes has been copied from
547  * user, but before any right is copied in.
548  *
549  * @discussion
550  * Nothing should be locked.
551  *
552  * @param kdata         the "kernel data" part of the incoming message.
553  *                      the descriptors data is copied in "kernel" format.
554  * @param send_uctx     the IPC kmsg send context for the current send operation.
555  * @param opts          the mach_msg() options, after sanitization
556  *                      via @c ipc_current_msg_options().
557  *
558  * @returns
559  * - MACH_MSG_SUCCESS   the message passed validation
560  * - MACH_SEND_TOO_LARGE
561  *                      a MACH64_SEND_KOBJECT_CALL had too many descriptors.
562  * - MACH_MSG_VM_KERNEL the message would use more than ipc_kmsg_max_vm_space
563  *                      of kernel wired memory.
564  */
565 extern mach_msg_return_t ipc_validate_kmsg_schema_from_user(
566 	mach_msg_header_t      *kdata,
567 	mach_msg_send_uctx_t   *send_uctx,
568 	mach_msg_option64_t     opts);
569 
570 /*!
571  * @brief
572  * Validation function that runs after the rights in the message header have
573  * been copied in.
574  *
575  * @discussion
576  * Nothing should be locked.
577  *
578  * @param hdr           the copied in message header.
579  * @param send_uctx     the IPC kmsg send context for the current send operation.
580  * @param opts          the mach_msg() options, after sanitization
581  *                      via @c ipc_current_msg_options().
582  * @returns
583  * - MACH_MSG_SUCCESS   the message passed validation
584  * - MACH_SEND_INVALID_OPTIONS
585  *                      some options are incompatible with the destination
586  *                      of the message. a kGUARD_EXC_INVALID_OPTIONS guard
587  *                      will be raised.
588  * - MACH_SEND_MSG_FILTERED
589  *                      the message failed a filtering check.
590  *                      a kGUARD_EXC_MSG_FILTERED guard might be raised.
591  */
592 extern mach_msg_return_t ipc_validate_kmsg_header_from_user(
593 	mach_msg_header_t      *hdr,
594 	mach_msg_send_uctx_t   *send_uctx,
595 	mach_msg_option64_t     opts);
596 
597 
598 #pragma mark port type policies and callouts
599 
600 /*!
601  * @brief
602  * Frees a label value according to the port type callout.
603  *
604  * @param label         The label to destroy.
605  */
606 static inline void
ipc_port_label_free(ipc_object_label_t label)607 ipc_port_label_free(ipc_object_label_t label)
608 {
609 	if (label.iol_pointer) {
610 		ipc_policy(label)->pol_label_free(label);
611 	}
612 }
613 
614 #pragma mark send immovability
615 
616 /*!
617  * @brief
618  * Returns whether an entry for this port should be marked as immovable send
619  *
620  * @param task      The task where the new entry is being created/copied out
621  * @param port      The port that the entry is being created/copied out for
622  *
623  * @returns
624  *      - true  The send right entry should be marked as immovable
625  *      - false The send right entry should not be marked as immovable
626  */
627 extern bool ipc_should_mark_immovable_send(
628 	task_t      task,
629 	ipc_port_t  port,
630 	ipc_object_label_t label);
631 
632 /*!
633  * @brief
634  * Determine whether we need to protect this port from being stashed as a naked
635  * send right in the kernel. We disallow this if the port is supposed to be immovable send
636  * as this would allow userspace to bypass the immovable send checks and move the send
637  * right to another process.
638  *
639  * @param port      The port that we want to protect
640  *
641  * @returns
642  *  - true          The port is allowed to be stashed
643  *  - false         The port is immovable send and should not be stashed
644  */
645 extern bool ipc_can_stash_naked_send(
646 	ipc_port_t port);
647 
648 
649 #pragma mark entry init
650 
651 /*!
652  * @brief
653  * Initialize the security fields/flags on a new right entry created through the
654  * new port creation path. This right could be any port or port set right.
655  *
656  * @param space         The space this entry is being created in
657  * @param object        The *initialized* port/portset object that is getting a new entry
658  * @param type          The type of this entry (send, send-once, receive, deadname, portset)
659  * @param entry         Pointer to the entry that is being initialized
660  * @param urefs         Number of refs this entry will be initialized to
661  * @param name          The name this entry will occupy in the space
662  */
663 extern void ipc_entry_init(
664 	ipc_space_t         space,
665 	ipc_object_t        object,
666 	mach_port_type_t    type,
667 	ipc_entry_t         entry,
668 	mach_port_urefs_t   urefs,
669 	mach_port_name_t    name);
670 
671 
672 #pragma mark receive immovability
673 
674 /*!
675  * @brief
676  * Returns whether the receive right of a port is allowed to move out
677  * of an ipc space.
678  *
679  * Condition: Space is write-locked and active. Port is not locked.
680  *
681  * @param space     The ipc space to copyin from
682  * @param port      The port whose receive right is being moved
683  *
684  * @returns
685  *      - true  The receive right can move out of the space
686  *      - false The receive right can not move out of the space
687  */
688 extern bool ipc_move_receive_allowed(
689 	ipc_space_t             space,
690 	ipc_port_t              port,
691 	mach_port_name_t        name);
692 
693 
694 #pragma mark policy guard violations
695 
696 /*!
697  * @brief
698  * Marks the thread with AST_MACH_EXCEPTION for mach port guard violation.
699  *
700  * @discussion
701  * Also saves exception info in thread structure.
702  *
703  * @param target        The port target of the exception (often a port name)
704  * @param payload       A 64bit value that will be put in the guard "subcode".
705  * @param reason        A valid mach_port_guard_exception_codes value.
706  */
707 __cold
708 extern void mach_port_guard_exception(
709 	uint32_t                target,
710 	uint64_t                payload,
711 	unsigned                reason);
712 
713 /*!
714  * @brief
715  * Deliver a soft or hard immovable guard exception.
716  *
717  * @param space         The space causing the immovable exception.
718  *                      The guard isn't delivered if it isn't the current space.
719  * @param name          The name of the port in @c space violating immovability.
720  * @param port          The port violating immovability (must be pol_movable_send).
721  */
722 __cold
723 extern void mach_port_guard_exception_immovable(
724 	ipc_space_t             space,
725 	mach_port_name_t        name,
726 	mach_port_t             port,
727 	mach_msg_type_name_t    disp,
728 	ipc_entry_t             entry);
729 
730 /*!
731  * @brief
732  * Deliver a soft or hard mod_refs guard exception.
733  *
734  * @param space         The space causing the pinned exception.
735  *                      The guard isn't delivered if it isn't the current space,
736  *                      or the task disables guards on pinned violations.
737  * @param name          The name of the entry in @c space violating pinned rules.
738  * @param payload       A valid @c MPG_FLAGS_MOD_REFS_PINNED_* value.
739  */
740 __cold
741 extern void mach_port_guard_exception_pinned(
742 	ipc_space_t             space,
743 	mach_port_name_t        name,
744 	uint64_t                payload);
745 
746 #pragma mark exception port policy
747 
748 /*!
749  * @brief
750  * Check whether the port can be a valid exception port for a given task.
751  *
752  * @param task          The task registering an exception port.
753  * @param port          The port being registered as exception port.
754  */
755 extern bool ipc_is_valid_exception_port(
756 	task_t task,
757 	ipc_port_t port);
758 
759 #pragma mark notification policies
760 
761 /*!
762  * @brief
763  * Check if requesting a port destroyed notification on pd_port is allowed.
764  *
765  * @discussion
766  * pd_port is locked and active.
767  * This function must raise a guard exception along every error path
768  *
769  * @param pd_port		the port to be reaped after destroy
770  * @param notify_port	the notify port that pd_port will be sent to after deat
771  *
772  * @returns
773  * - KERN_SUCCESS       port destroyed notification is allowed to be requested
774  * on this pd_port with this notify_port
775  * - KERN_FAILURE       pd_port already has a pd notification
776  * - KERN_INVALID_RIGHT some violation in the security policy
777  */
778 extern kern_return_t ipc_allow_register_pd_notification(
779 	ipc_port_t              pd_port,
780 	ipc_port_t              notify_port);
781 
782 #pragma GCC visibility pop
783 __ASSUME_PTR_ABI_SINGLE_END __END_DECLS
784 
785 #endif  /* _IPC_IPC_POLICY_H_ */
786