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 Software.Distribution@CS.CMU.EDU
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
95extern struct proc *current_proc(void);
96extern int csproc_hardened_runtime(struct proc* p);
97
98extern void * XNU_PTRAUTH_SIGNED_PTR("initproc") initproc;
99
100TUNABLE(bool, service_port_defense_enabled, "-service_port_defense_enabled", false);
101static 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 */
115kern_return_t
116ipc_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(array: table, i: 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(array: table, i: 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
262out_put_unlock:
263 ipc_object_unlock(object);
264out_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
281kern_return_t
282ipc_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
320kern_return_t
321ipc_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, name: name1)) == IE_NULL) {
341 is_write_unlock(space);
342 mach_port_guard_exception(name: name1, inguard: 0, portguard: 0, reason: kGUARD_EXC_INVALID_NAME);
343 return KERN_INVALID_NAME;
344 }
345 if ((entry2 = ipc_entry_lookup(space, name: name2)) == IE_NULL) {
346 is_write_unlock(space);
347 mach_port_guard_exception(name: name2, inguard: 0, portguard: 0, reason: 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
367bool
368ipc_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
435kern_return_t
436ipc_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, entryp: &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, flags: 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, index: 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, space: ipc_space_kernel) || !ip_full(port))) {
499 if (prev_request != IE_REQ_NONE) {
500 previous = ipc_port_request_cancel(port, name, index: 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(port: 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, index: 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, soright: notify,
524 options, indexp: &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(task: current_task())) {
550 if (ipc_port_importance_delta(port, options: IPID_OPTION_SENDPOSSIBLE, delta: 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(port: 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
612ipc_port_t
613ipc_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, index: 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
644bool
645ipc_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
667boolean_t
668ipc_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, index: 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
760void
761ipc_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 index: 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(port: request, name);
880 } else {
881 ipc_port_release_sonce(port: 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
905kern_return_t
906ipc_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, inguard: 0, portguard, reason: 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(port: 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
1056kern_return_t
1057ipc_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: {
1092dead_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, flags: 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(port: 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, flags: 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(port: 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, inguard: 0, portguard: 0, reason: 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
1272kern_return_t
1273ipc_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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard, reason: 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(port: 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, flags: IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1449 assert(!(entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE));
1450 mach_port_guard_exception(name, inguard: 0, portguard: 0, reason: 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(port: 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, flags: 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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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, flags: 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(port: 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
1687success:
1688 is_write_unlock(space);
1689 return KERN_SUCCESS;
1690
1691invalid_right:
1692 is_write_unlock(space);
1693 if (port != IP_NULL) {
1694 ip_release(port);
1695 }
1696 return KERN_INVALID_RIGHT;
1697
1698invalid_value:
1699 is_write_unlock(space);
1700 mach_port_guard_exception(name, inguard: 0, portguard: 0, reason: kGUARD_EXC_INVALID_VALUE);
1701 return KERN_INVALID_VALUE;
1702
1703guard_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
1721kern_return_t
1722ipc_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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard, reason: 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(port: request, name);
1885 }
1886
1887 return KERN_SUCCESS;
1888
1889invalid_value:
1890 is_write_unlock(space);
1891 mach_port_guard_exception(name, inguard: 0, portguard: 0, reason: 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
1907kern_return_t
1908ipc_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, index: 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, flags: IPC_OBJECT_COPYIN_FLAGS_NONE)) {
1941 if (request != IE_REQ_NONE) {
1942 type |= ipc_port_request_type(port, name, index: 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
1973boolean_t
1974ipc_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, name: reply_name, port: 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(name: reply_name, inguard: 0, portguard: 0, reason: 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 */
2103static kern_return_t
2104ipc_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, inguard: context, portguard: port->ip_context, reason: 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
2146kern_return_t
2147ipc_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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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: &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(type: WQT_PORT_SET, list: &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, flags: 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, inguard: 0, portguard: 0, reason: 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, flags: 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, inguard: 0, portguard: 0, reason: 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, inguard: 0, portguard: 0, reason: 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:
2556invalid_right:
2557 return KERN_INVALID_RIGHT;
2558 }
2559
2560 return KERN_SUCCESS;
2561
2562copy_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
2576move_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 */
2614static
2615kern_return_t
2616ipc_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, inguard: 0, portguard: 0, reason: kGUARD_EXC_INVALID_RIGHT);
2649 return KERN_INVALID_CAPABILITY;
2650 }
2651
2652 if (ipc_right_check(space, port, name, entry, flags: 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
2721invalid_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 */
2742kern_return_t
2743ipc_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 ipc_port_t port;
2756 kern_return_t kr;
2757 int assertcnt = 0;
2758
2759 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_one));
2760 assert(MACH_MSG_TYPE_PORT_ANY_SEND(msgt_two));
2761
2762 /*
2763 * This is a little tedious to make atomic, because
2764 * there are 25 combinations of valid dispositions.
2765 * However, most are easy.
2766 */
2767
2768 /*
2769 * If either is move-sonce, then there must be an error.
2770 */
2771 if (msgt_one == MACH_MSG_TYPE_MOVE_SEND_ONCE ||
2772 msgt_two == MACH_MSG_TYPE_MOVE_SEND_ONCE) {
2773 return KERN_INVALID_RIGHT;
2774 }
2775
2776 if ((msgt_one == MACH_MSG_TYPE_MAKE_SEND) ||
2777 (msgt_one == MACH_MSG_TYPE_MAKE_SEND_ONCE) ||
2778 (msgt_two == MACH_MSG_TYPE_MAKE_SEND) ||
2779 (msgt_two == MACH_MSG_TYPE_MAKE_SEND_ONCE)) {
2780 /*
2781 * One of the dispositions needs a receive right.
2782 *
2783 * If the copyin below succeeds, we know the receive
2784 * right is there (because the pre-validation of
2785 * the second disposition already succeeded in our
2786 * caller).
2787 *
2788 * Hence the port is not in danger of dying.
2789 */
2790 ipc_object_t object_two;
2791
2792 flags_one = flags_one | IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND;
2793 kr = ipc_right_copyin(space, name, entry,
2794 msgt_name: msgt_one, flags: flags_one,
2795 objectp, sorightp, releasep,
2796 assertcntp: &assertcnt, context: 0, NULL);
2797 assert(assertcnt == 0);
2798 if (kr != KERN_SUCCESS) {
2799 return kr;
2800 }
2801
2802 assert(IO_VALID(*objectp));
2803 assert(*sorightp == IP_NULL);
2804 assert(*releasep == IP_NULL);
2805
2806 /*
2807 * Now copyin the second (previously validated)
2808 * disposition. The result can't be a dead port,
2809 * as no valid disposition can make us lose our
2810 * receive right.
2811 */
2812 kr = ipc_right_copyin(space, name, entry,
2813 msgt_name: msgt_two, flags: flags_two,
2814 objectp: &object_two, sorightp, releasep,
2815 assertcntp: &assertcnt, context: 0, NULL);
2816 assert(assertcnt == 0);
2817 assert(kr == KERN_SUCCESS);
2818 assert(*sorightp == IP_NULL);
2819 assert(*releasep == IP_NULL);
2820 assert(object_two == *objectp);
2821 assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
2822 } else if ((msgt_one == MACH_MSG_TYPE_MOVE_SEND) &&
2823 (msgt_two == MACH_MSG_TYPE_MOVE_SEND)) {
2824 /*
2825 * This is an easy case. Just use our
2826 * handy-dandy special-purpose copyin call
2827 * to get two send rights for the price of one.
2828 */
2829 kr = ipc_right_copyin_two_move_sends(space, name, entry,
2830 objectp, sorightp,
2831 releasep);
2832 if (kr != KERN_SUCCESS) {
2833 return kr;
2834 }
2835 } else {
2836 mach_msg_type_name_t msgt_name;
2837
2838 /*
2839 * Must be either a single move-send and a
2840 * copy-send, or two copy-send dispositions.
2841 * Use the disposition with the greatest side
2842 * effects for the actual copyin - then just
2843 * duplicate the send right you get back.
2844 */
2845 if (msgt_one == MACH_MSG_TYPE_MOVE_SEND ||
2846 msgt_two == MACH_MSG_TYPE_MOVE_SEND) {
2847 msgt_name = MACH_MSG_TYPE_MOVE_SEND;
2848 } else {
2849 msgt_name = MACH_MSG_TYPE_COPY_SEND;
2850 }
2851
2852 kr = ipc_right_copyin(space, name, entry,
2853 msgt_name, flags: IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND,
2854 objectp, sorightp, releasep,
2855 assertcntp: &assertcnt, context: 0, NULL);
2856 assert(assertcnt == 0);
2857 if (kr != KERN_SUCCESS) {
2858 return kr;
2859 }
2860
2861 /*
2862 * Copy the right we got back. If it is dead now,
2863 * that's OK. Neither right will be usable to send
2864 * a message anyway.
2865 *
2866 * Note that the port could be concurrently moved
2867 * outside of the space as a descriptor, and then
2868 * destroyed, which would not happen under the space lock.
2869 *
2870 * It means we can't use ipc_port_copy_send() which
2871 * may fail if the port died.
2872 */
2873 port = ip_object_to_port(*objectp);
2874 ip_mq_lock(port);
2875 ipc_port_copy_send_any_locked(port);
2876 ip_mq_unlock(port);
2877 }
2878
2879 return KERN_SUCCESS;
2880}
2881
2882
2883/*
2884 * Routine: ipc_right_copyout
2885 * Purpose:
2886 * Copyout a capability to a space.
2887 * If successful, consumes a ref for the object.
2888 *
2889 * Always succeeds when given a newly-allocated entry,
2890 * because user-reference overflow isn't a possibility.
2891 *
2892 * If copying out the object would cause the user-reference
2893 * count in the entry to overflow, then the user-reference
2894 * count is left pegged to its maximum value and the copyout
2895 * succeeds anyway.
2896 * Conditions:
2897 * The space is write-locked and active.
2898 * The object is locked and active.
2899 * The object is unlocked; the space isn't.
2900 * Returns:
2901 * KERN_SUCCESS Copied out capability.
2902 */
2903
2904kern_return_t
2905ipc_right_copyout(
2906 ipc_space_t space,
2907 mach_port_name_t name,
2908 ipc_entry_t entry,
2909 mach_msg_type_name_t msgt_name,
2910 ipc_object_copyout_flags_t flags,
2911 mach_port_context_t *context,
2912 mach_msg_guard_flags_t *guard_flags,
2913 ipc_object_t object)
2914{
2915 ipc_entry_bits_t bits;
2916 ipc_port_t port;
2917 mach_port_name_t sp_name = MACH_PORT_NULL;
2918 mach_port_context_t sp_context = 0;
2919
2920 bits = entry->ie_bits;
2921
2922 assert(IO_VALID(object));
2923 assert(io_otype(object) == IOT_PORT);
2924 assert(io_active(object));
2925 assert(entry->ie_object == object);
2926
2927 port = ip_object_to_port(object);
2928
2929 if (flags & IPC_OBJECT_COPYOUT_FLAGS_PINNED) {
2930 assert(!ip_is_pinned(port));
2931 assert(ip_is_immovable_send(port));
2932 assert(task_is_immovable(space->is_task));
2933 assert(task_is_pinned(space->is_task));
2934 port->ip_pinned = 1;
2935 }
2936
2937 switch (msgt_name) {
2938 case MACH_MSG_TYPE_PORT_SEND_ONCE:
2939
2940 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
2941 assert(IE_BITS_UREFS(bits) == 0);
2942 assert(port->ip_sorights > 0);
2943
2944 if (port->ip_specialreply) {
2945 ipc_port_adjust_special_reply_port_locked(special_reply_port: port,
2946 kn: current_thread()->ith_knote, IPC_PORT_ADJUST_SR_LINK_WORKLOOP, FALSE);
2947 /* port unlocked on return */
2948 } else {
2949 ip_mq_unlock(port);
2950 }
2951
2952 entry->ie_bits = bits | (MACH_PORT_TYPE_SEND_ONCE | 1); /* set urefs to 1 */
2953 ipc_entry_modified(space, name, entry);
2954 break;
2955
2956 case MACH_MSG_TYPE_PORT_SEND:
2957 assert(port->ip_srights > 0);
2958
2959 if (bits & MACH_PORT_TYPE_SEND) {
2960 mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
2961
2962 assert(port->ip_srights > 1);
2963 assert(urefs > 0);
2964 assert(urefs <= MACH_PORT_UREFS_MAX);
2965
2966 if (urefs == MACH_PORT_UREFS_MAX) {
2967 /*
2968 * leave urefs pegged to maximum,
2969 * consume send right and ref
2970 */
2971
2972 ip_srights_dec(port);
2973 ip_mq_unlock(port);
2974 ip_release_live(port);
2975 return KERN_SUCCESS;
2976 }
2977
2978 /* consume send right and ref */
2979 ip_srights_dec(port);
2980 ip_mq_unlock(port);
2981 ip_release_live(port);
2982 } else if (bits & MACH_PORT_TYPE_RECEIVE) {
2983 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
2984 assert(IE_BITS_UREFS(bits) == 0);
2985
2986 /* transfer send right to entry, consume ref */
2987 ip_mq_unlock(port);
2988 ip_release_live(port);
2989 } else {
2990 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
2991 assert(IE_BITS_UREFS(bits) == 0);
2992
2993 /* transfer send right and ref to entry */
2994 ip_mq_unlock(port);
2995
2996 /* entry is locked holding ref, so can use port */
2997
2998 ipc_hash_insert(space, ip_to_object(port), name, entry);
2999 }
3000
3001 entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1; /* increment urefs */
3002 ipc_entry_modified(space, name, entry);
3003 break;
3004
3005 case MACH_MSG_TYPE_PORT_RECEIVE: {
3006 ipc_port_t dest;
3007#if IMPORTANCE_INHERITANCE
3008 natural_t assertcnt = port->ip_impcount;
3009#endif /* IMPORTANCE_INHERITANCE */
3010
3011 assert(port->ip_mscount == 0);
3012 assert(!ip_in_a_space(port));
3013
3014 /*
3015 * Don't copyout kobjects or kolabels as receive right
3016 */
3017 if (ip_is_kobject(port) || ip_is_kolabeled(port)) {
3018 panic("ipc_right_copyout: Copyout kobject/kolabel as receive right");
3019 }
3020
3021 dest = ip_get_destination(port);
3022
3023 /* port transitions to IN-SPACE state */
3024 port->ip_receiver_name = name;
3025 port->ip_receiver = space;
3026
3027 struct knote *kn = current_thread()->ith_knote;
3028
3029 if ((guard_flags != NULL) && ((*guard_flags & MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE) != 0)) {
3030 assert(port->ip_immovable_receive == 0);
3031 port->ip_guarded = 1;
3032 port->ip_strict_guard = 0;
3033 /* pseudo receive shouldn't set the receive right as immovable in the sender's space */
3034 if (kn != ITH_KNOTE_PSEUDO) {
3035 port->ip_immovable_receive = 1;
3036 }
3037 port->ip_context = current_thread()->ith_msg_addr;
3038 *context = port->ip_context;
3039 *guard_flags = *guard_flags & ~MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND;
3040 }
3041
3042 if (ip_is_libxpc_connection_port(port)) {
3043 /*
3044 * There are 3 ways to reach here.
3045 * 1. A libxpc client successfully sent this receive right to a named service
3046 * and we are copying out in that service's ipc space.
3047 * 2. A libxpc client tried doing (1) but failed so we are doing pseudo-receive.
3048 * 3. Kernel sent this receive right to a libxpc client as a part of port destroyed notification.
3049 *
3050 * This flag needs to be set again in all 3 cases as they reset it as part of their flow.
3051 */
3052 port->ip_immovable_receive = 1;
3053 }
3054
3055 /* Check if this is a service port */
3056 if (port->ip_service_port) {
3057 assert(port->ip_splabel != NULL);
3058 /*
3059 * This flag gets reset during all 3 ways described above for libxpc connection port.
3060 * The only difference is launchd acts as an initiator instead of a libxpc client.
3061 */
3062 if (service_port_defense_enabled) {
3063 port->ip_immovable_receive = 1;
3064 }
3065
3066 /* Check if this is a port-destroyed notification to ensure
3067 * that initproc doesnt end up with a guarded service port
3068 * sent in a regular message
3069 */
3070 if (!ipc_service_port_label_is_pd_notification((ipc_service_port_label_t)port->ip_splabel)) {
3071 goto skip_sp_check;
3072 }
3073
3074 ipc_service_port_label_clear_flag(port_splabel: port->ip_splabel, flag: ISPL_FLAGS_SEND_PD_NOTIFICATION);
3075#if !(DEVELOPMENT || DEBUG)
3076 if (get_bsdtask_info(current_task()) != initproc) {
3077 goto skip_sp_check;
3078 }
3079#endif /* !(DEVELOPMENT || DEBUG) */
3080 ipc_service_port_label_get_attr(port_splabel: port->ip_splabel, name: &sp_name, context: &sp_context);
3081 assert(sp_name != MACH_PORT_NULL);
3082 /* Verify the port name and restore the guard value, if any */
3083 if (name != sp_name) {
3084 panic("Service port name = 0x%x doesnt match the stored launchd port name = 0x%x", name, sp_name);
3085 }
3086 if (sp_context) {
3087 port->ip_guarded = 1;
3088 port->ip_strict_guard = 1;
3089 port->ip_context = sp_context;
3090 }
3091 }
3092skip_sp_check:
3093
3094 assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
3095 if (bits & MACH_PORT_TYPE_SEND) {
3096 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
3097 assert(IE_BITS_UREFS(bits) > 0);
3098 assert(port->ip_srights > 0);
3099 } else {
3100 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
3101 assert(IE_BITS_UREFS(bits) == 0);
3102 }
3103 entry->ie_bits = bits | MACH_PORT_TYPE_RECEIVE;
3104 ipc_entry_modified(space, name, entry);
3105
3106 boolean_t sync_bootstrap_checkin = FALSE;
3107 if (kn != ITH_KNOTE_PSEUDO && port->ip_sync_bootstrap_checkin) {
3108 sync_bootstrap_checkin = TRUE;
3109 }
3110 if (!ITH_KNOTE_VALID(kn, MACH_MSG_TYPE_PORT_RECEIVE)) {
3111 kn = NULL;
3112 }
3113 ipc_port_adjust_port_locked(port, kn, sync_bootstrap_checkin);
3114 /* port unlocked */
3115
3116 if (bits & MACH_PORT_TYPE_SEND) {
3117 ip_release_live(port);
3118
3119 /* entry is locked holding ref, so can use port */
3120 ipc_hash_delete(space, ip_to_object(port), name, entry);
3121 }
3122
3123 if (dest != IP_NULL) {
3124#if IMPORTANCE_INHERITANCE
3125 /*
3126 * Deduct the assertion counts we contributed to
3127 * the old destination port. They've already
3128 * been reflected into the task as a result of
3129 * getting enqueued.
3130 */
3131 ip_mq_lock(dest);
3132 ipc_port_impcount_delta(port: dest, delta: 0 - assertcnt, IP_NULL);
3133 ip_mq_unlock(dest);
3134#endif /* IMPORTANCE_INHERITANCE */
3135
3136 /* Drop turnstile ref on dest */
3137 ipc_port_send_turnstile_complete(port: dest);
3138 /* space lock is held */
3139 ip_release_safe(dest);
3140 }
3141 break;
3142 }
3143
3144 default:
3145 panic("ipc_right_copyout: strange rights");
3146 }
3147 return KERN_SUCCESS;
3148}
3149