xref: /xnu-10063.101.15/osfmk/ipc/ipc_kmsg.h (revision 94d3b452840153a99b38a3a9659680b2a006908e)
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 #define IKM_SAVED_KMSG_SIZE     256
182 #define IKM_SAVED_MSG_SIZE      (IKM_SAVED_KMSG_SIZE - sizeof(struct ipc_kmsg))
183 
184 KALLOC_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)                              \
193 MACRO_BEGIN                                                             \
194 	assert((port) != IP_NULL);                                      \
195 	(kmsg)->ikm_prealloc = (port);                                  \
196 	ip_validate(port);                                              \
197 	ip_reference(port);                                             \
198 MACRO_END
199 
200 #define ikm_prealloc_clear_inuse(kmsg)                            \
201 MACRO_BEGIN                                                             \
202 	(kmsg)->ikm_prealloc = IP_NULL;                                 \
203 MACRO_END
204 
205 /*
206  * Exported interfaces
207  */
208 struct ipc_kmsg_queue {
209 	struct ipc_kmsg *ikmq_base;
210 };
211 
212 typedef 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 
233 extern bool ipc_kmsg_enqueue_qos(
234 	ipc_kmsg_queue_t        queue,
235 	ipc_kmsg_t              kmsg);
236 
237 extern 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 
245 extern 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 */
251 extern 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 */
267 extern 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 */
274 extern 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 */
284 extern void ipc_kmsg_destroy(
285 	ipc_kmsg_t                kmsg,
286 	ipc_kmsg_destroy_flags_t  flags);
287 
288 /* Enqueue kernel message for deferred destruction */
289 extern bool ipc_kmsg_delayed_destroy(
290 	ipc_kmsg_t              kmsg);
291 
292 /* Enqueue queue of kernel messages for deferred destruction */
293 extern bool ipc_kmsg_delayed_destroy_queue(
294 	ipc_kmsg_queue_t        queue);
295 
296 /* Process all the delayed message destroys */
297 extern void ipc_kmsg_reap_delayed(void);
298 
299 /* bind a preallocated message buffer to a port */
300 extern 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 */
305 extern 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 */
309 extern void *ikm_udata(
310 	ipc_kmsg_t              kmsg,
311 	mach_msg_size_t         desc_count,
312 	bool                    complex);
313 
314 extern void * ikm_udata_from_header(
315 	ipc_kmsg_t              kmsg);
316 
317 /* get the size of auxiliary data for a kmsg */
318 extern mach_msg_size_t ipc_kmsg_aux_data_size(
319 	ipc_kmsg_t              kmsg);
320 
321 extern 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 */
326 extern 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 */
337 extern 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 */
343 extern 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 */
349 extern 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 */
361 extern 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 */
367 extern 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 */
376 extern 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 */
380 extern 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 */
388 extern 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 */
394 extern 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 */
399 extern 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 */
404 extern 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 */
410 extern struct thread_group *ipc_kmsg_get_thread_group(
411 	ipc_kmsg_t              kmsg);
412 
413 extern mach_msg_trailer_size_t ipc_kmsg_trailer_size(
414 	mach_msg_option_t       option,
415 	thread_t                thread);
416 
417 extern void ipc_kmsg_init_trailer(
418 	ipc_kmsg_t              kmsg,
419 	task_t                  sender);
420 
421 extern 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 
430 extern mach_msg_max_trailer_t *ipc_kmsg_get_trailer(
431 	ipc_kmsg_t              kmsg,
432 	bool                    body_copied_out);
433 
434 extern void ipc_kmsg_set_voucher_port(
435 	ipc_kmsg_t              kmsg,
436 	ipc_port_t              voucher,
437 	mach_msg_type_name_t    type);
438 
439 extern ipc_port_t ipc_kmsg_get_voucher_port(
440 	ipc_kmsg_t              kmsg);
441 
442 extern void ipc_kmsg_clear_voucher_port(
443 	ipc_kmsg_t              kmsg);
444 
445 extern 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 
451 extern void send_prp_telemetry(int msgh_id);
452 
453 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
454 extern 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)
462 vm_offset_t ikm_kdata_end(ipc_kmsg_t kmsg);
463 vm_offset_t ikm_udata_end(ipc_kmsg_t kmsg);
464 #endif
465 
466 #endif  /* _IPC_IPC_KMSG_H_ */
467