1 /* 2 * Copyright (c) 2000-2004 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 McAfee Research in 2004 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 * Copyright (c) 2005 SPARTA, Inc. 62 */ 63 /* 64 */ 65 /* 66 * File: ipc/ipc_kmsg.h 67 * Author: Rich Draves 68 * Date: 1989 69 * 70 * Definitions for kernel messages. 71 */ 72 73 #ifndef _IPC_IPC_KMSG_H_ 74 #define _IPC_IPC_KMSG_H_ 75 76 #include <mach/vm_types.h> 77 #include <mach/message.h> 78 #include <kern/kern_types.h> 79 #include <kern/assert.h> 80 #include <kern/macro_help.h> 81 #include <kern/kalloc.h> 82 #include <kern/circle_queue.h> 83 #include <ipc/ipc_types.h> 84 #include <ipc/ipc_object.h> 85 #include <sys/kdebug.h> 86 87 /* 88 * This structure is only the header for a kmsg buffer; 89 * the actual buffer is normally larger. The rest of the buffer 90 * holds the body of the message. 91 * 92 * In a kmsg, the port fields hold pointers to ports instead 93 * of port names. These pointers hold references. 94 * 95 * The ikm_header.msgh_remote_port field is the destination 96 * of the message. 97 * 98 * sync_qos and special_port_qos stores the qos for prealloced 99 * port, this fields could be deleted once we remove ip_prealloc. 100 */ 101 102 /* A kmsg can be in one of the following four layouts */ 103 __enum_decl(ipc_kmsg_type_t, uint8_t, { 104 /* 105 * IKM_TYPE_ALL_INLINED: The entire message (and aux) is allocated inline. 106 * mach_msg_header_t is immediately after the kmsg header. An optional aux 107 * may be following the inline message proper. 108 */ 109 IKM_TYPE_ALL_INLINED = 0, 110 /* 111 * IKM_TYPE_UDATA_OOL: Message header and descriptors are allocated inline, 112 * and message data, trailer, and aux are in buffer pointed to by ikm_udata. 113 * mach_msg_header_t is immediately after the kmsg header. 114 */ 115 IKM_TYPE_UDATA_OOL = 1, 116 /* 117 * IKM_TYPE_KDATA_OOL: The entire message is allocated out-of-line. 118 * An ipc_kmsg_vector_t follows the kmsg header specifying the address and 119 * size of the allocation. There is no aux data. 120 */ 121 IKM_TYPE_KDATA_OOL = 2, 122 /* 123 * IKM_TYPE_ALL_OOL: Everything is allocated out-of-line. Message header 124 * and descriptors are allocated from typed kernel heap (kalloc_type), and 125 * message data, trailer, and aux are in data buffer pointed to by ikm_udata. 126 * An ipc_kmsg_vector_t follows the kmsg header specifying the address and 127 * size of the kdata allocation. 128 */ 129 IKM_TYPE_ALL_OOL = 3 130 }); 131 132 struct ipc_kmsg { 133 queue_chain_t ikm_link; 134 union { 135 /* port we were preallocated from, for IKM_TYPE_ALL_INLINED */ 136 ipc_port_t XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_prealloc") ikm_prealloc; 137 /* user data buffer, unused for IKM_TYPE_ALL_INLINED */ 138 void *XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_udata") ikm_udata; 139 }; 140 ipc_port_t XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_voucher_port") ikm_voucher_port; /* voucher port carried */ 141 struct ipc_importance_elem *ikm_importance; /* inherited from */ 142 queue_chain_t ikm_inheritance; /* inherited from link */ 143 #if MACH_FLIPC 144 struct mach_node *ikm_node; /* originating node - needed for ack */ 145 #endif 146 mach_msg_size_t ikm_aux_size; /* size reserved for auxiliary data */ 147 uint32_t ikm_ppriority; /* pthread priority of this kmsg */ 148 union { 149 struct { 150 /* For PAC-supported devices */ 151 uint32_t ikm_sig_partial; /* partial sig for header + trailer */ 152 uint32_t ikm_sig_full; /* upper 32 bits is full signature */ 153 }; 154 uint64_t ikm_signature; /* sig for all kernel-processed data */ 155 }; 156 ipc_object_copyin_flags_t ikm_flags; 157 mach_msg_qos_t ikm_qos_override; /* qos override on this kmsg */ 158 159 mach_msg_type_name_t ikm_voucher_type: 6; /* disposition type the voucher came in with */ 160 ipc_kmsg_type_t ikm_type: 2; 161 162 /* size of buffer pointed to by ikm_udata, unused for IKM_TYPE_ALL_INLINED. */ 163 mach_msg_size_t ikm_udata_size; 164 /* inline data of size IKM_SAVED_MSG_SIZE follows */ 165 }; 166 167 typedef struct { 168 void *XNU_PTRAUTH_SIGNED_PTR("kmsgv.kmsgv_data") kmsgv_data; 169 mach_msg_size_t kmsgv_size; /* size of buffer, or descriptor count */ 170 } ipc_kmsg_vector_t; 171 172 /* 173 * XXX For debugging. 174 */ 175 #define IKM_BOGUS ((ipc_kmsg_t) 0xffffff10) 176 177 /* 178 * The size of the kernel message buffers that will be cached. 179 * IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't. 180 */ 181 extern zone_t ipc_kmsg_zone; 182 #define IKM_SAVED_KMSG_SIZE 256 183 #define IKM_SAVED_MSG_SIZE (IKM_SAVED_KMSG_SIZE - sizeof(struct ipc_kmsg)) 184 185 KALLOC_TYPE_VAR_DECLARE(KT_IPC_KMSG_KDATA_OOL); 186 187 #define ikm_prealloc_inuse_port(kmsg) \ 188 ((kmsg)->ikm_prealloc) 189 190 #define ikm_prealloc_inuse(kmsg) \ 191 ((kmsg)->ikm_prealloc != IP_NULL) 192 193 #define ikm_prealloc_set_inuse(kmsg, port) \ 194 MACRO_BEGIN \ 195 assert((port) != IP_NULL); \ 196 (kmsg)->ikm_prealloc = (port); \ 197 ip_validate(port); \ 198 ip_reference(port); \ 199 MACRO_END 200 201 #define ikm_prealloc_clear_inuse(kmsg) \ 202 MACRO_BEGIN \ 203 (kmsg)->ikm_prealloc = IP_NULL; \ 204 MACRO_END 205 206 /* 207 * Exported interfaces 208 */ 209 struct ipc_kmsg_queue { 210 struct ipc_kmsg *ikmq_base; 211 }; 212 213 typedef circle_queue_t ipc_kmsg_queue_t; 214 215 #define ipc_kmsg_queue_init(queue) circle_queue_init(queue) 216 217 #define ipc_kmsg_queue_empty(queue) circle_queue_empty(queue) 218 219 #define ipc_kmsg_queue_element(elem) \ 220 cqe_element(elem, struct ipc_kmsg, ikm_link) 221 222 #define ipc_kmsg_queue_first(queue) \ 223 cqe_queue_first(queue, struct ipc_kmsg, ikm_link) 224 225 #define ipc_kmsg_queue_next(queue, elt) \ 226 cqe_queue_next(&(elt)->ikm_link, queue, struct ipc_kmsg, ikm_link) 227 228 #define ipc_kmsg_enqueue(queue, kmsg) \ 229 circle_enqueue_tail(queue, &(kmsg)->ikm_link) 230 231 #define ipc_kmsg_rmqueue(queue, kmsg) \ 232 circle_dequeue(queue, &(kmsg)->ikm_link) 233 234 extern bool ipc_kmsg_enqueue_qos( 235 ipc_kmsg_queue_t queue, 236 ipc_kmsg_t kmsg); 237 238 extern bool ipc_kmsg_too_large( 239 mach_msg_size_t msg_size, 240 mach_msg_size_t aux_size, 241 mach_msg_option64_t options, 242 mach_msg_size_t max_msg_size, 243 mach_msg_size_t max_aux_size, 244 thread_t receiver); 245 246 extern bool ipc_kmsg_override_qos( 247 ipc_kmsg_queue_t queue, 248 ipc_kmsg_t kmsg, 249 mach_msg_qos_t qos_ovr); 250 251 /* Pull the (given) first kmsg out of a queue */ 252 extern void ipc_kmsg_rmqueue_first( 253 ipc_kmsg_queue_t queue, 254 ipc_kmsg_t kmsg); 255 256 __options_decl(ipc_kmsg_alloc_flags_t, uint32_t, { 257 /* specify either user or kernel flag */ 258 IPC_KMSG_ALLOC_USER = 0x0000, 259 IPC_KMSG_ALLOC_KERNEL = 0x0001, 260 261 IPC_KMSG_ALLOC_ZERO = 0x0002, 262 IPC_KMSG_ALLOC_SAVED = 0x0004, 263 IPC_KMSG_ALLOC_NOFAIL = 0x0008, 264 IPC_KMSG_ALLOC_LINEAR = 0x0010, 265 }); 266 267 /* Allocate a kernel message */ 268 extern ipc_kmsg_t ipc_kmsg_alloc( 269 mach_msg_size_t msg_size, 270 mach_msg_size_t aux_size, 271 mach_msg_size_t desc_count, 272 ipc_kmsg_alloc_flags_t flags); 273 274 /* Free a kernel message buffer */ 275 extern void ipc_kmsg_free( 276 ipc_kmsg_t kmsg); 277 278 __options_decl(ipc_kmsg_destroy_flags_t, uint32_t, { 279 IPC_KMSG_DESTROY_ALL = 0x0000, 280 IPC_KMSG_DESTROY_SKIP_REMOTE = 0x0001, 281 IPC_KMSG_DESTROY_SKIP_LOCAL = 0x0002, 282 IPC_KMSG_DESTROY_NOT_SIGNED = 0x0004, 283 }); 284 /* Destroy kernel message */ 285 extern void ipc_kmsg_destroy( 286 ipc_kmsg_t kmsg, 287 ipc_kmsg_destroy_flags_t flags); 288 289 /* Enqueue kernel message for deferred destruction */ 290 extern bool ipc_kmsg_delayed_destroy( 291 ipc_kmsg_t kmsg); 292 293 /* Enqueue queue of kernel messages for deferred destruction */ 294 extern bool ipc_kmsg_delayed_destroy_queue( 295 ipc_kmsg_queue_t queue); 296 297 /* Process all the delayed message destroys */ 298 extern void ipc_kmsg_reap_delayed(void); 299 300 /* bind a preallocated message buffer to a port */ 301 extern void ipc_kmsg_set_prealloc( 302 ipc_kmsg_t kmsg, 303 ipc_port_t port); 304 305 /* get the unshifted message header of a kmsg */ 306 extern mach_msg_header_t *ikm_header( 307 ipc_kmsg_t kmsg); 308 309 /* get the start address of user data (after the last descriptor) for a kmsg */ 310 extern void *ikm_udata( 311 ipc_kmsg_t kmsg, 312 mach_msg_size_t desc_count, 313 bool complex); 314 315 extern void * ikm_udata_from_header( 316 ipc_kmsg_t kmsg); 317 318 /* get the size of auxiliary data for a kmsg */ 319 extern mach_msg_size_t ipc_kmsg_aux_data_size( 320 ipc_kmsg_t kmsg); 321 322 extern void ipc_kmsg_set_aux_data_header( 323 ipc_kmsg_t kmsg, 324 mach_msg_aux_header_t *header); 325 326 /* Allocate a kernel message buffer and copy a user message to the buffer */ 327 extern mach_msg_return_t ipc_kmsg_get_from_user( 328 mach_vm_address_t msg_addr, 329 mach_msg_size_t user_msg_size, 330 mach_vm_address_t aux_addr, 331 mach_msg_size_t aux_size, 332 mach_msg_user_header_t user_header, 333 mach_msg_size_t desc_count, 334 mach_msg_option64_t option64, 335 ipc_kmsg_t *kmsgp); 336 337 /* Allocate a kernel message buffer and copy a kernel message to the buffer */ 338 extern mach_msg_return_t ipc_kmsg_get_from_kernel( 339 mach_msg_header_t *msg, 340 mach_msg_size_t size, 341 ipc_kmsg_t *kmsgp); 342 343 /* Send a message to a port */ 344 extern mach_msg_return_t ipc_kmsg_send( 345 ipc_kmsg_t kmsg, 346 mach_msg_option64_t option64, 347 mach_msg_timeout_t timeout_val); 348 349 /* Copy a kernel message buffer to a user message */ 350 extern mach_msg_return_t ipc_kmsg_put_to_user( 351 ipc_kmsg_t kmsg, /* scalar or vector */ 352 mach_msg_option64_t option, 353 mach_vm_address_t rcv_msg_addr, 354 mach_msg_size_t max_msg_size, 355 mach_vm_address_t rcv_aux_addr, 356 mach_msg_size_t max_aux_size, 357 mach_msg_size_t trailer_size, 358 mach_msg_size_t *msg_sizep, 359 mach_msg_size_t *aux_sizep); 360 361 /* Copy a kernel message buffer to a kernel message */ 362 extern void ipc_kmsg_put_to_kernel( 363 mach_msg_header_t *msg, 364 ipc_kmsg_t kmsg, 365 mach_msg_size_t size); 366 367 /* Copyin port rights and out-of-line memory from a user message */ 368 extern mach_msg_return_t ipc_kmsg_copyin_from_user( 369 ipc_kmsg_t kmsg, 370 ipc_space_t space, 371 vm_map_t map, 372 mach_msg_priority_t priority, 373 mach_msg_option64_t *optionp, 374 bool filter_nonfatal); 375 376 /* Copyin port rights and out-of-line memory from a kernel message */ 377 extern mach_msg_return_t ipc_kmsg_copyin_from_kernel( 378 ipc_kmsg_t kmsg); 379 380 /* Copyout the header and body to a user message */ 381 extern mach_msg_return_t ipc_kmsg_copyout( 382 ipc_kmsg_t kmsg, 383 ipc_space_t space, 384 vm_map_t map, 385 mach_msg_option_t option); 386 387 /* Copyout port rights and out-of-line memory to a user message, 388 * not reversing the ports in the header */ 389 extern mach_msg_return_t ipc_kmsg_copyout_pseudo( 390 ipc_kmsg_t kmsg, 391 ipc_space_t space, 392 vm_map_t map); 393 394 /* Compute size of message as copied out to the specified space/map */ 395 extern mach_msg_size_t ipc_kmsg_copyout_size( 396 ipc_kmsg_t kmsg, 397 vm_map_t map); 398 399 /* Copyout the destination port in the message */ 400 extern void ipc_kmsg_copyout_dest_to_user( 401 ipc_kmsg_t kmsg, 402 ipc_space_t space); 403 404 /* kernel's version of ipc_kmsg_copyout_dest_to_user */ 405 extern void ipc_kmsg_copyout_dest_to_kernel( 406 ipc_kmsg_t kmsg, 407 ipc_space_t space); 408 409 /* Returns a pointer to a thread group in the kmsg if any. Caller has a 410 * reference to the kmsg */ 411 extern struct thread_group *ipc_kmsg_get_thread_group( 412 ipc_kmsg_t kmsg); 413 414 extern mach_msg_trailer_size_t ipc_kmsg_trailer_size( 415 mach_msg_option_t option, 416 thread_t thread); 417 418 extern void ipc_kmsg_init_trailer( 419 ipc_kmsg_t kmsg, 420 task_t sender); 421 422 extern void ipc_kmsg_add_trailer( 423 ipc_kmsg_t kmsg, 424 ipc_space_t space, 425 mach_msg_option_t option, 426 thread_t thread, 427 mach_port_seqno_t seqno, 428 boolean_t minimal_trailer, 429 mach_vm_offset_t context); 430 431 extern mach_msg_max_trailer_t *ipc_kmsg_get_trailer( 432 ipc_kmsg_t kmsg, 433 bool body_copied_out); 434 435 extern void ipc_kmsg_set_voucher_port( 436 ipc_kmsg_t kmsg, 437 ipc_port_t voucher, 438 mach_msg_type_name_t type); 439 440 extern ipc_port_t ipc_kmsg_get_voucher_port( 441 ipc_kmsg_t kmsg); 442 443 extern void ipc_kmsg_clear_voucher_port( 444 ipc_kmsg_t kmsg); 445 446 extern void ipc_kmsg_validate_sig( 447 ipc_kmsg_t kmsg, 448 bool partial); 449 450 #define moved_provisional_reply_port(port_type, port) \ 451 (port_type == MACH_MSG_TYPE_MOVE_RECEIVE && IP_VALID(port) && ip_is_provisional_reply_port(port)) \ 452 453 extern void send_prp_telemetry(int msgh_id); 454 455 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD) 456 extern void ipc_kmsg_trace_send( 457 ipc_kmsg_t kmsg, 458 mach_msg_option_t option); 459 #else 460 #define ipc_kmsg_trace_send(a, b) do { } while (0) 461 #endif 462 463 #if (DEVELOPMENT || DEBUG) 464 vm_offset_t ikm_kdata_end(ipc_kmsg_t kmsg); 465 vm_offset_t ikm_udata_end(ipc_kmsg_t kmsg); 466 #endif 467 468 #endif /* _IPC_IPC_KMSG_H_ */ 469