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 <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
132struct 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
167typedef 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#define IKM_SAVED_KMSG_SIZE 256
182#define IKM_SAVED_MSG_SIZE (IKM_SAVED_KMSG_SIZE - sizeof(struct ipc_kmsg))
183
184KALLOC_TYPE_VAR_DECLARE(KT_IPC_KMSG_KDATA_OOL);
185
186#define ikm_prealloc_inuse_port(kmsg) \
187 ((kmsg)->ikm_prealloc)
188
189#define ikm_prealloc_inuse(kmsg) \
190 ((kmsg)->ikm_prealloc != IP_NULL)
191
192#define ikm_prealloc_set_inuse(kmsg, port) \
193MACRO_BEGIN \
194 assert((port) != IP_NULL); \
195 (kmsg)->ikm_prealloc = (port); \
196 ip_validate(port); \
197 ip_reference(port); \
198MACRO_END
199
200#define ikm_prealloc_clear_inuse(kmsg) \
201MACRO_BEGIN \
202 (kmsg)->ikm_prealloc = IP_NULL; \
203MACRO_END
204
205/*
206 * Exported interfaces
207 */
208struct ipc_kmsg_queue {
209 struct ipc_kmsg *ikmq_base;
210};
211
212typedef circle_queue_t ipc_kmsg_queue_t;
213
214#define ipc_kmsg_queue_init(queue) circle_queue_init(queue)
215
216#define ipc_kmsg_queue_empty(queue) circle_queue_empty(queue)
217
218#define ipc_kmsg_queue_element(elem) \
219 cqe_element(elem, struct ipc_kmsg, ikm_link)
220
221#define ipc_kmsg_queue_first(queue) \
222 cqe_queue_first(queue, struct ipc_kmsg, ikm_link)
223
224#define ipc_kmsg_queue_next(queue, elt) \
225 cqe_queue_next(&(elt)->ikm_link, queue, struct ipc_kmsg, ikm_link)
226
227#define ipc_kmsg_enqueue(queue, kmsg) \
228 circle_enqueue_tail(queue, &(kmsg)->ikm_link)
229
230#define ipc_kmsg_rmqueue(queue, kmsg) \
231 circle_dequeue(queue, &(kmsg)->ikm_link)
232
233extern bool ipc_kmsg_enqueue_qos(
234 ipc_kmsg_queue_t queue,
235 ipc_kmsg_t kmsg);
236
237extern bool ipc_kmsg_too_large(
238 mach_msg_size_t msg_size,
239 mach_msg_size_t aux_size,
240 mach_msg_option64_t options,
241 mach_msg_size_t max_msg_size,
242 mach_msg_size_t max_aux_size,
243 thread_t receiver);
244
245extern bool ipc_kmsg_override_qos(
246 ipc_kmsg_queue_t queue,
247 ipc_kmsg_t kmsg,
248 mach_msg_qos_t qos_ovr);
249
250/* Pull the (given) first kmsg out of a queue */
251extern void ipc_kmsg_rmqueue_first(
252 ipc_kmsg_queue_t queue,
253 ipc_kmsg_t kmsg);
254
255__options_decl(ipc_kmsg_alloc_flags_t, uint32_t, {
256 /* specify either user or kernel flag */
257 IPC_KMSG_ALLOC_USER = 0x0000,
258 IPC_KMSG_ALLOC_KERNEL = 0x0001,
259
260 IPC_KMSG_ALLOC_ZERO = 0x0002,
261 IPC_KMSG_ALLOC_SAVED = 0x0004,
262 IPC_KMSG_ALLOC_NOFAIL = 0x0008,
263 IPC_KMSG_ALLOC_LINEAR = 0x0010,
264});
265
266/* Allocate a kernel message */
267extern ipc_kmsg_t ipc_kmsg_alloc(
268 mach_msg_size_t msg_size,
269 mach_msg_size_t aux_size,
270 mach_msg_size_t desc_count,
271 ipc_kmsg_alloc_flags_t flags);
272
273/* Free a kernel message buffer */
274extern void ipc_kmsg_free(
275 ipc_kmsg_t kmsg);
276
277__options_decl(ipc_kmsg_destroy_flags_t, uint32_t, {
278 IPC_KMSG_DESTROY_ALL = 0x0000,
279 IPC_KMSG_DESTROY_SKIP_REMOTE = 0x0001,
280 IPC_KMSG_DESTROY_SKIP_LOCAL = 0x0002,
281 IPC_KMSG_DESTROY_NOT_SIGNED = 0x0004,
282});
283/* Destroy kernel message */
284extern void ipc_kmsg_destroy(
285 ipc_kmsg_t kmsg,
286 ipc_kmsg_destroy_flags_t flags);
287
288/* Enqueue kernel message for deferred destruction */
289extern bool ipc_kmsg_delayed_destroy(
290 ipc_kmsg_t kmsg);
291
292/* Enqueue queue of kernel messages for deferred destruction */
293extern bool ipc_kmsg_delayed_destroy_queue(
294 ipc_kmsg_queue_t queue);
295
296/* Process all the delayed message destroys */
297extern void ipc_kmsg_reap_delayed(void);
298
299/* bind a preallocated message buffer to a port */
300extern void ipc_kmsg_set_prealloc(
301 ipc_kmsg_t kmsg,
302 ipc_port_t port);
303
304/* get the unshifted message header of a kmsg */
305extern mach_msg_header_t *ikm_header(
306 ipc_kmsg_t kmsg);
307
308/* get the start address of user data (after the last descriptor) for a kmsg */
309extern void *ikm_udata(
310 ipc_kmsg_t kmsg,
311 mach_msg_size_t desc_count,
312 bool complex);
313
314extern void * ikm_udata_from_header(
315 ipc_kmsg_t kmsg);
316
317/* get the size of auxiliary data for a kmsg */
318extern mach_msg_size_t ipc_kmsg_aux_data_size(
319 ipc_kmsg_t kmsg);
320
321extern void ipc_kmsg_set_aux_data_header(
322 ipc_kmsg_t kmsg,
323 mach_msg_aux_header_t *header);
324
325/* Allocate a kernel message buffer and copy a user message to the buffer */
326extern mach_msg_return_t ipc_kmsg_get_from_user(
327 mach_vm_address_t msg_addr,
328 mach_msg_size_t user_msg_size,
329 mach_vm_address_t aux_addr,
330 mach_msg_size_t aux_size,
331 mach_msg_user_header_t user_header,
332 mach_msg_size_t desc_count,
333 mach_msg_option64_t option64,
334 ipc_kmsg_t *kmsgp);
335
336/* Allocate a kernel message buffer and copy a kernel message to the buffer */
337extern mach_msg_return_t ipc_kmsg_get_from_kernel(
338 mach_msg_header_t *msg,
339 mach_msg_size_t size,
340 ipc_kmsg_t *kmsgp);
341
342/* Send a message to a port */
343extern mach_msg_return_t ipc_kmsg_send(
344 ipc_kmsg_t kmsg,
345 mach_msg_option64_t option64,
346 mach_msg_timeout_t timeout_val);
347
348/* Copy a kernel message buffer to a user message */
349extern mach_msg_return_t ipc_kmsg_put_to_user(
350 ipc_kmsg_t kmsg, /* scalar or vector */
351 mach_msg_option64_t option,
352 mach_vm_address_t rcv_msg_addr,
353 mach_msg_size_t max_msg_size,
354 mach_vm_address_t rcv_aux_addr,
355 mach_msg_size_t max_aux_size,
356 mach_msg_size_t trailer_size,
357 mach_msg_size_t *msg_sizep,
358 mach_msg_size_t *aux_sizep);
359
360/* Copy a kernel message buffer to a kernel message */
361extern void ipc_kmsg_put_to_kernel(
362 mach_msg_header_t *msg,
363 ipc_kmsg_t kmsg,
364 mach_msg_size_t size);
365
366/* Copyin port rights and out-of-line memory from a user message */
367extern mach_msg_return_t ipc_kmsg_copyin_from_user(
368 ipc_kmsg_t kmsg,
369 ipc_space_t space,
370 vm_map_t map,
371 mach_msg_priority_t priority,
372 mach_msg_option64_t *optionp,
373 bool filter_nonfatal);
374
375/* Copyin port rights and out-of-line memory from a kernel message */
376extern mach_msg_return_t ipc_kmsg_copyin_from_kernel(
377 ipc_kmsg_t kmsg);
378
379/* Copyout the header and body to a user message */
380extern mach_msg_return_t ipc_kmsg_copyout(
381 ipc_kmsg_t kmsg,
382 ipc_space_t space,
383 vm_map_t map,
384 mach_msg_option_t option);
385
386/* Copyout port rights and out-of-line memory to a user message,
387 * not reversing the ports in the header */
388extern mach_msg_return_t ipc_kmsg_copyout_pseudo(
389 ipc_kmsg_t kmsg,
390 ipc_space_t space,
391 vm_map_t map);
392
393/* Compute size of message as copied out to the specified space/map */
394extern mach_msg_size_t ipc_kmsg_copyout_size(
395 ipc_kmsg_t kmsg,
396 vm_map_t map);
397
398/* Copyout the destination port in the message */
399extern void ipc_kmsg_copyout_dest_to_user(
400 ipc_kmsg_t kmsg,
401 ipc_space_t space);
402
403/* kernel's version of ipc_kmsg_copyout_dest_to_user */
404extern void ipc_kmsg_copyout_dest_to_kernel(
405 ipc_kmsg_t kmsg,
406 ipc_space_t space);
407
408/* Returns a pointer to a thread group in the kmsg if any. Caller has a
409 * reference to the kmsg */
410extern struct thread_group *ipc_kmsg_get_thread_group(
411 ipc_kmsg_t kmsg);
412
413extern mach_msg_trailer_size_t ipc_kmsg_trailer_size(
414 mach_msg_option_t option,
415 thread_t thread);
416
417extern void ipc_kmsg_init_trailer(
418 ipc_kmsg_t kmsg,
419 task_t sender);
420
421extern void ipc_kmsg_add_trailer(
422 ipc_kmsg_t kmsg,
423 ipc_space_t space,
424 mach_msg_option_t option,
425 thread_t thread,
426 mach_port_seqno_t seqno,
427 boolean_t minimal_trailer,
428 mach_vm_offset_t context);
429
430extern mach_msg_max_trailer_t *ipc_kmsg_get_trailer(
431 ipc_kmsg_t kmsg,
432 bool body_copied_out);
433
434extern void ipc_kmsg_set_voucher_port(
435 ipc_kmsg_t kmsg,
436 ipc_port_t voucher,
437 mach_msg_type_name_t type);
438
439extern ipc_port_t ipc_kmsg_get_voucher_port(
440 ipc_kmsg_t kmsg);
441
442extern void ipc_kmsg_clear_voucher_port(
443 ipc_kmsg_t kmsg);
444
445extern void ipc_kmsg_validate_partial_sig(
446 ipc_kmsg_t kmsg);
447
448#define moved_provisional_reply_port(port_type, port) \
449 (port_type == MACH_MSG_TYPE_MOVE_RECEIVE && IP_VALID(port) && ip_is_provisional_reply_port(port)) \
450
451extern void send_prp_telemetry(int msgh_id);
452
453#if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
454extern void ipc_kmsg_trace_send(
455 ipc_kmsg_t kmsg,
456 mach_msg_option_t option);
457#else
458#define ipc_kmsg_trace_send(a, b) do { } while (0)
459#endif
460
461#if (DEVELOPMENT || DEBUG)
462vm_offset_t ikm_kdata_end(ipc_kmsg_t kmsg);
463vm_offset_t ikm_udata_end(ipc_kmsg_t kmsg);
464#endif
465
466#endif /* _IPC_IPC_KMSG_H_ */
467