xref: /xnu-12377.1.9/osfmk/ipc/ipc_port.h (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1 /*
2  * Copyright (c) 2000-2016 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  */
62 /*
63  */
64 /*
65  *	File:	ipc/ipc_port.h
66  *	Author:	Rich Draves
67  *	Date:	1989
68  *
69  *	Definitions for ports.
70  */
71 
72 #ifndef _IPC_IPC_PORT_H_
73 #define _IPC_IPC_PORT_H_
74 
75 #include <mach/mach_types.h>
76 #include <mach/boolean.h>
77 #include <mach/kern_return.h>
78 #include <mach/port.h>
79 
80 #ifdef MACH_KERNEL_PRIVATE
81 #include <mach_assert.h>
82 
83 #include <kern/assert.h>
84 #include <kern/kern_types.h>
85 #include <kern/turnstile.h>
86 
87 #include <ipc/ipc_types.h>
88 #include <ipc/ipc_object.h>
89 #include <ipc/ipc_mqueue.h>
90 
91 #include <ptrauth.h>
92 #endif /* MACH_KERNEL_PRIVATE */
93 
94 __BEGIN_DECLS __ASSUME_PTR_ABI_SINGLE_BEGIN
95 #if MACH_KERNEL_PRIVATE
96 #pragma GCC visibility push(hidden)
97 
98 struct task_watchport_elem;
99 
100 typedef unsigned long ipc_port_timestamp_t;
101 
102 struct ipc_port_request {
103 	union {
104 		struct ipc_port                *ipr_soright;
105 		struct host_notify_entry *XNU_PTRAUTH_SIGNED_PTR("ipc_port_request.ipr_hnotify") ipr_hnotify;
106 		struct ipc_port_request *XNU_PTRAUTH_SIGNED_PTR("ipc_port_request.ipr_hn_slot") ipr_hn_slot;
107 	};
108 
109 	union {
110 #define IPR_HOST_NOTIFY                         0xfffffffeu
111 		mach_port_name_t                ipr_name;
112 		ipc_port_request_index_t        ipr_next;
113 	};
114 };
115 
116 KALLOC_ARRAY_TYPE_DECL(ipc_port_request_table, struct ipc_port_request);
117 
118 struct ipc_port {
119 	struct ipc_object               ip_object;
120 	union {
121 		/*
122 		 * The waitq_eventmask field is only used on the global queues.
123 		 * We hence repurpose all those bits for our own use.
124 		 *
125 		 * Note: if too many bits are added, compilation will fail
126 		 *       with errors about "negative bitfield sizes"
127 		 */
128 		WAITQ_FLAGS(ip_waitq
129 		    , ip_fullwaiters:1            /* Whether there are senders blocked on a full queue */
130 		    , ip_sprequests:1             /* send-possible requests outstanding */
131 		    , ip_spimportant:1            /* ... at least one is importance donating */
132 		    , ip_impdonation:1            /* port supports importance donation */
133 		    , ip_tempowner:1              /* dont give donations to current receiver */
134 		    , ip_guarded:1                /* port guarded (use context value as guard) */
135 		    , ip_strict_guard:1           /* Strict guarding; Prevents user manipulation of context values directly */
136 		    , ip_sync_link_state:3        /* link the port to destination port/ Workloop */
137 		    , ip_sync_bootstrap_checkin:1 /* port part of sync bootstrap checkin, push on thread doing the checkin */
138 		    , ip_tg_block_tracking:1      /* Track blocking relationship between thread groups during sync IPC */
139 		    , ip_has_watchport:1          /* port has an exec watchport */
140 		    , ip_kernel_iotier_override:2 /* kernel iotier override */
141 		    , ip_kernel_qos_override:3    /* kernel qos override */
142 		    /* development bits only */
143 		    , ip_srp_lost_link:1          /* special reply port turnstile link chain broken */
144 		    , ip_srp_msg_sent:1           /* special reply port msg sent */
145 		    , ip_bootstrap:1              /* whether it is a bootstrap port */
146 		    , __ip_unused:6               /* reserve of bits */
147 		    );
148 		struct waitq            ip_waitq;
149 	};
150 
151 	struct ipc_mqueue               ip_messages;
152 
153 	/*
154 	 * IMPORTANT: Direct access of unionized fields are highly discouraged.
155 	 * Use accessor functions below and see header doc for possible states.
156 	 */
157 	union {
158 		struct ipc_space       *XNU_PTRAUTH_SIGNED_PTR("ipc_port.ip_receiver") ip_receiver;
159 		struct ipc_port        *XNU_PTRAUTH_SIGNED_PTR("ipc_port.ip_destination") ip_destination;
160 		ipc_port_timestamp_t    ip_timestamp;
161 	};
162 
163 	union {
164 		uintptr_t               ip_kobject; /* manually PAC-ed, see ipc_kobject_get_raw() */
165 		struct ipc_port        *XNU_PTRAUTH_SIGNED_PTR("ipc_port.ip_nsrequest") ip_nsrequest;
166 	};
167 
168 	union {
169 		ipc_importance_task_t   ip_imp_task; /* use accessor ip_get_imp_task() */
170 		struct ipc_port        *ip_sync_inheritor_port;
171 		struct knote           *ip_sync_inheritor_knote;
172 		struct turnstile       *ip_sync_inheritor_ts;
173 	};
174 
175 	/*
176 	 * IOT_SPECIAL_REPLY:   ip_pid
177 	 * ip_has_watchport:    ip_twe
178 	 * else:                ip_pdrequest
179 	 */
180 	union {
181 		int                     ip_pid;
182 		struct task_watchport_elem *XNU_PTRAUTH_SIGNED_PTR("ipc_port.ip_twe") ip_twe;
183 		struct ipc_port *XNU_PTRAUTH_SIGNED_PTR("ipc_port.ip_pdrequest") ip_pdrequest;
184 	};
185 
186 	ipc_port_request_table_t XNU_PTRAUTH_SIGNED_PTR("ipc_port.ip_request") ip_requests;
187 	struct turnstile               *ip_send_turnstile;
188 	mach_vm_address_t               ip_context;
189 
190 	natural_t                       ip_impcount;    /* number of importance donations in nested queue */
191 	mach_port_mscount_t             ip_mscount;
192 	mach_port_rights_t              ip_srights;
193 	mach_port_rights_t              ip_sorights;
194 
195 #if MACH_ASSERT
196 	unsigned long                   ip_timetrack;   /* give an idea of "when" created */
197 	uint32_t                        ip_made_bt;     /* stack trace (btref_t) */
198 	uint32_t                        ip_made_pid;    /* for debugging */
199 #endif  /* MACH_ASSERT */
200 };
201 
202 static inline bool
ip_in_pset(ipc_port_t port)203 ip_in_pset(ipc_port_t port)
204 {
205 	return !circle_queue_empty(&port->ip_waitq.waitq_links);
206 }
207 
208 #define ip_receiver_name        ip_messages.imq_receiver_name
209 #define ip_reply_context        ip_messages.imq_context
210 #define ip_klist                ip_messages.imq_klist
211 
212 #define port_send_turnstile(port) \
213 	((port)->ip_send_turnstile)
214 
215 #define set_port_send_turnstile(port, value) \
216 MACRO_BEGIN                                  \
217 	(port)->ip_send_turnstile = (value); \
218 MACRO_END
219 
220 #define port_send_turnstile_address(port)    \
221 	(&((port)->ip_send_turnstile))
222 
223 #define port_rcv_turnstile_address(port)   (&(port)->ip_waitq.waitq_ts)
224 
225 extern void __ipc_right_delta_overflow_panic(
226 	ipc_port_t          port,
227 	natural_t          *field,
228 	int                 delta) __abortlike;
229 
230 #define ip_right_delta(port, field, delta)  ({ \
231     ipc_port_t __port = (port);                                  \
232     if (os_add_overflow(__port->field, delta, &__port->field)) { \
233 	__ipc_right_delta_overflow_panic(__port, &__port->field, delta);  \
234     }                                                            \
235     __port->field;                                               \
236 })
237 
238 #define ip_srights_inc(port)  ip_right_delta(port, ip_srights, 1)
239 #define ip_srights_dec(port)  ip_right_delta(port, ip_srights, -1)
240 #define ip_sorights_inc(port) ip_right_delta(port, ip_sorights, 1)
241 #define ip_sorights_dec(port) ip_right_delta(port, ip_sorights, -1)
242 
243 /*
244  * SYNC IPC state flags for special reply port/ rcv right.
245  *
246  * PORT_SYNC_LINK_ANY
247  *    Special reply port is not linked to any other port
248  *    or WL and linkage should be allowed.
249  *
250  * PORT_SYNC_LINK_PORT
251  *    Special reply port is linked to the port and
252  *    ip_sync_inheritor_port contains the inheritor
253  *    port.
254  *
255  * PORT_SYNC_LINK_WORKLOOP_KNOTE
256  *    Special reply port is linked to a WL (via a knote).
257  *    ip_sync_inheritor_knote contains a pointer to the knote
258  *    the port is stashed on.
259  *
260  * PORT_SYNC_LINK_WORKLOOP_STASH
261  *    Special reply port is linked to a WL (via a knote stash).
262  *    ip_sync_inheritor_ts contains a pointer to the turnstile with a +1
263  *    the port is stashed on.
264  *
265  * PORT_SYNC_LINK_NO_LINKAGE
266  *    Message sent to special reply port, do
267  *    not allow any linkages till receive is
268  *    complete.
269  *
270  * PORT_SYNC_LINK_RCV_THREAD
271  *    Receive right copied out as a part of bootstrap check in,
272  *    push on the thread which copied out the port.
273  */
274 #define PORT_SYNC_LINK_ANY              (0)
275 #define PORT_SYNC_LINK_PORT             (0x1)
276 #define PORT_SYNC_LINK_WORKLOOP_KNOTE   (0x2)
277 #define PORT_SYNC_LINK_WORKLOOP_STASH   (0x3)
278 #define PORT_SYNC_LINK_NO_LINKAGE       (0x4)
279 #define PORT_SYNC_LINK_RCV_THREAD       (0x5)
280 
281 #define IP_NULL                         IPC_PORT_NULL
282 #define IP_DEAD                         IPC_PORT_DEAD
283 #define IP_VALID(port)                  IPC_PORT_VALID(port)
284 
285 #define ip_object_to_port(io)           __container_of(io, struct ipc_port, ip_object)
286 #define ip_to_object(port)              (&(port)->ip_object)
287 #define ip_mq_lock_held(port)           io_lock_held(ip_to_object(port))
288 #define ip_mq_lock(port)                ipc_port_lock(port)
289 #define ip_mq_lock_label_get(port)      ipc_port_lock_label_get(port)
290 #define ip_mq_lock_check_aligned(port)  ipc_port_lock_check_aligned(port)
291 #define ip_mq_lock_try(port)            ipc_port_lock_try(port)
292 #define ip_mq_lock_held_kdp(port)       io_lock_held_kdp(ip_to_object(port))
293 #define ip_mq_unlock(port)              io_unlock(ip_to_object(port))
294 
295 #define ip_reference(port)              io_reference(ip_to_object(port))
296 #define ip_release(port)                io_release(ip_to_object(port))
297 #define ip_release_safe(port)           io_release_safe(ip_to_object(port))
298 #define ip_release_live(port)           io_release_live(ip_to_object(port))
299 #define ip_alloc()                      zalloc_id(ZONE_ID_IPC_PORT, Z_WAITOK_ZERO_NOFAIL)
300 #define ip_free(port)                   zfree_id(ZONE_ID_IPC_PORT, port)
301 #define ip_validate(port) \
302 	zone_id_require(ZONE_ID_IPC_PORT, sizeof(struct ipc_port), port)
303 
304 #define ip_from_waitq(wq)               __container_of(wq, struct ipc_port, ip_waitq)
305 #define ip_from_mq(mq)                  __container_of(mq, struct ipc_port, ip_messages)
306 
307 #define ip_type(port)                   io_type(ip_to_object(port))
308 #define ip_is_kobject(port)             io_is_kobject(ip_to_object(port))
309 #define ip_label_get(port, ...)         io_label_get(ip_to_object(port), ## __VA_ARGS__)
310 #define ip_label_put(port, label)       io_label_put(ip_to_object(port), label)
311 #define ip_label_peek_kdp(port, ...)    io_label_peek_kdp(ip_to_object(port), ## __VA_ARGS__)
312 
313 #define ip_full_kernel(port)            imq_full_kernel(&(port)->ip_messages)
314 #define ip_full(port)                   imq_full(&(port)->ip_messages)
315 
316 #define ip_active(port)                 io_state_active(ip_to_object(port)->io_state)
317 #define ip_in_a_space(port)             io_state_in_space(ip_to_object(port)->io_state)
318 #define ip_in_limbo(port)               io_state_in_limbo(ip_to_object(port)->io_state)
319 #define ip_in_transit(port)             io_state_in_transit(ip_to_object(port)->io_state)
320 #define ip_is_moving(port)              io_state_is_moving(ip_to_object(port)->io_state)
321 #define ip_is_immovable_receive(port)   (ip_to_object(port)->io_state == IO_STATE_IN_SPACE_IMMOVABLE)
322 
323 #define ip_is_exception_port(port)              (ip_type(port) == IOT_EXCEPTION_PORT)
324 #define ip_is_provisional_reply_port(port)      (ip_type(port) == IOT_PROVISIONAL_REPLY_PORT)
325 #define ip_is_special_reply_port_type(type)     ((type) == IOT_SPECIAL_REPLY_PORT)
326 #define ip_is_special_reply_port(port)          (ip_is_special_reply_port_type(ip_type(port)))
327 #define ip_is_any_service_port(port)            ip_is_any_service_port_type(ip_type(port))
328 #define ip_is_port_array_allowed(port)          (ip_type(port) == IOT_CONNECTION_PORT_WITH_PORT_ARRAY)
329 #define ip_is_timer(port)                       (ip_type(port) == IOT_TIMER_PORT)
330 #define ip_is_bootstrap_port(port)              ((port)->ip_bootstrap)
331 
332 static inline bool
ip_is_any_service_port_type(ipc_object_type_t type)333 ip_is_any_service_port_type(ipc_object_type_t type)
334 {
335 	return type == IOT_SERVICE_PORT || type == IOT_WEAK_SERVICE_PORT;
336 }
337 static inline bool
ip_is_reply_port_type(ipc_object_type_t type)338 ip_is_reply_port_type(ipc_object_type_t type)
339 {
340 	return type == IOT_REPLY_PORT || type == IOT_SPECIAL_REPLY_PORT;
341 }
342 static inline bool
ip_is_reply_port(ipc_port_t port)343 ip_is_reply_port(ipc_port_t port)
344 {
345 	ipc_object_type_t type = ip_type(port);
346 	return ip_is_reply_port_type(type);
347 }
348 
349 #define ip_is_tt_control_port(port)             (ip_is_tt_control_port_type(ip_type(port)))
350 
351 static inline bool
ip_is_tt_control_port_type(ipc_object_type_t type)352 ip_is_tt_control_port_type(ipc_object_type_t type)
353 {
354 	return type == IKOT_TASK_CONTROL || type == IKOT_THREAD_CONTROL;
355 }
356 
357 /*
358  * Use the low bits in the ipr_soright to specify the request type
359  */
360 __enum_decl(ipc_port_request_opts_t, uintptr_t, {
361 	IPR_SOR_SPARM_MASK = 0x01,              /* send-possible armed */
362 	IPR_SOR_SPREQ_MASK = 0x02,              /* send-possible requested */
363 });
364 #define IPR_SOR_SPBIT_MASK      3               /* combo */
365 #define IPR_SOR_SPARMED(sor)    (((uintptr_t)(sor) & IPR_SOR_SPARM_MASK) != 0)
366 #define IPR_SOR_SPREQ(sor)      (((uintptr_t)(sor) & IPR_SOR_SPREQ_MASK) != 0)
367 #define IPR_SOR_PORT(sor)       ((ipc_port_t)((uintptr_t)(sor) & ~IPR_SOR_SPBIT_MASK))
368 #define IPR_SOR_MAKE(p, m)      ((ipc_port_t)((uintptr_t)(p) | (m)))
369 
370 extern lck_grp_t        ipc_lck_grp;
371 extern lck_attr_t       ipc_lck_attr;
372 
373 /*
374  *	Taking the ipc_port_multiple lock grants the privilege
375  *	to lock multiple ports at once.  No ports must locked
376  *	when it is taken.
377  */
378 
379 extern lck_spin_t ipc_port_multiple_lock_data;
380 
381 #define ipc_port_multiple_lock()                                        \
382 	lck_spin_lock_grp(&ipc_port_multiple_lock_data, &ipc_lck_grp)
383 
384 #define ipc_port_multiple_unlock()                                      \
385 	lck_spin_unlock(&ipc_port_multiple_lock_data)
386 
387 /*
388  *	Search for the end of the chain (a port not in transit),
389  *	acquiring locks along the way.
390  */
391 extern boolean_t ipc_port_destination_chain_lock(
392 	ipc_port_t port,
393 	ipc_port_t *base);
394 
395 /*
396  *	The port timestamp facility provides timestamps
397  *	for port destruction.  It is used to serialize
398  *	mach_port_names with port death.
399  */
400 
401 /* Retrieve a port timestamp value */
402 extern ipc_port_timestamp_t ipc_port_timestamp(void);
403 
404 /*
405  *	Compares two timestamps, and returns TRUE if one
406  *	happened before two.  Note that this formulation
407  *	works when the timestamp wraps around at 2^32,
408  *	as long as one and two aren't too far apart.
409  */
410 
411 #define IP_TIMESTAMP_ORDER(one, two)    ((int) ((one) - (two)) < 0)
412 
413 extern void __abortlike __ipc_port_inactive_panic(ipc_port_t port);
414 
415 static inline void
require_ip_active(ipc_port_t port)416 require_ip_active(ipc_port_t port)
417 {
418 	if (!ip_active(port)) {
419 		__ipc_port_inactive_panic(port);
420 	}
421 }
422 
423 static inline void
ip_mq_unlock_label_put(ipc_port_t port,ipc_object_label_t * label)424 ip_mq_unlock_label_put(ipc_port_t port, ipc_object_label_t *label)
425 {
426 	ip_label_put(port, label);
427 	io_unlock_nocheck(ip_to_object(port));
428 }
429 
430 static inline bool
ip_in_space(ipc_port_t port,ipc_space_t space)431 ip_in_space(ipc_port_t port, ipc_space_t space)
432 {
433 	ip_mq_lock_held(port); /* port must be locked, otherwise PAC could fail */
434 	return ip_in_a_space(port) && port->ip_receiver == space;
435 }
436 
437 /* use sparsely when port lock is not possible, just compare raw pointer */
438 static inline bool
ip_in_space_noauth(ipc_port_t port,void * space)439 ip_in_space_noauth(ipc_port_t port, void* space)
440 {
441 	void *__single raw_ptr = ptrauth_strip(*(void **)&port->ip_receiver, ptrauth_key_process_independent_data);
442 	return raw_ptr == space;
443 }
444 
445 static inline ipc_space_t
ip_get_receiver(ipc_port_t port)446 ip_get_receiver(ipc_port_t port)
447 {
448 	ip_mq_lock_held(port); /* port must be locked, otherwise PAC could fail */
449 	return ip_in_a_space(port) ? port->ip_receiver : NULL;
450 }
451 
452 static inline mach_port_name_t
ip_get_receiver_name(ipc_port_t port)453 ip_get_receiver_name(ipc_port_t port)
454 {
455 	return ip_in_a_space(port) ? port->ip_receiver_name : MACH_PORT_NULL;
456 }
457 
458 static inline ipc_port_t
ip_get_destination(ipc_port_t port)459 ip_get_destination(ipc_port_t port)
460 {
461 	ip_mq_lock_held(port); /* port must be locked, otherwise PAC could fail */
462 	return ip_is_moving(port) ? port->ip_destination : IP_NULL;
463 }
464 
465 static inline ipc_port_timestamp_t
ip_get_death_time(ipc_port_t port)466 ip_get_death_time(ipc_port_t port)
467 {
468 	assert(!ip_active(port));
469 	return port->ip_timestamp;
470 }
471 
472 static inline ipc_importance_task_t
ip_get_imp_task(ipc_port_t port)473 ip_get_imp_task(ipc_port_t port)
474 {
475 	return (!ip_is_kobject(port) && !ip_is_special_reply_port(port) && port->ip_tempowner) ? port->ip_imp_task : IIT_NULL;
476 }
477 
478 extern kern_return_t ipc_port_translate_send(
479 	ipc_space_t                     space,
480 	mach_port_name_t                name,
481 	ipc_port_t                     *portp);
482 
483 extern kern_return_t ipc_port_translate_receive(
484 	ipc_space_t                     space,
485 	mach_port_name_t                name,
486 	ipc_port_t                     *portp);
487 
488 /* Allocate a notification request slot */
489 extern kern_return_t ipc_port_request_alloc(
490 	ipc_port_t                      port,
491 	mach_port_name_t                name,
492 	ipc_port_t                      soright,
493 	ipc_port_request_opts_t         options,
494 	ipc_port_request_index_t       *indexp);
495 
496 extern kern_return_t ipc_port_request_hnotify_alloc(
497 	ipc_port_t                      port,
498 	struct host_notify_entry       *hnotify,
499 	ipc_port_request_index_t       *indexp);
500 
501 /* Grow one of a port's tables of notifcation requests */
502 extern kern_return_t ipc_port_request_grow(
503 	ipc_port_t                      port);
504 
505 /* Return the type(s) of notification requests outstanding */
506 extern mach_port_type_t ipc_port_request_type(
507 	ipc_port_t                      port,
508 	mach_port_name_t                name,
509 	ipc_port_request_index_t        index);
510 
511 /* Cancel a notification request and return the send-once right */
512 extern ipc_port_t ipc_port_request_cancel(
513 	ipc_port_t                      port,
514 	mach_port_name_t                name,
515 	ipc_port_request_index_t        index);
516 
517 /* Arm any delayed send-possible notification */
518 extern bool ipc_port_request_sparm(
519 	ipc_port_t                port,
520 	mach_port_name_t          name,
521 	ipc_port_request_index_t  index,
522 	mach_msg_option64_t       option,
523 	mach_msg_priority_t       priority);
524 
525 
526 /*!
527  * @abstract
528  * Marks a port as in-space.
529  *
530  * @discussion
531  * The port must be in transit.
532  * @c port must be locked.
533  *
534  * @param port          the port to mark as in-space.
535  * @param label         the current object label for @c port.
536  * @param space         the space the port is being received into.
537  * @param name          the name the port will have in @c space.
538  * @param force_state   the state to force. Must be one of:
539  *                      - IO_STATE_INACTIVE (means default policy),
540  *                      - IO_STATE_IN_SPACE,
541  *                      - IO_STATE_IN_SPACE_IMMOVABLE.
542  * @returns             the current port destination or IP_NULL.
543  */
544 extern ipc_port_t ipc_port_mark_in_space(
545 	ipc_port_t              port,
546 	ipc_object_label_t     *label,
547 	ipc_space_t             space,
548 	mach_port_name_t        name,
549 	ipc_object_state_t      force_state);
550 
551 #define IPC_PORT_SET_IN_SPACE_DEFAULT         0
552 #define IPC_PORT_SET_IN_SPACE_PSEUDO_RECEIVE  1
553 #define IPC_PORT_SET_IN_SPACE_FORCE_IMMOVABLE 2
554 
555 
556 /*!
557  * @abstract
558  * Marks a port as in-limbo, and prepare it for a move.
559  *
560  * @discussion
561  * The port must be in space.
562  * @c port must be locked.
563  *
564  * @param port          the port to mark as in-space.
565  * @param label         the current object label for @c port.
566  * @param free_l        a list to accumulate waitq linkages to free
567  *                      by calling waitq_link_free_list(WQT_PORT_SET, &free_l)
568  *                      on it.
569  */
570 extern void ipc_port_mark_in_limbo(
571 	ipc_port_t              port,
572 	ipc_object_label_t     *label,
573 	waitq_link_list_t      *free_l);
574 
575 
576 /*!
577  * @abstract
578  * Sets a port as in-transit
579  *
580  * @discussion
581  * The port must be in limbo.
582  * @c port must be locked.
583  *
584  * A reference on @c dest is taken.
585  *
586  * @param port          the port to mark as in-space.
587  * @param dest          the port @c port is enqueued onto.
588  */
589 extern void ipc_port_mark_in_transit(
590 	ipc_port_t              port,
591 	ipc_port_t              dest);
592 
593 __options_decl(ipc_port_init_flags_t, uint32_t, {
594 	IP_INIT_NONE            = 0x00000000,
595 	IP_INIT_MAKE_SEND_RIGHT = 0x00000001,
596 });
597 
598 extern void ipc_port_lock(
599 	ipc_port_t              port);
600 
601 extern ipc_object_label_t ipc_port_lock_label_get(
602 	ipc_port_t              port) __result_use_check;
603 
604 extern ipc_object_label_t ipc_port_lock_check_aligned(
605 	ipc_port_t              port) __result_use_check;
606 
607 extern bool ipc_port_lock_try(
608 	ipc_port_t              port);
609 
610 /* Allocate a port */
611 extern kern_return_t ipc_port_alloc(
612 	ipc_space_t             space,
613 	ipc_object_label_t      label,
614 	ipc_port_init_flags_t   flags,
615 	mach_port_name_t       *namep,
616 	ipc_port_t             *portp);
617 
618 /* Allocate a port, with a specific name */
619 extern kern_return_t ipc_port_alloc_name(
620 	ipc_space_t             space,
621 	ipc_object_label_t      label,
622 	ipc_port_init_flags_t   flags,
623 	mach_port_name_t        name,
624 	ipc_port_t             *portp);
625 
626 extern ipc_object_label_t ipc_kobject_label_alloc(
627 	ipc_object_type_t       otype,
628 	ipc_label_t             label_tag,
629 	ipc_port_t              alt_port);
630 
631 extern void ipc_kobject_label_free(
632 	ipc_object_label_t      label);
633 
634 /* Generate dead name notifications */
635 extern void ipc_port_dnnotify(
636 	ipc_port_t              port);
637 
638 /* Generate send-possible notifications */
639 extern void ipc_port_spnotify(
640 	ipc_port_t              port);
641 
642 /* Destroy a port */
643 extern void ipc_port_destroy(
644 	ipc_port_t              port);
645 
646 /* Check if queueing "port" in a message for "dest" would create a circular
647  *  group of ports and messages */
648 extern boolean_t
649 ipc_port_check_circularity(
650 	ipc_port_t              port,
651 	ipc_port_t              dest);
652 
653 #if IMPORTANCE_INHERITANCE
654 
655 enum {
656 	IPID_OPTION_NORMAL       = 0, /* normal boost */
657 	IPID_OPTION_SENDPOSSIBLE = 1, /* send-possible induced boost */
658 };
659 
660 /* link the destination port with special reply port */
661 void
662 ipc_port_link_special_reply_port(
663 	ipc_port_t special_reply_port,
664 	ipc_port_t dest_port,
665 	boolean_t sync_bootstrap_checkin);
666 
667 #define IPC_PORT_ADJUST_SR_NONE                      0
668 #define IPC_PORT_ADJUST_SR_ALLOW_SYNC_LINKAGE        0x1
669 #define IPC_PORT_ADJUST_SR_LINK_WORKLOOP             0x2
670 #define IPC_PORT_ADJUST_UNLINK_THREAD                0x4
671 #define IPC_PORT_ADJUST_SR_RECEIVED_MSG              0x8
672 #define IPC_PORT_ADJUST_SR_ENABLE_EVENT              0x10
673 #define IPC_PORT_ADJUST_RESET_BOOSTRAP_CHECKIN       0x20
674 
675 void
676 ipc_special_reply_port_bits_reset(ipc_port_t special_reply_port);
677 
678 void
679 ipc_special_reply_port_msg_sent(ipc_port_t special_reply_port);
680 
681 void
682 ipc_special_reply_port_msg_sent(ipc_port_t special_reply_port);
683 
684 /* Adjust special reply port linkage */
685 void
686 ipc_port_adjust_special_reply_port_locked(
687 	ipc_port_t special_reply_port,
688 	struct knote *kn,
689 	uint8_t flags,
690 	boolean_t get_turnstile);
691 
692 void
693 ipc_port_adjust_sync_link_state_locked(
694 	ipc_port_t port,
695 	int sync_link_state,
696 	turnstile_inheritor_t inheritor);
697 
698 /* Adjust special reply port linkage */
699 void
700 ipc_port_adjust_special_reply_port(
701 	ipc_port_t special_reply_port,
702 	uint8_t flags);
703 
704 void
705 ipc_port_adjust_port_locked(
706 	ipc_port_t port,
707 	struct knote *kn,
708 	boolean_t sync_bootstrap_checkin);
709 
710 void
711 ipc_port_clear_sync_rcv_thread_boost_locked(
712 	ipc_port_t port);
713 
714 bool
715 ipc_port_has_prdrequest(
716 	ipc_port_t port);
717 
718 kern_return_t
719 ipc_port_add_watchport_elem_locked(
720 	ipc_port_t                 port,
721 	struct task_watchport_elem *watchport_elem,
722 	struct task_watchport_elem **old_elem);
723 
724 kern_return_t
725 ipc_port_clear_watchport_elem_internal_conditional_locked(
726 	ipc_port_t                 port,
727 	struct task_watchport_elem *watchport_elem);
728 
729 kern_return_t
730 ipc_port_replace_watchport_elem_conditional_locked(
731 	ipc_port_t                 port,
732 	struct task_watchport_elem *old_watchport_elem,
733 	struct task_watchport_elem *new_watchport_elem);
734 
735 struct task_watchport_elem *
736 ipc_port_clear_watchport_elem_internal(
737 	ipc_port_t                 port);
738 
739 void
740 ipc_port_send_turnstile_prepare(ipc_port_t port);
741 
742 void
743 ipc_port_send_turnstile_complete(ipc_port_t port);
744 
745 struct waitq *
746 ipc_port_rcv_turnstile_waitq(struct waitq *waitq);
747 
748 /* apply importance delta to port only */
749 extern mach_port_delta_t
750 ipc_port_impcount_delta(
751 	ipc_port_t              port,
752 	mach_port_delta_t       delta,
753 	ipc_port_t              base);
754 
755 /* apply importance delta to port, and return task importance for update */
756 extern boolean_t
757 ipc_port_importance_delta_internal(
758 	ipc_port_t              port,
759 	natural_t               options,
760 	mach_port_delta_t       *deltap,
761 	ipc_importance_task_t   *imp_task);
762 
763 /* Apply an importance delta to a port and reflect change in receiver task */
764 extern boolean_t
765 ipc_port_importance_delta(
766 	ipc_port_t              port,
767 	natural_t               options,
768 	mach_port_delta_t       delta);
769 #endif /* IMPORTANCE_INHERITANCE */
770 
771 /*!
772  * @function ipc_port_make_send_any_locked()
773  *
774  * @brief
775  * Makes a naked send right for a locked and active port.
776  *
777  * @decription
778  * @c ipc_port_make_send_*() should not be used in any generic IPC
779  * plumbing, as this is an operation that subsystem owners need
780  * to be able to synchronize against with the make-send-count
781  * and no-senders notifications.
782  *
783  * It is especially important for kobject types, and in general MIG upcalls
784  * or replies from the kernel should never use MAKE_SEND dispositions,
785  * and prefer COPY_SEND or MOVE_SEND, so that subsystems can control
786  * where that send right comes from.
787  *
788  * This function doesn't perform any validation on the type of port,
789  * this duty is left to the caller.
790  *
791  * @param port          An active and locked port.
792  */
793 extern ipc_port_t ipc_port_make_send_any_locked(
794 	ipc_port_t      port);
795 
796 /*!
797  * @function ipc_port_make_send_any()
798  *
799  * @brief
800  * Makes a naked send right for the specified port.
801  *
802  * @decription
803  * @see ipc_port_make_send_any_locked() for a general warning about
804  * making send rights.
805  *
806  * This function doesn't perform any validation on the type of port,
807  * this duty is left to the caller.
808  *
809  * Using @c ipc_port_make_send_mqueue() or @c ipc_kobject_make_send()
810  * is preferred.
811  *
812  * @param port          The target port.
813  *
814  * @returns
815  * - IP_DEAD            if @c port was dead.
816  * - @c port            if @c port was valid, in which case
817  *                      a naked send right was made.
818  */
819 extern ipc_port_t ipc_port_make_send_any(
820 	ipc_port_t      port) __result_use_check;
821 
822 /*!
823  * @function ipc_port_make_send_mqueue()
824  *
825  * @brief
826  * Makes a naked send right for the specified port.
827  *
828  * @decription
829  * @see ipc_port_make_send_any_locked() for a general warning about
830  * making send rights.
831  *
832  * This function will return IP_NULL if the port wasn't a message queue.
833  *
834  * This avoids confusions where kobject ports are being set in places
835  * where the system expects message queues.
836  *
837  * @param port          The target port.
838  *
839  * @returns
840  * - IP_NULL            if @c port was not a message queue port
841  *                      (!ip_is_kobject()), or @c port was IP_NULL.
842  * - IP_DEAD            if @c port was dead.
843  * - @c port            if @c port was valid, in which case
844  *                      a naked send right was made.
845  */
846 extern ipc_port_t ipc_port_make_send_mqueue(
847 	ipc_port_t      port) __result_use_check;
848 
849 /*!
850  * @function ipc_port_copy_send_any_locked()
851  *
852  * @brief
853  * Copies a naked send right for a locked and active port.
854  *
855  * @decription
856  * This function doesn't perform any validation on the type of port,
857  * this duty is left to the caller.
858  *
859  * @param port          An active and locked port.
860  */
861 extern void ipc_port_copy_send_any_locked(
862 	ipc_port_t      port);
863 
864 /*!
865  * @function ipc_port_make_send_any()
866  *
867  * @brief
868  * Copies a naked send right for the specified port.
869  *
870  * @decription
871  * This function doesn't perform any validation on the type of port,
872  * this duty is left to the caller.
873  *
874  * Using @c ipc_port_copy_send_mqueue() or @c ipc_kobject_copy_send()
875  * is preferred.
876  *
877  * @param port          The target port.
878  *
879  * @returns
880  * - IP_DEAD            if @c port was dead.
881  * - @c port            if @c port was valid, in which case
882  *                      a naked send right was made.
883  */
884 extern ipc_port_t ipc_port_copy_send_any(
885 	ipc_port_t      port) __result_use_check;
886 
887 /*!
888  * @function ipc_port_copy_send_mqueue()
889  *
890  * @brief
891  * Copies a naked send right for the specified port.
892  *
893  * @decription
894  * This function will return IP_NULL if the port wasn't a message queue.
895  *
896  * This avoids confusions where kobject ports are being set in places
897  * where the system expects message queues.
898  *
899  * @param port          The target port.
900  *
901  * @returns
902  * - IP_NULL            if @c port was not a message queue port
903  *                      (!ip_is_kobject()), or @c port was IP_NULL.
904  * - IP_DEAD            if @c port was dead.
905  * - @c port            if @c port was valid, in which case
906  *                      a naked send right was made.
907  */
908 extern ipc_port_t ipc_port_copy_send_mqueue(
909 	ipc_port_t      port) __result_use_check;
910 
911 /* Copyout a naked send right */
912 extern mach_port_name_t ipc_port_copyout_send(
913 	ipc_port_t      sright,
914 	ipc_space_t     space);
915 
916 extern mach_port_name_t ipc_port_copyout_send_pinned(
917 	ipc_port_t      sright,
918 	ipc_space_t     space);
919 
920 extern void ipc_port_thread_group_blocked(
921 	ipc_port_t      port);
922 
923 extern void ipc_port_thread_group_unblocked(void);
924 
925 extern void ipc_port_release_send_and_unlock(
926 	ipc_port_t      port);
927 
928 extern kern_return_t mach_port_deallocate_kernel(
929 	ipc_space_t             space,
930 	mach_port_name_t        name,
931 	ipc_object_type_t       otype);
932 
933 /* Make a naked send-once right from a locked and active receive right */
934 extern ipc_port_t ipc_port_make_sonce_locked(
935 	ipc_port_t              port);
936 
937 /* Make a naked send-once right from a receive right */
938 extern ipc_port_t ipc_port_make_sonce(
939 	ipc_port_t              port);
940 
941 /* Release a naked send-once right */
942 extern void ipc_port_release_sonce(
943 	ipc_port_t              port);
944 
945 /* Release a naked send-once right */
946 extern void ipc_port_release_sonce_and_unlock(
947 	ipc_port_t              port);
948 
949 /* Release a naked (in limbo or in transit) receive right */
950 extern void ipc_port_release_receive(
951 	ipc_port_t              port);
952 
953 /* Finalize the destruction of a port and free it */
954 extern void ipc_port_free(
955 	ipc_port_t              port);
956 
957 /* Get receiver task and its pid (if any) for port. Assumes port is locked. */
958 extern pid_t ipc_port_get_receiver_task_locked(
959 	ipc_port_t              port,
960 	task_t                 *task);
961 
962 /* Get receiver task and its pid (if any) for port. */
963 extern pid_t ipc_port_get_receiver_task(
964 	ipc_port_t              port,
965 	task_t                 *task);
966 
967 /* Allocate a port in a special space */
968 extern ipc_port_t ipc_port_alloc_special(
969 	ipc_space_t             space,
970 	ipc_object_label_t      label,
971 	ipc_port_init_flags_t   flags);
972 
973 extern void ipc_port_recv_update_inheritor(
974 	ipc_port_t              port,
975 	struct turnstile       *turnstile,
976 	turnstile_update_flags_t flags);
977 
978 extern void ipc_port_send_update_inheritor(
979 	ipc_port_t              port,
980 	struct turnstile       *turnstile,
981 	turnstile_update_flags_t flags);
982 
983 extern int ipc_special_reply_get_pid_locked(
984 	ipc_port_t              port);
985 
986 #pragma GCC visibility pop
987 #endif /* MACH_KERNEL_PRIVATE */
988 #if KERNEL_PRIVATE
989 
990 /* Release a (valid) naked send right */
991 extern void ipc_port_release_send(
992 	ipc_port_t             port);
993 
994 extern void ipc_port_reference(
995 	ipc_port_t             port);
996 
997 extern void ipc_port_release(
998 	ipc_port_t             port);
999 
1000 struct thread_attr_for_ipc_propagation {
1001 	union {
1002 		struct {
1003 			uint64_t tafip_iotier:2,
1004 			    tafip_qos:3;
1005 		};
1006 		uint64_t tafip_value;
1007 	};
1008 	uint64_t tafip_reserved;
1009 };
1010 
1011 extern kern_return_t ipc_port_propagate_thread_attr(
1012 	ipc_port_t             port,
1013 	struct thread_attr_for_ipc_propagation attr);
1014 
1015 extern kern_return_t ipc_port_reset_thread_attr(
1016 	ipc_port_t             port);
1017 
1018 #endif /* KERNEL_PRIVATE */
1019 
1020 __ASSUME_PTR_ABI_SINGLE_END __END_DECLS
1021 
1022 #endif  /* _IPC_IPC_PORT_H_ */
1023