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 Software.Distribution@CS.CMU.EDU 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 <ipc/ipc_types.h> 82#include <ipc/ipc_object.h> 83 84/* 85 * This structure is only the header for a kmsg buffer; 86 * the actual buffer is normally larger. The rest of the buffer 87 * holds the body of the message. 88 * 89 * In a kmsg, the port fields hold pointers to ports instead 90 * of port names. These pointers hold references. 91 * 92 * The ikm_header.msgh_remote_port field is the destination 93 * of the message. 94 */ 95 96struct ipc_labelh; 97 98struct ipc_kmsg { 99 struct ipc_kmsg *ikm_next; 100 struct ipc_kmsg *ikm_prev; 101 ipc_port_t ikm_prealloc; /* port we were preallocated from */ 102 mach_msg_size_t ikm_size; 103 struct ipc_labelh *ikm_sender; 104 mach_msg_header_t *ikm_header; 105}; 106 107#if defined(__i386__) || defined(__arm__) 108#define IKM_SUPPORT_LEGACY 1 109#else 110#define IKM_SUPPORT_LEGACY 0 111#endif 112 113#define IKM_OVERHEAD (sizeof(struct ipc_kmsg)) 114 115#define ikm_plus_overhead(size) ((mach_msg_size_t)((size) + IKM_OVERHEAD)) 116#define ikm_less_overhead(size) ((mach_msg_size_t)((size) - IKM_OVERHEAD)) 117 118/* 119 * XXX For debugging. 120 */ 121#define IKM_BOGUS ((ipc_kmsg_t) 0xffffff10) 122 123/* 124 * The size of the kernel message buffers that will be cached. 125 * IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't. 126 */ 127extern zone_t ipc_kmsg_zone; 128#define IKM_SAVED_KMSG_SIZE 256 129#define IKM_SAVED_MSG_SIZE ikm_less_overhead(IKM_SAVED_KMSG_SIZE) 130 131#define ikm_prealloc_inuse_port(kmsg) \ 132 ((kmsg)->ikm_prealloc) 133 134#define ikm_prealloc_inuse(kmsg) \ 135 ((kmsg)->ikm_prealloc != IP_NULL) 136 137#define ikm_prealloc_set_inuse(kmsg, port) \ 138MACRO_BEGIN \ 139 assert((port) != IP_NULL); \ 140 (kmsg)->ikm_prealloc = (port); \ 141 ip_reference(port); \ 142MACRO_END 143 144#define ikm_prealloc_clear_inuse(kmsg, port) \ 145MACRO_BEGIN \ 146 (kmsg)->ikm_prealloc = IP_NULL; \ 147MACRO_END 148 149#define ikm_init(kmsg, size) \ 150MACRO_BEGIN \ 151 (kmsg)->ikm_size = (size); \ 152 (kmsg)->ikm_prealloc = IP_NULL; \ 153 (kmsg)->ikm_sender = NULL; \ 154 assert((kmsg)->ikm_prev = (kmsg)->ikm_next = IKM_BOGUS); \ 155MACRO_END 156 157#define ikm_check_init(kmsg, size) \ 158MACRO_BEGIN \ 159 assert((kmsg)->ikm_size == (size)); \ 160 assert((kmsg)->ikm_prev == IKM_BOGUS); \ 161 assert((kmsg)->ikm_next == IKM_BOGUS); \ 162MACRO_END 163 164#define ikm_set_header(kmsg, mtsize) \ 165MACRO_BEGIN \ 166 (kmsg)->ikm_header = (mach_msg_header_t *) \ 167 ((vm_offset_t)((kmsg) + 1) + (kmsg)->ikm_size - (mtsize)); \ 168MACRO_END 169 170struct ipc_kmsg_queue { 171 struct ipc_kmsg *ikmq_base; 172}; 173 174typedef struct ipc_kmsg_queue *ipc_kmsg_queue_t; 175 176#define IKMQ_NULL ((ipc_kmsg_queue_t) 0) 177 178 179/* 180 * Exported interfaces 181 */ 182 183#define ipc_kmsg_queue_init(queue) \ 184MACRO_BEGIN \ 185 (queue)->ikmq_base = IKM_NULL; \ 186MACRO_END 187 188#define ipc_kmsg_queue_empty(queue) ((queue)->ikmq_base == IKM_NULL) 189 190/* Enqueue a kmsg */ 191extern void ipc_kmsg_enqueue( 192 ipc_kmsg_queue_t queue, 193 ipc_kmsg_t kmsg); 194 195/* Dequeue and return a kmsg */ 196extern ipc_kmsg_t ipc_kmsg_dequeue( 197 ipc_kmsg_queue_t queue); 198 199/* Pull a kmsg out of a queue */ 200extern void ipc_kmsg_rmqueue( 201 ipc_kmsg_queue_t queue, 202 ipc_kmsg_t kmsg); 203 204#define ipc_kmsg_queue_first(queue) ((queue)->ikmq_base) 205 206/* Return the kmsg following the given kmsg */ 207extern ipc_kmsg_t ipc_kmsg_queue_next( 208 ipc_kmsg_queue_t queue, 209 ipc_kmsg_t kmsg); 210 211#define ipc_kmsg_rmqueue_first_macro(queue, kmsg) \ 212MACRO_BEGIN \ 213 register ipc_kmsg_t _next; \ 214 \ 215 assert((queue)->ikmq_base == (kmsg)); \ 216 \ 217 _next = (kmsg)->ikm_next; \ 218 if (_next == (kmsg)) { \ 219 assert((kmsg)->ikm_prev == (kmsg)); \ 220 (queue)->ikmq_base = IKM_NULL; \ 221 } else { \ 222 register ipc_kmsg_t _prev = (kmsg)->ikm_prev; \ 223 \ 224 (queue)->ikmq_base = _next; \ 225 _next->ikm_prev = _prev; \ 226 _prev->ikm_next = _next; \ 227 } \ 228 /* XXX Debug paranoia ASSIGNMENTS */ \ 229 assert(kmsg->ikm_next = IKM_BOGUS); \ 230 assert(kmsg->ikm_prev = IKM_BOGUS); \ 231MACRO_END 232 233#define ipc_kmsg_enqueue_macro(queue, kmsg) \ 234MACRO_BEGIN \ 235 register ipc_kmsg_t _first = (queue)->ikmq_base; \ 236 \ 237 if (_first == IKM_NULL) { \ 238 (queue)->ikmq_base = (kmsg); \ 239 (kmsg)->ikm_next = (kmsg); \ 240 (kmsg)->ikm_prev = (kmsg); \ 241 } else { \ 242 register ipc_kmsg_t _last = _first->ikm_prev; \ 243 \ 244 (kmsg)->ikm_next = _first; \ 245 (kmsg)->ikm_prev = _last; \ 246 _first->ikm_prev = (kmsg); \ 247 _last->ikm_next = (kmsg); \ 248 } \ 249MACRO_END 250 251/* 252 * extern void 253 * ipc_kmsg_send_always(ipc_kmsg_t); 254 */ 255#define ipc_kmsg_send_always(kmsg) \ 256 ipc_kmsg_send((kmsg), MACH_SEND_ALWAYS, MACH_MSG_TIMEOUT_NONE) 257 258 259/* Allocate a kernel message */ 260extern ipc_kmsg_t ipc_kmsg_alloc( 261 mach_msg_size_t size); 262 263/* Free a kernel message buffer */ 264extern void ipc_kmsg_free( 265 ipc_kmsg_t kmsg); 266 267/* Destroy kernel message */ 268extern void ipc_kmsg_destroy( 269 ipc_kmsg_t kmsg); 270 271/* Enqueue kernel message for deferred destruction */ 272extern boolean_t ipc_kmsg_delayed_destroy( 273 ipc_kmsg_t kmsg); 274 275/* Process all the delayed message destroys */ 276extern void ipc_kmsg_reap_delayed(void); 277 278/* Preallocate a kernel message buffer */ 279extern ipc_kmsg_t ipc_kmsg_prealloc( 280 mach_msg_size_t size); 281 282/* bind a preallocated message buffer to a port */ 283extern void ipc_kmsg_set_prealloc( 284 ipc_kmsg_t kmsg, 285 ipc_port_t port); 286 287/* Clear preallocated message buffer binding */ 288extern void ipc_kmsg_clear_prealloc( 289 ipc_kmsg_t kmsg, 290 ipc_port_t port); 291 292/* Allocate a kernel message buffer and copy a user message to the buffer */ 293extern mach_msg_return_t ipc_kmsg_get( 294 mach_vm_address_t msg_addr, 295 mach_msg_size_t size, 296 ipc_kmsg_t *kmsgp); 297 298/* Allocate a kernel message buffer and copy a kernel message to the buffer */ 299extern mach_msg_return_t ipc_kmsg_get_from_kernel( 300 mach_msg_header_t *msg, 301 mach_msg_size_t size, 302 ipc_kmsg_t *kmsgp); 303 304/* Send a message to a port */ 305extern mach_msg_return_t ipc_kmsg_send( 306 ipc_kmsg_t kmsg, 307 mach_msg_option_t option, 308 mach_msg_timeout_t timeout_val); 309 310/* Copy a kernel message buffer to a user message */ 311extern mach_msg_return_t ipc_kmsg_put( 312 mach_vm_address_t msg_addr, 313 ipc_kmsg_t kmsg, 314 mach_msg_size_t size); 315 316/* Copy a kernel message buffer to a kernel message */ 317extern void ipc_kmsg_put_to_kernel( 318 mach_msg_header_t *msg, 319 ipc_kmsg_t kmsg, 320 mach_msg_size_t size); 321 322/* Copyin port rights in the header of a message */ 323extern mach_msg_return_t ipc_kmsg_copyin_header( 324 mach_msg_header_t *msg, 325 ipc_space_t space, 326 boolean_t notify); 327 328/* Copyin port rights and out-of-line memory from a user message */ 329extern mach_msg_return_t ipc_kmsg_copyin( 330 ipc_kmsg_t kmsg, 331 ipc_space_t space, 332 vm_map_t map, 333 boolean_t notify); 334 335/* Copyin port rights and out-of-line memory from a kernel message */ 336extern mach_msg_return_t ipc_kmsg_copyin_from_kernel( 337 ipc_kmsg_t kmsg); 338 339#if IKM_SUPPORT_LEGACY 340extern mach_msg_return_t ipc_kmsg_copyin_from_kernel_legacy( 341 ipc_kmsg_t kmsg); 342#endif 343 344/* Copyout port rights in the header of a message */ 345extern mach_msg_return_t ipc_kmsg_copyout_header( 346 mach_msg_header_t *msg, 347 ipc_space_t space); 348 349/* Copyout a port right returning a name */ 350extern mach_msg_return_t ipc_kmsg_copyout_object( 351 ipc_space_t space, 352 ipc_object_t object, 353 mach_msg_type_name_t msgt_name, 354 mach_port_name_t *namep); 355 356/* Copyout the header and body to a user message */ 357extern mach_msg_return_t ipc_kmsg_copyout( 358 ipc_kmsg_t kmsg, 359 ipc_space_t space, 360 vm_map_t map, 361 mach_msg_body_t *slist); 362 363/* Copyout port rights and out-of-line memory from the body of a message */ 364extern mach_msg_return_t ipc_kmsg_copyout_body( 365 ipc_kmsg_t kmsg, 366 ipc_space_t space, 367 vm_map_t map, 368 mach_msg_body_t *slist); 369 370/* Copyout port rights and out-of-line memory to a user message, 371 not reversing the ports in the header */ 372extern mach_msg_return_t ipc_kmsg_copyout_pseudo( 373 ipc_kmsg_t kmsg, 374 ipc_space_t space, 375 vm_map_t map, 376 mach_msg_body_t *slist); 377 378/* Compute size of message as copied out to the specified space/map */ 379extern mach_msg_size_t ipc_kmsg_copyout_size( 380 ipc_kmsg_t kmsg, 381 vm_map_t map); 382 383/* Copyout the destination port in the message */ 384extern void ipc_kmsg_copyout_dest( 385 ipc_kmsg_t kmsg, 386 ipc_space_t space); 387 388/* kernel's version of ipc_kmsg_copyout_dest */ 389extern void ipc_kmsg_copyout_to_kernel( 390 ipc_kmsg_t kmsg, 391 ipc_space_t space); 392 393#if IKM_SUPPORT_LEGACY 394extern void ipc_kmsg_copyout_to_kernel_legacy( 395 ipc_kmsg_t kmsg, 396 ipc_space_t space); 397#endif 398 399/* get a scatter list and check consistency */ 400extern mach_msg_body_t *ipc_kmsg_get_scatter( 401 mach_vm_address_t msg_addr, 402 mach_msg_size_t slist_size, 403 ipc_kmsg_t kmsg); 404 405/* free a scatter list */ 406extern void ipc_kmsg_free_scatter( 407 mach_msg_body_t *slist, 408 mach_msg_size_t slist_size); 409 410 411extern mach_msg_trailer_size_t 412ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space, 413 mach_msg_option_t option, thread_t thread, 414 mach_port_seqno_t seqno, boolean_t minimal_trailer, 415 mach_vm_offset_t context); 416 417#endif /* _IPC_IPC_KMSG_H_ */ 418 419