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