xref: /xnu-8796.141.3/osfmk/ipc/ipc_kmsg.h (revision 1b191cb58250d0705d8a51287127505aa4bc0789)
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         user_descriptors,
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 /* get the size of auxiliary data for a kmsg */
316 extern mach_msg_size_t ipc_kmsg_aux_data_size(
317 	ipc_kmsg_t              kmsg);
318 
319 extern void ipc_kmsg_set_aux_data_header(
320 	ipc_kmsg_t              kmsg,
321 	mach_msg_aux_header_t   *header);
322 
323 /* Allocate a kernel message buffer and copy a user message to the buffer */
324 extern mach_msg_return_t ipc_kmsg_get_from_user(
325 	mach_vm_address_t       msg_addr,
326 	mach_msg_size_t         user_msg_size,
327 	mach_vm_address_t       aux_addr,
328 	mach_msg_size_t         aux_size,
329 	mach_msg_user_header_t  user_header,
330 	mach_msg_size_t         desc_count,
331 	mach_msg_option64_t     option64,
332 	ipc_kmsg_t              *kmsgp);
333 
334 /* Allocate a kernel message buffer and copy a kernel message to the buffer */
335 extern mach_msg_return_t ipc_kmsg_get_from_kernel(
336 	mach_msg_header_t       *msg,
337 	mach_msg_size_t         size,
338 	ipc_kmsg_t              *kmsgp);
339 
340 /* Send a message to a port */
341 extern mach_msg_return_t ipc_kmsg_send(
342 	ipc_kmsg_t              kmsg,
343 	mach_msg_option64_t     option64,
344 	mach_msg_timeout_t      timeout_val);
345 
346 /* Copy a kernel message buffer to a user message */
347 extern mach_msg_return_t ipc_kmsg_put_to_user(
348 	ipc_kmsg_t              kmsg,     /* scalar or vector */
349 	mach_msg_option64_t     option,
350 	mach_vm_address_t       rcv_msg_addr,
351 	mach_msg_size_t         max_msg_size,
352 	mach_vm_address_t       rcv_aux_addr,
353 	mach_msg_size_t         max_aux_size,
354 	mach_msg_size_t         trailer_size,
355 	mach_msg_size_t         *msg_sizep,
356 	mach_msg_size_t         *aux_sizep);
357 
358 /* Copy a kernel message buffer to a kernel message */
359 extern void ipc_kmsg_put_to_kernel(
360 	mach_msg_header_t       *msg,
361 	ipc_kmsg_t              kmsg,
362 	mach_msg_size_t         size);
363 
364 /* Copyin port rights and out-of-line memory from a user message */
365 extern mach_msg_return_t ipc_kmsg_copyin_from_user(
366 	ipc_kmsg_t              kmsg,
367 	ipc_space_t             space,
368 	vm_map_t                map,
369 	mach_msg_priority_t     priority,
370 	mach_msg_option64_t     *optionp,
371 	bool                    filter_nonfatal);
372 
373 /* Copyin port rights and out-of-line memory from a kernel message */
374 extern mach_msg_return_t ipc_kmsg_copyin_from_kernel(
375 	ipc_kmsg_t              kmsg);
376 
377 /* Copyout the header and body to a user message */
378 extern mach_msg_return_t ipc_kmsg_copyout(
379 	ipc_kmsg_t              kmsg,
380 	ipc_space_t             space,
381 	vm_map_t                map,
382 	mach_msg_option_t       option);
383 
384 /* Copyout port rights and out-of-line memory to a user message,
385  *  not reversing the ports in the header */
386 extern mach_msg_return_t ipc_kmsg_copyout_pseudo(
387 	ipc_kmsg_t              kmsg,
388 	ipc_space_t             space,
389 	vm_map_t                map);
390 
391 /* Compute size of message as copied out to the specified space/map */
392 extern mach_msg_size_t ipc_kmsg_copyout_size(
393 	ipc_kmsg_t              kmsg,
394 	vm_map_t                map);
395 
396 /* Copyout the destination port in the message */
397 extern void ipc_kmsg_copyout_dest_to_user(
398 	ipc_kmsg_t              kmsg,
399 	ipc_space_t             space);
400 
401 /* kernel's version of ipc_kmsg_copyout_dest_to_user */
402 extern void ipc_kmsg_copyout_dest_to_kernel(
403 	ipc_kmsg_t              kmsg,
404 	ipc_space_t             space);
405 
406 /* Returns a pointer to a thread group in the kmsg if any. Caller has a
407  * reference to the kmsg */
408 extern struct thread_group *ipc_kmsg_get_thread_group(
409 	ipc_kmsg_t              kmsg);
410 
411 extern mach_msg_trailer_size_t ipc_kmsg_trailer_size(
412 	mach_msg_option_t       option,
413 	thread_t                thread);
414 
415 extern void ipc_kmsg_init_trailer(
416 	ipc_kmsg_t              kmsg,
417 	task_t                  sender);
418 
419 extern void ipc_kmsg_add_trailer(
420 	ipc_kmsg_t              kmsg,
421 	ipc_space_t             space,
422 	mach_msg_option_t       option,
423 	thread_t                thread,
424 	mach_port_seqno_t       seqno,
425 	boolean_t               minimal_trailer,
426 	mach_vm_offset_t        context);
427 
428 extern mach_msg_max_trailer_t *ipc_kmsg_get_trailer(
429 	ipc_kmsg_t              kmsg,
430 	bool                    body_copied_out);
431 
432 extern void ipc_kmsg_set_voucher_port(
433 	ipc_kmsg_t              kmsg,
434 	ipc_port_t              voucher,
435 	mach_msg_type_name_t    type);
436 
437 extern ipc_port_t ipc_kmsg_get_voucher_port(
438 	ipc_kmsg_t              kmsg);
439 
440 extern void ipc_kmsg_clear_voucher_port(
441 	ipc_kmsg_t              kmsg);
442 
443 extern void ipc_kmsg_validate_sig(
444 	ipc_kmsg_t              kmsg,
445 	bool                    partial);
446 
447 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
448 extern void ipc_kmsg_trace_send(
449 	ipc_kmsg_t              kmsg,
450 	mach_msg_option_t       option);
451 #else
452 #define ipc_kmsg_trace_send(a, b) do { } while (0)
453 #endif
454 
455 #endif  /* _IPC_IPC_KMSG_H_ */
456