]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/ipc_right.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_right.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * @OSF_FREE_COPYRIGHT@
32 */
33 /*
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
36 * All Rights Reserved.
37 *
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
43 *
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47 *
48 * Carnegie Mellon requests users of this software to return to
49 *
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
54 *
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
57 */
58 /*
59 */
60 /*
61 * File: ipc/ipc_right.c
62 * Author: Rich Draves
63 * Date: 1989
64 *
65 * Functions to manipulate IPC capabilities.
66 */
67
68 #include <mach/boolean.h>
69 #include <mach/kern_return.h>
70 #include <mach/port.h>
71 #include <mach/message.h>
72 #include <kern/assert.h>
73 #include <kern/misc_protos.h>
74 #include <ipc/port.h>
75 #include <ipc/ipc_entry.h>
76 #include <ipc/ipc_space.h>
77 #include <ipc/ipc_object.h>
78 #include <ipc/ipc_hash.h>
79 #include <ipc/ipc_port.h>
80 #include <ipc/ipc_pset.h>
81 #include <ipc/ipc_right.h>
82 #include <ipc/ipc_notify.h>
83 #include <ipc/ipc_table.h>
84
85 /*
86 * Routine: ipc_right_lookup_write
87 * Purpose:
88 * Finds an entry in a space, given the name.
89 * Conditions:
90 * Nothing locked. If successful, the space is write-locked.
91 * Returns:
92 * KERN_SUCCESS Found an entry.
93 * KERN_INVALID_TASK The space is dead.
94 * KERN_INVALID_NAME Name doesn't exist in space.
95 */
96
97 kern_return_t
98 ipc_right_lookup_write(
99 ipc_space_t space,
100 mach_port_name_t name,
101 ipc_entry_t *entryp)
102 {
103 ipc_entry_t entry;
104
105 assert(space != IS_NULL);
106
107 is_write_lock(space);
108
109 if (!space->is_active) {
110 is_write_unlock(space);
111 return KERN_INVALID_TASK;
112 }
113
114 if ((entry = ipc_entry_lookup(space, name)) == IE_NULL) {
115 is_write_unlock(space);
116 return KERN_INVALID_NAME;
117 }
118
119 *entryp = entry;
120 return KERN_SUCCESS;
121 }
122
123 /*
124 * Routine: ipc_right_lookup_two_write
125 * Purpose:
126 * Like ipc_right_lookup except that it returns two
127 * entries for two different names that were looked
128 * up under the same space lock.
129 * Conditions:
130 * Nothing locked. If successful, the space is write-locked.
131 * Returns:
132 * KERN_INVALID_TASK The space is dead.
133 * KERN_INVALID_NAME Name doesn't exist in space.
134 */
135
136 kern_return_t
137 ipc_right_lookup_two_write(
138 ipc_space_t space,
139 mach_port_name_t name1,
140 ipc_entry_t *entryp1,
141 mach_port_name_t name2,
142 ipc_entry_t *entryp2)
143 {
144 ipc_entry_t entry1;
145 ipc_entry_t entry2;
146
147 assert(space != IS_NULL);
148
149 is_write_lock(space);
150
151 if (!space->is_active) {
152 is_write_unlock(space);
153 return KERN_INVALID_TASK;
154 }
155
156 if ((entry1 = ipc_entry_lookup(space, name1)) == IE_NULL) {
157 is_write_unlock(space);
158 return KERN_INVALID_NAME;
159 }
160 if ((entry2 = ipc_entry_lookup(space, name2)) == IE_NULL) {
161 is_write_unlock(space);
162 return KERN_INVALID_NAME;
163 }
164 *entryp1 = entry1;
165 *entryp2 = entry2;
166 return KERN_SUCCESS;
167 }
168
169 /*
170 * Routine: ipc_right_reverse
171 * Purpose:
172 * Translate (space, object) -> (name, entry).
173 * Only finds send/receive rights.
174 * Returns TRUE if an entry is found; if so,
175 * the object is locked and active.
176 * Conditions:
177 * The space must be locked (read or write) and active.
178 * Nothing else locked.
179 */
180
181 boolean_t
182 ipc_right_reverse(
183 ipc_space_t space,
184 ipc_object_t object,
185 mach_port_name_t *namep,
186 ipc_entry_t *entryp)
187 {
188 ipc_port_t port;
189 mach_port_name_t name;
190 ipc_entry_t entry;
191
192 /* would switch on io_otype to handle multiple types of object */
193
194 assert(space->is_active);
195 assert(io_otype(object) == IOT_PORT);
196
197 port = (ipc_port_t) object;
198
199 ip_lock(port);
200 if (!ip_active(port)) {
201 ip_unlock(port);
202
203 return FALSE;
204 }
205
206 if (port->ip_receiver == space) {
207 name = port->ip_receiver_name;
208 assert(name != MACH_PORT_NULL);
209
210 entry = ipc_entry_lookup(space, name);
211
212 assert(entry != IE_NULL);
213 assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
214 assert(port == (ipc_port_t) entry->ie_object);
215
216 *namep = name;
217 *entryp = entry;
218 return TRUE;
219 }
220
221 if (ipc_hash_lookup(space, (ipc_object_t) port, namep, entryp)) {
222 assert((entry = *entryp) != IE_NULL);
223 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_SEND);
224 assert(port == (ipc_port_t) entry->ie_object);
225
226 return TRUE;
227 }
228
229 ip_unlock(port);
230 return FALSE;
231 }
232
233 /*
234 * Routine: ipc_right_dnrequest
235 * Purpose:
236 * Make a dead-name request, returning the previously
237 * registered send-once right. If notify is IP_NULL,
238 * just cancels the previously registered request.
239 *
240 * This interacts with the IE_BITS_COMPAT, because they
241 * both use ie_request. If this is a compat entry, then
242 * previous always gets IP_NULL. If notify is IP_NULL,
243 * then the entry remains a compat entry. Otherwise
244 * the real dead-name request is registered and the entry
245 * is no longer a compat entry.
246 * Conditions:
247 * Nothing locked. May allocate memory.
248 * Only consumes/returns refs if successful.
249 * Returns:
250 * KERN_SUCCESS Made/canceled dead-name request.
251 * KERN_INVALID_TASK The space is dead.
252 * KERN_INVALID_NAME Name doesn't exist in space.
253 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
254 * KERN_INVALID_ARGUMENT Name denotes dead name, but
255 * immediate is FALSE or notify is IP_NULL.
256 * KERN_UREFS_OVERFLOW Name denotes dead name, but
257 * generating immediate notif. would overflow urefs.
258 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
259 */
260
261 kern_return_t
262 ipc_right_dnrequest(
263 ipc_space_t space,
264 mach_port_name_t name,
265 boolean_t immediate,
266 ipc_port_t notify,
267 ipc_port_t *previousp)
268 {
269 ipc_port_t previous;
270
271 for (;;) {
272 ipc_entry_t entry;
273 ipc_entry_bits_t bits;
274 kern_return_t kr;
275
276 kr = ipc_right_lookup_write(space, name, &entry);
277 if (kr != KERN_SUCCESS)
278 return kr;
279 /* space is write-locked and active */
280 bits = entry->ie_bits;
281 if (bits & MACH_PORT_TYPE_PORT_RIGHTS) {
282 ipc_port_t port;
283 ipc_port_request_index_t request;
284
285 port = (ipc_port_t) entry->ie_object;
286 assert(port != IP_NULL);
287
288 if (!ipc_right_check(space, port, name, entry)) {
289 /* port is locked and active */
290
291 if (notify == IP_NULL) {
292 previous = ipc_right_dncancel_macro(
293 space, port, name, entry);
294
295 ip_unlock(port);
296 is_write_unlock(space);
297 break;
298 }
299
300 /*
301 * If a registered soright exists,
302 * want to atomically switch with it.
303 * If ipc_port_dncancel finds us a
304 * soright, then the following
305 * ipc_port_dnrequest will reuse
306 * that slot, so we are guaranteed
307 * not to unlock and retry.
308 */
309
310 previous = ipc_right_dncancel_macro(space,
311 port, name, entry);
312
313 kr = ipc_port_dnrequest(port, name, notify,
314 &request);
315 if (kr != KERN_SUCCESS) {
316 assert(previous == IP_NULL);
317 is_write_unlock(space);
318
319 kr = ipc_port_dngrow(port,
320 ITS_SIZE_NONE);
321 /* port is unlocked */
322 if (kr != KERN_SUCCESS)
323 return kr;
324
325 continue;
326 }
327
328 assert(request != 0);
329 ip_unlock(port);
330
331 entry->ie_request = request;
332 is_write_unlock(space);
333 break;
334 } else {
335
336 /*
337 * Our capability bits were changed by ipc_right_check
338 * because it found an inactive port and removed our
339 * references to it (converting our entry into a dead
340 * one). Reload the bits (and obviously we can't use
341 * the port name anymore).
342 */
343 bits = entry->ie_bits;
344
345 }
346
347 assert(bits & MACH_PORT_TYPE_DEAD_NAME);
348 }
349
350 if ((bits & MACH_PORT_TYPE_DEAD_NAME) &&
351 immediate && (notify != IP_NULL)) {
352 mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
353
354 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
355 assert(urefs > 0);
356
357 if (MACH_PORT_UREFS_OVERFLOW(urefs, 1)) {
358 is_write_unlock(space);
359 return KERN_UREFS_OVERFLOW;
360 }
361
362 (entry->ie_bits)++; /* increment urefs */
363 is_write_unlock(space);
364
365 ipc_notify_dead_name(notify, name);
366 previous = IP_NULL;
367 break;
368 }
369
370 is_write_unlock(space);
371 if (bits & MACH_PORT_TYPE_PORT_OR_DEAD)
372 return KERN_INVALID_ARGUMENT;
373 else
374 return KERN_INVALID_RIGHT;
375 }
376
377 *previousp = previous;
378 return KERN_SUCCESS;
379 }
380
381 /*
382 * Routine: ipc_right_dncancel
383 * Purpose:
384 * Cancel a dead-name request and return the send-once right.
385 * Afterwards, entry->ie_request == 0.
386 * Conditions:
387 * The space must be write-locked; the port must be locked.
388 * The port must be active; the space doesn't have to be.
389 */
390
391 ipc_port_t
392 ipc_right_dncancel(
393 __unused ipc_space_t space,
394 ipc_port_t port,
395 mach_port_name_t name,
396 ipc_entry_t entry)
397 {
398 ipc_port_t dnrequest;
399
400 assert(ip_active(port));
401 assert(port == (ipc_port_t) entry->ie_object);
402
403 dnrequest = ipc_port_dncancel(port, name, entry->ie_request);
404 entry->ie_request = 0;
405
406 return dnrequest;
407 }
408
409 /*
410 * Routine: ipc_right_inuse
411 * Purpose:
412 * Check if an entry is being used.
413 * Returns TRUE if it is.
414 * Conditions:
415 * The space is write-locked and active.
416 * It is unlocked if the entry is inuse.
417 */
418
419 boolean_t
420 ipc_right_inuse(
421 ipc_space_t space,
422 __unused mach_port_name_t name,
423 ipc_entry_t entry)
424 {
425 if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_NONE) {
426 is_write_unlock(space);
427 return TRUE;
428 }
429 return FALSE;
430 }
431
432 /*
433 * Routine: ipc_right_check
434 * Purpose:
435 * Check if the port has died. If it has,
436 * clean up the entry and return TRUE.
437 * Conditions:
438 * The space is write-locked; the port is not locked.
439 * If returns FALSE, the port is also locked and active.
440 * Otherwise, entry is converted to a dead name, freeing
441 * a reference to port.
442 */
443
444 boolean_t
445 ipc_right_check(
446 ipc_space_t space,
447 ipc_port_t port,
448 mach_port_name_t name,
449 ipc_entry_t entry)
450 {
451 ipc_entry_bits_t bits;
452
453 assert(space->is_active);
454 assert(port == (ipc_port_t) entry->ie_object);
455
456 ip_lock(port);
457 if (ip_active(port))
458 return FALSE;
459 ip_unlock(port);
460
461 /* this was either a pure send right or a send-once right */
462
463 bits = entry->ie_bits;
464 assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
465 assert(IE_BITS_UREFS(bits) > 0);
466
467 if (bits & MACH_PORT_TYPE_SEND) {
468 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
469 } else {
470 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
471 assert(IE_BITS_UREFS(bits) == 1);
472 }
473
474
475 ipc_port_release(port);
476
477 /* convert entry to dead name */
478
479 if ((bits & MACH_PORT_TYPE_SEND) && !(bits & MACH_PORT_TYPE_RECEIVE))
480 ipc_hash_delete(space, (ipc_object_t)port, name, entry);
481
482 bits = (bits &~ IE_BITS_TYPE_MASK) | MACH_PORT_TYPE_DEAD_NAME;
483
484 /*
485 * If there was a notification request outstanding on this
486 * name, and since the port went dead, that notification
487 * must already be on its way up from the port layer. We
488 * don't need the index of the notification port anymore.
489 *
490 * JMM - We also add a reference to the entry since the
491 * notification only carries the name and NOT a reference
492 * (or right). This makes for pretty loose reference
493 * counting, since it is only happenstance that we
494 * detected the notification in progress like this.
495 * But most (all?) calls that try to deal with this entry
496 * will also come through here, so the reference gets added
497 * before the entry gets used eventually (I would rather it
498 * be explicit in the notification generation, though)
499 */
500 if (entry->ie_request != 0) {
501 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
502 entry->ie_request = 0;
503 bits++;
504 }
505 entry->ie_bits = bits;
506 entry->ie_object = IO_NULL;
507 return TRUE;
508 }
509
510 /*
511 * Routine: ipc_right_clean
512 * Purpose:
513 * Cleans up an entry in a dead space.
514 * The entry isn't deallocated or removed
515 * from reverse hash tables.
516 * Conditions:
517 * The space is dead and unlocked.
518 */
519
520 void
521 ipc_right_clean(
522 ipc_space_t space,
523 mach_port_name_t name,
524 ipc_entry_t entry)
525 {
526 ipc_entry_bits_t bits;
527 mach_port_type_t type;
528
529 bits = entry->ie_bits;
530 type = IE_BITS_TYPE(bits);
531
532 assert(!space->is_active);
533
534 /*
535 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
536 * problem, because we check that the port is active. If
537 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
538 * would still work, but dead space refs would accumulate
539 * in ip_dnrequests. They would use up slots in
540 * ip_dnrequests and keep the spaces from being freed.
541 */
542
543 switch (type) {
544 case MACH_PORT_TYPE_DEAD_NAME:
545 assert(entry->ie_request == 0);
546 assert(entry->ie_object == IO_NULL);
547 break;
548
549 case MACH_PORT_TYPE_PORT_SET: {
550 ipc_pset_t pset = (ipc_pset_t) entry->ie_object;
551
552 assert(entry->ie_request == 0);
553 assert(pset != IPS_NULL);
554
555 ips_lock(pset);
556 assert(ips_active(pset));
557
558 ipc_pset_destroy(pset); /* consumes ref, unlocks */
559 break;
560 }
561
562 case MACH_PORT_TYPE_SEND:
563 case MACH_PORT_TYPE_RECEIVE:
564 case MACH_PORT_TYPE_SEND_RECEIVE:
565 case MACH_PORT_TYPE_SEND_ONCE: {
566 ipc_port_t port = (ipc_port_t) entry->ie_object;
567 ipc_port_t dnrequest;
568 ipc_port_t nsrequest = IP_NULL;
569 mach_port_mscount_t mscount = 0;
570
571 assert(port != IP_NULL);
572 ip_lock(port);
573
574 if (!ip_active(port)) {
575 ip_release(port);
576 ip_check_unlock(port);
577 break;
578 }
579
580 dnrequest = ipc_right_dncancel_macro(space, port,
581 name, entry);
582
583 if (type & MACH_PORT_TYPE_SEND) {
584 assert(port->ip_srights > 0);
585 if (--port->ip_srights == 0
586 ) {
587 nsrequest = port->ip_nsrequest;
588 if (nsrequest != IP_NULL) {
589 port->ip_nsrequest = IP_NULL;
590 mscount = port->ip_mscount;
591 }
592 }
593 }
594
595 if (type & MACH_PORT_TYPE_RECEIVE) {
596 assert(port->ip_receiver_name == name);
597 assert(port->ip_receiver == space);
598
599 ipc_port_clear_receiver(port);
600 ipc_port_destroy(port); /* consumes our ref, unlocks */
601 } else if (type & MACH_PORT_TYPE_SEND_ONCE) {
602 assert(port->ip_sorights > 0);
603 ip_unlock(port);
604
605 ipc_notify_send_once(port); /* consumes our ref */
606 } else {
607 assert(port->ip_receiver != space);
608
609 ip_release(port);
610 ip_unlock(port); /* port is active */
611 }
612
613 if (nsrequest != IP_NULL)
614 ipc_notify_no_senders(nsrequest, mscount);
615
616 if (dnrequest != IP_NULL)
617 ipc_notify_port_deleted(dnrequest, name);
618 break;
619 }
620
621 default:
622 panic("ipc_right_clean: strange type");
623 }
624 }
625
626 /*
627 * Routine: ipc_right_destroy
628 * Purpose:
629 * Destroys an entry in a space.
630 * Conditions:
631 * The space is write-locked.
632 * The space must be active.
633 * Returns:
634 * KERN_SUCCESS The entry was destroyed.
635 */
636
637 kern_return_t
638 ipc_right_destroy(
639 ipc_space_t space,
640 mach_port_name_t name,
641 ipc_entry_t entry)
642 {
643 ipc_entry_bits_t bits;
644 mach_port_type_t type;
645
646 bits = entry->ie_bits;
647 entry->ie_bits &= ~IE_BITS_TYPE_MASK;
648 type = IE_BITS_TYPE(bits);
649
650 assert(space->is_active);
651
652 switch (type) {
653 case MACH_PORT_TYPE_DEAD_NAME:
654 assert(entry->ie_request == 0);
655 assert(entry->ie_object == IO_NULL);
656
657 ipc_entry_dealloc(space, name, entry);
658 break;
659
660 case MACH_PORT_TYPE_PORT_SET: {
661 ipc_pset_t pset = (ipc_pset_t) entry->ie_object;
662
663 assert(entry->ie_request == 0);
664 assert(pset != IPS_NULL);
665
666 entry->ie_object = IO_NULL;
667 ipc_entry_dealloc(space, name, entry);
668
669 ips_lock(pset);
670 assert(ips_active(pset));
671
672 ipc_pset_destroy(pset); /* consumes ref, unlocks */
673 break;
674 }
675
676 case MACH_PORT_TYPE_SEND:
677 case MACH_PORT_TYPE_RECEIVE:
678 case MACH_PORT_TYPE_SEND_RECEIVE:
679 case MACH_PORT_TYPE_SEND_ONCE: {
680 ipc_port_t port = (ipc_port_t) entry->ie_object;
681 ipc_port_t nsrequest = IP_NULL;
682 mach_port_mscount_t mscount = 0;
683 ipc_port_t dnrequest;
684
685 assert(port != IP_NULL);
686
687 if (type == MACH_PORT_TYPE_SEND)
688 ipc_hash_delete(space, (ipc_object_t) port,
689 name, entry);
690
691 ip_lock(port);
692
693 if (!ip_active(port)) {
694 assert((type & MACH_PORT_TYPE_RECEIVE) == 0);
695 ip_release(port);
696 ip_check_unlock(port);
697
698 entry->ie_request = 0;
699 entry->ie_object = IO_NULL;
700 ipc_entry_dealloc(space, name, entry);
701
702 break;
703 }
704
705 dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
706
707 entry->ie_object = IO_NULL;
708 ipc_entry_dealloc(space, name, entry);
709
710 if (type & MACH_PORT_TYPE_SEND) {
711 assert(port->ip_srights > 0);
712 if (--port->ip_srights == 0) {
713 nsrequest = port->ip_nsrequest;
714 if (nsrequest != IP_NULL) {
715 port->ip_nsrequest = IP_NULL;
716 mscount = port->ip_mscount;
717 }
718 }
719 }
720
721 if (type & MACH_PORT_TYPE_RECEIVE) {
722 assert(ip_active(port));
723 assert(port->ip_receiver == space);
724
725 ipc_port_clear_receiver(port);
726 ipc_port_destroy(port); /* consumes our ref, unlocks */
727 } else if (type & MACH_PORT_TYPE_SEND_ONCE) {
728 assert(port->ip_sorights > 0);
729 ip_unlock(port);
730
731 ipc_notify_send_once(port); /* consumes our ref */
732 } else {
733 assert(port->ip_receiver != space);
734
735 ip_release(port);
736 ip_unlock(port);
737 }
738
739 if (nsrequest != IP_NULL)
740 ipc_notify_no_senders(nsrequest, mscount);
741
742 if (dnrequest != IP_NULL)
743 ipc_notify_port_deleted(dnrequest, name);
744 break;
745 }
746
747 default:
748 panic("ipc_right_destroy: strange type");
749 }
750
751 return KERN_SUCCESS;
752 }
753
754 /*
755 * Routine: ipc_right_dealloc
756 * Purpose:
757 * Releases a send/send-once/dead-name user ref.
758 * Like ipc_right_delta with a delta of -1,
759 * but looks at the entry to determine the right.
760 * Conditions:
761 * The space is write-locked, and is unlocked upon return.
762 * The space must be active.
763 * Returns:
764 * KERN_SUCCESS A user ref was released.
765 * KERN_INVALID_RIGHT Entry has wrong type.
766 */
767
768 kern_return_t
769 ipc_right_dealloc(
770 ipc_space_t space,
771 mach_port_name_t name,
772 ipc_entry_t entry)
773 {
774
775 ipc_entry_bits_t bits;
776 mach_port_type_t type;
777
778 bits = entry->ie_bits;
779 type = IE_BITS_TYPE(bits);
780
781
782 assert(space->is_active);
783
784 switch (type) {
785 case MACH_PORT_TYPE_DEAD_NAME: {
786 dead_name:
787
788 assert(IE_BITS_UREFS(bits) > 0);
789 assert(entry->ie_request == 0);
790 assert(entry->ie_object == IO_NULL);
791
792 if (IE_BITS_UREFS(bits) == 1) {
793 ipc_entry_dealloc(space, name, entry);
794 }
795 else
796 entry->ie_bits = bits-1; /* decrement urefs */
797
798 is_write_unlock(space);
799 break;
800 }
801
802 case MACH_PORT_TYPE_SEND_ONCE: {
803 ipc_port_t port, dnrequest;
804
805 assert(IE_BITS_UREFS(bits) == 1);
806
807 port = (ipc_port_t) entry->ie_object;
808 assert(port != IP_NULL);
809
810 if (ipc_right_check(space, port, name, entry)) {
811
812 bits = entry->ie_bits;
813 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
814 goto dead_name;
815 }
816 /* port is locked and active */
817
818 assert(port->ip_sorights > 0);
819
820 dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
821 ip_unlock(port);
822
823 entry->ie_object = IO_NULL;
824 ipc_entry_dealloc(space, name, entry);
825
826 is_write_unlock(space);
827
828 ipc_notify_send_once(port);
829
830 if (dnrequest != IP_NULL)
831 ipc_notify_port_deleted(dnrequest, name);
832 break;
833 }
834
835 case MACH_PORT_TYPE_SEND: {
836 ipc_port_t port;
837 ipc_port_t dnrequest = IP_NULL;
838 ipc_port_t nsrequest = IP_NULL;
839 mach_port_mscount_t mscount = 0;
840
841
842 assert(IE_BITS_UREFS(bits) > 0);
843
844 port = (ipc_port_t) entry->ie_object;
845 assert(port != IP_NULL);
846
847 if (ipc_right_check(space, port, name, entry)) {
848 bits = entry->ie_bits;
849 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
850 goto dead_name;
851 }
852 /* port is locked and active */
853
854 assert(port->ip_srights > 0);
855
856 if (IE_BITS_UREFS(bits) == 1) {
857 if (--port->ip_srights == 0) {
858 nsrequest = port->ip_nsrequest;
859 if (nsrequest != IP_NULL) {
860 port->ip_nsrequest = IP_NULL;
861 mscount = port->ip_mscount;
862 }
863 }
864
865 dnrequest = ipc_right_dncancel_macro(space, port,
866 name, entry);
867 ipc_hash_delete(space, (ipc_object_t) port,
868 name, entry);
869
870 ip_release(port);
871 entry->ie_object = IO_NULL;
872 ipc_entry_dealloc(space, name, entry);
873
874 } else
875 entry->ie_bits = bits-1; /* decrement urefs */
876
877 /* even if dropped a ref, port is active */
878 ip_unlock(port);
879 is_write_unlock(space);
880
881 if (nsrequest != IP_NULL)
882 ipc_notify_no_senders(nsrequest, mscount);
883
884 if (dnrequest != IP_NULL)
885 ipc_notify_port_deleted(dnrequest, name);
886 break;
887 }
888
889 case MACH_PORT_TYPE_SEND_RECEIVE: {
890 ipc_port_t port;
891 ipc_port_t nsrequest = IP_NULL;
892 mach_port_mscount_t mscount = 0;
893
894 assert(IE_BITS_UREFS(bits) > 0);
895
896 port = (ipc_port_t) entry->ie_object;
897 assert(port != IP_NULL);
898
899 ip_lock(port);
900 assert(ip_active(port));
901 assert(port->ip_receiver_name == name);
902 assert(port->ip_receiver == space);
903 assert(port->ip_srights > 0);
904
905 if (IE_BITS_UREFS(bits) == 1) {
906 if (--port->ip_srights == 0) {
907 nsrequest = port->ip_nsrequest;
908 if (nsrequest != IP_NULL) {
909 port->ip_nsrequest = IP_NULL;
910 mscount = port->ip_mscount;
911 }
912 }
913
914 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK |
915 MACH_PORT_TYPE_SEND);
916 } else
917 entry->ie_bits = bits-1; /* decrement urefs */
918
919 ip_unlock(port);
920 is_write_unlock(space);
921
922 if (nsrequest != IP_NULL)
923 ipc_notify_no_senders(nsrequest, mscount);
924 break;
925 }
926
927 default:
928 is_write_unlock(space);
929 return KERN_INVALID_RIGHT;
930 }
931
932 return KERN_SUCCESS;
933 }
934
935 /*
936 * Routine: ipc_right_delta
937 * Purpose:
938 * Modifies the user-reference count for a right.
939 * May deallocate the right, if the count goes to zero.
940 * Conditions:
941 * The space is write-locked, and is unlocked upon return.
942 * The space must be active.
943 * Returns:
944 * KERN_SUCCESS Count was modified.
945 * KERN_INVALID_RIGHT Entry has wrong type.
946 * KERN_INVALID_VALUE Bad delta for the right.
947 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
948 */
949
950 kern_return_t
951 ipc_right_delta(
952 ipc_space_t space,
953 mach_port_name_t name,
954 ipc_entry_t entry,
955 mach_port_right_t right,
956 mach_port_delta_t delta)
957 {
958 ipc_entry_bits_t bits;
959
960 bits = entry->ie_bits;
961
962
963 /*
964 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
965 * switch below. It is used to keep track of those cases (in DIPC)
966 * where we have postponed the dropping of a port reference. Since
967 * the dropping of the reference could cause the port to disappear
968 * we postpone doing so when we are holding the space lock.
969 */
970
971 assert(space->is_active);
972 assert(right < MACH_PORT_RIGHT_NUMBER);
973
974 /* Rights-specific restrictions and operations. */
975
976 switch (right) {
977 case MACH_PORT_RIGHT_PORT_SET: {
978 ipc_pset_t pset;
979
980 if ((bits & MACH_PORT_TYPE_PORT_SET) == 0)
981 goto invalid_right;
982
983 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_PORT_SET);
984 assert(IE_BITS_UREFS(bits) == 0);
985 assert(entry->ie_request == 0);
986
987 if (delta == 0)
988 goto success;
989
990 if (delta != -1)
991 goto invalid_value;
992
993 pset = (ipc_pset_t) entry->ie_object;
994 assert(pset != IPS_NULL);
995
996
997
998 entry->ie_object = IO_NULL;
999 ipc_entry_dealloc(space, name, entry);
1000
1001
1002 ips_lock(pset);
1003 assert(ips_active(pset));
1004 is_write_unlock(space);
1005
1006 ipc_pset_destroy(pset); /* consumes ref, unlocks */
1007 break;
1008 }
1009
1010 case MACH_PORT_RIGHT_RECEIVE: {
1011 ipc_port_t port;
1012 ipc_port_t dnrequest = IP_NULL;
1013
1014 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1015 goto invalid_right;
1016
1017 if (delta == 0)
1018 goto success;
1019
1020 if (delta != -1)
1021 goto invalid_value;
1022
1023 port = (ipc_port_t) entry->ie_object;
1024 assert(port != IP_NULL);
1025
1026 /*
1027 * The port lock is needed for ipc_right_dncancel;
1028 * otherwise, we wouldn't have to take the lock
1029 * until just before dropping the space lock.
1030 */
1031
1032 ip_lock(port);
1033 assert(ip_active(port));
1034 assert(port->ip_receiver_name == name);
1035 assert(port->ip_receiver == space);
1036
1037 if (bits & MACH_PORT_TYPE_SEND) {
1038 assert(IE_BITS_TYPE(bits) ==
1039 MACH_PORT_TYPE_SEND_RECEIVE);
1040 assert(IE_BITS_UREFS(bits) > 0);
1041 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
1042 assert(port->ip_srights > 0);
1043
1044 /*
1045 * The remaining send right turns into a
1046 * dead name. Notice we don't decrement
1047 * ip_srights, generate a no-senders notif,
1048 * or use ipc_right_dncancel, because the
1049 * port is destroyed "first".
1050 */
1051 bits &= ~IE_BITS_TYPE_MASK;
1052 bits |= MACH_PORT_TYPE_DEAD_NAME;
1053 if (entry->ie_request) {
1054 entry->ie_request = 0;
1055 bits++;
1056 }
1057 entry->ie_bits = bits;
1058 entry->ie_object = IO_NULL;
1059 } else {
1060 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
1061 assert(IE_BITS_UREFS(bits) == 0);
1062
1063 dnrequest = ipc_right_dncancel_macro(space, port,
1064 name, entry);
1065 entry->ie_object = IO_NULL;
1066 ipc_entry_dealloc(space, name, entry);
1067 }
1068 is_write_unlock(space);
1069
1070 ipc_port_clear_receiver(port);
1071 ipc_port_destroy(port); /* consumes ref, unlocks */
1072
1073 if (dnrequest != IP_NULL)
1074 ipc_notify_port_deleted(dnrequest, name);
1075 break;
1076 }
1077
1078 case MACH_PORT_RIGHT_SEND_ONCE: {
1079 ipc_port_t port, dnrequest;
1080
1081 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0)
1082 goto invalid_right;
1083
1084 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1085 assert(IE_BITS_UREFS(bits) == 1);
1086
1087 port = (ipc_port_t) entry->ie_object;
1088 assert(port != IP_NULL);
1089
1090 if (ipc_right_check(space, port, name, entry)) {
1091 assert(!(entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE));
1092 goto invalid_right;
1093 }
1094 /* port is locked and active */
1095
1096 assert(port->ip_sorights > 0);
1097
1098 if ((delta > 0) || (delta < -1)) {
1099 ip_unlock(port);
1100 goto invalid_value;
1101 }
1102
1103 if (delta == 0) {
1104 ip_unlock(port);
1105 goto success;
1106 }
1107
1108 dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
1109 ip_unlock(port);
1110
1111 entry->ie_object = IO_NULL;
1112 ipc_entry_dealloc(space, name, entry);
1113
1114 is_write_unlock(space);
1115
1116 ipc_notify_send_once(port);
1117
1118 if (dnrequest != IP_NULL)
1119 ipc_notify_port_deleted(dnrequest, name);
1120 break;
1121 }
1122
1123 case MACH_PORT_RIGHT_DEAD_NAME: {
1124 mach_port_urefs_t urefs;
1125
1126 if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
1127 ipc_port_t port;
1128
1129 port = (ipc_port_t) entry->ie_object;
1130 assert(port != IP_NULL);
1131
1132 if (!ipc_right_check(space, port, name, entry)) {
1133 /* port is locked and active */
1134 ip_unlock(port);
1135 goto invalid_right;
1136 }
1137 bits = entry->ie_bits;
1138 } else if ((bits & MACH_PORT_TYPE_DEAD_NAME) == 0)
1139 goto invalid_right;
1140
1141 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1142 assert(IE_BITS_UREFS(bits) > 0);
1143 assert(entry->ie_object == IO_NULL);
1144 assert(entry->ie_request == 0);
1145
1146 urefs = IE_BITS_UREFS(bits);
1147 if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta))
1148 goto invalid_value;
1149 if (MACH_PORT_UREFS_OVERFLOW(urefs, delta))
1150 goto urefs_overflow;
1151
1152 if ((urefs + delta) == 0) {
1153 ipc_entry_dealloc(space, name, entry);
1154 }
1155 else
1156 entry->ie_bits = bits + delta;
1157
1158 is_write_unlock(space);
1159
1160 break;
1161 }
1162
1163 case MACH_PORT_RIGHT_SEND: {
1164 mach_port_urefs_t urefs;
1165 ipc_port_t port;
1166 ipc_port_t dnrequest = IP_NULL;
1167 ipc_port_t nsrequest = IP_NULL;
1168 mach_port_mscount_t mscount = 0;
1169
1170 if ((bits & MACH_PORT_TYPE_SEND) == 0)
1171 goto invalid_right;
1172
1173 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1174
1175 port = (ipc_port_t) entry->ie_object;
1176 assert(port != IP_NULL);
1177
1178 if (ipc_right_check(space, port, name, entry)) {
1179 assert((entry->ie_bits & MACH_PORT_TYPE_SEND) == 0);
1180 goto invalid_right;
1181 }
1182 /* port is locked and active */
1183
1184 assert(port->ip_srights > 0);
1185
1186 urefs = IE_BITS_UREFS(bits);
1187 if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta)) {
1188 ip_unlock(port);
1189 goto invalid_value;
1190 }
1191 if (MACH_PORT_UREFS_OVERFLOW(urefs+1, delta)) {
1192 ip_unlock(port);
1193 goto urefs_overflow;
1194 }
1195
1196 if ((urefs + delta) == 0) {
1197 if (--port->ip_srights == 0) {
1198 nsrequest = port->ip_nsrequest;
1199 if (nsrequest != IP_NULL) {
1200 port->ip_nsrequest = IP_NULL;
1201 mscount = port->ip_mscount;
1202 }
1203 }
1204
1205 if (bits & MACH_PORT_TYPE_RECEIVE) {
1206 assert(port->ip_receiver_name == name);
1207 assert(port->ip_receiver == space);
1208 assert(IE_BITS_TYPE(bits) ==
1209 MACH_PORT_TYPE_SEND_RECEIVE);
1210
1211 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|
1212 MACH_PORT_TYPE_SEND);
1213 } else {
1214 assert(IE_BITS_TYPE(bits) ==
1215 MACH_PORT_TYPE_SEND);
1216
1217 dnrequest = ipc_right_dncancel_macro(space, port,
1218 name, entry);
1219 ipc_hash_delete(space, (ipc_object_t) port,
1220 name, entry);
1221
1222 ip_release(port);
1223
1224 entry->ie_object = IO_NULL;
1225 ipc_entry_dealloc(space, name, entry);
1226 }
1227 } else
1228 entry->ie_bits = bits + delta;
1229
1230 /* even if dropped a ref, port is active */
1231 ip_unlock(port);
1232 is_write_unlock(space);
1233
1234 if (nsrequest != IP_NULL)
1235 ipc_notify_no_senders(nsrequest, mscount);
1236
1237 if (dnrequest != IP_NULL)
1238 ipc_notify_port_deleted(dnrequest, name);
1239 break;
1240 }
1241
1242 default:
1243 panic("ipc_right_delta: strange right");
1244 }
1245
1246 return KERN_SUCCESS;
1247
1248 success:
1249 is_write_unlock(space);
1250 return KERN_SUCCESS;
1251
1252 invalid_right:
1253 is_write_unlock(space);
1254 return KERN_INVALID_RIGHT;
1255
1256 invalid_value:
1257 is_write_unlock(space);
1258 return KERN_INVALID_VALUE;
1259
1260 urefs_overflow:
1261 is_write_unlock(space);
1262 return KERN_UREFS_OVERFLOW;
1263 }
1264
1265 /*
1266 * Routine: ipc_right_info
1267 * Purpose:
1268 * Retrieves information about the right.
1269 * Conditions:
1270 * The space is write-locked, and is unlocked upon return
1271 * if the call is unsuccessful. The space must be active.
1272 * Returns:
1273 * KERN_SUCCESS Retrieved info; space still locked.
1274 */
1275
1276 kern_return_t
1277 ipc_right_info(
1278 ipc_space_t space,
1279 mach_port_name_t name,
1280 ipc_entry_t entry,
1281 mach_port_type_t *typep,
1282 mach_port_urefs_t *urefsp)
1283 {
1284 ipc_entry_bits_t bits;
1285 mach_port_type_t type;
1286 ipc_port_request_index_t request;
1287
1288 bits = entry->ie_bits;
1289
1290 if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
1291 ipc_port_t port = (ipc_port_t) entry->ie_object;
1292
1293 if (ipc_right_check(space, port, name, entry)) {
1294 bits = entry->ie_bits;
1295 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1296 } else
1297 ip_unlock(port);
1298 }
1299
1300 type = IE_BITS_TYPE(bits);
1301 request = entry->ie_request;
1302
1303 if (request != 0)
1304 type |= MACH_PORT_TYPE_DNREQUEST;
1305
1306 *typep = type;
1307 *urefsp = IE_BITS_UREFS(bits);
1308 return KERN_SUCCESS;
1309 }
1310
1311 /*
1312 * Routine: ipc_right_copyin_check
1313 * Purpose:
1314 * Check if a subsequent ipc_right_copyin would succeed.
1315 * Conditions:
1316 * The space is locked (read or write) and active.
1317 */
1318
1319 boolean_t
1320 ipc_right_copyin_check(
1321 __assert_only ipc_space_t space,
1322 __unused mach_port_name_t name,
1323 ipc_entry_t entry,
1324 mach_msg_type_name_t msgt_name)
1325 {
1326 ipc_entry_bits_t bits;
1327
1328 bits= entry->ie_bits;
1329 assert(space->is_active);
1330
1331 switch (msgt_name) {
1332 case MACH_MSG_TYPE_MAKE_SEND:
1333 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
1334 case MACH_MSG_TYPE_MOVE_RECEIVE:
1335 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1336 return FALSE;
1337
1338 break;
1339
1340 case MACH_MSG_TYPE_COPY_SEND:
1341 case MACH_MSG_TYPE_MOVE_SEND:
1342 case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
1343 ipc_port_t port;
1344 boolean_t active;
1345
1346 if (bits & MACH_PORT_TYPE_DEAD_NAME)
1347 break;
1348
1349 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1350 return FALSE;
1351
1352 port = (ipc_port_t) entry->ie_object;
1353 assert(port != IP_NULL);
1354
1355 ip_lock(port);
1356 active = ip_active(port);
1357 ip_unlock(port);
1358
1359 if (!active) {
1360 break;
1361 }
1362
1363 if (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE) {
1364 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0)
1365 return FALSE;
1366 } else {
1367 if ((bits & MACH_PORT_TYPE_SEND) == 0)
1368 return FALSE;
1369 }
1370
1371 break;
1372 }
1373
1374 default:
1375 panic("ipc_right_copyin_check: strange rights");
1376 }
1377
1378 return TRUE;
1379 }
1380
1381 /*
1382 * Routine: ipc_right_copyin
1383 * Purpose:
1384 * Copyin a capability from a space.
1385 * If successful, the caller gets a ref
1386 * for the resulting object, unless it is IO_DEAD,
1387 * and possibly a send-once right which should
1388 * be used in a port-deleted notification.
1389 *
1390 * If deadok is not TRUE, the copyin operation
1391 * will fail instead of producing IO_DEAD.
1392 *
1393 * The entry is never deallocated (except
1394 * when KERN_INVALID_NAME), so the caller
1395 * should deallocate the entry if its type
1396 * is MACH_PORT_TYPE_NONE.
1397 * Conditions:
1398 * The space is write-locked and active.
1399 * Returns:
1400 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1401 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1402 */
1403
1404 kern_return_t
1405 ipc_right_copyin(
1406 ipc_space_t space,
1407 mach_port_name_t name,
1408 ipc_entry_t entry,
1409 mach_msg_type_name_t msgt_name,
1410 boolean_t deadok,
1411 ipc_object_t *objectp,
1412 ipc_port_t *sorightp)
1413 {
1414 ipc_entry_bits_t bits;
1415
1416 bits = entry->ie_bits;
1417
1418 assert(space->is_active);
1419
1420 switch (msgt_name) {
1421 case MACH_MSG_TYPE_MAKE_SEND: {
1422 ipc_port_t port;
1423
1424 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1425 goto invalid_right;
1426
1427 port = (ipc_port_t) entry->ie_object;
1428 assert(port != IP_NULL);
1429
1430 ip_lock(port);
1431 assert(ip_active(port));
1432 assert(port->ip_receiver_name == name);
1433 assert(port->ip_receiver == space);
1434
1435 port->ip_mscount++;
1436 port->ip_srights++;
1437 ip_reference(port);
1438 ip_unlock(port);
1439
1440 *objectp = (ipc_object_t) port;
1441 *sorightp = IP_NULL;
1442 break;
1443 }
1444
1445 case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
1446 ipc_port_t port;
1447
1448 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1449 goto invalid_right;
1450
1451 port = (ipc_port_t) entry->ie_object;
1452 assert(port != IP_NULL);
1453
1454 ip_lock(port);
1455 assert(ip_active(port));
1456 assert(port->ip_receiver_name == name);
1457 assert(port->ip_receiver == space);
1458
1459 port->ip_sorights++;
1460 ip_reference(port);
1461 ip_unlock(port);
1462
1463 *objectp = (ipc_object_t) port;
1464 *sorightp = IP_NULL;
1465 break;
1466 }
1467
1468 case MACH_MSG_TYPE_MOVE_RECEIVE: {
1469 ipc_port_t port;
1470 ipc_port_t dnrequest = IP_NULL;
1471
1472 if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1473 goto invalid_right;
1474
1475 port = (ipc_port_t) entry->ie_object;
1476 assert(port != IP_NULL);
1477
1478 ip_lock(port);
1479 assert(ip_active(port));
1480 assert(port->ip_receiver_name == name);
1481 assert(port->ip_receiver == space);
1482
1483 if (bits & MACH_PORT_TYPE_SEND) {
1484 assert(IE_BITS_TYPE(bits) ==
1485 MACH_PORT_TYPE_SEND_RECEIVE);
1486 assert(IE_BITS_UREFS(bits) > 0);
1487 assert(port->ip_srights > 0);
1488
1489 ipc_hash_insert(space, (ipc_object_t) port,
1490 name, entry);
1491 ip_reference(port);
1492 } else {
1493 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
1494 assert(IE_BITS_UREFS(bits) == 0);
1495
1496 dnrequest = ipc_right_dncancel_macro(space, port,
1497 name, entry);
1498 entry->ie_object = IO_NULL;
1499 }
1500 entry->ie_bits = bits &~ MACH_PORT_TYPE_RECEIVE;
1501
1502 ipc_port_clear_receiver(port);
1503
1504 port->ip_receiver_name = MACH_PORT_NULL;
1505 port->ip_destination = IP_NULL;
1506 ip_unlock(port);
1507
1508 *objectp = (ipc_object_t) port;
1509 *sorightp = dnrequest;
1510 break;
1511 }
1512
1513 case MACH_MSG_TYPE_COPY_SEND: {
1514 ipc_port_t port;
1515
1516 if (bits & MACH_PORT_TYPE_DEAD_NAME)
1517 goto copy_dead;
1518
1519 /* allow for dead send-once rights */
1520
1521 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1522 goto invalid_right;
1523
1524 assert(IE_BITS_UREFS(bits) > 0);
1525
1526 port = (ipc_port_t) entry->ie_object;
1527 assert(port != IP_NULL);
1528
1529 if (ipc_right_check(space, port, name, entry)) {
1530 bits = entry->ie_bits;
1531 goto copy_dead;
1532 }
1533 /* port is locked and active */
1534
1535 if ((bits & MACH_PORT_TYPE_SEND) == 0) {
1536 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1537 assert(port->ip_sorights > 0);
1538
1539 ip_unlock(port);
1540 goto invalid_right;
1541 }
1542
1543 assert(port->ip_srights > 0);
1544
1545 port->ip_srights++;
1546 ip_reference(port);
1547 ip_unlock(port);
1548
1549 *objectp = (ipc_object_t) port;
1550 *sorightp = IP_NULL;
1551 break;
1552 }
1553
1554 case MACH_MSG_TYPE_MOVE_SEND: {
1555 ipc_port_t port;
1556 ipc_port_t dnrequest = IP_NULL;
1557
1558 if (bits & MACH_PORT_TYPE_DEAD_NAME)
1559 goto move_dead;
1560
1561 /* allow for dead send-once rights */
1562
1563 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1564 goto invalid_right;
1565
1566 assert(IE_BITS_UREFS(bits) > 0);
1567
1568 port = (ipc_port_t) entry->ie_object;
1569 assert(port != IP_NULL);
1570
1571 if (ipc_right_check(space, port, name, entry)) {
1572 bits = entry->ie_bits;
1573 goto move_dead;
1574 }
1575 /* port is locked and active */
1576
1577 if ((bits & MACH_PORT_TYPE_SEND) == 0) {
1578 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1579 assert(port->ip_sorights > 0);
1580
1581 ip_unlock(port);
1582 goto invalid_right;
1583 }
1584
1585 assert(port->ip_srights > 0);
1586
1587 if (IE_BITS_UREFS(bits) == 1) {
1588 if (bits & MACH_PORT_TYPE_RECEIVE) {
1589 assert(port->ip_receiver_name == name);
1590 assert(port->ip_receiver == space);
1591 assert(IE_BITS_TYPE(bits) ==
1592 MACH_PORT_TYPE_SEND_RECEIVE);
1593
1594 ip_reference(port);
1595 } else {
1596 assert(IE_BITS_TYPE(bits) ==
1597 MACH_PORT_TYPE_SEND);
1598
1599 dnrequest = ipc_right_dncancel_macro(space, port,
1600 name, entry);
1601 ipc_hash_delete(space, (ipc_object_t) port,
1602 name, entry);
1603 entry->ie_object = IO_NULL;
1604 }
1605 entry->ie_bits = bits &~
1606 (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND);
1607 } else {
1608 port->ip_srights++;
1609 ip_reference(port);
1610 entry->ie_bits = bits-1; /* decrement urefs */
1611 }
1612
1613 ip_unlock(port);
1614
1615 *objectp = (ipc_object_t) port;
1616 *sorightp = dnrequest;
1617 break;
1618 }
1619
1620 case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
1621 ipc_port_t port;
1622 ipc_port_t dnrequest;
1623
1624 if (bits & MACH_PORT_TYPE_DEAD_NAME)
1625 goto move_dead;
1626
1627 /* allow for dead send rights */
1628
1629 if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1630 goto invalid_right;
1631
1632 assert(IE_BITS_UREFS(bits) > 0);
1633
1634 port = (ipc_port_t) entry->ie_object;
1635 assert(port != IP_NULL);
1636
1637 if (ipc_right_check(space, port, name, entry)) {
1638 bits = entry->ie_bits;
1639 goto move_dead;
1640 }
1641 /* port is locked and active */
1642
1643 if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) {
1644 assert(bits & MACH_PORT_TYPE_SEND);
1645 assert(port->ip_srights > 0);
1646
1647 ip_unlock(port);
1648 goto invalid_right;
1649 }
1650
1651 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1652 assert(IE_BITS_UREFS(bits) == 1);
1653 assert(port->ip_sorights > 0);
1654
1655 dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
1656 ip_unlock(port);
1657
1658 entry->ie_object = IO_NULL;
1659 entry->ie_bits = bits &~
1660 (IE_BITS_UREFS_MASK | MACH_PORT_TYPE_SEND_ONCE);
1661
1662 *objectp = (ipc_object_t) port;
1663 *sorightp = dnrequest;
1664 break;
1665 }
1666
1667 default:
1668 invalid_right:
1669 return KERN_INVALID_RIGHT;
1670 }
1671
1672 return KERN_SUCCESS;
1673
1674 copy_dead:
1675 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1676 assert(IE_BITS_UREFS(bits) > 0);
1677 assert(entry->ie_request == 0);
1678 assert(entry->ie_object == 0);
1679
1680 if (!deadok)
1681 goto invalid_right;
1682
1683 *objectp = IO_DEAD;
1684 *sorightp = IP_NULL;
1685 return KERN_SUCCESS;
1686
1687 move_dead:
1688 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1689 assert(IE_BITS_UREFS(bits) > 0);
1690 assert(entry->ie_request == 0);
1691 assert(entry->ie_object == 0);
1692
1693 if (!deadok)
1694 goto invalid_right;
1695
1696 if (IE_BITS_UREFS(bits) == 1) {
1697 bits &= ~MACH_PORT_TYPE_DEAD_NAME;
1698 }
1699 entry->ie_bits = bits-1; /* decrement urefs */
1700
1701 *objectp = IO_DEAD;
1702 *sorightp = IP_NULL;
1703 return KERN_SUCCESS;
1704
1705 }
1706
1707 /*
1708 * Routine: ipc_right_copyin_undo
1709 * Purpose:
1710 * Undoes the effects of an ipc_right_copyin
1711 * of a send/send-once right that is dead.
1712 * (Object is either IO_DEAD or a dead port.)
1713 * Conditions:
1714 * The space is write-locked and active.
1715 */
1716
1717 void
1718 ipc_right_copyin_undo(
1719 ipc_space_t space,
1720 mach_port_name_t name,
1721 ipc_entry_t entry,
1722 mach_msg_type_name_t msgt_name,
1723 ipc_object_t object,
1724 ipc_port_t soright)
1725 {
1726 ipc_entry_bits_t bits;
1727
1728 bits = entry->ie_bits;
1729
1730 assert(space->is_active);
1731
1732 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1733 (msgt_name == MACH_MSG_TYPE_COPY_SEND) ||
1734 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
1735
1736 if (soright != IP_NULL) {
1737 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1738 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
1739 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
1740 assert(object != IO_DEAD);
1741
1742 entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) |
1743 MACH_PORT_TYPE_DEAD_NAME | 2);
1744
1745 } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE) {
1746 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1747 (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
1748
1749 entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) |
1750 MACH_PORT_TYPE_DEAD_NAME | 1);
1751 } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME) {
1752 assert(object == IO_DEAD);
1753 assert(IE_BITS_UREFS(bits) > 0);
1754
1755 if (msgt_name != MACH_MSG_TYPE_COPY_SEND) {
1756 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
1757 entry->ie_bits = bits+1; /* increment urefs */
1758 }
1759 } else {
1760 assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1761 (msgt_name == MACH_MSG_TYPE_COPY_SEND));
1762 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
1763 assert(object != IO_DEAD);
1764 assert(entry->ie_object == object);
1765 assert(IE_BITS_UREFS(bits) > 0);
1766
1767 if (msgt_name != MACH_MSG_TYPE_COPY_SEND) {
1768 assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX-1);
1769 entry->ie_bits = bits+1; /* increment urefs */
1770 }
1771
1772 /*
1773 * May as well convert the entry to a dead name.
1774 * (Or if it is a compat entry, destroy it.)
1775 */
1776
1777 (void) ipc_right_check(space, (ipc_port_t) object,
1778 name, entry);
1779 /* object is dead so it is not locked */
1780 }
1781
1782 /* release the reference acquired by copyin */
1783
1784 if (object != IO_DEAD)
1785 ipc_object_release(object);
1786 }
1787
1788 /*
1789 * Routine: ipc_right_copyin_two
1790 * Purpose:
1791 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
1792 * and deadok == FALSE, except that this moves two
1793 * send rights at once.
1794 * Conditions:
1795 * The space is write-locked and active.
1796 * The object is returned with two refs/send rights.
1797 * Returns:
1798 * KERN_SUCCESS Acquired an object.
1799 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1800 */
1801
1802 kern_return_t
1803 ipc_right_copyin_two(
1804 ipc_space_t space,
1805 mach_port_name_t name,
1806 ipc_entry_t entry,
1807 ipc_object_t *objectp,
1808 ipc_port_t *sorightp)
1809 {
1810 ipc_entry_bits_t bits;
1811 mach_port_urefs_t urefs;
1812 ipc_port_t port;
1813 ipc_port_t dnrequest = IP_NULL;
1814
1815 assert(space->is_active);
1816
1817 bits = entry->ie_bits;
1818
1819 if ((bits & MACH_PORT_TYPE_SEND) == 0)
1820 goto invalid_right;
1821
1822 urefs = IE_BITS_UREFS(bits);
1823 if (urefs < 2)
1824 goto invalid_right;
1825
1826 port = (ipc_port_t) entry->ie_object;
1827 assert(port != IP_NULL);
1828
1829 if (ipc_right_check(space, port, name, entry)) {
1830 goto invalid_right;
1831 }
1832 /* port is locked and active */
1833
1834 assert(port->ip_srights > 0);
1835
1836 if (urefs == 2) {
1837 if (bits & MACH_PORT_TYPE_RECEIVE) {
1838 assert(port->ip_receiver_name == name);
1839 assert(port->ip_receiver == space);
1840 assert(IE_BITS_TYPE(bits) ==
1841 MACH_PORT_TYPE_SEND_RECEIVE);
1842
1843 port->ip_srights++;
1844 ip_reference(port);
1845 ip_reference(port);
1846 } else {
1847 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
1848
1849 dnrequest = ipc_right_dncancel_macro(space, port,
1850 name, entry);
1851
1852 port->ip_srights++;
1853 ip_reference(port);
1854 ipc_hash_delete(space, (ipc_object_t) port,
1855 name, entry);
1856 entry->ie_object = IO_NULL;
1857 }
1858 entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND);
1859 } else {
1860 port->ip_srights += 2;
1861 ip_reference(port);
1862 ip_reference(port);
1863 entry->ie_bits = bits-2; /* decrement urefs */
1864 }
1865 ip_unlock(port);
1866
1867 *objectp = (ipc_object_t) port;
1868 *sorightp = dnrequest;
1869 return KERN_SUCCESS;
1870
1871 invalid_right:
1872 return KERN_INVALID_RIGHT;
1873 }
1874
1875 /*
1876 * Routine: ipc_right_copyout
1877 * Purpose:
1878 * Copyout a capability to a space.
1879 * If successful, consumes a ref for the object.
1880 *
1881 * Always succeeds when given a newly-allocated entry,
1882 * because user-reference overflow isn't a possibility.
1883 *
1884 * If copying out the object would cause the user-reference
1885 * count in the entry to overflow, and overflow is TRUE,
1886 * then instead the user-reference count is left pegged
1887 * to its maximum value and the copyout succeeds anyway.
1888 * Conditions:
1889 * The space is write-locked and active.
1890 * The object is locked and active.
1891 * The object is unlocked; the space isn't.
1892 * Returns:
1893 * KERN_SUCCESS Copied out capability.
1894 * KERN_UREFS_OVERFLOW User-refs would overflow;
1895 * guaranteed not to happen with a fresh entry
1896 * or if overflow=TRUE was specified.
1897 */
1898
1899 kern_return_t
1900 ipc_right_copyout(
1901 ipc_space_t space,
1902 mach_port_name_t name,
1903 ipc_entry_t entry,
1904 mach_msg_type_name_t msgt_name,
1905 boolean_t overflow,
1906 ipc_object_t object)
1907 {
1908 ipc_entry_bits_t bits;
1909 ipc_port_t port;
1910
1911 bits = entry->ie_bits;
1912
1913 assert(IO_VALID(object));
1914 assert(io_otype(object) == IOT_PORT);
1915 assert(io_active(object));
1916 assert(entry->ie_object == object);
1917
1918 port = (ipc_port_t) object;
1919
1920 switch (msgt_name) {
1921 case MACH_MSG_TYPE_PORT_SEND_ONCE:
1922
1923 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
1924 assert(port->ip_sorights > 0);
1925
1926 /* transfer send-once right and ref to entry */
1927 ip_unlock(port);
1928
1929 entry->ie_bits = bits | (MACH_PORT_TYPE_SEND_ONCE | 1);
1930 break;
1931
1932 case MACH_MSG_TYPE_PORT_SEND:
1933 assert(port->ip_srights > 0);
1934
1935 if (bits & MACH_PORT_TYPE_SEND) {
1936 mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
1937
1938 assert(port->ip_srights > 1);
1939 assert(urefs > 0);
1940 assert(urefs < MACH_PORT_UREFS_MAX);
1941
1942 if (urefs+1 == MACH_PORT_UREFS_MAX) {
1943 if (overflow) {
1944 /* leave urefs pegged to maximum */
1945
1946 port->ip_srights--;
1947 ip_release(port);
1948 ip_unlock(port);
1949 return KERN_SUCCESS;
1950 }
1951
1952 ip_unlock(port);
1953 return KERN_UREFS_OVERFLOW;
1954 }
1955
1956 port->ip_srights--;
1957 ip_release(port);
1958 ip_unlock(port);
1959 } else if (bits & MACH_PORT_TYPE_RECEIVE) {
1960 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
1961 assert(IE_BITS_UREFS(bits) == 0);
1962
1963 /* transfer send right to entry */
1964 ip_release(port);
1965 ip_unlock(port);
1966 } else {
1967 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
1968 assert(IE_BITS_UREFS(bits) == 0);
1969
1970 /* transfer send right and ref to entry */
1971 ip_unlock(port);
1972
1973 /* entry is locked holding ref, so can use port */
1974
1975 ipc_hash_insert(space, (ipc_object_t) port,
1976 name, entry);
1977 }
1978
1979 entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1;
1980 break;
1981
1982 case MACH_MSG_TYPE_PORT_RECEIVE: {
1983 ipc_port_t dest;
1984
1985 assert(port->ip_mscount == 0);
1986 assert(port->ip_receiver_name == MACH_PORT_NULL);
1987 dest = port->ip_destination;
1988
1989 port->ip_receiver_name = name;
1990 port->ip_receiver = space;
1991
1992 assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
1993
1994 if (bits & MACH_PORT_TYPE_SEND) {
1995 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
1996 assert(IE_BITS_UREFS(bits) > 0);
1997 assert(port->ip_srights > 0);
1998
1999 ip_release(port);
2000 ip_unlock(port);
2001
2002 /* entry is locked holding ref, so can use port */
2003
2004 ipc_hash_delete(space, (ipc_object_t) port,
2005 name, entry);
2006 } else {
2007 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
2008 assert(IE_BITS_UREFS(bits) == 0);
2009
2010 /* transfer ref to entry */
2011 ip_unlock(port);
2012 }
2013 entry->ie_bits = bits | MACH_PORT_TYPE_RECEIVE;
2014
2015 if (dest != IP_NULL)
2016 ipc_port_release(dest);
2017 break;
2018 }
2019
2020 default:
2021 panic("ipc_right_copyout: strange rights");
2022 }
2023
2024 return KERN_SUCCESS;
2025 }
2026
2027 /*
2028 * Routine: ipc_right_rename
2029 * Purpose:
2030 * Transfer an entry from one name to another.
2031 * The old entry is deallocated.
2032 * Conditions:
2033 * The space is write-locked and active.
2034 * The new entry is unused. Upon return,
2035 * the space is unlocked.
2036 * Returns:
2037 * KERN_SUCCESS Moved entry to new name.
2038 */
2039
2040 kern_return_t
2041 ipc_right_rename(
2042 ipc_space_t space,
2043 mach_port_name_t oname,
2044 ipc_entry_t oentry,
2045 mach_port_name_t nname,
2046 ipc_entry_t nentry)
2047 {
2048 ipc_port_request_index_t request = oentry->ie_request;
2049 ipc_entry_bits_t bits = oentry->ie_bits;
2050 ipc_object_t object = oentry->ie_object;
2051
2052 assert(space->is_active);
2053 assert(oname != nname);
2054
2055 /*
2056 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2057 * if the port is dead. (This would foil ipc_port_destroy.)
2058 * Instead we should fail because oentry shouldn't exist.
2059 * Note IE_BITS_COMPAT implies ie_request != 0.
2060 */
2061
2062 if (request != 0) {
2063 ipc_port_t port;
2064
2065 assert(bits & MACH_PORT_TYPE_PORT_RIGHTS);
2066 port = (ipc_port_t) object;
2067 assert(port != IP_NULL);
2068
2069 if (ipc_right_check(space, port, oname, oentry)) {
2070 request = 0;
2071 object = IO_NULL;
2072 bits = oentry->ie_bits;
2073 assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
2074 assert(oentry->ie_request == 0);
2075 } else {
2076 /* port is locked and active */
2077
2078 ipc_port_dnrename(port, request, oname, nname);
2079 ip_unlock(port);
2080 oentry->ie_request = 0;
2081 }
2082 }
2083
2084 /* initialize nentry before letting ipc_hash_insert see it */
2085
2086 assert((nentry->ie_bits & IE_BITS_RIGHT_MASK) == 0);
2087 nentry->ie_bits |= bits & IE_BITS_RIGHT_MASK;
2088 nentry->ie_request = request;
2089 nentry->ie_object = object;
2090
2091 switch (IE_BITS_TYPE(bits)) {
2092 case MACH_PORT_TYPE_SEND: {
2093 ipc_port_t port;
2094
2095 port = (ipc_port_t) object;
2096 assert(port != IP_NULL);
2097
2098 /* remember, there are no other share entries possible */
2099 /* or we can't do the rename. Therefore we do not need */
2100 /* to check the other subspaces */
2101 ipc_hash_delete(space, (ipc_object_t) port, oname, oentry);
2102 ipc_hash_insert(space, (ipc_object_t) port, nname, nentry);
2103 break;
2104 }
2105
2106 case MACH_PORT_TYPE_RECEIVE:
2107 case MACH_PORT_TYPE_SEND_RECEIVE: {
2108 ipc_port_t port;
2109
2110 port = (ipc_port_t) object;
2111 assert(port != IP_NULL);
2112
2113 ip_lock(port);
2114 assert(ip_active(port));
2115 assert(port->ip_receiver_name == oname);
2116 assert(port->ip_receiver == space);
2117
2118 port->ip_receiver_name = nname;
2119 ip_unlock(port);
2120 break;
2121 }
2122
2123 case MACH_PORT_TYPE_PORT_SET: {
2124 ipc_pset_t pset;
2125
2126 pset = (ipc_pset_t) object;
2127 assert(pset != IPS_NULL);
2128
2129 ips_lock(pset);
2130 assert(ips_active(pset));
2131 assert(pset->ips_local_name == oname);
2132
2133 pset->ips_local_name = nname;
2134 ips_unlock(pset);
2135 break;
2136 }
2137
2138 case MACH_PORT_TYPE_SEND_ONCE:
2139 case MACH_PORT_TYPE_DEAD_NAME:
2140 break;
2141
2142 default:
2143 panic("ipc_right_rename: strange rights");
2144 }
2145
2146 assert(oentry->ie_request == 0);
2147 oentry->ie_object = IO_NULL;
2148 ipc_entry_dealloc(space, oname, oentry);
2149 is_write_unlock(space);
2150
2151 return KERN_SUCCESS;
2152 }