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