xref: /xnu-10002.41.9/osfmk/ipc/ipc_right.c (revision 699cd48037512bf4380799317ca44ca453c82f57)
1 /*
2  * Copyright (c) 2000-2007 Apple 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_FREE_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-2006 SPARTA, Inc.
62  */
63 /*
64  */
65 /*
66  *	File:	ipc/ipc_right.c
67  *	Author:	Rich Draves
68  *	Date:	1989
69  *
70  *	Functions to manipulate IPC capabilities.
71  */
72 
73 #include <mach/boolean.h>
74 #include <mach/kern_return.h>
75 #include <mach/port.h>
76 #include <mach/message.h>
77 #include <kern/assert.h>
78 #include <kern/ipc_kobject.h>
79 #include <kern/misc_protos.h>
80 #include <kern/policy_internal.h>
81 #include <libkern/coreanalytics/coreanalytics.h>
82 #include <ipc/port.h>
83 #include <ipc/ipc_entry.h>
84 #include <ipc/ipc_space.h>
85 #include <ipc/ipc_object.h>
86 #include <ipc/ipc_hash.h>
87 #include <ipc/ipc_port.h>
88 #include <ipc/ipc_pset.h>
89 #include <ipc/ipc_right.h>
90 #include <ipc/ipc_notify.h>
91 #include <ipc/ipc_importance.h>
92 #include <ipc/ipc_service_port.h>
93 #include <security/mac_mach_internal.h>
94 
95 extern struct proc *current_proc(void);
96 extern int csproc_hardened_runtime(struct proc* p);
97 
98 extern void * XNU_PTRAUTH_SIGNED_PTR("initproc") initproc;
99 
100 TUNABLE(bool, service_port_defense_enabled, "-service_port_defense_enabled", false);
101 static TUNABLE(bool, reply_port_semantics, "reply_port_semantics", true);
102 
103 /*
104  *	Routine:	ipc_right_lookup_read
105  *	Purpose:
106  *		Finds an entry in a space, given the name.
107  *	Conditions:
108  *		Nothing locked.
109  *		If an object is found, it is locked and active.
110  *	Returns:
111  *		KERN_SUCCESS		Found an entry.
112  *		KERN_INVALID_TASK	The space is dead.
113  *		KERN_INVALID_NAME	Name doesn't exist in space.
114  */
115 kern_return_t
ipc_right_lookup_read(ipc_space_t space,mach_port_name_t name,ipc_entry_bits_t * bitsp,ipc_object_t * objectp)116 ipc_right_lookup_read(
117 	ipc_space_t             space,
118 	mach_port_name_t        name,
119 	ipc_entry_bits_t       *bitsp,
120 	ipc_object_t           *objectp)
121 {
122 	mach_port_index_t index;
123 	ipc_entry_table_t table;
124 	ipc_entry_t entry;
125 	ipc_object_t object;
126 	kern_return_t kr;
127 
128 	index = MACH_PORT_INDEX(name);
129 	if (__improbable(index == 0)) {
130 		*bitsp = 0;
131 		*objectp = IO_NULL;
132 		return KERN_INVALID_NAME;
133 	}
134 
135 	smr_ipc_enter();
136 
137 	/*
138 	 * Acquire a (possibly stale) pointer to the table,
139 	 * and guard it so that it can't be deallocated while we use it.
140 	 *
141 	 * smr_ipc_enter() has the property that it strongly serializes
142 	 * after any store-release. This is important because it means that if
143 	 * one considers this (broken) userspace usage:
144 	 *
145 	 * Thread 1:
146 	 *   - makes a semaphore, gets name 0x1003
147 	 *   - stores that name to a global `sema` in userspace
148 	 *
149 	 * Thread 2:
150 	 *   - spins to observe `sema` becoming non 0
151 	 *   - calls semaphore_wait() on 0x1003
152 	 *
153 	 * Then, because in order to return 0x1003 this thread issued
154 	 * a store-release (when calling is_write_unlock()),
155 	 * then this smr_entered_load() can't possibly observe a table
156 	 * pointer that is older than the one that was current when the
157 	 * semaphore was made.
158 	 *
159 	 * This fundamental property allows us to never loop.
160 	 */
161 	table = smr_entered_load(&space->is_table);
162 	if (__improbable(table == NULL)) {
163 		kr = KERN_INVALID_TASK;
164 		goto out_put;
165 	}
166 	entry = ipc_entry_table_get(table, index);
167 	if (__improbable(entry == NULL)) {
168 		kr = KERN_INVALID_NAME;
169 		goto out_put;
170 	}
171 
172 	/*
173 	 * Note: this should be an atomic load, but PAC and atomics
174 	 *       don't work interact well together.
175 	 */
176 	object = entry->ie_volatile_object;
177 
178 	/*
179 	 * Attempt to lock an object that lives in this entry.
180 	 * It might fail or be a completely different object by now.
181 	 *
182 	 * Make sure that acquiring the lock is fully ordered after any
183 	 * lock-release (using os_atomic_barrier_before_lock_acquire()).
184 	 * This allows us to always reliably observe space termination below.
185 	 */
186 	os_atomic_barrier_before_lock_acquire();
187 	if (__improbable(object == IO_NULL || !io_lock_allow_invalid(object))) {
188 		kr = KERN_INVALID_NAME;
189 		goto out_put;
190 	}
191 
192 	/*
193 	 * Now that we hold the object lock, we are preventing any entry
194 	 * in this space for this object to be mutated.
195 	 *
196 	 * If the space didn't grow after we acquired our hazardous reference,
197 	 * and before a mutation of the entry, then holding the object lock
198 	 * guarantees we will observe the truth of ie_bits, ie_object and
199 	 * ie_request (those are always mutated with the object lock held).
200 	 *
201 	 * However this ordering is problematic:
202 	 * - [A]cquisition of the table pointer
203 	 * - [G]rowth of the space (making the table pointer in [A] stale)
204 	 * - [M]utation of the entry
205 	 * - [L]ocking of the object read through [A].
206 	 *
207 	 * The space lock is held for both [G] and [M], and the object lock
208 	 * is held for [M], which means that once we lock the object we can
209 	 * observe if [G] happenend by reloading the table pointer.
210 	 *
211 	 * We might still fail to observe any growth operation that happened
212 	 * after the last mutation of this object's entry, because holding
213 	 * an object lock doesn't guarantee anything about the liveness
214 	 * of the space table pointer. This is not a problem at all: by
215 	 * definition, those didn't affect the state of the entry.
216 	 *
217 	 * TODO: a data-structure where the entries are grown by "slabs",
218 	 *       would allow for the address of an ipc_entry_t to never
219 	 *       change once it exists in a space and would avoid a reload
220 	 *       (as well as making space growth faster).
221 	 *       We however still need to check for termination.
222 	 */
223 	table = smr_entered_load(&space->is_table);
224 	if (__improbable(table == NULL)) {
225 		kr = KERN_INVALID_TASK;
226 		goto out_put_unlock;
227 	}
228 
229 	/*
230 	 * Tables never shrink so we don't need to validate the length twice.
231 	 */
232 	entry = ipc_entry_table_get_nocheck(table, index);
233 
234 	/*
235 	 * Now that we hold the lock and have a "fresh enough" table pointer,
236 	 * validate if this entry is what we think it is.
237 	 *
238 	 * To the risk of being repetitive, we still need to protect
239 	 * those accesses under SMR, because subsequent
240 	 * table growths might retire the memory. However we know
241 	 * those growths will have left our entry unchanged.
242 	 */
243 	if (__improbable(entry->ie_object != object)) {
244 		kr = KERN_INVALID_NAME;
245 		goto out_put_unlock;
246 	}
247 
248 	ipc_entry_bits_t bits = entry->ie_bits;
249 	if (__improbable(IE_BITS_GEN(bits) != MACH_PORT_GEN(name) ||
250 	    IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE)) {
251 		kr = KERN_INVALID_NAME;
252 		goto out_put_unlock;
253 	}
254 
255 	/* Done with hazardous accesses to the table */
256 	smr_ipc_leave();
257 
258 	*bitsp = bits;
259 	*objectp = object;
260 	return KERN_SUCCESS;
261 
262 out_put_unlock:
263 	ipc_object_unlock(object);
264 out_put:
265 	smr_ipc_leave();
266 	return kr;
267 }
268 
269 /*
270  *	Routine:	ipc_right_lookup_write
271  *	Purpose:
272  *		Finds an entry in a space, given the name.
273  *	Conditions:
274  *		Nothing locked.  If successful, the space is write-locked.
275  *	Returns:
276  *		KERN_SUCCESS		Found an entry.
277  *		KERN_INVALID_TASK	The space is dead.
278  *		KERN_INVALID_NAME	Name doesn't exist in space.
279  */
280 
281 kern_return_t
ipc_right_lookup_write(ipc_space_t space,mach_port_name_t name,ipc_entry_t * entryp)282 ipc_right_lookup_write(
283 	ipc_space_t             space,
284 	mach_port_name_t        name,
285 	ipc_entry_t             *entryp)
286 {
287 	ipc_entry_t entry;
288 
289 	assert(space != IS_NULL);
290 
291 	is_write_lock(space);
292 
293 	if (!is_active(space)) {
294 		is_write_unlock(space);
295 		return KERN_INVALID_TASK;
296 	}
297 
298 	if ((entry = ipc_entry_lookup(space, name)) == IE_NULL) {
299 		is_write_unlock(space);
300 		return KERN_INVALID_NAME;
301 	}
302 
303 	*entryp = entry;
304 	return KERN_SUCCESS;
305 }
306 
307 /*
308  *	Routine:	ipc_right_lookup_two_write
309  *	Purpose:
310  *		Like ipc_right_lookup except that it returns two
311  *		entries for two different names that were looked
312  *		up under the same space lock.
313  *	Conditions:
314  *		Nothing locked.  If successful, the space is write-locked.
315  *	Returns:
316  *		KERN_INVALID_TASK	The space is dead.
317  *		KERN_INVALID_NAME	Name doesn't exist in space.
318  */
319 
320 kern_return_t
ipc_right_lookup_two_write(ipc_space_t space,mach_port_name_t name1,ipc_entry_t * entryp1,mach_port_name_t name2,ipc_entry_t * entryp2)321 ipc_right_lookup_two_write(
322 	ipc_space_t             space,
323 	mach_port_name_t        name1,
324 	ipc_entry_t             *entryp1,
325 	mach_port_name_t        name2,
326 	ipc_entry_t             *entryp2)
327 {
328 	ipc_entry_t entry1;
329 	ipc_entry_t entry2;
330 
331 	assert(space != IS_NULL);
332 
333 	is_write_lock(space);
334 
335 	if (!is_active(space)) {
336 		is_write_unlock(space);
337 		return KERN_INVALID_TASK;
338 	}
339 
340 	if ((entry1 = ipc_entry_lookup(space, name1)) == IE_NULL) {
341 		is_write_unlock(space);
342 		mach_port_guard_exception(name1, 0, 0, kGUARD_EXC_INVALID_NAME);
343 		return KERN_INVALID_NAME;
344 	}
345 	if ((entry2 = ipc_entry_lookup(space, name2)) == IE_NULL) {
346 		is_write_unlock(space);
347 		mach_port_guard_exception(name2, 0, 0, kGUARD_EXC_INVALID_NAME);
348 		return KERN_INVALID_NAME;
349 	}
350 	*entryp1 = entry1;
351 	*entryp2 = entry2;
352 	return KERN_SUCCESS;
353 }
354 
355 /*
356  *	Routine:	ipc_right_reverse
357  *	Purpose:
358  *		Translate (space, object) -> (name, entry).
359  *		Only finds send/receive rights.
360  *		Returns TRUE if an entry is found; if so,
361  *		the object active.
362  *	Conditions:
363  *		The space must be locked (read or write) and active.
364  *		The port is locked and active
365  */
366 
367 bool
ipc_right_reverse(ipc_space_t space,ipc_object_t object,mach_port_name_t * namep,ipc_entry_t * entryp)368 ipc_right_reverse(
369 	ipc_space_t             space,
370 	ipc_object_t            object,
371 	mach_port_name_t        *namep,
372 	ipc_entry_t             *entryp)
373 {
374 	ipc_port_t port;
375 	mach_port_name_t name;
376 	ipc_entry_t entry;
377 
378 	/* would switch on io_otype to handle multiple types of object */
379 
380 	assert(is_active(space));
381 	assert(io_otype(object) == IOT_PORT);
382 
383 	port = ip_object_to_port(object);
384 	require_ip_active(port);
385 
386 	ip_mq_lock_held(port);
387 
388 	if (ip_in_space(port, space)) {
389 		name = ip_get_receiver_name(port);
390 		assert(name != MACH_PORT_NULL);
391 
392 		entry = ipc_entry_lookup(space, name);
393 
394 		assert(entry != IE_NULL);
395 		assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
396 		assert(port == ip_object_to_port(entry->ie_object));
397 
398 		*namep = name;
399 		*entryp = entry;
400 		return true;
401 	}
402 
403 	if (ipc_hash_lookup(space, ip_to_object(port), namep, entryp)) {
404 		entry = *entryp;
405 		assert(entry != IE_NULL);
406 		assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_SEND);
407 		assert(port == ip_object_to_port(entry->ie_object));
408 
409 		return true;
410 	}
411 
412 	return false;
413 }
414 
415 /*
416  *	Routine:	ipc_right_dnrequest
417  *	Purpose:
418  *		Make a dead-name request, returning the previously
419  *		registered send-once right.  If notify is IP_NULL,
420  *		just cancels the previously registered request.
421  *
422  *	Conditions:
423  *		Nothing locked.  May allocate memory.
424  *		Only consumes/returns refs if successful.
425  *	Returns:
426  *		KERN_SUCCESS		Made/canceled dead-name request.
427  *		KERN_INVALID_TASK	The space is dead.
428  *		KERN_INVALID_NAME	Name doesn't exist in space.
429  *		KERN_INVALID_RIGHT	Name doesn't denote port/dead rights.
430  *		KERN_INVALID_ARGUMENT	Name denotes dead name, but
431  *			immediate is FALSE or notify is IP_NULL.
432  *		KERN_RESOURCE_SHORTAGE	Couldn't allocate memory.
433  */
434 
435 kern_return_t
ipc_right_request_alloc(ipc_space_t space,mach_port_name_t name,ipc_port_request_opts_t options,ipc_port_t notify,ipc_port_t * previousp)436 ipc_right_request_alloc(
437 	ipc_space_t             space,
438 	mach_port_name_t        name,
439 	ipc_port_request_opts_t options,
440 	ipc_port_t              notify,
441 	ipc_port_t              *previousp)
442 {
443 	ipc_port_request_index_t prev_request;
444 	ipc_port_t previous = IP_NULL;
445 	ipc_entry_t entry;
446 	kern_return_t kr;
447 #if IMPORTANCE_INHERITANCE
448 	bool will_arm = false;
449 #endif /* IMPORTANCE_INHERITANCE */
450 
451 	for (;;) {
452 		ipc_port_t port = IP_NULL;
453 
454 		kr = ipc_right_lookup_write(space, name, &entry);
455 		if (kr != KERN_SUCCESS) {
456 			return kr;
457 		}
458 
459 		/* space is write-locked and active */
460 
461 		prev_request = entry->ie_request;
462 
463 		/* if nothing to do or undo, we're done */
464 		if (notify == IP_NULL && prev_request == IE_REQ_NONE) {
465 			is_write_unlock(space);
466 			*previousp = IP_NULL;
467 			return KERN_SUCCESS;
468 		}
469 
470 		/* see if the entry is of proper type for requests */
471 		if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) {
472 			ipc_port_request_index_t new_request;
473 
474 			port = ip_object_to_port(entry->ie_object);
475 			assert(port != IP_NULL);
476 
477 			if (!ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
478 				/* port is locked and active */
479 
480 				/* if no new request, just cancel previous */
481 				if (notify == IP_NULL) {
482 					if (prev_request != IE_REQ_NONE) {
483 						previous = ipc_port_request_cancel(port, name, prev_request);
484 						entry->ie_request = IE_REQ_NONE;
485 					}
486 					ip_mq_unlock(port);
487 					ipc_entry_modified(space, name, entry);
488 					is_write_unlock(space);
489 					break;
490 				}
491 
492 				/*
493 				 * send-once rights, kernel objects, and non-full other queues
494 				 * fire immediately (if immediate specified).
495 				 */
496 				if (options == (IPR_SOR_SPARM_MASK | IPR_SOR_SPREQ_MASK) &&
497 				    ((entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE) ||
498 				    ip_in_space(port, ipc_space_kernel) || !ip_full(port))) {
499 					if (prev_request != IE_REQ_NONE) {
500 						previous = ipc_port_request_cancel(port, name, prev_request);
501 						entry->ie_request = IE_REQ_NONE;
502 					}
503 					ip_mq_unlock(port);
504 					ipc_entry_modified(space, name, entry);
505 					is_write_unlock(space);
506 
507 					ipc_notify_send_possible(notify, name);
508 					break;
509 				}
510 
511 				/*
512 				 * If there is a previous request, free it.  Any subsequent
513 				 * allocation cannot fail, thus assuring an atomic swap.
514 				 */
515 				if (prev_request != IE_REQ_NONE) {
516 					previous = ipc_port_request_cancel(port, name, prev_request);
517 				}
518 
519 #if IMPORTANCE_INHERITANCE
520 				will_arm = port->ip_sprequests == 0 &&
521 				    options == (IPR_SOR_SPARM_MASK | IPR_SOR_SPREQ_MASK);
522 #endif /* IMPORTANCE_INHERITANCE */
523 				kr = ipc_port_request_alloc(port, name, notify,
524 				    options, &new_request);
525 
526 				if (kr != KERN_SUCCESS) {
527 					assert(previous == IP_NULL);
528 					is_write_unlock(space);
529 
530 					kr = ipc_port_request_grow(port);
531 					/* port is unlocked */
532 
533 					if (kr != KERN_SUCCESS) {
534 						return kr;
535 					}
536 
537 					continue;
538 				}
539 
540 				assert(new_request != IE_REQ_NONE);
541 				entry->ie_request = new_request;
542 				ipc_entry_modified(space, name, entry);
543 				is_write_unlock(space);
544 
545 #if IMPORTANCE_INHERITANCE
546 				if (will_arm &&
547 				    port->ip_impdonation != 0 &&
548 				    port->ip_spimportant == 0 &&
549 				    task_is_importance_donor(current_task())) {
550 					if (ipc_port_importance_delta(port, IPID_OPTION_SENDPOSSIBLE, 1) == FALSE) {
551 						ip_mq_unlock(port);
552 					}
553 				} else
554 #endif /* IMPORTANCE_INHERITANCE */
555 				ip_mq_unlock(port);
556 
557 				break;
558 			}
559 			/* entry may have changed to dead-name by ipc_right_check() */
560 		}
561 
562 		/* treat send_possible requests as immediate w.r.t. dead-name */
563 		if (options && notify != IP_NULL &&
564 		    (entry->ie_bits & MACH_PORT_TYPE_DEAD_NAME)) {
565 			mach_port_urefs_t urefs = IE_BITS_UREFS(entry->ie_bits);
566 
567 			assert(urefs > 0);
568 
569 			/* leave urefs pegged to maximum if it overflowed */
570 			if (urefs < MACH_PORT_UREFS_MAX) {
571 				(entry->ie_bits)++; /* increment urefs */
572 			}
573 			ipc_entry_modified(space, name, entry);
574 
575 			is_write_unlock(space);
576 
577 			if (port != IP_NULL) {
578 				ip_release(port);
579 			}
580 
581 			ipc_notify_dead_name(notify, name);
582 			previous = IP_NULL;
583 			break;
584 		}
585 
586 		kr = (entry->ie_bits & MACH_PORT_TYPE_PORT_OR_DEAD) ?
587 		    KERN_INVALID_ARGUMENT : KERN_INVALID_RIGHT;
588 
589 		is_write_unlock(space);
590 
591 		if (port != IP_NULL) {
592 			ip_release(port);
593 		}
594 
595 		return kr;
596 	}
597 
598 	*previousp = previous;
599 	return KERN_SUCCESS;
600 }
601 
602 /*
603  *	Routine:	ipc_right_request_cancel
604  *	Purpose:
605  *		Cancel a notification request and return the send-once right.
606  *		Afterwards, entry->ie_request == 0.
607  *	Conditions:
608  *		The space must be write-locked; the port must be locked.
609  *		The port and space must be active.
610  */
611 
612 ipc_port_t
ipc_right_request_cancel(ipc_space_t space,ipc_port_t port,mach_port_name_t name,ipc_entry_t entry)613 ipc_right_request_cancel(
614 	ipc_space_t                     space,
615 	ipc_port_t                      port,
616 	mach_port_name_t                name,
617 	ipc_entry_t                     entry)
618 {
619 	ipc_port_t previous;
620 
621 	require_ip_active(port);
622 	assert(is_active(space));
623 	assert(port == ip_object_to_port(entry->ie_object));
624 
625 	if (entry->ie_request == IE_REQ_NONE) {
626 		return IP_NULL;
627 	}
628 
629 	previous = ipc_port_request_cancel(port, name, entry->ie_request);
630 	entry->ie_request = IE_REQ_NONE;
631 	ipc_entry_modified(space, name, entry);
632 	return previous;
633 }
634 
635 /*
636  *	Routine:	ipc_right_inuse
637  *	Purpose:
638  *		Check if an entry is being used.
639  *		Returns TRUE if it is.
640  *	Conditions:
641  *		The space is write-locked and active.
642  */
643 
644 bool
ipc_right_inuse(ipc_entry_t entry)645 ipc_right_inuse(
646 	ipc_entry_t entry)
647 {
648 	return IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_NONE;
649 }
650 
651 /*
652  *	Routine:	ipc_right_check
653  *	Purpose:
654  *		Check if the port has died.  If it has,
655  *              and IPC_OBJECT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE is not
656  *              passed and it is not a send once right then
657  *		clean up the entry and return TRUE.
658  *	Conditions:
659  *		The space is write-locked; the port is not locked.
660  *		If returns FALSE, the port is also locked.
661  *		Otherwise, entry is converted to a dead name.
662  *
663  *		Caller is responsible for a reference to port if it
664  *		had died (returns TRUE).
665  */
666 
667 boolean_t
ipc_right_check(ipc_space_t space,ipc_port_t port,mach_port_name_t name,ipc_entry_t entry,ipc_object_copyin_flags_t flags)668 ipc_right_check(
669 	ipc_space_t              space,
670 	ipc_port_t               port,
671 	mach_port_name_t         name,
672 	ipc_entry_t              entry,
673 	ipc_object_copyin_flags_t flags)
674 {
675 	ipc_entry_bits_t bits;
676 
677 	assert(is_active(space));
678 	assert(port == ip_object_to_port(entry->ie_object));
679 
680 	ip_mq_lock(port);
681 	if (ip_active(port) ||
682 	    ((flags & IPC_OBJECT_COPYIN_FLAGS_ALLOW_DEAD_SEND_ONCE) &&
683 	    entry->ie_request == IE_REQ_NONE &&
684 	    (entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE))) {
685 		return FALSE;
686 	}
687 
688 	/* this was either a pure send right or a send-once right */
689 
690 	bits = entry->ie_bits;
691 	assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
692 	assert(IE_BITS_UREFS(bits) > 0);
693 
694 	if (bits & MACH_PORT_TYPE_SEND) {
695 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
696 		assert(IE_BITS_UREFS(bits) > 0);
697 		ip_srights_dec(port);
698 	} else {
699 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
700 		assert(IE_BITS_UREFS(bits) == 1);
701 		ip_sorights_dec(port);
702 	}
703 
704 	/*
705 	 * delete SEND rights from ipc hash.
706 	 */
707 
708 	if ((bits & MACH_PORT_TYPE_SEND) != 0) {
709 		ipc_hash_delete(space, ip_to_object(port), name, entry);
710 	}
711 
712 	/* convert entry to dead name */
713 	bits = (bits & ~IE_BITS_TYPE_MASK) | MACH_PORT_TYPE_DEAD_NAME;
714 
715 	/*
716 	 * If there was a notification request outstanding on this
717 	 * name, and the port went dead, that notification
718 	 * must already be on its way up from the port layer.
719 	 *
720 	 * Add the reference that the notification carries. It
721 	 * is done here, and not in the notification delivery,
722 	 * because the latter doesn't have a space reference and
723 	 * trying to actually move a send-right reference would
724 	 * get short-circuited into a MACH_PORT_DEAD by IPC. Since
725 	 * all calls that deal with the right eventually come
726 	 * through here, it has the same result.
727 	 *
728 	 * Once done, clear the request index so we only account
729 	 * for it once.
730 	 */
731 	if (entry->ie_request != IE_REQ_NONE) {
732 		if (ipc_port_request_type(port, name, entry->ie_request) != 0) {
733 			/* if urefs are pegged due to overflow, leave them pegged */
734 			if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
735 				bits++; /* increment urefs */
736 			}
737 		}
738 		entry->ie_request = IE_REQ_NONE;
739 	}
740 	entry->ie_bits = bits;
741 	entry->ie_object = IO_NULL;
742 
743 	ip_mq_unlock(port);
744 
745 	ipc_entry_modified(space, name, entry);
746 
747 	return TRUE;
748 }
749 
750 /*
751  *	Routine:	ipc_right_terminate
752  *	Purpose:
753  *		Cleans up an entry in a terminated space.
754  *		The entry isn't deallocated or removed
755  *		from reverse hash tables.
756  *	Conditions:
757  *		The space is dead and unlocked.
758  */
759 
760 void
ipc_right_terminate(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry)761 ipc_right_terminate(
762 	ipc_space_t             space,
763 	mach_port_name_t        name,
764 	ipc_entry_t             entry)
765 {
766 	mach_port_type_t type;
767 	ipc_object_t object;
768 
769 	assert(!is_active(space));
770 
771 	type   = IE_BITS_TYPE(entry->ie_bits);
772 	object = entry->ie_object;
773 
774 	/*
775 	 * Hollow the entry under the port lock,
776 	 * in order to avoid dangling pointers.
777 	 *
778 	 * ipc_right_lookup_read() doesn't need it for correctness,
779 	 * but ipc_space_terminate() as it now goes through 2 rounds
780 	 * of termination (receive rights first, the rest second).
781 	 */
782 
783 	if (type != MACH_PORT_TYPE_DEAD_NAME) {
784 		assert(object != IO_NULL);
785 		io_lock(object);
786 	}
787 	entry->ie_object = IO_NULL;
788 	entry->ie_bits  &= (IE_BITS_GEN_MASK | IE_BITS_ROLL_MASK);
789 
790 	switch (type) {
791 	case MACH_PORT_TYPE_DEAD_NAME:
792 		assert(entry->ie_request == IE_REQ_NONE);
793 		assert(object == IO_NULL);
794 		break;
795 
796 	case MACH_PORT_TYPE_PORT_SET: {
797 		ipc_pset_t pset = ips_object_to_pset(object);
798 
799 		assert(entry->ie_request == IE_REQ_NONE);
800 		assert(ips_active(pset));
801 
802 		ipc_pset_destroy(space, pset); /* consumes ref, unlocks */
803 		break;
804 	}
805 
806 	case MACH_PORT_TYPE_SEND:
807 	case MACH_PORT_TYPE_RECEIVE:
808 	case MACH_PORT_TYPE_SEND_RECEIVE:
809 	case MACH_PORT_TYPE_SEND_ONCE: {
810 		ipc_port_t port = ip_object_to_port(object);
811 		ipc_port_t request = IP_NULL;
812 		ipc_notify_nsenders_t nsrequest = { };
813 
814 		if (!ip_active(port)) {
815 			ip_mq_unlock(port);
816 			ip_release(port);
817 			break;
818 		}
819 
820 		/*
821 		 * same as ipc_right_request_cancel(),
822 		 * except for calling ipc_entry_modified()
823 		 * as the space is now table-less.
824 		 */
825 		if (entry->ie_request != IE_REQ_NONE) {
826 			request = ipc_port_request_cancel(port, name,
827 			    entry->ie_request);
828 			entry->ie_request = IE_REQ_NONE;
829 		}
830 
831 		if (type & MACH_PORT_TYPE_SEND) {
832 			ip_srights_dec(port);
833 			if (port->ip_srights == 0) {
834 				nsrequest = ipc_notify_no_senders_prepare(port);
835 			}
836 		}
837 
838 		if (type & MACH_PORT_TYPE_RECEIVE) {
839 			assert(ip_get_receiver_name(port) == name);
840 			assert(ip_in_space(port, space));
841 
842 			ipc_port_destroy(port); /* clears receiver, consumes our ref, unlocks */
843 		} else if (type & MACH_PORT_TYPE_SEND_ONCE) {
844 			assert(port->ip_sorights > 0);
845 			port->ip_reply_context = 0;
846 
847 			ipc_notify_send_once_and_unlock(port); /* consumes our ref */
848 		} else {
849 			/* port could be dead, in-transit, or in a foreign space */
850 			assert(!ip_in_space(port, space));
851 
852 			ip_mq_unlock(port);
853 			ip_release(port);
854 		}
855 
856 		/*
857 		 * For both no-senders and port-deleted notifications,
858 		 * look at whether the destination is still active.
859 		 * If it isn't, just swallow the send-once right.
860 		 *
861 		 * This is a racy check, but this ok because we can only
862 		 * fail to notice that the port is now inactive, which
863 		 * only causes us to fail at an optimizaiton.
864 		 *
865 		 * The purpose here is to avoid sending messages
866 		 * to receive rights that used to be in this space,
867 		 * which we can't fail to observe.
868 		 */
869 		if (nsrequest.ns_notify != IP_NULL) {
870 			if (ip_active(nsrequest.ns_notify)) {
871 				ipc_notify_no_senders_emit(nsrequest);
872 			} else {
873 				ipc_notify_no_senders_consume(nsrequest);
874 			}
875 		}
876 
877 		if (request != IP_NULL) {
878 			if (ip_active(request)) {
879 				ipc_notify_port_deleted(request, name);
880 			} else {
881 				ipc_port_release_sonce(request);
882 			}
883 		}
884 		break;
885 	}
886 
887 	default:
888 		panic("ipc_right_terminate: strange type - 0x%x", type);
889 	}
890 }
891 
892 /*
893  *	Routine:	ipc_right_destroy
894  *	Purpose:
895  *		Destroys an entry in a space.
896  *	Conditions:
897  *		The space is write-locked (returns unlocked).
898  *		The space must be active.
899  *	Returns:
900  *		KERN_SUCCESS		      The entry was destroyed.
901  *      KERN_INVALID_CAPABILITY   The port is pinned.
902  *      KERN_INVALID_RIGHT        Port guard violation.
903  */
904 
905 kern_return_t
ipc_right_destroy(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,boolean_t check_guard,uint64_t guard)906 ipc_right_destroy(
907 	ipc_space_t             space,
908 	mach_port_name_t        name,
909 	ipc_entry_t             entry,
910 	boolean_t               check_guard,
911 	uint64_t                guard)
912 {
913 	ipc_entry_bits_t bits;
914 	mach_port_type_t type;
915 
916 	bits = entry->ie_bits;
917 	type = IE_BITS_TYPE(bits);
918 
919 	assert(is_active(space));
920 
921 	switch (type) {
922 	case MACH_PORT_TYPE_DEAD_NAME:
923 		assert(entry->ie_request == IE_REQ_NONE);
924 		assert(entry->ie_object == IO_NULL);
925 
926 		ipc_entry_dealloc(space, IO_NULL, name, entry);
927 		is_write_unlock(space);
928 		break;
929 
930 	case MACH_PORT_TYPE_PORT_SET: {
931 		ipc_pset_t pset = ips_object_to_pset(entry->ie_object);
932 
933 		assert(entry->ie_request == IE_REQ_NONE);
934 		assert(pset != IPS_NULL);
935 
936 		ips_mq_lock(pset);
937 		assert(ips_active(pset));
938 
939 		ipc_entry_dealloc(space, ips_to_object(pset), name, entry);
940 
941 		is_write_unlock(space);
942 
943 		ipc_pset_destroy(space, pset); /* consumes ref, unlocks */
944 		break;
945 	}
946 
947 	case MACH_PORT_TYPE_SEND:
948 	case MACH_PORT_TYPE_RECEIVE:
949 	case MACH_PORT_TYPE_SEND_RECEIVE:
950 	case MACH_PORT_TYPE_SEND_ONCE: {
951 		ipc_port_t port = ip_object_to_port(entry->ie_object);
952 		ipc_notify_nsenders_t nsrequest = { };
953 		ipc_port_t request;
954 
955 		assert(port != IP_NULL);
956 
957 		if (type == MACH_PORT_TYPE_SEND) {
958 			if (ip_is_pinned(port)) {
959 				assert(ip_active(port));
960 				is_write_unlock(space);
961 				mach_port_guard_exception_pinned(space, name, port, MPG_FLAGS_MOD_REFS_PINNED_DESTROY);
962 				return KERN_INVALID_CAPABILITY;
963 			}
964 			ipc_hash_delete(space, ip_to_object(port), name, entry);
965 		}
966 
967 		ip_mq_lock(port);
968 
969 		if (!ip_active(port)) {
970 			assert((type & MACH_PORT_TYPE_RECEIVE) == 0);
971 			entry->ie_request = IE_REQ_NONE;
972 			assert(!ip_is_pinned(port));
973 			ipc_entry_dealloc(space, ip_to_object(port), name, entry);
974 			ip_mq_unlock(port);
975 			is_write_unlock(space);
976 			ip_release(port);
977 			break;
978 		}
979 
980 		/* For receive rights, check for guarding */
981 		if ((type & MACH_PORT_TYPE_RECEIVE) &&
982 		    (check_guard) && (port->ip_guarded) &&
983 		    (guard != port->ip_context)) {
984 			/* Guard Violation */
985 			uint64_t portguard = port->ip_context;
986 			ip_mq_unlock(port);
987 			is_write_unlock(space);
988 			/* Raise mach port guard exception */
989 			mach_port_guard_exception(name, 0, portguard, kGUARD_EXC_DESTROY);
990 			return KERN_INVALID_RIGHT;
991 		}
992 
993 
994 		request = ipc_right_request_cancel_macro(space, port,
995 		    name, entry);
996 		assert(!ip_is_pinned(port));
997 		ipc_entry_dealloc(space, ip_to_object(port), name, entry);
998 
999 		is_write_unlock(space);
1000 
1001 		if (type & MACH_PORT_TYPE_SEND) {
1002 			ip_srights_dec(port);
1003 			if (port->ip_srights == 0) {
1004 				nsrequest = ipc_notify_no_senders_prepare(port);
1005 			}
1006 		}
1007 
1008 		if (type & MACH_PORT_TYPE_RECEIVE) {
1009 			require_ip_active(port);
1010 			assert(ip_in_space(port, space));
1011 
1012 			ipc_port_destroy(port); /* clears receiver, consumes our ref, unlocks */
1013 		} else if (type & MACH_PORT_TYPE_SEND_ONCE) {
1014 			assert(port->ip_sorights > 0);
1015 			port->ip_reply_context = 0;
1016 			ipc_notify_send_once_and_unlock(port); /* consumes our ref */
1017 		} else {
1018 			assert(!ip_in_space(port, space));
1019 
1020 			ip_mq_unlock(port);
1021 			ip_release(port);
1022 		}
1023 
1024 		ipc_notify_no_senders_emit(nsrequest);
1025 
1026 		if (request != IP_NULL) {
1027 			ipc_notify_port_deleted(request, name);
1028 		}
1029 
1030 
1031 		break;
1032 	}
1033 
1034 	default:
1035 		panic("ipc_right_destroy: strange type");
1036 	}
1037 
1038 	return KERN_SUCCESS;
1039 }
1040 
1041 /*
1042  *	Routine:	ipc_right_dealloc
1043  *	Purpose:
1044  *		Releases a send/send-once/dead-name/port_set user ref.
1045  *		Like ipc_right_delta with a delta of -1,
1046  *		but looks at the entry to determine the right.
1047  *	Conditions:
1048  *		The space is write-locked, and is unlocked upon return.
1049  *		The space must be active.
1050  *	Returns:
1051  *		KERN_SUCCESS		A user ref was released.
1052  *		KERN_INVALID_RIGHT	Entry has wrong type.
1053  *      KERN_INVALID_CAPABILITY  Deallocating a pinned right.
1054  */
1055 
1056 kern_return_t
ipc_right_dealloc(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry)1057 ipc_right_dealloc(
1058 	ipc_space_t             space,
1059 	mach_port_name_t        name,
1060 	ipc_entry_t             entry)
1061 {
1062 	ipc_port_t port = IP_NULL;
1063 	ipc_entry_bits_t bits;
1064 	mach_port_type_t type;
1065 
1066 	bits = entry->ie_bits;
1067 	type = IE_BITS_TYPE(bits);
1068 
1069 
1070 	assert(is_active(space));
1071 
1072 	switch (type) {
1073 	case MACH_PORT_TYPE_PORT_SET: {
1074 		ipc_pset_t pset;
1075 
1076 		assert(IE_BITS_UREFS(bits) == 0);
1077 		assert(entry->ie_request == IE_REQ_NONE);
1078 
1079 		pset = ips_object_to_pset(entry->ie_object);
1080 		ips_mq_lock(pset);
1081 		assert(ips_active(pset));
1082 
1083 		ipc_entry_dealloc(space, ips_to_object(pset), name, entry);
1084 
1085 		is_write_unlock(space);
1086 
1087 		ipc_pset_destroy(space, pset); /* consumes ref, unlocks */
1088 		break;
1089 	}
1090 
1091 	case MACH_PORT_TYPE_DEAD_NAME: {
1092 dead_name:
1093 
1094 		assert(IE_BITS_UREFS(bits) > 0);
1095 		assert(entry->ie_request == IE_REQ_NONE);
1096 		assert(entry->ie_object == IO_NULL);
1097 
1098 		if (IE_BITS_UREFS(bits) == 1) {
1099 			ipc_entry_dealloc(space, IO_NULL, name, entry);
1100 		} else {
1101 			/* if urefs are pegged due to overflow, leave them pegged */
1102 			if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
1103 				entry->ie_bits = bits - 1; /* decrement urefs */
1104 			}
1105 			ipc_entry_modified(space, name, entry);
1106 		}
1107 		is_write_unlock(space);
1108 
1109 		/* release any port that got converted to dead name below */
1110 		if (port != IP_NULL) {
1111 			ip_release(port);
1112 		}
1113 		break;
1114 	}
1115 
1116 	case MACH_PORT_TYPE_SEND_ONCE: {
1117 		ipc_port_t request;
1118 
1119 		assert(IE_BITS_UREFS(bits) == 1);
1120 
1121 		port = ip_object_to_port(entry->ie_object);
1122 		assert(port != IP_NULL);
1123 
1124 		if (ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1125 			bits = entry->ie_bits;
1126 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1127 			goto dead_name;     /* it will release port */
1128 		}
1129 		/* port is locked and active */
1130 
1131 		assert(port->ip_sorights > 0);
1132 
1133 		/*
1134 		 * clear any reply context:
1135 		 * no one will be sending the response b/c we are destroying
1136 		 * the single, outstanding send once right.
1137 		 */
1138 		port->ip_reply_context = 0;
1139 
1140 		request = ipc_right_request_cancel_macro(space, port,
1141 		    name, entry);
1142 		assert(!ip_is_pinned(port));
1143 		ipc_entry_dealloc(space, ip_to_object(port), name, entry);
1144 
1145 		is_write_unlock(space);
1146 
1147 		ipc_notify_send_once_and_unlock(port);
1148 
1149 		if (request != IP_NULL) {
1150 			ipc_notify_port_deleted(request, name);
1151 		}
1152 		break;
1153 	}
1154 
1155 	case MACH_PORT_TYPE_SEND: {
1156 		ipc_port_t request = IP_NULL;
1157 		ipc_notify_nsenders_t nsrequest = { };
1158 
1159 		assert(IE_BITS_UREFS(bits) > 0);
1160 
1161 		port = ip_object_to_port(entry->ie_object);
1162 		assert(port != IP_NULL);
1163 
1164 		if (ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1165 			bits = entry->ie_bits;
1166 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1167 			goto dead_name;     /* it will release port */
1168 		}
1169 		/* port is locked and active */
1170 
1171 		assert(port->ip_srights > 0);
1172 
1173 		if (IE_BITS_UREFS(bits) == 1) {
1174 			if (ip_is_pinned(port)) {
1175 				ip_mq_unlock(port);
1176 				is_write_unlock(space);
1177 				mach_port_guard_exception_pinned(space, name, port, MPG_FLAGS_MOD_REFS_PINNED_DEALLOC);
1178 				return KERN_INVALID_CAPABILITY;
1179 			}
1180 			ip_srights_dec(port);
1181 			if (port->ip_srights == 0) {
1182 				nsrequest = ipc_notify_no_senders_prepare(port);
1183 			}
1184 
1185 			request = ipc_right_request_cancel_macro(space, port,
1186 			    name, entry);
1187 			ipc_hash_delete(space, ip_to_object(port), name, entry);
1188 			ipc_entry_dealloc(space, ip_to_object(port), name, entry);
1189 			ip_mq_unlock(port);
1190 			is_write_unlock(space);
1191 
1192 			ip_release(port);
1193 		} else {
1194 			/* if urefs are pegged due to overflow, leave them pegged */
1195 			if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
1196 				entry->ie_bits = bits - 1; /* decrement urefs */
1197 			}
1198 			ip_mq_unlock(port);
1199 			ipc_entry_modified(space, name, entry);
1200 			is_write_unlock(space);
1201 		}
1202 
1203 		ipc_notify_no_senders_emit(nsrequest);
1204 
1205 		if (request != IP_NULL) {
1206 			ipc_notify_port_deleted(request, name);
1207 		}
1208 		break;
1209 	}
1210 
1211 	case MACH_PORT_TYPE_SEND_RECEIVE: {
1212 		ipc_notify_nsenders_t nsrequest = { };
1213 
1214 		assert(IE_BITS_UREFS(bits) > 0);
1215 
1216 		port = ip_object_to_port(entry->ie_object);
1217 		assert(port != IP_NULL);
1218 
1219 		ip_mq_lock(port);
1220 		require_ip_active(port);
1221 		assert(ip_get_receiver_name(port) == name);
1222 		assert(ip_in_space(port, space));
1223 		assert(port->ip_srights > 0);
1224 
1225 		if (IE_BITS_UREFS(bits) == 1) {
1226 			ip_srights_dec(port);
1227 			if (port->ip_srights == 0) {
1228 				nsrequest = ipc_notify_no_senders_prepare(port);
1229 			}
1230 
1231 			entry->ie_bits = bits & ~(IE_BITS_UREFS_MASK |
1232 			    MACH_PORT_TYPE_SEND);
1233 		} else {
1234 			/* if urefs are pegged due to overflow, leave them pegged */
1235 			if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
1236 				entry->ie_bits = bits - 1; /* decrement urefs */
1237 			}
1238 		}
1239 		ip_mq_unlock(port);
1240 
1241 		ipc_entry_modified(space, name, entry);
1242 		is_write_unlock(space);
1243 
1244 		ipc_notify_no_senders_emit(nsrequest);
1245 		break;
1246 	}
1247 
1248 	default:
1249 		is_write_unlock(space);
1250 		mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1251 		return KERN_INVALID_RIGHT;
1252 	}
1253 
1254 	return KERN_SUCCESS;
1255 }
1256 
1257 /*
1258  *	Routine:	ipc_right_delta
1259  *	Purpose:
1260  *		Modifies the user-reference count for a right.
1261  *		May deallocate the right, if the count goes to zero.
1262  *	Conditions:
1263  *		The space is write-locked, and is unlocked upon return.
1264  *		The space must be active.
1265  *	Returns:
1266  *		KERN_SUCCESS		Count was modified.
1267  *		KERN_INVALID_RIGHT	Entry has wrong type.
1268  *		KERN_INVALID_VALUE	Bad delta for the right.
1269  *		KERN_INVALID_CAPABILITY Deallocating a pinned right.
1270  */
1271 
1272 kern_return_t
ipc_right_delta(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,mach_port_right_t right,mach_port_delta_t delta)1273 ipc_right_delta(
1274 	ipc_space_t             space,
1275 	mach_port_name_t        name,
1276 	ipc_entry_t             entry,
1277 	mach_port_right_t       right,
1278 	mach_port_delta_t       delta)
1279 {
1280 	ipc_port_t port = IP_NULL;
1281 	ipc_entry_bits_t bits;
1282 
1283 	bits = entry->ie_bits;
1284 
1285 /*
1286  *	The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
1287  *	switch below. It is used to keep track of those cases (in DIPC)
1288  *	where we have postponed the dropping of a port reference. Since
1289  *	the dropping of the reference could cause the port to disappear
1290  *	we postpone doing so when we are holding the space lock.
1291  */
1292 
1293 	assert(is_active(space));
1294 	assert(right < MACH_PORT_RIGHT_NUMBER);
1295 
1296 	/* Rights-specific restrictions and operations. */
1297 
1298 	switch (right) {
1299 	case MACH_PORT_RIGHT_PORT_SET: {
1300 		ipc_pset_t pset;
1301 
1302 		if ((bits & MACH_PORT_TYPE_PORT_SET) == 0) {
1303 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1304 			goto invalid_right;
1305 		}
1306 
1307 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_PORT_SET);
1308 		assert(IE_BITS_UREFS(bits) == 0);
1309 		assert(entry->ie_request == IE_REQ_NONE);
1310 
1311 		if (delta == 0) {
1312 			goto success;
1313 		}
1314 
1315 		if (delta != -1) {
1316 			goto invalid_value;
1317 		}
1318 
1319 		pset = ips_object_to_pset(entry->ie_object);
1320 		ips_mq_lock(pset);
1321 		assert(ips_active(pset));
1322 
1323 		ipc_entry_dealloc(space, ips_to_object(pset), name, entry);
1324 
1325 		is_write_unlock(space);
1326 
1327 		ipc_pset_destroy(space, pset); /* consumes ref, unlocks */
1328 		break;
1329 	}
1330 
1331 	case MACH_PORT_RIGHT_RECEIVE: {
1332 		ipc_port_t request = IP_NULL;
1333 
1334 		if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1335 			if ((bits & MACH_PORT_TYPE_EX_RECEIVE) == 0) {
1336 				mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1337 			}
1338 			goto invalid_right;
1339 		}
1340 
1341 		if (delta == 0) {
1342 			goto success;
1343 		}
1344 
1345 		if (delta != -1) {
1346 			goto invalid_value;
1347 		}
1348 
1349 		port = ip_object_to_port(entry->ie_object);
1350 		assert(port != IP_NULL);
1351 
1352 		/*
1353 		 *	The port lock is needed for ipc_right_dncancel;
1354 		 *	otherwise, we wouldn't have to take the lock
1355 		 *	until just before dropping the space lock.
1356 		 */
1357 
1358 		ip_mq_lock(port);
1359 		require_ip_active(port);
1360 		assert(ip_get_receiver_name(port) == name);
1361 		assert(ip_in_space(port, space));
1362 
1363 		/* Mach Port Guard Checking */
1364 		if (port->ip_guarded) {
1365 			uint64_t portguard = port->ip_context;
1366 			ip_mq_unlock(port);
1367 			is_write_unlock(space);
1368 			/* Raise mach port guard exception */
1369 			mach_port_guard_exception(name, 0, portguard, kGUARD_EXC_MOD_REFS);
1370 			goto guard_failure;
1371 		}
1372 
1373 		if (bits & MACH_PORT_TYPE_SEND) {
1374 			assert(IE_BITS_TYPE(bits) ==
1375 			    MACH_PORT_TYPE_SEND_RECEIVE);
1376 			assert(IE_BITS_UREFS(bits) > 0);
1377 			assert(port->ip_srights > 0);
1378 
1379 			if (ipc_port_has_prdrequest(port)) {
1380 				/*
1381 				 * Since another task has requested a
1382 				 * destroy notification for this port, it
1383 				 * isn't actually being destroyed - the receive
1384 				 * right is just being moved to another task.
1385 				 * Since we still have one or more send rights,
1386 				 * we need to record the loss of the receive
1387 				 * right and enter the remaining send right
1388 				 * into the hash table.
1389 				 */
1390 				bits &= ~MACH_PORT_TYPE_RECEIVE;
1391 				bits |= MACH_PORT_TYPE_EX_RECEIVE;
1392 				ipc_hash_insert(space, ip_to_object(port),
1393 				    name, entry);
1394 				ip_reference(port);
1395 			} else {
1396 				/*
1397 				 *	The remaining send right turns into a
1398 				 *	dead name.  Notice we don't decrement
1399 				 *	ip_srights, generate a no-senders notif,
1400 				 *	or use ipc_right_dncancel, because the
1401 				 *	port is destroyed "first".
1402 				 */
1403 				bits &= ~IE_BITS_TYPE_MASK;
1404 				bits |= (MACH_PORT_TYPE_DEAD_NAME | MACH_PORT_TYPE_EX_RECEIVE);
1405 				if (entry->ie_request) {
1406 					entry->ie_request = IE_REQ_NONE;
1407 					/* if urefs are pegged due to overflow, leave them pegged */
1408 					if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
1409 						bits++; /* increment urefs */
1410 					}
1411 				}
1412 				entry->ie_object = IO_NULL;
1413 			}
1414 			entry->ie_bits = bits;
1415 			ipc_entry_modified(space, name, entry);
1416 		} else {
1417 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
1418 			assert(IE_BITS_UREFS(bits) == 0);
1419 
1420 			request = ipc_right_request_cancel_macro(space, port,
1421 			    name, entry);
1422 			assert(!ip_is_pinned(port));
1423 			ipc_entry_dealloc(space, ip_to_object(port), name, entry);
1424 		}
1425 		is_write_unlock(space);
1426 
1427 		ipc_port_destroy(port); /* clears receiver, consumes ref, unlocks */
1428 
1429 		if (request != IP_NULL) {
1430 			ipc_notify_port_deleted(request, name);
1431 		}
1432 		break;
1433 	}
1434 
1435 	case MACH_PORT_RIGHT_SEND_ONCE: {
1436 		ipc_port_t request;
1437 
1438 		if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) {
1439 			goto invalid_right;
1440 		}
1441 
1442 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1443 		assert(IE_BITS_UREFS(bits) == 1);
1444 
1445 		port = ip_object_to_port(entry->ie_object);
1446 		assert(port != IP_NULL);
1447 
1448 		if (ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1449 			assert(!(entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE));
1450 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1451 			goto invalid_right;
1452 		}
1453 		/* port is locked and active */
1454 
1455 		assert(port->ip_sorights > 0);
1456 
1457 		if ((delta > 0) || (delta < -1)) {
1458 			ip_mq_unlock(port);
1459 			goto invalid_value;
1460 		}
1461 
1462 		if (delta == 0) {
1463 			ip_mq_unlock(port);
1464 			goto success;
1465 		}
1466 
1467 		/*
1468 		 * clear any reply context:
1469 		 * no one will be sending the response b/c we are destroying
1470 		 * the single, outstanding send once right.
1471 		 */
1472 		port->ip_reply_context = 0;
1473 
1474 		request = ipc_right_request_cancel_macro(space, port, name, entry);
1475 		assert(!ip_is_pinned(port));
1476 		ipc_entry_dealloc(space, ip_to_object(port), name, entry);
1477 
1478 		is_write_unlock(space);
1479 
1480 		ipc_notify_send_once_and_unlock(port);
1481 
1482 		if (request != IP_NULL) {
1483 			ipc_notify_port_deleted(request, name);
1484 		}
1485 		break;
1486 	}
1487 
1488 	case MACH_PORT_RIGHT_DEAD_NAME: {
1489 		ipc_port_t relport = IP_NULL;
1490 		mach_port_urefs_t urefs;
1491 
1492 		if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
1493 			port = ip_object_to_port(entry->ie_object);
1494 			assert(port != IP_NULL);
1495 
1496 			if (!ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1497 				/* port is locked and active */
1498 				ip_mq_unlock(port);
1499 				port = IP_NULL;
1500 				mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1501 				goto invalid_right;
1502 			}
1503 			bits = entry->ie_bits;
1504 			relport = port;
1505 			port = IP_NULL;
1506 		} else if ((bits & MACH_PORT_TYPE_DEAD_NAME) == 0) {
1507 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1508 			goto invalid_right;
1509 		}
1510 
1511 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1512 		assert(IE_BITS_UREFS(bits) > 0);
1513 		assert(entry->ie_object == IO_NULL);
1514 		assert(entry->ie_request == IE_REQ_NONE);
1515 
1516 		if (delta > ((mach_port_delta_t)MACH_PORT_UREFS_MAX) ||
1517 		    delta < (-((mach_port_delta_t)MACH_PORT_UREFS_MAX))) {
1518 			goto invalid_value;
1519 		}
1520 
1521 		urefs = IE_BITS_UREFS(bits);
1522 
1523 		if (urefs == MACH_PORT_UREFS_MAX) {
1524 			/*
1525 			 * urefs are pegged due to an overflow
1526 			 * only a delta removing all refs at once can change it
1527 			 */
1528 
1529 			if (delta != (-((mach_port_delta_t)MACH_PORT_UREFS_MAX))) {
1530 				delta = 0;
1531 			}
1532 		} else {
1533 			if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta)) {
1534 				goto invalid_value;
1535 			}
1536 			if (MACH_PORT_UREFS_OVERFLOW(urefs, delta)) {
1537 				/* leave urefs pegged to maximum if it overflowed */
1538 				delta = MACH_PORT_UREFS_MAX - urefs;
1539 			}
1540 		}
1541 
1542 		if ((urefs + delta) == 0) {
1543 			ipc_entry_dealloc(space, IO_NULL, name, entry);
1544 		} else if (delta != 0) {
1545 			entry->ie_bits = bits + delta;
1546 			ipc_entry_modified(space, name, entry);
1547 		}
1548 
1549 		is_write_unlock(space);
1550 
1551 		if (relport != IP_NULL) {
1552 			ip_release(relport);
1553 		}
1554 
1555 		break;
1556 	}
1557 
1558 	case MACH_PORT_RIGHT_SEND: {
1559 		mach_port_urefs_t urefs;
1560 		ipc_port_t request = IP_NULL;
1561 		ipc_notify_nsenders_t nsrequest = { };
1562 		ipc_port_t port_to_release = IP_NULL;
1563 
1564 		if ((bits & MACH_PORT_TYPE_SEND) == 0) {
1565 			/* invalid right exception only when not live/dead confusion */
1566 			if ((bits & MACH_PORT_TYPE_DEAD_NAME) == 0
1567 #if !defined(AE_MAKESENDRIGHT_FIXED)
1568 			    /*
1569 			     * AE tries to add single send right without knowing if it already owns one.
1570 			     * But if it doesn't, it should own the receive right and delta should be 1.
1571 			     */
1572 			    && (((bits & MACH_PORT_TYPE_RECEIVE) == 0) || (delta != 1))
1573 #endif
1574 			    ) {
1575 				mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1576 			}
1577 			goto invalid_right;
1578 		}
1579 
1580 		/* maximum urefs for send is MACH_PORT_UREFS_MAX */
1581 
1582 		port = ip_object_to_port(entry->ie_object);
1583 		assert(port != IP_NULL);
1584 
1585 		if (ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1586 			assert((entry->ie_bits & MACH_PORT_TYPE_SEND) == 0);
1587 			goto invalid_right;
1588 		}
1589 		/* port is locked and active */
1590 
1591 		assert(port->ip_srights > 0);
1592 
1593 		if (delta > ((mach_port_delta_t)MACH_PORT_UREFS_MAX) ||
1594 		    delta < (-((mach_port_delta_t)MACH_PORT_UREFS_MAX))) {
1595 			ip_mq_unlock(port);
1596 			goto invalid_value;
1597 		}
1598 
1599 		urefs = IE_BITS_UREFS(bits);
1600 
1601 		if (urefs == MACH_PORT_UREFS_MAX) {
1602 			/*
1603 			 * urefs are pegged due to an overflow
1604 			 * only a delta removing all refs at once can change it
1605 			 */
1606 
1607 			if (delta != (-((mach_port_delta_t)MACH_PORT_UREFS_MAX))) {
1608 				delta = 0;
1609 			}
1610 		} else {
1611 			if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta)) {
1612 				ip_mq_unlock(port);
1613 				goto invalid_value;
1614 			}
1615 			if (MACH_PORT_UREFS_OVERFLOW(urefs, delta)) {
1616 				/* leave urefs pegged to maximum if it overflowed */
1617 				delta = MACH_PORT_UREFS_MAX - urefs;
1618 			}
1619 		}
1620 
1621 		if ((urefs + delta) == 0) {
1622 			if (ip_is_pinned(port)) {
1623 				ip_mq_unlock(port);
1624 				is_write_unlock(space);
1625 				mach_port_guard_exception_pinned(space, name, port, MPG_FLAGS_MOD_REFS_PINNED_DEALLOC);
1626 				return KERN_INVALID_CAPABILITY;
1627 			}
1628 
1629 			ip_srights_dec(port);
1630 			if (port->ip_srights == 0) {
1631 				nsrequest = ipc_notify_no_senders_prepare(port);
1632 			}
1633 
1634 			if (bits & MACH_PORT_TYPE_RECEIVE) {
1635 				assert(ip_get_receiver_name(port) == name);
1636 				assert(ip_in_space(port, space));
1637 				assert(IE_BITS_TYPE(bits) ==
1638 				    MACH_PORT_TYPE_SEND_RECEIVE);
1639 
1640 				entry->ie_bits = bits & ~(IE_BITS_UREFS_MASK |
1641 				    MACH_PORT_TYPE_SEND);
1642 				ipc_entry_modified(space, name, entry);
1643 			} else {
1644 				assert(IE_BITS_TYPE(bits) ==
1645 				    MACH_PORT_TYPE_SEND);
1646 
1647 				request = ipc_right_request_cancel_macro(space, port,
1648 				    name, entry);
1649 				ipc_hash_delete(space, ip_to_object(port),
1650 				    name, entry);
1651 				assert(!ip_is_pinned(port));
1652 				ipc_entry_dealloc(space, ip_to_object(port),
1653 				    name, entry);
1654 				port_to_release = port;
1655 			}
1656 		} else if (delta != 0) {
1657 			entry->ie_bits = bits + delta;
1658 			ipc_entry_modified(space, name, entry);
1659 		}
1660 
1661 		ip_mq_unlock(port);
1662 
1663 		is_write_unlock(space);
1664 
1665 		if (port_to_release != IP_NULL) {
1666 			ip_release(port_to_release);
1667 		}
1668 
1669 		ipc_notify_no_senders_emit(nsrequest);
1670 
1671 		if (request != IP_NULL) {
1672 			ipc_notify_port_deleted(request, name);
1673 		}
1674 		break;
1675 	}
1676 
1677 	case MACH_PORT_RIGHT_LABELH:
1678 		goto invalid_right;
1679 
1680 	default:
1681 		panic("ipc_right_delta: strange right %d for 0x%x (%p) in space:%p",
1682 		    right, name, (void *)entry, (void *)space);
1683 	}
1684 
1685 	return KERN_SUCCESS;
1686 
1687 success:
1688 	is_write_unlock(space);
1689 	return KERN_SUCCESS;
1690 
1691 invalid_right:
1692 	is_write_unlock(space);
1693 	if (port != IP_NULL) {
1694 		ip_release(port);
1695 	}
1696 	return KERN_INVALID_RIGHT;
1697 
1698 invalid_value:
1699 	is_write_unlock(space);
1700 	mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_VALUE);
1701 	return KERN_INVALID_VALUE;
1702 
1703 guard_failure:
1704 	return KERN_INVALID_RIGHT;
1705 }
1706 
1707 /*
1708  *	Routine:	ipc_right_destruct
1709  *	Purpose:
1710  *		Deallocates the receive right and modifies the
1711  *		user-reference count for the send rights as requested.
1712  *	Conditions:
1713  *		The space is write-locked, and is unlocked upon return.
1714  *		The space must be active.
1715  *	Returns:
1716  *		KERN_SUCCESS		Count was modified.
1717  *		KERN_INVALID_RIGHT	Entry has wrong type.
1718  *		KERN_INVALID_VALUE	Bad delta for the right.
1719  */
1720 
1721 kern_return_t
ipc_right_destruct(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,mach_port_delta_t srdelta,uint64_t guard)1722 ipc_right_destruct(
1723 	ipc_space_t             space,
1724 	mach_port_name_t        name,
1725 	ipc_entry_t             entry,
1726 	mach_port_delta_t       srdelta,
1727 	uint64_t                guard)
1728 {
1729 	ipc_port_t port = IP_NULL;
1730 	ipc_entry_bits_t bits;
1731 
1732 	mach_port_urefs_t urefs;
1733 	ipc_port_t request = IP_NULL;
1734 	ipc_notify_nsenders_t nsrequest = { };
1735 
1736 	bits = entry->ie_bits;
1737 
1738 	assert(is_active(space));
1739 
1740 	if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1741 		is_write_unlock(space);
1742 
1743 		/* No exception if we used to have receive and held entry since */
1744 		if ((bits & MACH_PORT_TYPE_EX_RECEIVE) == 0) {
1745 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1746 		}
1747 		return KERN_INVALID_RIGHT;
1748 	}
1749 
1750 	if (srdelta && (bits & MACH_PORT_TYPE_SEND) == 0) {
1751 		is_write_unlock(space);
1752 		mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
1753 		return KERN_INVALID_RIGHT;
1754 	}
1755 
1756 	if (srdelta > 0) {
1757 		goto invalid_value;
1758 	}
1759 
1760 	port = ip_object_to_port(entry->ie_object);
1761 	assert(port != IP_NULL);
1762 
1763 	ip_mq_lock(port);
1764 	require_ip_active(port);
1765 	assert(ip_get_receiver_name(port) == name);
1766 	assert(ip_in_space(port, space));
1767 
1768 	/* Mach Port Guard Checking */
1769 	if (port->ip_guarded && (guard != port->ip_context)) {
1770 		uint64_t portguard = port->ip_context;
1771 		ip_mq_unlock(port);
1772 		is_write_unlock(space);
1773 		mach_port_guard_exception(name, 0, portguard, kGUARD_EXC_DESTROY);
1774 		return KERN_INVALID_ARGUMENT;
1775 	}
1776 
1777 	/*
1778 	 * First reduce the send rights as requested and
1779 	 * adjust the entry->ie_bits accordingly. The
1780 	 * ipc_entry_modified() call is made once the receive
1781 	 * right is destroyed too.
1782 	 */
1783 
1784 	if (srdelta) {
1785 		assert(port->ip_srights > 0);
1786 
1787 		urefs = IE_BITS_UREFS(bits);
1788 
1789 		/*
1790 		 * Since we made sure that srdelta is negative,
1791 		 * the check for urefs overflow is not required.
1792 		 */
1793 		if (MACH_PORT_UREFS_UNDERFLOW(urefs, srdelta)) {
1794 			ip_mq_unlock(port);
1795 			goto invalid_value;
1796 		}
1797 
1798 		if (urefs == MACH_PORT_UREFS_MAX) {
1799 			/*
1800 			 * urefs are pegged due to an overflow
1801 			 * only a delta removing all refs at once can change it
1802 			 */
1803 			if (srdelta != (-((mach_port_delta_t)MACH_PORT_UREFS_MAX))) {
1804 				srdelta = 0;
1805 			}
1806 		}
1807 
1808 		if ((urefs + srdelta) == 0) {
1809 			ip_srights_dec(port);
1810 			if (port->ip_srights == 0) {
1811 				nsrequest = ipc_notify_no_senders_prepare(port);
1812 			}
1813 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_RECEIVE);
1814 			entry->ie_bits = bits & ~(IE_BITS_UREFS_MASK |
1815 			    MACH_PORT_TYPE_SEND);
1816 		} else {
1817 			entry->ie_bits = bits + srdelta;
1818 		}
1819 	}
1820 
1821 	/*
1822 	 * Now destroy the receive right. Update space and
1823 	 * entry accordingly.
1824 	 */
1825 
1826 	bits = entry->ie_bits;
1827 	if (bits & MACH_PORT_TYPE_SEND) {
1828 		assert(IE_BITS_UREFS(bits) > 0);
1829 		assert(IE_BITS_UREFS(bits) <= MACH_PORT_UREFS_MAX);
1830 
1831 		if (ipc_port_has_prdrequest(port)) {
1832 			/*
1833 			 * Since another task has requested a
1834 			 * destroy notification for this port, it
1835 			 * isn't actually being destroyed - the receive
1836 			 * right is just being moved to another task.
1837 			 * Since we still have one or more send rights,
1838 			 * we need to record the loss of the receive
1839 			 * right and enter the remaining send right
1840 			 * into the hash table.
1841 			 */
1842 			bits &= ~MACH_PORT_TYPE_RECEIVE;
1843 			bits |= MACH_PORT_TYPE_EX_RECEIVE;
1844 			ipc_hash_insert(space, ip_to_object(port),
1845 			    name, entry);
1846 			ip_reference(port);
1847 		} else {
1848 			/*
1849 			 *	The remaining send right turns into a
1850 			 *	dead name.  Notice we don't decrement
1851 			 *	ip_srights, generate a no-senders notif,
1852 			 *	or use ipc_right_dncancel, because the
1853 			 *	port is destroyed "first".
1854 			 */
1855 			bits &= ~IE_BITS_TYPE_MASK;
1856 			bits |= (MACH_PORT_TYPE_DEAD_NAME | MACH_PORT_TYPE_EX_RECEIVE);
1857 			if (entry->ie_request) {
1858 				entry->ie_request = IE_REQ_NONE;
1859 				if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
1860 					bits++; /* increment urefs */
1861 				}
1862 			}
1863 			entry->ie_object = IO_NULL;
1864 		}
1865 		entry->ie_bits = bits;
1866 		ipc_entry_modified(space, name, entry);
1867 	} else {
1868 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
1869 		assert(IE_BITS_UREFS(bits) == 0);
1870 		request = ipc_right_request_cancel_macro(space, port,
1871 		    name, entry);
1872 		assert(!ip_is_pinned(port));
1873 		ipc_entry_dealloc(space, ip_to_object(port), name, entry);
1874 	}
1875 
1876 	/* Unlock space */
1877 	is_write_unlock(space);
1878 
1879 	ipc_notify_no_senders_emit(nsrequest);
1880 
1881 	ipc_port_destroy(port); /* clears receiver, consumes ref, unlocks */
1882 
1883 	if (request != IP_NULL) {
1884 		ipc_notify_port_deleted(request, name);
1885 	}
1886 
1887 	return KERN_SUCCESS;
1888 
1889 invalid_value:
1890 	is_write_unlock(space);
1891 	mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_VALUE);
1892 	return KERN_INVALID_VALUE;
1893 }
1894 
1895 
1896 /*
1897  *	Routine:	ipc_right_info
1898  *	Purpose:
1899  *		Retrieves information about the right.
1900  *	Conditions:
1901  *		The space is active and write-locked.
1902  *	        The space is unlocked upon return.
1903  *	Returns:
1904  *		KERN_SUCCESS		Retrieved info
1905  */
1906 
1907 kern_return_t
ipc_right_info(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,mach_port_type_t * typep,mach_port_urefs_t * urefsp)1908 ipc_right_info(
1909 	ipc_space_t             space,
1910 	mach_port_name_t        name,
1911 	ipc_entry_t             entry,
1912 	mach_port_type_t        *typep,
1913 	mach_port_urefs_t       *urefsp)
1914 {
1915 	ipc_port_t port;
1916 	ipc_entry_bits_t bits;
1917 	mach_port_type_t type = 0;
1918 	ipc_port_request_index_t request;
1919 
1920 	bits = entry->ie_bits;
1921 	request = entry->ie_request;
1922 	port = ip_object_to_port(entry->ie_object);
1923 
1924 	if (bits & MACH_PORT_TYPE_RECEIVE) {
1925 		assert(IP_VALID(port));
1926 
1927 		if (request != IE_REQ_NONE) {
1928 			ip_mq_lock(port);
1929 			require_ip_active(port);
1930 			type |= ipc_port_request_type(port, name, request);
1931 			ip_mq_unlock(port);
1932 		}
1933 		is_write_unlock(space);
1934 	} else if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
1935 		/*
1936 		 * validate port is still alive - if so, get request
1937 		 * types while we still have it locked.  Otherwise,
1938 		 * recapture the (now dead) bits.
1939 		 */
1940 		if (!ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1941 			if (request != IE_REQ_NONE) {
1942 				type |= ipc_port_request_type(port, name, request);
1943 			}
1944 			ip_mq_unlock(port);
1945 			is_write_unlock(space);
1946 		} else {
1947 			bits = entry->ie_bits;
1948 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1949 			is_write_unlock(space);
1950 			ip_release(port);
1951 		}
1952 	} else {
1953 		is_write_unlock(space);
1954 	}
1955 
1956 	type |= IE_BITS_TYPE(bits);
1957 
1958 	*typep = type;
1959 	*urefsp = IE_BITS_UREFS(bits);
1960 	return KERN_SUCCESS;
1961 }
1962 
1963 /*
1964  *	Routine:	ipc_right_copyin_check_reply
1965  *	Purpose:
1966  *		Check if a subsequent ipc_right_copyin would succeed. Used only
1967  *		by ipc_kmsg_copyin_header to check if reply_port can be copied in.
1968  *		If the reply port is an immovable send right, it errors out.
1969  *	Conditions:
1970  *		The space is locked (read or write) and active.
1971  */
1972 
1973 boolean_t
ipc_right_copyin_check_reply(__assert_only ipc_space_t space,mach_port_name_t reply_name,ipc_entry_t reply_entry,mach_msg_type_name_t reply_type,ipc_entry_t dest_entry,int * reply_port_semantics_violation)1974 ipc_right_copyin_check_reply(
1975 	__assert_only ipc_space_t       space,
1976 	mach_port_name_t                reply_name,
1977 	ipc_entry_t                     reply_entry,
1978 	mach_msg_type_name_t            reply_type,
1979 	ipc_entry_t                     dest_entry,
1980 	int                             *reply_port_semantics_violation)
1981 {
1982 	ipc_entry_bits_t bits;
1983 	ipc_port_t reply_port;
1984 	ipc_port_t dest_port;
1985 
1986 	bits = reply_entry->ie_bits;
1987 	assert(is_active(space));
1988 
1989 	switch (reply_type) {
1990 	case MACH_MSG_TYPE_MAKE_SEND:
1991 		if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1992 			return FALSE;
1993 		}
1994 		break;
1995 
1996 	case MACH_MSG_TYPE_MAKE_SEND_ONCE:
1997 		if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1998 			return FALSE;
1999 		}
2000 		break;
2001 
2002 	case MACH_MSG_TYPE_MOVE_RECEIVE:
2003 		/* ipc_kmsg_copyin_header already filters it out */
2004 		return FALSE;
2005 
2006 	case MACH_MSG_TYPE_COPY_SEND:
2007 	case MACH_MSG_TYPE_MOVE_SEND:
2008 	case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
2009 		if (bits & MACH_PORT_TYPE_DEAD_NAME) {
2010 			break;
2011 		}
2012 
2013 		if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) {
2014 			return FALSE;
2015 		}
2016 
2017 		reply_port = ip_object_to_port(reply_entry->ie_object);
2018 		assert(reply_port != IP_NULL);
2019 
2020 		/*
2021 		 * active status peek to avoid checks that will be skipped
2022 		 * on copyin for dead ports.  Lock not held, so will not be
2023 		 * atomic (but once dead, there's no going back).
2024 		 */
2025 		if (!ip_active(reply_port)) {
2026 			break;
2027 		}
2028 
2029 		/*
2030 		 * Can't copyin a send right that is marked immovable. This bit
2031 		 * is set only during port creation and never unset. So it can
2032 		 * be read without a lock.
2033 		 */
2034 		if (ip_is_immovable_send(reply_port)) {
2035 			mach_port_guard_exception_immovable(space, reply_name, reply_port, MPG_FLAGS_NONE);
2036 			return FALSE;
2037 		}
2038 
2039 		if (reply_type == MACH_MSG_TYPE_MOVE_SEND_ONCE) {
2040 			if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) {
2041 				return FALSE;
2042 			}
2043 		} else {
2044 			if ((bits & MACH_PORT_TYPE_SEND) == 0) {
2045 				return FALSE;
2046 			}
2047 		}
2048 
2049 		break;
2050 	}
2051 
2052 	default:
2053 		panic("ipc_right_copyin_check: strange rights");
2054 	}
2055 
2056 	if ((IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_PORT_SET) ||
2057 	    (IE_BITS_TYPE(reply_entry->ie_bits) == MACH_PORT_TYPE_PORT_SET)) {
2058 		return TRUE;
2059 	}
2060 
2061 	/* The only disp allowed when a reply port is a local port of mach msg is MAKE_SO. */
2062 	reply_port = ip_object_to_port(reply_entry->ie_object);
2063 	assert(reply_port != IP_NULL);
2064 
2065 	if (ip_active(reply_port)) {
2066 		if (ip_is_reply_port(reply_port) && (reply_type != MACH_MSG_TYPE_MAKE_SEND_ONCE)) {
2067 			return FALSE;
2068 		}
2069 
2070 		/* When sending a msg to remote port that requires reply port semantics enforced the local port of that msg needs to be a reply port. */
2071 		dest_port = ip_object_to_port(dest_entry->ie_object);
2072 		if (IP_VALID(dest_port) && ip_active(dest_port)) {
2073 			/* populates reply_port_semantics_violation if we need to send telemetry */
2074 			if (ip_violates_rigid_reply_port_semantics(dest_port, reply_port, reply_port_semantics_violation) ||
2075 			    ip_violates_reply_port_semantics(dest_port, reply_port, reply_port_semantics_violation)) {
2076 				if (reply_port_semantics && (*reply_port_semantics_violation == REPLY_PORT_SEMANTICS_VIOLATOR)) {
2077 					/* Don't crash for rigid reply ports */
2078 					mach_port_guard_exception(reply_name, 0, 0, kGUARD_EXC_REQUIRE_REPLY_PORT_SEMANTICS);
2079 					return FALSE;
2080 				}
2081 			}
2082 		}
2083 	}
2084 
2085 	return TRUE;
2086 }
2087 
2088 /*
2089  *	Routine:	ipc_right_copyin_check_guard_locked
2090  *	Purpose:
2091  *		Check if the port is guarded and the guard
2092  *		value matches the one passed in the arguments.
2093  *		If MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND is set,
2094  *		check if the port is unguarded.
2095  *	Conditions:
2096  *		The port is locked.
2097  *	Returns:
2098  *		KERN_SUCCESS		Port is either unguarded
2099  *					or guarded with expected value
2100  *		KERN_INVALID_ARGUMENT	Port is either unguarded already or guard mismatch.
2101  *					This also raises a EXC_GUARD exception.
2102  */
2103 static kern_return_t
ipc_right_copyin_check_guard_locked(mach_port_name_t name,ipc_port_t port,mach_port_context_t context,mach_msg_guard_flags_t * guard_flags)2104 ipc_right_copyin_check_guard_locked(
2105 	mach_port_name_t name,
2106 	ipc_port_t port,
2107 	mach_port_context_t context,
2108 	mach_msg_guard_flags_t *guard_flags)
2109 {
2110 	mach_msg_guard_flags_t flags = *guard_flags;
2111 	if ((flags & MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND) && !port->ip_guarded && !context) {
2112 		return KERN_SUCCESS;
2113 	} else if (port->ip_guarded && (port->ip_context == context)) {
2114 		return KERN_SUCCESS;
2115 	}
2116 
2117 	/* Incorrect guard; Raise exception */
2118 	mach_port_guard_exception(name, context, port->ip_context, kGUARD_EXC_INCORRECT_GUARD);
2119 	return KERN_INVALID_ARGUMENT;
2120 }
2121 
2122 /*
2123  *	Routine:	ipc_right_copyin
2124  *	Purpose:
2125  *		Copyin a capability from a space.
2126  *		If successful, the caller gets a ref
2127  *		for the resulting object, unless it is IO_DEAD,
2128  *		and possibly a send-once right which should
2129  *		be used in a port-deleted notification.
2130  *
2131  *		If deadok is not TRUE, the copyin operation
2132  *		will fail instead of producing IO_DEAD.
2133  *
2134  *		The entry is deallocated if the entry type becomes
2135  *		MACH_PORT_TYPE_NONE.
2136  *	Conditions:
2137  *		The space is write-locked and active.
2138  *	Returns:
2139  *		KERN_SUCCESS		Acquired an object, possibly IO_DEAD.
2140  *		KERN_INVALID_RIGHT	Name doesn't denote correct right.
2141  *		KERN_INVALID_CAPABILITY	Trying to move an kobject port or an immovable right,
2142  *								or moving the last ref of pinned right
2143  *		KERN_INVALID_ARGUMENT	Port is unguarded or guard mismatch
2144  */
2145 
2146 kern_return_t
ipc_right_copyin(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,mach_msg_type_name_t msgt_name,ipc_object_copyin_flags_t flags,ipc_object_t * objectp,ipc_port_t * sorightp,ipc_port_t * releasep,int * assertcntp,mach_port_context_t context,mach_msg_guard_flags_t * guard_flags)2147 ipc_right_copyin(
2148 	ipc_space_t                space,
2149 	mach_port_name_t           name,
2150 	ipc_entry_t                entry,
2151 	mach_msg_type_name_t       msgt_name,
2152 	ipc_object_copyin_flags_t  flags,
2153 	ipc_object_t               *objectp,
2154 	ipc_port_t                 *sorightp,
2155 	ipc_port_t                 *releasep,
2156 	int                        *assertcntp,
2157 	mach_port_context_t        context,
2158 	mach_msg_guard_flags_t     *guard_flags)
2159 {
2160 	ipc_entry_bits_t bits;
2161 	ipc_port_t port;
2162 	kern_return_t kr;
2163 	boolean_t deadok = !!(flags & IPC_OBJECT_COPYIN_FLAGS_DEADOK);
2164 	boolean_t allow_imm_send = !!(flags & IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND);
2165 	boolean_t allow_reply_make_so = !!(flags & IPC_OBJECT_COPYIN_FLAGS_ALLOW_REPLY_MAKE_SEND_ONCE);
2166 	boolean_t allow_reply_move_so = !!(flags & IPC_OBJECT_COPYIN_FLAGS_ALLOW_REPLY_MOVE_SEND_ONCE);
2167 
2168 	*releasep = IP_NULL;
2169 	*assertcntp = 0;
2170 
2171 	bits = entry->ie_bits;
2172 
2173 	assert(is_active(space));
2174 
2175 	switch (msgt_name) {
2176 	case MACH_MSG_TYPE_MAKE_SEND: {
2177 		if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) {
2178 			goto invalid_right;
2179 		}
2180 
2181 		port = ip_object_to_port(entry->ie_object);
2182 		assert(port != IP_NULL);
2183 
2184 		if (ip_is_reply_port(port)) {
2185 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
2186 			return KERN_INVALID_CAPABILITY;
2187 		}
2188 
2189 		ip_mq_lock(port);
2190 		assert(ip_get_receiver_name(port) == name);
2191 		assert(ip_in_space(port, space));
2192 
2193 		ipc_port_make_send_any_locked(port);
2194 		ip_mq_unlock(port);
2195 
2196 		*objectp = ip_to_object(port);
2197 		*sorightp = IP_NULL;
2198 		break;
2199 	}
2200 
2201 	case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
2202 		if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) {
2203 			goto invalid_right;
2204 		}
2205 
2206 		port = ip_object_to_port(entry->ie_object);
2207 		assert(port != IP_NULL);
2208 
2209 		if ((ip_is_reply_port(port)) && !allow_reply_make_so) {
2210 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
2211 			return KERN_INVALID_CAPABILITY;
2212 		}
2213 
2214 		ip_mq_lock(port);
2215 		require_ip_active(port);
2216 		assert(ip_get_receiver_name(port) == name);
2217 		assert(ip_in_space(port, space));
2218 
2219 		ipc_port_make_sonce_locked(port);
2220 		ip_mq_unlock(port);
2221 
2222 		*objectp = ip_to_object(port);
2223 		*sorightp = IP_NULL;
2224 		break;
2225 	}
2226 
2227 	case MACH_MSG_TYPE_MOVE_RECEIVE: {
2228 		bool allow_imm_recv = false;
2229 		ipc_port_t request = IP_NULL;
2230 		waitq_link_list_t free_l = { };
2231 
2232 		if ((bits & MACH_PORT_TYPE_RECEIVE) == 0) {
2233 			goto invalid_right;
2234 		}
2235 
2236 		port = ip_object_to_port(entry->ie_object);
2237 		assert(port != IP_NULL);
2238 
2239 		ip_mq_lock(port);
2240 		require_ip_active(port);
2241 		assert(ip_get_receiver_name(port) == name);
2242 		assert(ip_in_space(port, space));
2243 
2244 		/*
2245 		 * Disallow moving receive-right kobjects/kolabel, e.g. mk_timer ports
2246 		 * The ipc_port structure uses the kdata union of kobject and
2247 		 * imp_task exclusively. Thus, general use of a kobject port as
2248 		 * a receive right can cause type confusion in the importance
2249 		 * code.
2250 		 */
2251 		if (ip_is_kobject(port) || ip_is_kolabeled(port)) {
2252 			/*
2253 			 * Distinguish an invalid right, e.g., trying to move
2254 			 * a send right as a receive right, from this
2255 			 * situation which is, "This is a valid receive right,
2256 			 * but it's also a kobject and you can't move it."
2257 			 */
2258 			ip_mq_unlock(port);
2259 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_IMMOVABLE);
2260 			return KERN_INVALID_CAPABILITY;
2261 		}
2262 
2263 		if (port->ip_service_port && port->ip_splabel &&
2264 		    !ipc_service_port_label_is_bootstrap_port((ipc_service_port_label_t)port->ip_splabel)) {
2265 			allow_imm_recv = !!(flags & IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_RECEIVE);
2266 		} else if (ip_is_libxpc_connection_port(port)) {
2267 			allow_imm_recv = !!(flags & IPC_OBJECT_COPYIN_FLAGS_ALLOW_CONN_IMMOVABLE_RECEIVE);
2268 		}
2269 
2270 		if ((!allow_imm_recv && port->ip_immovable_receive) ||
2271 		    ip_is_reply_port(port) ||     /* never move reply port rcv right */
2272 		    port->ip_specialreply) {
2273 			assert(!ip_in_space(port, ipc_space_kernel));
2274 			ip_mq_unlock(port);
2275 			assert(current_task() != kernel_task);
2276 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_IMMOVABLE);
2277 			return KERN_INVALID_CAPABILITY;
2278 		}
2279 
2280 		if (guard_flags != NULL) {
2281 			kr = ipc_right_copyin_check_guard_locked(name, port, context, guard_flags);
2282 			if (kr != KERN_SUCCESS) {
2283 				ip_mq_unlock(port);
2284 				return kr;
2285 			}
2286 		}
2287 
2288 		if (bits & MACH_PORT_TYPE_SEND) {
2289 			assert(IE_BITS_TYPE(bits) ==
2290 			    MACH_PORT_TYPE_SEND_RECEIVE);
2291 			assert(IE_BITS_UREFS(bits) > 0);
2292 			assert(port->ip_srights > 0);
2293 
2294 			bits &= ~MACH_PORT_TYPE_RECEIVE;
2295 			bits |= MACH_PORT_TYPE_EX_RECEIVE;
2296 			entry->ie_bits = bits;
2297 			ipc_hash_insert(space, ip_to_object(port),
2298 			    name, entry);
2299 			ip_reference(port);
2300 			ipc_entry_modified(space, name, entry);
2301 		} else {
2302 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
2303 			assert(IE_BITS_UREFS(bits) == 0);
2304 
2305 			request = ipc_right_request_cancel_macro(space, port,
2306 			    name, entry);
2307 			assert(!ip_is_pinned(port));
2308 			ipc_entry_dealloc(space, ip_to_object(port), name, entry);
2309 		}
2310 
2311 		/* ipc_port_clear_receiver unguards the port and clears the ip_immovable_receive bit */
2312 		(void)ipc_port_clear_receiver(port, FALSE, &free_l); /* don't destroy the port/mqueue */
2313 		if (guard_flags != NULL) {
2314 			/* this flag will be cleared during copyout */
2315 			*guard_flags = *guard_flags | MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND;
2316 		}
2317 
2318 #if IMPORTANCE_INHERITANCE
2319 		/*
2320 		 * Account for boosts the current task is going to lose when
2321 		 * copying this right in.  Tempowner ports have either not
2322 		 * been accounting to any task (and therefore are already in
2323 		 * "limbo" state w.r.t. assertions) or to some other specific
2324 		 * task. As we have no way to drop the latter task's assertions
2325 		 * here, We'll deduct those when we enqueue it on its
2326 		 * destination port (see ipc_port_check_circularity()).
2327 		 */
2328 		if (port->ip_tempowner == 0) {
2329 			assert(IIT_NULL == ip_get_imp_task(port));
2330 
2331 			/* ports in limbo have to be tempowner */
2332 			port->ip_tempowner = 1;
2333 			*assertcntp = port->ip_impcount;
2334 		}
2335 #endif /* IMPORTANCE_INHERITANCE */
2336 
2337 		ip_mq_unlock(port);
2338 
2339 		/*
2340 		 * This is unfortunate to do this while the space is locked,
2341 		 * but plumbing it through all callers really hurts.
2342 		 */
2343 		waitq_link_free_list(WQT_PORT_SET, &free_l);
2344 
2345 		*objectp = ip_to_object(port);
2346 		*sorightp = request;
2347 		break;
2348 	}
2349 
2350 	case MACH_MSG_TYPE_COPY_SEND: {
2351 		if (bits & MACH_PORT_TYPE_DEAD_NAME) {
2352 			goto copy_dead;
2353 		}
2354 
2355 		/* allow for dead send-once rights */
2356 
2357 		if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) {
2358 			goto invalid_right;
2359 		}
2360 
2361 		assert(IE_BITS_UREFS(bits) > 0);
2362 
2363 		port = ip_object_to_port(entry->ie_object);
2364 		assert(port != IP_NULL);
2365 
2366 		if (ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
2367 			bits = entry->ie_bits;
2368 			*releasep = port;
2369 			goto copy_dead;
2370 		}
2371 		/* port is locked and active */
2372 
2373 		if ((bits & MACH_PORT_TYPE_SEND) == 0) {
2374 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
2375 			assert(port->ip_sorights > 0);
2376 
2377 			ip_mq_unlock(port);
2378 			goto invalid_right;
2379 		}
2380 
2381 		if (ip_is_reply_port(port)) {
2382 			ip_mq_unlock(port);
2383 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
2384 			return KERN_INVALID_CAPABILITY;
2385 		}
2386 
2387 		if (!allow_imm_send && ip_is_immovable_send(port)) {
2388 			ip_mq_unlock(port);
2389 			mach_port_guard_exception_immovable(space, name, port, MPG_FLAGS_NONE);
2390 			return KERN_INVALID_CAPABILITY;
2391 		}
2392 
2393 		ipc_port_copy_send_any_locked(port);
2394 		ip_mq_unlock(port);
2395 
2396 		*objectp = ip_to_object(port);
2397 		*sorightp = IP_NULL;
2398 		break;
2399 	}
2400 
2401 	case MACH_MSG_TYPE_MOVE_SEND: {
2402 		ipc_port_t request = IP_NULL;
2403 
2404 		if (bits & MACH_PORT_TYPE_DEAD_NAME) {
2405 			goto move_dead;
2406 		}
2407 
2408 		/* allow for dead send-once rights */
2409 
2410 		if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) {
2411 			goto invalid_right;
2412 		}
2413 
2414 		assert(IE_BITS_UREFS(bits) > 0);
2415 
2416 		port = ip_object_to_port(entry->ie_object);
2417 		assert(port != IP_NULL);
2418 
2419 		if (ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
2420 			bits = entry->ie_bits;
2421 			*releasep = port;
2422 			goto move_dead;
2423 		}
2424 		/* port is locked and active */
2425 
2426 		if ((bits & MACH_PORT_TYPE_SEND) == 0) {
2427 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
2428 			assert(port->ip_sorights > 0);
2429 			ip_mq_unlock(port);
2430 			goto invalid_right;
2431 		}
2432 
2433 		if (ip_is_reply_port(port)) {
2434 			ip_mq_unlock(port);
2435 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
2436 			return KERN_INVALID_CAPABILITY;
2437 		}
2438 
2439 		if (!allow_imm_send && ip_is_immovable_send(port)) {
2440 			ip_mq_unlock(port);
2441 			mach_port_guard_exception_immovable(space, name, port, MPG_FLAGS_NONE);
2442 			return KERN_INVALID_CAPABILITY;
2443 		}
2444 
2445 		if (IE_BITS_UREFS(bits) == 1) {
2446 			assert(port->ip_srights > 0);
2447 			if (bits & MACH_PORT_TYPE_RECEIVE) {
2448 				assert(ip_get_receiver_name(port) == name);
2449 				assert(ip_in_space(port, space));
2450 				assert(IE_BITS_TYPE(bits) ==
2451 				    MACH_PORT_TYPE_SEND_RECEIVE);
2452 				assert(!ip_is_pinned(port));
2453 
2454 				entry->ie_bits = bits & ~
2455 				    (IE_BITS_UREFS_MASK | MACH_PORT_TYPE_SEND);
2456 				ipc_entry_modified(space, name, entry);
2457 				ip_reference(port);
2458 			} else {
2459 				assert(IE_BITS_TYPE(bits) ==
2460 				    MACH_PORT_TYPE_SEND);
2461 
2462 				if (ip_is_pinned(port)) {
2463 					ip_mq_unlock(port);
2464 					mach_port_guard_exception_pinned(space, name, port, MPG_FLAGS_MOD_REFS_PINNED_COPYIN);
2465 					return KERN_INVALID_CAPABILITY;
2466 				}
2467 
2468 				request = ipc_right_request_cancel_macro(space, port,
2469 				    name, entry);
2470 				ipc_hash_delete(space, ip_to_object(port),
2471 				    name, entry);
2472 				ipc_entry_dealloc(space, ip_to_object(port),
2473 				    name, entry);
2474 				/* transfer entry's reference to caller */
2475 			}
2476 		} else {
2477 			ipc_port_copy_send_any_locked(port);
2478 			/* if urefs are pegged due to overflow, leave them pegged */
2479 			if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
2480 				entry->ie_bits = bits - 1; /* decrement urefs */
2481 			}
2482 			ipc_entry_modified(space, name, entry);
2483 		}
2484 
2485 		ip_mq_unlock(port);
2486 		*objectp = ip_to_object(port);
2487 		*sorightp = request;
2488 		break;
2489 	}
2490 
2491 	case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
2492 		ipc_port_t request;
2493 
2494 		if (bits & MACH_PORT_TYPE_DEAD_NAME) {
2495 			goto move_dead;
2496 		}
2497 
2498 		/* allow for dead send rights */
2499 
2500 		if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) {
2501 			goto invalid_right;
2502 		}
2503 
2504 		assert(IE_BITS_UREFS(bits) > 0);
2505 
2506 		port = ip_object_to_port(entry->ie_object);
2507 		assert(port != IP_NULL);
2508 
2509 		if (ipc_right_check(space, port, name, entry, flags)) {
2510 			bits = entry->ie_bits;
2511 			*releasep = port;
2512 			goto move_dead;
2513 		}
2514 		/*
2515 		 * port is locked, but may not be active:
2516 		 * Allow copyin of inactive ports with no dead name request and treat it
2517 		 * as if the copyin of the port was successful and port became inactive
2518 		 * later.
2519 		 */
2520 
2521 		if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) {
2522 			assert(bits & MACH_PORT_TYPE_SEND);
2523 			assert(port->ip_srights > 0);
2524 
2525 			ip_mq_unlock(port);
2526 			goto invalid_right;
2527 		}
2528 
2529 		if (ip_is_reply_port(port) && !allow_reply_move_so) {
2530 			ip_mq_unlock(port);
2531 			mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
2532 			return KERN_INVALID_CAPABILITY;
2533 		}
2534 
2535 		if (!allow_imm_send && ip_is_immovable_send(port)) {
2536 			ip_mq_unlock(port);
2537 			mach_port_guard_exception_immovable(space, name, port, MPG_FLAGS_NONE);
2538 			return KERN_INVALID_CAPABILITY;
2539 		}
2540 
2541 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
2542 		assert(IE_BITS_UREFS(bits) == 1);
2543 		assert(port->ip_sorights > 0);
2544 
2545 		request = ipc_right_request_cancel_macro(space, port, name, entry);
2546 		assert(!ip_is_pinned(port));
2547 		ipc_entry_dealloc(space, ip_to_object(port), name, entry);
2548 		ip_mq_unlock(port);
2549 
2550 		*objectp = ip_to_object(port);
2551 		*sorightp = request;
2552 		break;
2553 	}
2554 
2555 	default:
2556 invalid_right:
2557 		return KERN_INVALID_RIGHT;
2558 	}
2559 
2560 	return KERN_SUCCESS;
2561 
2562 copy_dead:
2563 	assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
2564 	assert(IE_BITS_UREFS(bits) > 0);
2565 	assert(entry->ie_request == IE_REQ_NONE);
2566 	assert(entry->ie_object == 0);
2567 
2568 	if (!deadok) {
2569 		goto invalid_right;
2570 	}
2571 
2572 	*objectp = IO_DEAD;
2573 	*sorightp = IP_NULL;
2574 	return KERN_SUCCESS;
2575 
2576 move_dead:
2577 	assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
2578 	assert(IE_BITS_UREFS(bits) > 0);
2579 	assert(entry->ie_request == IE_REQ_NONE);
2580 	assert(entry->ie_object == IO_NULL);
2581 
2582 	if (!deadok) {
2583 		goto invalid_right;
2584 	}
2585 
2586 	if (IE_BITS_UREFS(bits) == 1) {
2587 		ipc_entry_dealloc(space, IO_NULL, name, entry);
2588 	} else {
2589 		/* if urefs are pegged due to overflow, leave them pegged */
2590 		if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
2591 			entry->ie_bits = bits - 1; /* decrement urefs */
2592 		}
2593 		ipc_entry_modified(space, name, entry);
2594 	}
2595 	*objectp = IO_DEAD;
2596 	*sorightp = IP_NULL;
2597 	return KERN_SUCCESS;
2598 }
2599 
2600 /*
2601  *	Routine:	ipc_right_copyin_two_move_sends
2602  *	Purpose:
2603  *		Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
2604  *		and deadok == FALSE, except that this moves two
2605  *		send rights at once.
2606  *	Conditions:
2607  *		The space is write-locked and active.
2608  *		The object is returned with two refs/send rights.
2609  *	Returns:
2610  *		KERN_SUCCESS					Acquired an object.
2611  *		KERN_INVALID_RIGHT				Name doesn't denote correct right.
2612  *		KERN_INVALID_CAPABILITY			Name does not allow copyin move send capability.
2613  */
2614 static
2615 kern_return_t
ipc_right_copyin_two_move_sends(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,ipc_object_t * objectp,ipc_port_t * sorightp,ipc_port_t * releasep)2616 ipc_right_copyin_two_move_sends(
2617 	ipc_space_t             space,
2618 	mach_port_name_t        name,
2619 	ipc_entry_t             entry,
2620 	ipc_object_t            *objectp,
2621 	ipc_port_t              *sorightp,
2622 	ipc_port_t              *releasep)
2623 {
2624 	ipc_entry_bits_t bits;
2625 	mach_port_urefs_t urefs;
2626 	ipc_port_t port;
2627 	ipc_port_t request = IP_NULL;
2628 
2629 	*releasep = IP_NULL;
2630 
2631 	assert(is_active(space));
2632 
2633 	bits = entry->ie_bits;
2634 
2635 	if ((bits & MACH_PORT_TYPE_SEND) == 0) {
2636 		goto invalid_right;
2637 	}
2638 
2639 	urefs = IE_BITS_UREFS(bits);
2640 	if (urefs < 2) {
2641 		goto invalid_right;
2642 	}
2643 
2644 	port = ip_object_to_port(entry->ie_object);
2645 	assert(port != IP_NULL);
2646 
2647 	if (ip_is_reply_port(port)) {
2648 		mach_port_guard_exception(name, 0, 0, kGUARD_EXC_INVALID_RIGHT);
2649 		return KERN_INVALID_CAPABILITY;
2650 	}
2651 
2652 	if (ipc_right_check(space, port, name, entry, IPC_OBJECT_COPYIN_FLAGS_NONE)) {
2653 		*releasep = port;
2654 		goto invalid_right;
2655 	}
2656 	/* port is locked and active */
2657 
2658 	/*
2659 	 * To reach here we either have:
2660 	 * (1) reply_name == voucher_name, but voucher is not immovable send right.
2661 	 * (2) reply_name == dest_name, but ipc_right_copyin_check_reply() guaranteed
2662 	 * that we can't use MOVE_SEND on reply port marked as immovable send right.
2663 	 */
2664 	assert(!ip_is_immovable_send(port));
2665 	assert(!ip_is_pinned(port));
2666 
2667 	if (urefs > 2) {
2668 		/*
2669 		 * We are moving 2 urefs as naked send rights, which is decomposed as:
2670 		 * - two copy sends (which doesn't affect the make send count)
2671 		 * - decrementing the local urefs twice.
2672 		 */
2673 		ipc_port_copy_send_any_locked(port);
2674 		ipc_port_copy_send_any_locked(port);
2675 		/* if urefs are pegged due to overflow, leave them pegged */
2676 		if (IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX) {
2677 			entry->ie_bits = bits - 2; /* decrement urefs */
2678 		}
2679 		ipc_entry_modified(space, name, entry);
2680 	} else {
2681 		/*
2682 		 * We have exactly 2 send rights for this port in this space,
2683 		 * which means that we will liberate the naked send right held
2684 		 * by this entry.
2685 		 *
2686 		 * However refcounting rules around entries are that naked send rights
2687 		 * on behalf of spaces do not have an associated port reference,
2688 		 * so we need to donate one ...
2689 		 */
2690 		ipc_port_copy_send_any_locked(port);
2691 
2692 		if (bits & MACH_PORT_TYPE_RECEIVE) {
2693 			assert(ip_get_receiver_name(port) == name);
2694 			assert(ip_in_space(port, space));
2695 			assert(IE_BITS_TYPE(bits) ==
2696 			    MACH_PORT_TYPE_SEND_RECEIVE);
2697 
2698 			/* ... that we inject manually when the entry stays alive */
2699 			entry->ie_bits = bits & ~(IE_BITS_UREFS_MASK | MACH_PORT_TYPE_SEND);
2700 			ipc_entry_modified(space, name, entry);
2701 			ip_reference(port);
2702 		} else {
2703 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
2704 
2705 			/* ... that we steal from the entry when it dies */
2706 			request = ipc_right_request_cancel_macro(space, port,
2707 			    name, entry);
2708 			ipc_hash_delete(space, ip_to_object(port),
2709 			    name, entry);
2710 			ipc_entry_dealloc(space, ip_to_object(port),
2711 			    name, entry);
2712 		}
2713 	}
2714 
2715 	ip_mq_unlock(port);
2716 
2717 	*objectp = ip_to_object(port);
2718 	*sorightp = request;
2719 	return KERN_SUCCESS;
2720 
2721 invalid_right:
2722 	return KERN_INVALID_RIGHT;
2723 }
2724 
2725 
2726 /*
2727  *	Routine:	ipc_right_copyin_two
2728  *	Purpose:
2729  *		Like ipc_right_copyin with two dispositions,
2730  *		each of which results in a send or send-once right,
2731  *		and deadok = FALSE.
2732  *	Conditions:
2733  *		The space is write-locked and active.
2734  *		The object is returned with two refs/rights.
2735  *		Msgt_one refers to the dest_type.
2736  *      Copyin flags are currently only used in the context of send once rights.
2737  *	Returns:
2738  *		KERN_SUCCESS		Acquired an object.
2739  *		KERN_INVALID_RIGHT	Name doesn't denote correct right(s).
2740  *		KERN_INVALID_CAPABILITY	Name doesn't denote correct right for msgt_two.
2741  */
2742 kern_return_t
ipc_right_copyin_two(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,mach_msg_type_name_t msgt_one,mach_msg_type_name_t msgt_two,ipc_object_copyin_flags_t flags_one,ipc_object_copyin_flags_t flags_two,ipc_object_t * objectp,ipc_port_t * sorightp,ipc_port_t * releasep)2743 ipc_right_copyin_two(
2744 	ipc_space_t               space,
2745 	mach_port_name_t          name,
2746 	ipc_entry_t               entry,
2747 	mach_msg_type_name_t      msgt_one,
2748 	mach_msg_type_name_t      msgt_two,
2749 	ipc_object_copyin_flags_t flags_one, /* Used only for send once rights. */
2750 	ipc_object_copyin_flags_t flags_two, /* Used only for send once rights. */
2751 	ipc_object_t              *objectp,
2752 	ipc_port_t                *sorightp,
2753 	ipc_port_t                *releasep)
2754 {
2755 	kern_return_t kr;
2756 	int assertcnt = 0;
2757 
2758 	assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one));
2759 	assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two));
2760 
2761 	/*
2762 	 *	This is a little tedious to make atomic, because
2763 	 *	there are 25 combinations of valid dispositions.
2764 	 *	However, most are easy.
2765 	 */
2766 
2767 	/*
2768 	 *	If either is move-sonce, then there must be an error.
2769 	 */
2770 	if (msgt_one == MACH_MSG_TYPE_MOVE_SEND_ONCE ||
2771 	    msgt_two == MACH_MSG_TYPE_MOVE_SEND_ONCE) {
2772 		return KERN_INVALID_RIGHT;
2773 	}
2774 
2775 	if ((msgt_one == MACH_MSG_TYPE_MAKE_SEND) ||
2776 	    (msgt_one == MACH_MSG_TYPE_MAKE_SEND_ONCE) ||
2777 	    (msgt_two == MACH_MSG_TYPE_MAKE_SEND) ||
2778 	    (msgt_two == MACH_MSG_TYPE_MAKE_SEND_ONCE)) {
2779 		/*
2780 		 *	One of the dispositions needs a receive right.
2781 		 *
2782 		 *	If the copyin below succeeds, we know the receive
2783 		 *	right is there (because the pre-validation of
2784 		 *	the second disposition already succeeded in our
2785 		 *	caller).
2786 		 *
2787 		 *	Hence the port is not in danger of dying.
2788 		 */
2789 		ipc_object_t object_two;
2790 
2791 		flags_one = flags_one | IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND;
2792 		kr = ipc_right_copyin(space, name, entry,
2793 		    msgt_one, flags_one,
2794 		    objectp, sorightp, releasep,
2795 		    &assertcnt, 0, NULL);
2796 		assert(assertcnt == 0);
2797 		if (kr != KERN_SUCCESS) {
2798 			return kr;
2799 		}
2800 
2801 		assert(IO_VALID(*objectp));
2802 		assert(*sorightp == IP_NULL);
2803 		assert(*releasep == IP_NULL);
2804 
2805 		/*
2806 		 *	Now copyin the second (previously validated)
2807 		 *	disposition.  The result can't be a dead port,
2808 		 *	as no valid disposition can make us lose our
2809 		 *	receive right.
2810 		 */
2811 		kr = ipc_right_copyin(space, name, entry,
2812 		    msgt_two, flags_two,
2813 		    &object_two, sorightp, releasep,
2814 		    &assertcnt, 0, NULL);
2815 		assert(assertcnt == 0);
2816 		assert(kr == KERN_SUCCESS);
2817 		assert(*sorightp == IP_NULL);
2818 		assert(*releasep == IP_NULL);
2819 		assert(object_two == *objectp);
2820 		assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
2821 	} else if ((msgt_one == MACH_MSG_TYPE_MOVE_SEND) &&
2822 	    (msgt_two == MACH_MSG_TYPE_MOVE_SEND)) {
2823 		/*
2824 		 *	This is an easy case.  Just use our
2825 		 *	handy-dandy special-purpose copyin call
2826 		 *	to get two send rights for the price of one.
2827 		 */
2828 		kr = ipc_right_copyin_two_move_sends(space, name, entry,
2829 		    objectp, sorightp,
2830 		    releasep);
2831 		if (kr != KERN_SUCCESS) {
2832 			return kr;
2833 		}
2834 	} else {
2835 		mach_msg_type_name_t msgt_name;
2836 
2837 		/*
2838 		 *	Must be either a single move-send and a
2839 		 *	copy-send, or two copy-send dispositions.
2840 		 *	Use the disposition with the greatest side
2841 		 *	effects for the actual copyin - then just
2842 		 *	duplicate the send right you get back.
2843 		 */
2844 		if (msgt_one == MACH_MSG_TYPE_MOVE_SEND ||
2845 		    msgt_two == MACH_MSG_TYPE_MOVE_SEND) {
2846 			msgt_name = MACH_MSG_TYPE_MOVE_SEND;
2847 		} else {
2848 			msgt_name = MACH_MSG_TYPE_COPY_SEND;
2849 		}
2850 
2851 		kr = ipc_right_copyin(space, name, entry,
2852 		    msgt_name, IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND,
2853 		    objectp, sorightp, releasep,
2854 		    &assertcnt, 0, NULL);
2855 		assert(assertcnt == 0);
2856 		if (kr != KERN_SUCCESS) {
2857 			return kr;
2858 		}
2859 
2860 		/*
2861 		 *	Copy the right we got back.  If it is dead now,
2862 		 *	that's OK.  Neither right will be usable to send
2863 		 *	a message anyway.
2864 		 *
2865 		 *	Note that the port could be concurrently moved
2866 		 *	outside of the space as a descriptor, and then
2867 		 *	destroyed, which would not happen under the space lock.
2868 		 *
2869 		 *	It means we can't use ipc_port_copy_send() which
2870 		 *	may fail if the port died.
2871 		 */
2872 		io_lock(*objectp);
2873 		ipc_port_copy_send_any_locked(ip_object_to_port(*objectp));
2874 		io_unlock(*objectp);
2875 	}
2876 
2877 	return KERN_SUCCESS;
2878 }
2879 
2880 
2881 /*
2882  *	Routine:	ipc_right_copyout
2883  *	Purpose:
2884  *		Copyout a capability to a space.
2885  *		If successful, consumes a ref for the object.
2886  *
2887  *		Always succeeds when given a newly-allocated entry,
2888  *		because user-reference overflow isn't a possibility.
2889  *
2890  *		If copying out the object would cause the user-reference
2891  *		count in the entry to overflow, then the user-reference
2892  *		count is left pegged to its maximum value and the copyout
2893  *		succeeds anyway.
2894  *	Conditions:
2895  *		The space is write-locked and active.
2896  *		The object is locked and active.
2897  *		The object is unlocked; the space isn't.
2898  *	Returns:
2899  *		KERN_SUCCESS		Copied out capability.
2900  */
2901 
2902 kern_return_t
ipc_right_copyout(ipc_space_t space,mach_port_name_t name,ipc_entry_t entry,mach_msg_type_name_t msgt_name,ipc_object_copyout_flags_t flags,mach_port_context_t * context,mach_msg_guard_flags_t * guard_flags,ipc_object_t object)2903 ipc_right_copyout(
2904 	ipc_space_t             space,
2905 	mach_port_name_t        name,
2906 	ipc_entry_t             entry,
2907 	mach_msg_type_name_t    msgt_name,
2908 	ipc_object_copyout_flags_t flags,
2909 	mach_port_context_t     *context,
2910 	mach_msg_guard_flags_t  *guard_flags,
2911 	ipc_object_t            object)
2912 {
2913 	ipc_entry_bits_t bits;
2914 	ipc_port_t port;
2915 	mach_port_name_t sp_name = MACH_PORT_NULL;
2916 	mach_port_context_t sp_context = 0;
2917 
2918 	bits = entry->ie_bits;
2919 
2920 	assert(IO_VALID(object));
2921 	assert(io_otype(object) == IOT_PORT);
2922 	assert(io_active(object));
2923 	assert(entry->ie_object == object);
2924 
2925 	port = ip_object_to_port(object);
2926 
2927 	if (flags & IPC_OBJECT_COPYOUT_FLAGS_PINNED) {
2928 		assert(!ip_is_pinned(port));
2929 		assert(ip_is_immovable_send(port));
2930 		assert(task_is_immovable(space->is_task));
2931 		assert(task_is_pinned(space->is_task));
2932 		port->ip_pinned = 1;
2933 	}
2934 
2935 	switch (msgt_name) {
2936 	case MACH_MSG_TYPE_PORT_SEND_ONCE:
2937 
2938 		assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
2939 		assert(IE_BITS_UREFS(bits) == 0);
2940 		assert(port->ip_sorights > 0);
2941 
2942 		if (port->ip_specialreply) {
2943 			ipc_port_adjust_special_reply_port_locked(port,
2944 			    current_thread()->ith_knote, IPC_PORT_ADJUST_SR_LINK_WORKLOOP, FALSE);
2945 			/* port unlocked on return */
2946 		} else {
2947 			ip_mq_unlock(port);
2948 		}
2949 
2950 		entry->ie_bits = bits | (MACH_PORT_TYPE_SEND_ONCE | 1); /* set urefs to 1 */
2951 		ipc_entry_modified(space, name, entry);
2952 		break;
2953 
2954 	case MACH_MSG_TYPE_PORT_SEND:
2955 		assert(port->ip_srights > 0);
2956 
2957 		if (bits & MACH_PORT_TYPE_SEND) {
2958 			mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
2959 
2960 			assert(port->ip_srights > 1);
2961 			assert(urefs > 0);
2962 			assert(urefs <= MACH_PORT_UREFS_MAX);
2963 
2964 			if (urefs == MACH_PORT_UREFS_MAX) {
2965 				/*
2966 				 * leave urefs pegged to maximum,
2967 				 * consume send right and ref
2968 				 */
2969 
2970 				ip_srights_dec(port);
2971 				ip_mq_unlock(port);
2972 				ip_release_live(port);
2973 				return KERN_SUCCESS;
2974 			}
2975 
2976 			/* consume send right and ref */
2977 			ip_srights_dec(port);
2978 			ip_mq_unlock(port);
2979 			ip_release_live(port);
2980 		} else if (bits & MACH_PORT_TYPE_RECEIVE) {
2981 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
2982 			assert(IE_BITS_UREFS(bits) == 0);
2983 
2984 			/* transfer send right to entry, consume ref */
2985 			ip_mq_unlock(port);
2986 			ip_release_live(port);
2987 		} else {
2988 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
2989 			assert(IE_BITS_UREFS(bits) == 0);
2990 
2991 			/* transfer send right and ref to entry */
2992 			ip_mq_unlock(port);
2993 
2994 			/* entry is locked holding ref, so can use port */
2995 
2996 			ipc_hash_insert(space, ip_to_object(port), name, entry);
2997 		}
2998 
2999 		entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1; /* increment urefs */
3000 		ipc_entry_modified(space, name, entry);
3001 		break;
3002 
3003 	case MACH_MSG_TYPE_PORT_RECEIVE: {
3004 		ipc_port_t dest;
3005 #if IMPORTANCE_INHERITANCE
3006 		natural_t assertcnt = port->ip_impcount;
3007 #endif /* IMPORTANCE_INHERITANCE */
3008 
3009 		assert(port->ip_mscount == 0);
3010 		assert(!ip_in_a_space(port));
3011 
3012 		/*
3013 		 * Don't copyout kobjects or kolabels as receive right
3014 		 */
3015 		if (ip_is_kobject(port) || ip_is_kolabeled(port)) {
3016 			panic("ipc_right_copyout: Copyout kobject/kolabel as receive right");
3017 		}
3018 
3019 		dest = ip_get_destination(port);
3020 
3021 		/* port transitions to IN-SPACE state */
3022 		port->ip_receiver_name = name;
3023 		port->ip_receiver = space;
3024 
3025 		struct knote *kn = current_thread()->ith_knote;
3026 
3027 		if ((guard_flags != NULL) && ((*guard_flags & MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE) != 0)) {
3028 			assert(port->ip_immovable_receive == 0);
3029 			port->ip_guarded = 1;
3030 			port->ip_strict_guard = 0;
3031 			/* pseudo receive shouldn't set the receive right as immovable in the sender's space */
3032 			if (kn != ITH_KNOTE_PSEUDO) {
3033 				port->ip_immovable_receive = 1;
3034 			}
3035 			port->ip_context = current_thread()->ith_msg_addr;
3036 			*context = port->ip_context;
3037 			*guard_flags = *guard_flags & ~MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND;
3038 		}
3039 
3040 		if (ip_is_libxpc_connection_port(port)) {
3041 			/*
3042 			 * There are 3 ways to reach here.
3043 			 * 1. A libxpc client successfully sent this receive right to a named service
3044 			 *    and we are copying out in that service's ipc space.
3045 			 * 2. A libxpc client tried doing (1) but failed so we are doing pseudo-receive.
3046 			 * 3. Kernel sent this receive right to a libxpc client as a part of port destroyed notification.
3047 			 *
3048 			 * This flag needs to be set again in all 3 cases as they reset it as part of their flow.
3049 			 */
3050 			port->ip_immovable_receive = 1;
3051 		}
3052 
3053 		/* Check if this is a service port */
3054 		if (port->ip_service_port) {
3055 			assert(port->ip_splabel != NULL);
3056 			/*
3057 			 * This flag gets reset during all 3 ways described above for libxpc connection port.
3058 			 * The only difference is launchd acts as an initiator instead of a libxpc client.
3059 			 */
3060 			if (service_port_defense_enabled) {
3061 				port->ip_immovable_receive = 1;
3062 			}
3063 
3064 			/* Check if this is a port-destroyed notification to ensure
3065 			 * that initproc doesnt end up with a guarded service port
3066 			 * sent in a regular message
3067 			 */
3068 			if (!ipc_service_port_label_is_pd_notification((ipc_service_port_label_t)port->ip_splabel)) {
3069 				goto skip_sp_check;
3070 			}
3071 
3072 			ipc_service_port_label_clear_flag(port->ip_splabel, ISPL_FLAGS_SEND_PD_NOTIFICATION);
3073 #if !(DEVELOPMENT || DEBUG)
3074 			if (get_bsdtask_info(current_task()) != initproc) {
3075 				goto skip_sp_check;
3076 			}
3077 #endif /* !(DEVELOPMENT || DEBUG) */
3078 			ipc_service_port_label_get_attr(port->ip_splabel, &sp_name, &sp_context);
3079 			assert(sp_name != MACH_PORT_NULL);
3080 			/* Verify the port name and restore the guard value, if any */
3081 			if (name != sp_name) {
3082 				panic("Service port name = 0x%x doesnt match the stored launchd port name = 0x%x", name, sp_name);
3083 			}
3084 			if (sp_context) {
3085 				port->ip_guarded = 1;
3086 				port->ip_strict_guard = 1;
3087 				port->ip_context = sp_context;
3088 			}
3089 		}
3090 skip_sp_check:
3091 
3092 		assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
3093 		if (bits & MACH_PORT_TYPE_SEND) {
3094 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
3095 			assert(IE_BITS_UREFS(bits) > 0);
3096 			assert(port->ip_srights > 0);
3097 		} else {
3098 			assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
3099 			assert(IE_BITS_UREFS(bits) == 0);
3100 		}
3101 		entry->ie_bits = bits | MACH_PORT_TYPE_RECEIVE;
3102 		ipc_entry_modified(space, name, entry);
3103 
3104 		boolean_t sync_bootstrap_checkin = FALSE;
3105 		if (kn != ITH_KNOTE_PSEUDO && port->ip_sync_bootstrap_checkin) {
3106 			sync_bootstrap_checkin = TRUE;
3107 		}
3108 		if (!ITH_KNOTE_VALID(kn, MACH_MSG_TYPE_PORT_RECEIVE)) {
3109 			kn = NULL;
3110 		}
3111 		ipc_port_adjust_port_locked(port, kn, sync_bootstrap_checkin);
3112 		/* port unlocked */
3113 
3114 		if (bits & MACH_PORT_TYPE_SEND) {
3115 			ip_release_live(port);
3116 
3117 			/* entry is locked holding ref, so can use port */
3118 			ipc_hash_delete(space, ip_to_object(port), name, entry);
3119 		}
3120 
3121 		if (dest != IP_NULL) {
3122 #if IMPORTANCE_INHERITANCE
3123 			/*
3124 			 * Deduct the assertion counts we contributed to
3125 			 * the old destination port.  They've already
3126 			 * been reflected into the task as a result of
3127 			 * getting enqueued.
3128 			 */
3129 			ip_mq_lock(dest);
3130 			ipc_port_impcount_delta(dest, 0 - assertcnt, IP_NULL);
3131 			ip_mq_unlock(dest);
3132 #endif /* IMPORTANCE_INHERITANCE */
3133 
3134 			/* Drop turnstile ref on dest */
3135 			ipc_port_send_turnstile_complete(dest);
3136 			/* space lock is held */
3137 			ip_release_safe(dest);
3138 		}
3139 		break;
3140 	}
3141 
3142 	default:
3143 		panic("ipc_right_copyout: strange rights");
3144 	}
3145 	return KERN_SUCCESS;
3146 }
3147