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_kmsg { 97 mach_msg_size_t ikm_size; 98 struct ipc_kmsg *ikm_next; /* next message on port/discard queue */ 99 struct ipc_kmsg *ikm_prev; /* prev message on port/discard queue */ 100 mach_msg_header_t *ikm_header; 101 ipc_port_t ikm_prealloc; /* port we were preallocated from */ 102 ipc_port_t ikm_voucher; /* voucher port carried */ 103 struct ipc_importance_elem *ikm_importance;/* inherited from */ 104 queue_chain_t ikm_inheritance;/* inherited from link */ 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_voucher = IP_NULL; \ 154 (kmsg)->ikm_importance = IIE_NULL; \ 155 assert((kmsg)->ikm_prev = (kmsg)->ikm_next = IKM_BOGUS); \ 156MACRO_END 157 158#define ikm_check_init(kmsg, size) \ 159MACRO_BEGIN \ 160 assert((kmsg)->ikm_size == (size)); \ 161 assert((kmsg)->ikm_prev == IKM_BOGUS); \ 162 assert((kmsg)->ikm_next == IKM_BOGUS); \ 163MACRO_END 164 165#define ikm_set_header(kmsg, mtsize) \ 166MACRO_BEGIN \ 167 (kmsg)->ikm_header = (mach_msg_header_t *) \ 168 ((vm_offset_t)((kmsg) + 1) + (kmsg)->ikm_size - (mtsize)); \ 169MACRO_END 170 171struct ipc_kmsg_queue { 172 struct ipc_kmsg *ikmq_base; 173}; 174 175typedef struct ipc_kmsg_queue *ipc_kmsg_queue_t; 176 177#define IKMQ_NULL ((ipc_kmsg_queue_t) 0) 178 179 180/* 181 * Exported interfaces 182 */ 183 184#define ipc_kmsg_queue_init(queue) \ 185MACRO_BEGIN \ 186 (queue)->ikmq_base = IKM_NULL; \ 187MACRO_END 188 189#define ipc_kmsg_queue_empty(queue) ((queue)->ikmq_base == IKM_NULL) 190 191/* Enqueue a kmsg */ 192extern void ipc_kmsg_enqueue( 193 ipc_kmsg_queue_t queue, 194 ipc_kmsg_t kmsg); 195 196/* Dequeue and return a kmsg */ 197extern ipc_kmsg_t ipc_kmsg_dequeue( 198 ipc_kmsg_queue_t queue); 199 200/* Pull a kmsg out of a queue */ 201extern void ipc_kmsg_rmqueue( 202 ipc_kmsg_queue_t queue, 203 ipc_kmsg_t kmsg); 204 205#define ipc_kmsg_queue_first(queue) ((queue)->ikmq_base) 206 207/* Return the kmsg following the given kmsg */ 208extern ipc_kmsg_t ipc_kmsg_queue_next( 209 ipc_kmsg_queue_t queue, 210 ipc_kmsg_t kmsg); 211 212#define ipc_kmsg_rmqueue_first_macro(queue, kmsg) \ 213MACRO_BEGIN \ 214 register ipc_kmsg_t _next; \ 215 \ 216 assert((queue)->ikmq_base == (kmsg)); \ 217 \ 218 _next = (kmsg)->ikm_next; \ 219 if (_next == (kmsg)) { \ 220 assert((kmsg)->ikm_prev == (kmsg)); \ 221 (queue)->ikmq_base = IKM_NULL; \ 222 } else { \ 223 register ipc_kmsg_t _prev = (kmsg)->ikm_prev; \ 224 \ 225 (queue)->ikmq_base = _next; \ 226 _next->ikm_prev = _prev; \ 227 _prev->ikm_next = _next; \ 228 } \ 229 /* XXX Debug paranoia ASSIGNMENTS */ \ 230 assert(kmsg->ikm_next = IKM_BOGUS); \ 231 assert(kmsg->ikm_prev = IKM_BOGUS); \ 232MACRO_END 233 234#define ipc_kmsg_enqueue_macro(queue, kmsg) \ 235MACRO_BEGIN \ 236 register ipc_kmsg_t _first = (queue)->ikmq_base; \ 237 \ 238 if (_first == IKM_NULL) { \ 239 (queue)->ikmq_base = (kmsg); \ 240 (kmsg)->ikm_next = (kmsg); \ 241 (kmsg)->ikm_prev = (kmsg); \ 242 } else { \ 243 register ipc_kmsg_t _last = _first->ikm_prev; \ 244 \ 245 (kmsg)->ikm_next = _first; \ 246 (kmsg)->ikm_prev = _last; \ 247 _first->ikm_prev = (kmsg); \ 248 _last->ikm_next = (kmsg); \ 249 } \ 250MACRO_END 251 252/* Allocate a kernel message */ 253extern ipc_kmsg_t ipc_kmsg_alloc( 254 mach_msg_size_t size); 255 256/* Free a kernel message buffer */ 257extern void ipc_kmsg_free( 258 ipc_kmsg_t kmsg); 259 260/* Destroy kernel message */ 261extern void ipc_kmsg_destroy( 262 ipc_kmsg_t kmsg); 263 264/* Enqueue kernel message for deferred destruction */ 265extern boolean_t ipc_kmsg_delayed_destroy( 266 ipc_kmsg_t kmsg); 267 268/* Process all the delayed message destroys */ 269extern void ipc_kmsg_reap_delayed(void); 270 271/* Preallocate a kernel message buffer */ 272extern ipc_kmsg_t ipc_kmsg_prealloc( 273 mach_msg_size_t size); 274 275/* bind a preallocated message buffer to a port */ 276extern void ipc_kmsg_set_prealloc( 277 ipc_kmsg_t kmsg, 278 ipc_port_t port); 279 280/* Clear preallocated message buffer binding */ 281extern void ipc_kmsg_clear_prealloc( 282 ipc_kmsg_t kmsg, 283 ipc_port_t port); 284 285/* Allocate a kernel message buffer and copy a user message to the buffer */ 286extern mach_msg_return_t ipc_kmsg_get( 287 mach_vm_address_t msg_addr, 288 mach_msg_size_t size, 289 ipc_kmsg_t *kmsgp); 290 291/* Allocate a kernel message buffer and copy a kernel message to the buffer */ 292extern mach_msg_return_t ipc_kmsg_get_from_kernel( 293 mach_msg_header_t *msg, 294 mach_msg_size_t size, 295 ipc_kmsg_t *kmsgp); 296 297/* Send a message to a port */ 298extern mach_msg_return_t ipc_kmsg_send( 299 ipc_kmsg_t kmsg, 300 mach_msg_option_t option, 301 mach_msg_timeout_t timeout_val); 302 303/* Copy a kernel message buffer to a user message */ 304extern mach_msg_return_t ipc_kmsg_put( 305 mach_vm_address_t msg_addr, 306 ipc_kmsg_t kmsg, 307 mach_msg_size_t size); 308 309/* Copy a kernel message buffer to a kernel message */ 310extern void ipc_kmsg_put_to_kernel( 311 mach_msg_header_t *msg, 312 ipc_kmsg_t kmsg, 313 mach_msg_size_t size); 314 315/* Copyin port rights in the header of a message */ 316extern mach_msg_return_t ipc_kmsg_copyin_header( 317 ipc_kmsg_t kmsg, 318 ipc_space_t space, 319 mach_msg_option_t *optionp); 320 321/* Copyin port rights and out-of-line memory from a user message */ 322extern mach_msg_return_t ipc_kmsg_copyin( 323 ipc_kmsg_t kmsg, 324 ipc_space_t space, 325 vm_map_t map, 326 mach_msg_option_t *optionp); 327 328/* Copyin port rights and out-of-line memory from a kernel message */ 329extern mach_msg_return_t ipc_kmsg_copyin_from_kernel( 330 ipc_kmsg_t kmsg); 331 332#if IKM_SUPPORT_LEGACY 333extern mach_msg_return_t ipc_kmsg_copyin_from_kernel_legacy( 334 ipc_kmsg_t kmsg); 335#endif 336 337/* Copyout port rights in the header of a message */ 338extern mach_msg_return_t ipc_kmsg_copyout_header( 339 ipc_kmsg_t kmsg, 340 ipc_space_t space, 341 mach_msg_option_t option); 342 343/* Copyout a port right returning a name */ 344extern mach_msg_return_t ipc_kmsg_copyout_object( 345 ipc_space_t space, 346 ipc_object_t object, 347 mach_msg_type_name_t msgt_name, 348 mach_port_name_t *namep); 349 350/* Copyout the header and body to a user message */ 351extern mach_msg_return_t ipc_kmsg_copyout( 352 ipc_kmsg_t kmsg, 353 ipc_space_t space, 354 vm_map_t map, 355 mach_msg_body_t *slist, 356 mach_msg_option_t option); 357 358/* Copyout port rights and out-of-line memory from the body of a message */ 359extern mach_msg_return_t ipc_kmsg_copyout_body( 360 ipc_kmsg_t kmsg, 361 ipc_space_t space, 362 vm_map_t map, 363 mach_msg_body_t *slist); 364 365/* Copyout port rights and out-of-line memory to a user message, 366 not reversing the ports in the header */ 367extern mach_msg_return_t ipc_kmsg_copyout_pseudo( 368 ipc_kmsg_t kmsg, 369 ipc_space_t space, 370 vm_map_t map, 371 mach_msg_body_t *slist); 372 373/* Compute size of message as copied out to the specified space/map */ 374extern mach_msg_size_t ipc_kmsg_copyout_size( 375 ipc_kmsg_t kmsg, 376 vm_map_t map); 377 378/* Copyout the destination port in the message */ 379extern void ipc_kmsg_copyout_dest( 380 ipc_kmsg_t kmsg, 381 ipc_space_t space); 382 383/* kernel's version of ipc_kmsg_copyout_dest */ 384extern void ipc_kmsg_copyout_to_kernel( 385 ipc_kmsg_t kmsg, 386 ipc_space_t space); 387 388#if IKM_SUPPORT_LEGACY 389extern void ipc_kmsg_copyout_to_kernel_legacy( 390 ipc_kmsg_t kmsg, 391 ipc_space_t space); 392#endif 393 394/* get a scatter list and check consistency */ 395extern mach_msg_body_t *ipc_kmsg_get_scatter( 396 mach_vm_address_t msg_addr, 397 mach_msg_size_t slist_size, 398 ipc_kmsg_t kmsg); 399 400/* free a scatter list */ 401extern void ipc_kmsg_free_scatter( 402 mach_msg_body_t *slist, 403 mach_msg_size_t slist_size); 404 405 406extern mach_msg_trailer_size_t 407ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space, 408 mach_msg_option_t option, thread_t thread, 409 mach_port_seqno_t seqno, boolean_t minimal_trailer, 410 mach_vm_offset_t context); 411 412#endif /* _IPC_IPC_KMSG_H_ */ 413 414