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