xref: /xnu-11215.41.3/osfmk/ipc/ipc_policy.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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 <ipc/ipc_types.h>
33 #include <ipc/ipc_port.h>
34 
35 __BEGIN_DECLS __ASSUME_PTR_ABI_SINGLE_BEGIN
36 #pragma GCC visibility push(hidden)
37 
38 /*!
39  * @file <ipc/ipc_policy.h>
40  *
41  * @description
42  * This file exports interfaces that implement various security policies
43  * for Mach IPC.
44  */
45 
46 
47 #pragma mark compile time globals and configurations
48 
49 /*!
50  * @const IPC_HAS_LEGACY_MACH_MSG_TRAP
51  * Whether the legacy mach_msg_trap() is (somewhat) supported
52  */
53 #if XNU_TARGET_OS_OSX || XNU_TARGET_OS_IOS
54 #define IPC_HAS_LEGACY_MACH_MSG_TRAP    1
55 #else
56 #define IPC_HAS_LEGACY_MACH_MSG_TRAP    0
57 #endif
58 
59 /*!
60  * @const IPC_KOBJECT_DESC_MAX
61  * The maximum number of inline descriptors
62  * allowed in an incoming MACH64_SEND_KOBJECT_CALL message.
63  */
64 #define IPC_KOBJECT_DESC_MAX          3
65 /*!
66  * @const IPC_KOBJECT_RDESC_MAX
67  * The maximum number of inline descriptors
68  * allowed in a reply to a MACH64_SEND_KOBJECT_CALL message.
69  */
70 #define IPC_KOBJECT_RDESC_MAX        32
71 
72 /*!
73  * @const IPC_KMSG_MAX_BODY_SPACE
74  * Maximum size of ipc kmsg body sizes (not including trailer or aux).
75  */
76 #define IPC_KMSG_MAX_BODY_SPACE ((64 * 1024 * 1024 * 3) / 4 - MAX_TRAILER_SIZE)
77 
78 /*!
79  * @const IPC_KMSG_MAX_AUX_DATA_SPACE
80  * Maximum size for the auxiliary data of an IPC kmsg.
81  */
82 #define IPC_KMSG_MAX_AUX_DATA_SPACE  1024
83 
84 /*!
85  * @const IPC_KMSG_MAX_OOL_PORT_COUNT
86  * The maximum number of ports that can be sent at once in a message.
87  */
88 #define IPC_KMSG_MAX_OOL_PORT_COUNT  16383
89 
90 
91 #pragma mark policy utils
92 
93 /*!
94  * @brief
95  * Implementation backend for ipc_unreachable() and friends.
96  */
97 __abortlike
98 extern void __ipc_unreachable(
99 	const char *reason,
100 	const char *file,
101 	int         line);
102 
103 /*!
104  * @brief
105  * Denote that a path is unreachable.
106  *
107  * @discussion
108  * If this codepath is ever reached, it will reliably panic,
109  * even on release kernels.
110  */
111 #define ipc_unreachable(reason) \
112 	__ipc_unreachable(reason, __FILE_NAME__, __LINE__)
113 
114 /*!
115  * @brief
116  * Performs an invariant check that stays on release kernels.
117  */
118 #define ipc_release_assert(expr) \
119 	((expr) ? (void)0 : ipc_unreachable(#expr))
120 
121 
122 #pragma mark policy options
123 
124 /*!
125  * @brief
126  * Derive the current policy flags for the current process.
127  *
128  * @discussion
129  * This function will derive the proper in-kernel mach_msg options
130  * from user specified flags and the current context.
131  *
132  * @param task          the current task
133  * @param user_flags    flags passed in from userspace
134  */
135 extern mach_msg_option64_t ipc_current_user_policy(
136 	task_t                  task,
137 	mach_msg_option64_t     user_flags);
138 
139 /*!
140  * @brief
141  * Preflight send options for invalid combinations
142  *
143  * @discussion
144  * If the send options have "obviously" incorrect parameters,
145  * then a mach port guard exception (@c kGUARD_EXC_INVALID_OPTIONS) is raised.
146  *
147  * @param opts          the mach_msg() options, after sanitization
148  *                      via @c ipc_current_user_policy().
149  * @returns
150  * - MACH_MSG_SUCCESS   success,
151  * - MACH_SEND_INVALID_OPTIONS
152  *                      for failure cases if MACH64_MACH_MSG2 is set
153  * - KERN_NOT_SUPPORTED for failure cases if MACH64_MACH_MSG2 is not set
154  */
155 extern mach_msg_return_t ipc_preflight_msg_option64(
156 	mach_msg_option64_t     opts);
157 
158 
159 #pragma mark legacy trap policies
160 #if IPC_HAS_LEGACY_MACH_MSG_TRAP
161 
162 /*!
163  * @brief
164  * Whether the current task is allowed to use the legacy @c mach_msg_trap().
165  *
166  * @description
167  * If using the legacy mach_msg_trap() is disallowed, this will raise
168  * a mach port guard exception (@c kGUARD_EXC_INVALID_OPTIONS).
169  *
170  * Nothing should be locked.
171  *
172  * @param msgid         the message ID of the message being sent
173  *                      with the legacy interface.
174  * @param opts          the mach_msg() options passed to the legacy interface,
175  *                      after sanitization via @c ipc_current_user_policy().
176  * @returns
177  * - MACH_MSG_SUCCESS   success,
178  * - KERN_NOT_SUPPORTED for failure cases.
179  */
180 extern mach_msg_return_t ipc_policy_allow_legacy_send_trap(
181 	mach_msg_id_t           msgid,
182 	mach_msg_option64_t     opts);
183 
184 
185 #endif /* IPC_HAS_LEGACY_MACH_MSG_TRAP */
186 #pragma mark reply port semantics telemetry [temporary]
187 
188 extern void stash_reply_port_semantics_violations_telemetry(
189 	mach_service_port_info_t sp_info,
190 	int                     reply_port_semantics_violation,
191 	int                     msgh_id);
192 
193 
194 #pragma mark MACH_SEND_MSG policies
195 
196 /*!
197  * @brief
198  * Validation function that runs after the message header bytes have been copied
199  * from user, but before any other content or right is copied in.
200  *
201  * @discussion
202  * Nothing should be locked.
203  *
204  * @param hdr           the user message header bytes, before anything
205  *                      else has been copied in.
206  * @param dsc_count     the number of inline descriptors for the user message.
207  * @param opts          the mach_msg() options, after sanitization
208  *                      via @c ipc_current_user_policy().
209  *
210  * @returns
211  * - MACH_MSG_SUCCESS   the message passed validation
212  * - MACH_SEND_TOO_LARGE
213  *                      a MACH64_SEND_KOBJECT_CALL had too many descriptors.
214  * - MACH_MSG_VM_KERNEL the message would use more than ipc_kmsg_max_vm_space
215  *                      of kernel wired memory.
216  */
217 extern mach_msg_return_t ipc_validate_kmsg_header_schema_from_user(
218 	mach_msg_user_header_t *hdr,
219 	mach_msg_size_t         dsc_count,
220 	mach_msg_option64_t     opts);
221 
222 /*!
223  * @brief
224  * Validation function that runs after the message bytes has been copied from
225  * user, but before any right is copied in.
226  *
227  * @discussion
228  * Nothing should be locked.
229  *
230  * @param kdata         the "kernel data" part of the incoming message.
231  *                      the descriptors data is copied in "kernel" format.
232  * @param send_uctx     the IPC kmsg send context for the current send operation.
233  * @param opts          the mach_msg() options, after sanitization
234  *                      via @c ipc_current_user_policy().
235  *
236  * @returns
237  * - MACH_MSG_SUCCESS   the message passed validation
238  * - MACH_SEND_TOO_LARGE
239  *                      a MACH64_SEND_KOBJECT_CALL had too many descriptors.
240  * - MACH_MSG_VM_KERNEL the message would use more than ipc_kmsg_max_vm_space
241  *                      of kernel wired memory.
242  */
243 extern mach_msg_return_t ipc_validate_kmsg_schema_from_user(
244 	mach_msg_header_t      *kdata,
245 	mach_msg_send_uctx_t   *send_uctx,
246 	mach_msg_option64_t     opts);
247 
248 
249 /*!
250  * @brief
251  * Validation function that runs after the rights in the message header have
252  * been copied in.
253  *
254  * @discussion
255  * Nothing should be locked.
256  *
257  * @param hdr           the copied in message header.
258  * @param send_uctx     the IPC kmsg send context for the current send operation.
259  * @param opts          the mach_msg() options, after sanitization
260  *                      via @c ipc_current_user_policy().
261  * @returns
262  * - MACH_MSG_SUCCESS   the message passed validation
263  * - MACH_SEND_INVALID_OPTIONS
264  *                      some options are incompatible with the destination
265  *                      of the message. a kGUARD_EXC_INVALID_OPTIONS guard
266  *                      will be raised.
267  * - MACH_SEND_MSG_FILTERED
268  *                      the message failed a filtering check.
269  *                      a kGUARD_EXC_MSG_FILTERED guard might be raised.
270  * - MACH_SEND_NO_GRANT_DEST
271  *                      attempting to send descriptors to a no_grant port.
272  */
273 extern mach_msg_return_t ipc_validate_kmsg_header_from_user(
274 	mach_msg_header_t      *hdr,
275 	mach_msg_send_uctx_t   *send_uctx,
276 	mach_msg_option64_t     opts);
277 
278 
279 #pragma GCC visibility pop
280 __ASSUME_PTR_ABI_SINGLE_END __END_DECLS
281 
282 #endif  /* _IPC_IPC_POLICY_H_ */
283