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/* Allocate a kernel message */ 252extern ipc_kmsg_t ipc_kmsg_alloc( 253 mach_msg_size_t size); 254 255/* Free a kernel message buffer */ 256extern void ipc_kmsg_free( 257 ipc_kmsg_t kmsg); 258 259/* Destroy kernel message */ 260extern void ipc_kmsg_destroy( 261 ipc_kmsg_t kmsg); 262 263/* Enqueue kernel message for deferred destruction */ 264extern boolean_t ipc_kmsg_delayed_destroy( 265 ipc_kmsg_t kmsg); 266 267/* Process all the delayed message destroys */ 268extern void ipc_kmsg_reap_delayed(void); 269 270/* Preallocate a kernel message buffer */ 271extern ipc_kmsg_t ipc_kmsg_prealloc( 272 mach_msg_size_t size); 273 274/* bind a preallocated message buffer to a port */ 275extern void ipc_kmsg_set_prealloc( 276 ipc_kmsg_t kmsg, 277 ipc_port_t port); 278 279/* Clear preallocated message buffer binding */ 280extern void ipc_kmsg_clear_prealloc( 281 ipc_kmsg_t kmsg, 282 ipc_port_t port); 283 284/* Allocate a kernel message buffer and copy a user message to the buffer */ 285extern mach_msg_return_t ipc_kmsg_get( 286 mach_vm_address_t msg_addr, 287 mach_msg_size_t size, 288 ipc_kmsg_t *kmsgp); 289 290/* Allocate a kernel message buffer and copy a kernel message to the buffer */ 291extern mach_msg_return_t ipc_kmsg_get_from_kernel( 292 mach_msg_header_t *msg, 293 mach_msg_size_t size, 294 ipc_kmsg_t *kmsgp); 295 296/* Send a message to a port */ 297extern mach_msg_return_t ipc_kmsg_send( 298 ipc_kmsg_t kmsg, 299 mach_msg_option_t option, 300 mach_msg_timeout_t timeout_val); 301 302/* Copy a kernel message buffer to a user message */ 303extern mach_msg_return_t ipc_kmsg_put( 304 mach_vm_address_t msg_addr, 305 ipc_kmsg_t kmsg, 306 mach_msg_size_t size); 307 308/* Copy a kernel message buffer to a kernel message */ 309extern void ipc_kmsg_put_to_kernel( 310 mach_msg_header_t *msg, 311 ipc_kmsg_t kmsg, 312 mach_msg_size_t size); 313 314/* Copyin port rights in the header of a message */ 315extern mach_msg_return_t ipc_kmsg_copyin_header( 316 mach_msg_header_t *msg, 317 ipc_space_t space, 318 mach_msg_option_t *optionp); 319 320/* Copyin port rights and out-of-line memory from a user message */ 321extern mach_msg_return_t ipc_kmsg_copyin( 322 ipc_kmsg_t kmsg, 323 ipc_space_t space, 324 vm_map_t map, 325 mach_msg_option_t *optionp); 326 327/* Copyin port rights and out-of-line memory from a kernel message */ 328extern mach_msg_return_t ipc_kmsg_copyin_from_kernel( 329 ipc_kmsg_t kmsg); 330 331#if IKM_SUPPORT_LEGACY 332extern mach_msg_return_t ipc_kmsg_copyin_from_kernel_legacy( 333 ipc_kmsg_t kmsg); 334#endif 335 336/* Copyout port rights in the header of a message */ 337extern mach_msg_return_t ipc_kmsg_copyout_header( 338 mach_msg_header_t *msg, 339 ipc_space_t space); 340 341/* Copyout a port right returning a name */ 342extern mach_msg_return_t ipc_kmsg_copyout_object( 343 ipc_space_t space, 344 ipc_object_t object, 345 mach_msg_type_name_t msgt_name, 346 mach_port_name_t *namep); 347 348/* Copyout the header and body to a user message */ 349extern mach_msg_return_t ipc_kmsg_copyout( 350 ipc_kmsg_t kmsg, 351 ipc_space_t space, 352 vm_map_t map, 353 mach_msg_body_t *slist); 354 355/* Copyout port rights and out-of-line memory from the body of a message */ 356extern mach_msg_return_t ipc_kmsg_copyout_body( 357 ipc_kmsg_t kmsg, 358 ipc_space_t space, 359 vm_map_t map, 360 mach_msg_body_t *slist); 361 362/* Copyout port rights and out-of-line memory to a user message, 363 not reversing the ports in the header */ 364extern mach_msg_return_t ipc_kmsg_copyout_pseudo( 365 ipc_kmsg_t kmsg, 366 ipc_space_t space, 367 vm_map_t map, 368 mach_msg_body_t *slist); 369 370/* Compute size of message as copied out to the specified space/map */ 371extern mach_msg_size_t ipc_kmsg_copyout_size( 372 ipc_kmsg_t kmsg, 373 vm_map_t map); 374 375/* Copyout the destination port in the message */ 376extern void ipc_kmsg_copyout_dest( 377 ipc_kmsg_t kmsg, 378 ipc_space_t space); 379 380/* kernel's version of ipc_kmsg_copyout_dest */ 381extern void ipc_kmsg_copyout_to_kernel( 382 ipc_kmsg_t kmsg, 383 ipc_space_t space); 384 385#if IKM_SUPPORT_LEGACY 386extern void ipc_kmsg_copyout_to_kernel_legacy( 387 ipc_kmsg_t kmsg, 388 ipc_space_t space); 389#endif 390 391/* get a scatter list and check consistency */ 392extern mach_msg_body_t *ipc_kmsg_get_scatter( 393 mach_vm_address_t msg_addr, 394 mach_msg_size_t slist_size, 395 ipc_kmsg_t kmsg); 396 397/* free a scatter list */ 398extern void ipc_kmsg_free_scatter( 399 mach_msg_body_t *slist, 400 mach_msg_size_t slist_size); 401 402 403extern mach_msg_trailer_size_t 404ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space, 405 mach_msg_option_t option, thread_t thread, 406 mach_port_seqno_t seqno, boolean_t minimal_trailer, 407 mach_vm_offset_t context); 408 409#endif /* _IPC_IPC_KMSG_H_ */ 410 411