xref: /xnu-8792.81.2/osfmk/ipc/ipc_kmsg.h (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
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/circle_queue.h>
82 #include <ipc/ipc_types.h>
83 #include <ipc/ipc_object.h>
84 #include <sys/kdebug.h>
85 
86 /*
87  *	This structure is only the header for a kmsg buffer;
88  *	the actual buffer is normally larger. The rest of the buffer
89  *	holds the body of the message.
90  *
91  *	In a kmsg, the port fields hold pointers to ports instead
92  *	of port names. These pointers hold references.
93  *
94  *	The ikm_header.msgh_remote_port field is the destination
95  *	of the message.
96  *
97  *	sync_qos and special_port_qos stores the qos for prealloced
98  *	port, this fields could be deleted once we remove ip_prealloc.
99  */
100 
101 /* A kmsg can be in one of the following four layouts */
102 __enum_decl(ipc_kmsg_type_t, uint8_t, {
103 	/*
104 	 * IKM_TYPE_ALL_INLINED: The entire message (and aux) is allocated inline.
105 	 * mach_msg_header_t is immediately after the kmsg header. An optional aux
106 	 * may be following the inline message proper.
107 	 */
108 	IKM_TYPE_ALL_INLINED    = 0,
109 	/*
110 	 * IKM_TYPE_UDATA_OOL: Message header and descriptors are allocated inline,
111 	 * and message data, trailer, and aux are in buffer pointed to by ikm_udata.
112 	 * mach_msg_header_t is immediately after the kmsg header.
113 	 */
114 	IKM_TYPE_UDATA_OOL      = 1,
115 	/*
116 	 * IKM_TYPE_KDATA_OOL: The entire message is allocated out-of-line.
117 	 * An ipc_kmsg_vector_t follows the kmsg header specifying the address and
118 	 * size of the allocation. There is no aux data.
119 	 */
120 	IKM_TYPE_KDATA_OOL      = 2,
121 	/*
122 	 * IKM_TYPE_ALL_OOL: Everything is allocated out-of-line. Message header
123 	 * and descriptors are allocated from typed kernel heap (kalloc_type), and
124 	 * message data, trailer, and aux are in data buffer pointed to by ikm_udata.
125 	 * An ipc_kmsg_vector_t follows the kmsg header specifying the address and
126 	 * size of the kdata allocation.
127 	 */
128 	IKM_TYPE_ALL_OOL        = 3
129 });
130 
131 struct ipc_kmsg {
132 	queue_chain_t              ikm_link;
133 	union {
134 		/* port we were preallocated from, for IKM_TYPE_ALL_INLINED */
135 		ipc_port_t XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_prealloc") ikm_prealloc;
136 		/* user data buffer, unused for IKM_TYPE_ALL_INLINED */
137 		void      *XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_udata")    ikm_udata;
138 	};
139 	ipc_port_t                 XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_voucher_port") ikm_voucher_port;   /* voucher port carried */
140 	struct ipc_importance_elem *ikm_importance;  /* inherited from */
141 	queue_chain_t              ikm_inheritance;  /* inherited from link */
142 #if MACH_FLIPC
143 	struct mach_node           *ikm_node;        /* originating node - needed for ack */
144 #endif
145 	mach_msg_size_t            ikm_aux_size;     /* size reserved for auxiliary data */
146 	uint32_t                   ikm_ppriority;    /* pthread priority of this kmsg */
147 	union {
148 		struct {
149 			/* For PAC-supported devices */
150 			uint32_t           ikm_sig_partial;  /* partial sig for header + trailer */
151 			uint32_t           ikm_sig_full;     /* upper 32 bits is full signature */
152 		};
153 		uint64_t               ikm_signature;    /* sig for all kernel-processed data */
154 	};
155 	ipc_object_copyin_flags_t  ikm_flags;
156 	mach_msg_qos_t             ikm_qos_override; /* qos override on this kmsg */
157 
158 	mach_msg_type_name_t       ikm_voucher_type: 6; /* disposition type the voucher came in with */
159 	ipc_kmsg_type_t            ikm_type: 2;
160 
161 	/* size of buffer pointed to by ikm_udata, unused for IKM_TYPE_ALL_INLINED. */
162 	mach_msg_size_t            ikm_udata_size;
163 	/* inline data of size IKM_SAVED_MSG_SIZE follows */
164 };
165 
166 typedef struct {
167 	void                            *XNU_PTRAUTH_SIGNED_PTR("kmsgv.kmsgv_data") kmsgv_data;
168 	mach_msg_size_t                 kmsgv_size; /* size of buffer, or descriptor count */
169 } ipc_kmsg_vector_t;
170 
171 /*
172  * XXX	For debugging.
173  */
174 #define IKM_BOGUS               ((ipc_kmsg_t) 0xffffff10)
175 
176 /*
177  *	The size of the kernel message buffers that will be cached.
178  *	IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't.
179  */
180 extern zone_t ipc_kmsg_zone;
181 #define IKM_SAVED_KMSG_SIZE     256
182 #define IKM_SAVED_MSG_SIZE      (IKM_SAVED_KMSG_SIZE - sizeof(struct ipc_kmsg))
183 
184 #define ikm_prealloc_inuse_port(kmsg)                                   \
185 	((kmsg)->ikm_prealloc)
186 
187 #define ikm_prealloc_inuse(kmsg)                                        \
188 	((kmsg)->ikm_prealloc != IP_NULL)
189 
190 #define ikm_prealloc_set_inuse(kmsg, port)                              \
191 MACRO_BEGIN                                                             \
192 	assert((port) != IP_NULL);                                      \
193 	(kmsg)->ikm_prealloc = (port);                                  \
194 	ip_validate(port);                                              \
195 	ip_reference(port);                                             \
196 MACRO_END
197 
198 #define ikm_prealloc_clear_inuse(kmsg)                            \
199 MACRO_BEGIN                                                             \
200 	(kmsg)->ikm_prealloc = IP_NULL;                                 \
201 MACRO_END
202 
203 /*
204  * Exported interfaces
205  */
206 struct ipc_kmsg_queue {
207 	struct ipc_kmsg *ikmq_base;
208 };
209 
210 typedef circle_queue_t                  ipc_kmsg_queue_t;
211 
212 #define ipc_kmsg_queue_init(queue)      circle_queue_init(queue)
213 
214 #define ipc_kmsg_queue_empty(queue)     circle_queue_empty(queue)
215 
216 #define ipc_kmsg_queue_element(elem) \
217 	cqe_element(elem, struct ipc_kmsg, ikm_link)
218 
219 #define ipc_kmsg_queue_first(queue) \
220 	cqe_queue_first(queue, struct ipc_kmsg, ikm_link)
221 
222 #define ipc_kmsg_queue_next(queue, elt) \
223 	cqe_queue_next(&(elt)->ikm_link, queue, struct ipc_kmsg, ikm_link)
224 
225 #define ipc_kmsg_enqueue(queue, kmsg) \
226 	circle_enqueue_tail(queue, &(kmsg)->ikm_link)
227 
228 #define ipc_kmsg_rmqueue(queue, kmsg) \
229 	circle_dequeue(queue, &(kmsg)->ikm_link)
230 
231 extern bool ipc_kmsg_enqueue_qos(
232 	ipc_kmsg_queue_t        queue,
233 	ipc_kmsg_t              kmsg);
234 
235 extern bool ipc_kmsg_too_large(
236 	mach_msg_size_t         msg_size,
237 	mach_msg_size_t         aux_size,
238 	mach_msg_option64_t     options,
239 	mach_msg_size_t         max_msg_size,
240 	mach_msg_size_t         max_aux_size,
241 	thread_t                receiver);
242 
243 extern bool ipc_kmsg_override_qos(
244 	ipc_kmsg_queue_t        queue,
245 	ipc_kmsg_t              kmsg,
246 	mach_msg_qos_t          qos_ovr);
247 
248 /* Pull the (given) first kmsg out of a queue */
249 extern void ipc_kmsg_rmqueue_first(
250 	ipc_kmsg_queue_t        queue,
251 	ipc_kmsg_t              kmsg);
252 
253 __options_decl(ipc_kmsg_alloc_flags_t, uint32_t, {
254 	/* specify either user or kernel flag */
255 	IPC_KMSG_ALLOC_USER     = 0x0000,
256 	IPC_KMSG_ALLOC_KERNEL   = 0x0001,
257 
258 	IPC_KMSG_ALLOC_ZERO     = 0x0002,
259 	IPC_KMSG_ALLOC_SAVED    = 0x0004,
260 	IPC_KMSG_ALLOC_NOFAIL   = 0x0008,
261 	IPC_KMSG_ALLOC_LINEAR   = 0x0010,
262 });
263 
264 /* Allocate a kernel message */
265 extern ipc_kmsg_t ipc_kmsg_alloc(
266 	mach_msg_size_t         msg_size,
267 	mach_msg_size_t         aux_size,
268 	mach_msg_size_t         user_descriptors,
269 	ipc_kmsg_alloc_flags_t  flags);
270 
271 /* Free a kernel message buffer */
272 extern void ipc_kmsg_free(
273 	ipc_kmsg_t              kmsg);
274 
275 __options_decl(ipc_kmsg_destroy_flags_t, uint32_t, {
276 	IPC_KMSG_DESTROY_ALL           = 0x0000,
277 	IPC_KMSG_DESTROY_SKIP_REMOTE   = 0x0001,
278 	IPC_KMSG_DESTROY_SKIP_LOCAL    = 0x0002,
279 	IPC_KMSG_DESTROY_NOT_SIGNED    = 0x0004,
280 });
281 /* Destroy kernel message */
282 extern void ipc_kmsg_destroy(
283 	ipc_kmsg_t                kmsg,
284 	ipc_kmsg_destroy_flags_t  flags);
285 
286 /* Enqueue kernel message for deferred destruction */
287 extern bool ipc_kmsg_delayed_destroy(
288 	ipc_kmsg_t              kmsg);
289 
290 /* Enqueue queue of kernel messages for deferred destruction */
291 extern bool ipc_kmsg_delayed_destroy_queue(
292 	ipc_kmsg_queue_t        queue);
293 
294 /* Process all the delayed message destroys */
295 extern void ipc_kmsg_reap_delayed(void);
296 
297 /* bind a preallocated message buffer to a port */
298 extern void ipc_kmsg_set_prealloc(
299 	ipc_kmsg_t              kmsg,
300 	ipc_port_t              port);
301 
302 /* get the unshifted message header of a kmsg */
303 extern mach_msg_header_t *ikm_header(
304 	ipc_kmsg_t              kmsg);
305 
306 /* get the start address of user data (after the last descriptor) for a kmsg */
307 extern void *ikm_udata(
308 	ipc_kmsg_t              kmsg,
309 	mach_msg_size_t         desc_count,
310 	bool                    complex);
311 
312 /* get the size of auxiliary data for a kmsg */
313 extern mach_msg_size_t ipc_kmsg_aux_data_size(
314 	ipc_kmsg_t              kmsg);
315 
316 extern void ipc_kmsg_set_aux_data_header(
317 	ipc_kmsg_t              kmsg,
318 	mach_msg_aux_header_t   *header);
319 
320 /* Allocate a kernel message buffer and copy a user message to the buffer */
321 extern mach_msg_return_t ipc_kmsg_get_from_user(
322 	mach_vm_address_t       msg_addr,
323 	mach_msg_size_t         user_msg_size,
324 	mach_vm_address_t       aux_addr,
325 	mach_msg_size_t         aux_size,
326 	mach_msg_user_header_t  user_header,
327 	mach_msg_size_t         desc_count,
328 	mach_msg_option64_t     option64,
329 	ipc_kmsg_t              *kmsgp);
330 
331 /* Allocate a kernel message buffer and copy a kernel message to the buffer */
332 extern mach_msg_return_t ipc_kmsg_get_from_kernel(
333 	mach_msg_header_t       *msg,
334 	mach_msg_size_t         size,
335 	ipc_kmsg_t              *kmsgp);
336 
337 /* Send a message to a port */
338 extern mach_msg_return_t ipc_kmsg_send(
339 	ipc_kmsg_t              kmsg,
340 	mach_msg_option64_t     option64,
341 	mach_msg_timeout_t      timeout_val);
342 
343 /* Copy a kernel message buffer to a user message */
344 extern mach_msg_return_t ipc_kmsg_put_to_user(
345 	ipc_kmsg_t              kmsg,     /* scalar or vector */
346 	mach_msg_option64_t     option,
347 	mach_vm_address_t       rcv_msg_addr,
348 	mach_msg_size_t         max_msg_size,
349 	mach_vm_address_t       rcv_aux_addr,
350 	mach_msg_size_t         max_aux_size,
351 	mach_msg_size_t         trailer_size,
352 	mach_msg_size_t         *msg_sizep,
353 	mach_msg_size_t         *aux_sizep);
354 
355 /* Copy a kernel message buffer to a kernel message */
356 extern void ipc_kmsg_put_to_kernel(
357 	mach_msg_header_t       *msg,
358 	ipc_kmsg_t              kmsg,
359 	mach_msg_size_t         size);
360 
361 /* Copyin port rights and out-of-line memory from a user message */
362 extern mach_msg_return_t ipc_kmsg_copyin_from_user(
363 	ipc_kmsg_t              kmsg,
364 	ipc_space_t             space,
365 	vm_map_t                map,
366 	mach_msg_priority_t     priority,
367 	mach_msg_option64_t     *optionp,
368 	bool                    filter_nonfatal);
369 
370 /* Copyin port rights and out-of-line memory from a kernel message */
371 extern mach_msg_return_t ipc_kmsg_copyin_from_kernel(
372 	ipc_kmsg_t              kmsg);
373 
374 /* Copyout the header and body to a user message */
375 extern mach_msg_return_t ipc_kmsg_copyout(
376 	ipc_kmsg_t              kmsg,
377 	ipc_space_t             space,
378 	vm_map_t                map,
379 	mach_msg_option_t       option);
380 
381 /* Copyout port rights and out-of-line memory to a user message,
382  *  not reversing the ports in the header */
383 extern mach_msg_return_t ipc_kmsg_copyout_pseudo(
384 	ipc_kmsg_t              kmsg,
385 	ipc_space_t             space,
386 	vm_map_t                map);
387 
388 /* Compute size of message as copied out to the specified space/map */
389 extern mach_msg_size_t ipc_kmsg_copyout_size(
390 	ipc_kmsg_t              kmsg,
391 	vm_map_t                map);
392 
393 /* Copyout the destination port in the message */
394 extern void ipc_kmsg_copyout_dest_to_user(
395 	ipc_kmsg_t              kmsg,
396 	ipc_space_t             space);
397 
398 /* kernel's version of ipc_kmsg_copyout_dest_to_user */
399 extern void ipc_kmsg_copyout_dest_to_kernel(
400 	ipc_kmsg_t              kmsg,
401 	ipc_space_t             space);
402 
403 /* Returns a pointer to a thread group in the kmsg if any. Caller has a
404  * reference to the kmsg */
405 extern struct thread_group *ipc_kmsg_get_thread_group(
406 	ipc_kmsg_t              kmsg);
407 
408 extern mach_msg_trailer_size_t ipc_kmsg_trailer_size(
409 	mach_msg_option_t       option,
410 	thread_t                thread);
411 
412 extern void ipc_kmsg_init_trailer(
413 	ipc_kmsg_t              kmsg,
414 	task_t                  sender);
415 
416 extern void ipc_kmsg_add_trailer(
417 	ipc_kmsg_t              kmsg,
418 	ipc_space_t             space,
419 	mach_msg_option_t       option,
420 	thread_t                thread,
421 	mach_port_seqno_t       seqno,
422 	boolean_t               minimal_trailer,
423 	mach_vm_offset_t        context);
424 
425 extern mach_msg_max_trailer_t *ipc_kmsg_get_trailer(
426 	ipc_kmsg_t              kmsg,
427 	bool                    body_copied_out);
428 
429 extern void ipc_kmsg_set_voucher_port(
430 	ipc_kmsg_t              kmsg,
431 	ipc_port_t              voucher,
432 	mach_msg_type_name_t    type);
433 
434 extern ipc_port_t ipc_kmsg_get_voucher_port(
435 	ipc_kmsg_t              kmsg);
436 
437 extern void ipc_kmsg_clear_voucher_port(
438 	ipc_kmsg_t              kmsg);
439 
440 extern void ipc_kmsg_validate_sig(
441 	ipc_kmsg_t              kmsg,
442 	bool                    partial);
443 
444 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
445 extern void ipc_kmsg_trace_send(
446 	ipc_kmsg_t              kmsg,
447 	mach_msg_option_t       option);
448 #else
449 #define ipc_kmsg_trace_send(a, b) do { } while (0)
450 #endif
451 
452 #endif  /* _IPC_IPC_KMSG_H_ */
453