xref: /xnu-8020.101.4/osfmk/ipc/ipc_kmsg.h (revision e7776783b89a353188416a9a346c6cdb4928faad)
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 <ipc/ipc_types.h>
82 #include <ipc/ipc_object.h>
83 #include <sys/kdebug.h>
84 
85 #if (DEVELOPMENT || DEBUG)
86 /* Turn on to keep partial message signatures for better debug */
87 #define IKM_PARTIAL_SIG        0
88 #endif
89 
90 /*
91  *	This structure is only the header for a kmsg buffer;
92  *	the actual buffer is normally larger.  The rest of the buffer
93  *	holds the body of the message.
94  *
95  *	In a kmsg, the port fields hold pointers to ports instead
96  *	of port names.  These pointers hold references.
97  *
98  *	The ikm_header.msgh_remote_port field is the destination
99  *	of the message.
100  *
101  *	sync_qos and special_port_qos stores the qos for prealloced
102  *	port, this fields could be deleted once we remove ip_prealloc.
103  */
104 
105 struct ipc_kmsg {
106 	struct ipc_kmsg            *ikm_next;        /* next message on port/discard queue */
107 	struct ipc_kmsg            *ikm_prev;        /* prev message on port/discard queue */
108 	union {
109 		ipc_port_t XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_prealloc") ikm_prealloc; /* port we were preallocated from */
110 		void      *XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_data")     ikm_data;
111 	};
112 	mach_msg_header_t          *XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_header") ikm_header;
113 	ipc_port_t                 XNU_PTRAUTH_SIGNED_PTR("kmsg.ikm_voucher_port") ikm_voucher_port;   /* voucher port carried */
114 	struct ipc_importance_elem *ikm_importance;  /* inherited from */
115 	queue_chain_t              ikm_inheritance;  /* inherited from link */
116 	struct turnstile           *ikm_turnstile;   /* send turnstile for ikm_prealloc port */
117 #if MACH_FLIPC
118 	struct mach_node           *ikm_node;        /* Originating node - needed for ack */
119 #endif
120 	mach_msg_size_t            ikm_size;
121 	uint32_t                   ikm_ppriority;    /* pthread priority of this kmsg */
122 #if IKM_PARTIAL_SIG
123 	uintptr_t                  ikm_header_sig;   /* sig for just the header */
124 	uintptr_t                  ikm_headtrail_sig;/* sif for header and trailer */
125 #endif
126 	uintptr_t                  ikm_signature;    /* sig for all kernel-processed data */
127 	ipc_object_copyin_flags_t  ikm_flags;
128 	mach_msg_qos_t             ikm_qos_override; /* qos override on this kmsg */
129 	mach_msg_type_name_t       ikm_voucher_type : 8; /* disposition type the voucher came in with */
130 
131 	uint8_t                    ikm_inline_data[] __attribute__((aligned(4)));
132 };
133 
134 /*
135  * XXX	For debugging.
136  */
137 #define IKM_BOGUS               ((ipc_kmsg_t) 0xffffff10)
138 
139 /*
140  *	The size of the kernel message buffers that will be cached.
141  *	IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't.
142  */
143 extern zone_t ipc_kmsg_zone;
144 #define IKM_SAVED_KMSG_SIZE     256
145 #define IKM_SAVED_MSG_SIZE      (IKM_SAVED_KMSG_SIZE - sizeof(struct ipc_kmsg))
146 
147 #define ikm_prealloc_inuse_port(kmsg)                                   \
148 	((kmsg)->ikm_prealloc)
149 
150 #define ikm_prealloc_inuse(kmsg)                                        \
151 	((kmsg)->ikm_prealloc != IP_NULL)
152 
153 #define ikm_prealloc_set_inuse(kmsg, port)                              \
154 MACRO_BEGIN                                                             \
155 	assert((port) != IP_NULL);                                      \
156 	(kmsg)->ikm_prealloc = (port);                                  \
157 	ip_reference(port);                                             \
158 MACRO_END
159 
160 #define ikm_prealloc_clear_inuse(kmsg, port)                            \
161 MACRO_BEGIN                                                             \
162 	(kmsg)->ikm_prealloc = IP_NULL;                                 \
163 MACRO_END
164 
165 struct ipc_kmsg_queue {
166 	struct ipc_kmsg *ikmq_base;
167 };
168 
169 typedef struct ipc_kmsg_queue *ipc_kmsg_queue_t;
170 
171 #define IKMQ_NULL               ((ipc_kmsg_queue_t) 0)
172 
173 
174 /*
175  * Exported interfaces
176  */
177 
178 #define ipc_kmsg_queue_init(queue)              \
179 MACRO_BEGIN                                     \
180 	(queue)->ikmq_base = IKM_NULL;          \
181 MACRO_END
182 
183 #define ipc_kmsg_queue_empty(queue)     ((queue)->ikmq_base == IKM_NULL)
184 
185 /* Enqueue a kmsg */
186 extern void ipc_kmsg_enqueue(
187 	ipc_kmsg_queue_t        queue,
188 	ipc_kmsg_t              kmsg);
189 
190 extern boolean_t ipc_kmsg_enqueue_qos(
191 	ipc_kmsg_queue_t        queue,
192 	ipc_kmsg_t              kmsg);
193 
194 extern boolean_t ipc_kmsg_override_qos(
195 	ipc_kmsg_queue_t        queue,
196 	ipc_kmsg_t              kmsg,
197 	mach_msg_qos_t          qos_ovr);
198 
199 /* Dequeue and return a kmsg */
200 extern ipc_kmsg_t ipc_kmsg_dequeue(
201 	ipc_kmsg_queue_t        queue);
202 
203 /* Pull a kmsg out of a queue */
204 extern void ipc_kmsg_rmqueue(
205 	ipc_kmsg_queue_t        queue,
206 	ipc_kmsg_t              kmsg);
207 
208 /* Pull the (given) first kmsg out of a queue */
209 extern void ipc_kmsg_rmqueue_first(
210 	ipc_kmsg_queue_t        queue,
211 	ipc_kmsg_t              kmsg);
212 
213 #define ipc_kmsg_queue_first(queue)             ((queue)->ikmq_base)
214 
215 /* Return the kmsg following the given kmsg */
216 extern ipc_kmsg_t ipc_kmsg_queue_next(
217 	ipc_kmsg_queue_t        queue,
218 	ipc_kmsg_t              kmsg);
219 
220 __options_decl(ipc_kmsg_alloc_flags_t, uint32_t, {
221 	IPC_KMSG_ALLOC_USER     = 0x0000,
222 	IPC_KMSG_ALLOC_KERNEL   = 0x0001,
223 	IPC_KMSG_ALLOC_ZERO     = 0x0002,
224 	IPC_KMSG_ALLOC_SAVED    = 0x0004,
225 	IPC_KMSG_ALLOC_NOFAIL   = 0x0008,
226 });
227 
228 /* Allocate a kernel message */
229 extern ipc_kmsg_t ipc_kmsg_alloc(
230 	mach_msg_size_t         size,
231 	mach_msg_size_t         user_descriptors,
232 	ipc_kmsg_alloc_flags_t  flags);
233 
234 /* Free a kernel message buffer */
235 extern void ipc_kmsg_free(
236 	ipc_kmsg_t              kmsg);
237 
238 /* Destroy kernel message */
239 extern void ipc_kmsg_destroy(
240 	ipc_kmsg_t              kmsg);
241 
242 /* Enqueue kernel message for deferred destruction */
243 extern boolean_t ipc_kmsg_delayed_destroy(
244 	ipc_kmsg_t              kmsg);
245 
246 /* Enqueue queue of kernel messages for deferred destruction */
247 extern boolean_t ipc_kmsg_delayed_destroy_queue(
248 	ipc_kmsg_queue_t        queue);
249 
250 /* Process all the delayed message destroys */
251 extern void ipc_kmsg_reap_delayed(void);
252 
253 /* bind a preallocated message buffer to a port */
254 extern void ipc_kmsg_set_prealloc(
255 	ipc_kmsg_t              kmsg,
256 	ipc_port_t              port);
257 
258 /* Allocate a kernel message buffer and copy a user message to the buffer */
259 extern mach_msg_return_t ipc_kmsg_get_from_user(
260 	mach_vm_address_t       msg_addr,
261 	mach_msg_size_t         size,
262 	ipc_kmsg_t              *kmsgp);
263 
264 /* Allocate a kernel message buffer and copy a kernel message to the buffer */
265 extern mach_msg_return_t ipc_kmsg_get_from_kernel(
266 	mach_msg_header_t       *msg,
267 	mach_msg_size_t         size,
268 	ipc_kmsg_t              *kmsgp);
269 
270 /* Send a message to a port */
271 extern mach_msg_return_t ipc_kmsg_send(
272 	ipc_kmsg_t              kmsg,
273 	mach_msg_option_t       option,
274 	mach_msg_timeout_t      timeout_val);
275 
276 /* Copy a kernel message buffer to a user message */
277 extern mach_msg_return_t ipc_kmsg_put_to_user(
278 	ipc_kmsg_t              kmsg,
279 	mach_msg_option_t       option,
280 	mach_vm_address_t       rcv_addr,
281 	mach_msg_size_t         rcv_size,
282 	mach_msg_size_t         trailer_size,
283 	mach_msg_size_t         *size);
284 
285 /* Copy a kernel message buffer to a kernel message */
286 extern void ipc_kmsg_put_to_kernel(
287 	mach_msg_header_t       *msg,
288 	ipc_kmsg_t              kmsg,
289 	mach_msg_size_t         size);
290 
291 /* Copyin port rights and out-of-line memory from a user message */
292 extern mach_msg_return_t ipc_kmsg_copyin_from_user(
293 	ipc_kmsg_t              kmsg,
294 	ipc_space_t             space,
295 	vm_map_t                map,
296 	mach_msg_priority_t     priority,
297 	mach_msg_option_t       *optionp,
298 	bool                    filter_nonfatal);
299 
300 /* Copyin port rights and out-of-line memory from a kernel message */
301 extern mach_msg_return_t ipc_kmsg_copyin_from_kernel(
302 	ipc_kmsg_t              kmsg);
303 
304 /* Copyout the header and body to a user message */
305 extern mach_msg_return_t ipc_kmsg_copyout(
306 	ipc_kmsg_t              kmsg,
307 	ipc_space_t             space,
308 	vm_map_t                map,
309 	mach_msg_body_t         *slist,
310 	mach_msg_option_t       option);
311 
312 /* Copyout port rights and out-of-line memory to a user message,
313  *  not reversing the ports in the header */
314 extern mach_msg_return_t ipc_kmsg_copyout_pseudo(
315 	ipc_kmsg_t              kmsg,
316 	ipc_space_t             space,
317 	vm_map_t                map,
318 	mach_msg_body_t         *slist);
319 
320 /* Compute size of message as copied out to the specified space/map */
321 extern mach_msg_size_t ipc_kmsg_copyout_size(
322 	ipc_kmsg_t              kmsg,
323 	vm_map_t                map);
324 
325 /* Copyout the destination port in the message */
326 extern void ipc_kmsg_copyout_dest_to_user(
327 	ipc_kmsg_t              kmsg,
328 	ipc_space_t             space);
329 
330 /* kernel's version of ipc_kmsg_copyout_dest_to_user */
331 extern void ipc_kmsg_copyout_dest_to_kernel(
332 	ipc_kmsg_t              kmsg,
333 	ipc_space_t             space);
334 
335 /* Returns a pointer to a thread group in the kmsg if any. Caller has a
336  * reference to the kmsg */
337 extern struct thread_group *ipc_kmsg_get_thread_group(
338 	ipc_kmsg_t              kmsg);
339 
340 extern mach_msg_trailer_size_t ipc_kmsg_trailer_size(
341 	mach_msg_option_t       option,
342 	thread_t                thread);
343 
344 extern void ipc_kmsg_init_trailer(
345 	ipc_kmsg_t              kmsg,
346 	mach_msg_size_t         msg_size,
347 	task_t                  sender);
348 
349 extern void ipc_kmsg_add_trailer(
350 	ipc_kmsg_t              kmsg,
351 	ipc_space_t             space,
352 	mach_msg_option_t       option,
353 	thread_t                thread,
354 	mach_port_seqno_t       seqno,
355 	boolean_t               minimal_trailer,
356 	mach_vm_offset_t        context);
357 
358 extern void ipc_kmsg_set_voucher_port(
359 	ipc_kmsg_t              kmsg,
360 	ipc_port_t              voucher,
361 	mach_msg_type_name_t    type);
362 
363 extern ipc_port_t ipc_kmsg_get_voucher_port(
364 	ipc_kmsg_t              kmsg);
365 
366 extern void ipc_kmsg_clear_voucher_port(
367 	ipc_kmsg_t              kmsg);
368 
369 #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD)
370 extern void ipc_kmsg_trace_send(
371 	ipc_kmsg_t              kmsg,
372 	mach_msg_option_t       option);
373 #else
374 #define ipc_kmsg_trace_send(a, b) do { } while (0)
375 #endif
376 
377 extern mach_msg_header_t *
378     ipc_kmsg_msg_header(ipc_kmsg_t);
379 
380 #endif  /* _IPC_IPC_KMSG_H_ */
381