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