|
|
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_port.h>
47: #include <ipc/ipc_pset.h>
48: #include <ipc/ipc_marequest.h>
49: #include <ipc/ipc_right.h>
50: #include <ipc/ipc_notify.h>
51:
52:
53:
54: /*
55: * Routine: ipc_right_lookup_write
56: * Purpose:
57: * Finds an entry in a space, given the name.
58: * Conditions:
59: * Nothing locked. If successful, the space is write-locked.
60: * Returns:
61: * KERN_SUCCESS Found an entry.
62: * KERN_INVALID_TASK The space is dead.
63: * KERN_INVALID_NAME Name doesn't exist in space.
64: */
65:
66: kern_return_t
67: ipc_right_lookup_write(
68: ipc_space_t space,
69: mach_port_t name,
70: ipc_entry_t *entryp)
71: {
72: ipc_entry_t entry;
73:
74: assert(space != IS_NULL);
75:
76: is_write_lock(space);
77:
78: if (!space->is_active) {
79: is_write_unlock(space);
80: return KERN_INVALID_TASK;
81: }
82:
83: if ((entry = ipc_entry_lookup(space, name)) == IE_NULL) {
84: is_write_unlock(space);
85: return KERN_INVALID_NAME;
86: }
87:
88: *entryp = entry;
89: return KERN_SUCCESS;
90: }
91:
92: /*
93: * Routine: ipc_right_reverse
94: * Purpose:
95: * Translate (space, object) -> (name, entry).
96: * Only finds send/receive rights.
97: * Returns TRUE if an entry is found; if so,
98: * the object is locked and active.
99: * Conditions:
100: * The space must be locked (read or write) and active.
101: * Nothing else locked.
102: */
103:
104: boolean_t
105: ipc_right_reverse(
106: ipc_space_t space,
107: ipc_object_t object,
108: mach_port_t *namep,
109: ipc_entry_t *entryp)
110: {
111: ipc_port_t port;
112: mach_port_t name;
113: ipc_entry_t entry;
114:
115: /* would switch on io_otype to handle multiple types of object */
116:
117: assert(space->is_active);
118: assert(io_otype(object) == IOT_PORT);
119:
120: port = (ipc_port_t) object;
121:
122: ip_lock(port);
123: if (!ip_active(port)) {
124: ip_unlock(port);
125:
126: return FALSE;
127: }
128:
129: if (port->ip_receiver == space) {
130: name = port->ip_receiver_name;
131: assert(name != MACH_PORT_NULL);
132:
133: entry = ipc_entry_lookup(space, name);
134:
135: assert(entry != IE_NULL);
136: assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
137: assert(port == (ipc_port_t) entry->ie_object);
138:
139: *namep = name;
140: *entryp = entry;
141: return TRUE;
142: }
143:
1.1.1.5 ! root 144: if ((*entryp = ipc_reverse_lookup(space, (ipc_object_t) port))) {
! 145: *namep = (*entryp)->ie_name;
1.1 root 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:
1.1.1.5 ! root 395: ipc_reverse_remove(space, (ipc_object_t) port);
1.1 root 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
1.1.1.5 ! root 426: * from the reverse mappings.
1.1 root 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)
1.1.1.5 ! root 612: ipc_reverse_remove(space, (ipc_object_t) port);
1.1 root 613:
614: ip_lock(port);
615:
616: if (!ip_active(port)) {
617: assert((type & MACH_PORT_TYPE_RECEIVE) == 0);
618:
619: ip_release(port);
620: ip_check_unlock(port);
621:
622: entry->ie_request = 0;
623: entry->ie_object = IO_NULL;
624: ipc_entry_dealloc(space, name, entry);
625: is_write_unlock(space);
626:
627: break;
628: }
629:
630: dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
631:
632: entry->ie_object = IO_NULL;
633: ipc_entry_dealloc(space, name, entry);
634: is_write_unlock(space);
635:
636: if (type & MACH_PORT_TYPE_SEND) {
637: assert(port->ip_srights > 0);
638: if (--port->ip_srights == 0) {
639: nsrequest = port->ip_nsrequest;
640: if (nsrequest != IP_NULL) {
641: port->ip_nsrequest = IP_NULL;
642: mscount = port->ip_mscount;
643: }
644: }
645: }
646:
647: if (type & MACH_PORT_TYPE_RECEIVE) {
648: assert(ip_active(port));
649: assert(port->ip_receiver == space);
650:
651: ipc_port_clear_receiver(port);
652: ipc_port_destroy(port); /* consumes our ref, unlocks */
653: } else if (type & MACH_PORT_TYPE_SEND_ONCE) {
654: assert(port->ip_sorights > 0);
655: ip_unlock(port);
656:
657: ipc_notify_send_once(port); /* consumes our ref */
658: } else {
659: assert(port->ip_receiver != space);
660:
661: ip_release(port);
662: ip_unlock(port);
663: }
664:
665: if (nsrequest != IP_NULL)
666: ipc_notify_no_senders(nsrequest, mscount);
667:
668: if (dnrequest != IP_NULL)
669: ipc_notify_port_deleted(dnrequest, name);
670: break;
671: }
672:
673: default:
674: #if MACH_ASSERT
675: assert(!"ipc_right_destroy: strange type");
676: #else
677: panic("ipc_right_destroy: strange type");
678: #endif
679: }
680:
681: return KERN_SUCCESS;
682: }
683:
684: /*
685: * Routine: ipc_right_dealloc
686: * Purpose:
687: * Releases a send/send-once/dead-name user ref.
688: * Like ipc_right_delta with a delta of -1,
689: * but looks at the entry to determine the right.
690: * Conditions:
691: * The space is write-locked, and is unlocked upon return.
692: * The space must be active.
693: * Returns:
694: * KERN_SUCCESS A user ref was released.
695: * KERN_INVALID_RIGHT Entry has wrong type.
696: */
697:
698: kern_return_t
1.1.1.4 root 699: ipc_right_dealloc(
700: ipc_space_t space,
701: mach_port_t name,
702: ipc_entry_t entry)
1.1 root 703: {
704: ipc_entry_bits_t bits = entry->ie_bits;
705: mach_port_type_t type = IE_BITS_TYPE(bits);
706:
707: assert(space->is_active);
708:
709: switch (type) {
710: case MACH_PORT_TYPE_DEAD_NAME: {
711: dead_name:
712:
713: assert(IE_BITS_UREFS(bits) > 0);
714: assert(entry->ie_request == 0);
715: assert(entry->ie_object == IO_NULL);
716: assert((bits & IE_BITS_MAREQUEST) == 0);
717:
718: if (IE_BITS_UREFS(bits) == 1)
719: ipc_entry_dealloc(space, name, entry);
720: else
721: entry->ie_bits = bits-1; /* decrement urefs */
722:
723: is_write_unlock(space);
724: break;
725: }
726:
727: case MACH_PORT_TYPE_SEND_ONCE: {
728: ipc_port_t port, dnrequest;
729:
730: assert(IE_BITS_UREFS(bits) == 1);
731: assert((bits & IE_BITS_MAREQUEST) == 0);
732:
733: port = (ipc_port_t) entry->ie_object;
734: assert(port != IP_NULL);
735:
736: if (ipc_right_check(space, port, name, entry)) {
737: bits = entry->ie_bits;
738: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
739: goto dead_name;
740: }
741: /* port is locked and active */
742:
743: assert(port->ip_sorights > 0);
744:
745: dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
746: ip_unlock(port);
747:
748: entry->ie_object = IO_NULL;
749: ipc_entry_dealloc(space, name, entry);
750: is_write_unlock(space);
751:
752: ipc_notify_send_once(port);
753:
754: if (dnrequest != IP_NULL)
755: ipc_notify_port_deleted(dnrequest, name);
756: break;
757: }
758:
759: case MACH_PORT_TYPE_SEND: {
760: ipc_port_t port;
761: ipc_port_t dnrequest = IP_NULL;
762: ipc_port_t nsrequest = IP_NULL;
763: mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
764:
765: assert(IE_BITS_UREFS(bits) > 0);
766:
767: port = (ipc_port_t) entry->ie_object;
768: assert(port != IP_NULL);
769:
770: if (ipc_right_check(space, port, name, entry)) {
771: bits = entry->ie_bits;
772: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
773: goto dead_name;
774: }
775: /* port is locked and active */
776:
777: assert(port->ip_srights > 0);
778:
779: if (IE_BITS_UREFS(bits) == 1) {
780: if (--port->ip_srights == 0) {
781: nsrequest = port->ip_nsrequest;
782: if (nsrequest != IP_NULL) {
783: port->ip_nsrequest = IP_NULL;
784: mscount = port->ip_mscount;
785: }
786: }
787:
788: dnrequest = ipc_right_dncancel_macro(space, port,
789: name, entry);
790:
1.1.1.5 ! root 791: ipc_reverse_remove(space, (ipc_object_t) port);
1.1 root 792:
793: if (bits & IE_BITS_MAREQUEST)
794: ipc_marequest_cancel(space, name);
795:
796: ip_release(port);
797: entry->ie_object = IO_NULL;
798: ipc_entry_dealloc(space, name, entry);
799: } else
800: entry->ie_bits = bits-1; /* decrement urefs */
801:
802: ip_unlock(port); /* even if dropped a ref, port is active */
803: is_write_unlock(space);
804:
805: if (nsrequest != IP_NULL)
806: ipc_notify_no_senders(nsrequest, mscount);
807:
808: if (dnrequest != IP_NULL)
809: ipc_notify_port_deleted(dnrequest, name);
810: break;
811: }
812:
813: case MACH_PORT_TYPE_SEND_RECEIVE: {
814: ipc_port_t port;
815: ipc_port_t nsrequest = IP_NULL;
816: mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
817:
818: assert(IE_BITS_UREFS(bits) > 0);
819:
820: port = (ipc_port_t) entry->ie_object;
821: assert(port != IP_NULL);
822:
823: ip_lock(port);
824: assert(ip_active(port));
825: assert(port->ip_receiver_name == name);
826: assert(port->ip_receiver == space);
827: assert(port->ip_srights > 0);
828:
829: if (IE_BITS_UREFS(bits) == 1) {
830: if (--port->ip_srights == 0) {
831: nsrequest = port->ip_nsrequest;
832: if (nsrequest != IP_NULL) {
833: port->ip_nsrequest = IP_NULL;
834: mscount = port->ip_mscount;
835: }
836: }
837:
838: entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|
839: MACH_PORT_TYPE_SEND);
840: } else
841: entry->ie_bits = bits-1; /* decrement urefs */
842:
843: ip_unlock(port);
844: is_write_unlock(space);
845:
846: if (nsrequest != IP_NULL)
847: ipc_notify_no_senders(nsrequest, mscount);
848: break;
849: }
850:
851: default:
852: is_write_unlock(space);
853: return KERN_INVALID_RIGHT;
854: }
855:
856: return KERN_SUCCESS;
857: }
858:
859: /*
860: * Routine: ipc_right_delta
861: * Purpose:
862: * Modifies the user-reference count for a right.
863: * May deallocate the right, if the count goes to zero.
864: * Conditions:
865: * The space is write-locked, and is unlocked upon return.
866: * The space must be active.
867: * Returns:
868: * KERN_SUCCESS Count was modified.
869: * KERN_INVALID_RIGHT Entry has wrong type.
870: * KERN_INVALID_VALUE Bad delta for the right.
871: * KERN_UREFS_OVERFLOW OK delta, except would overflow.
872: */
873:
874: kern_return_t
1.1.1.4 root 875: ipc_right_delta(
876: ipc_space_t space,
877: mach_port_t name,
878: ipc_entry_t entry,
879: mach_port_right_t right,
880: mach_port_delta_t delta)
1.1 root 881: {
882: ipc_entry_bits_t bits = entry->ie_bits;
883:
884: assert(space->is_active);
885: assert(right < MACH_PORT_RIGHT_NUMBER);
886:
887: /* Rights-specific restrictions and operations. */
888:
889: switch (right) {
890: case MACH_PORT_RIGHT_PORT_SET: {
891: ipc_pset_t pset;
892:
893: if ((bits & MACH_PORT_TYPE_PORT_SET) == 0)
894: goto invalid_right;
895:
896: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_PORT_SET);
897: assert(IE_BITS_UREFS(bits) == 0);
898: assert((bits & IE_BITS_MAREQUEST) == 0);
899: assert(entry->ie_request == 0);
900:
901: if (delta == 0)
902: goto success;
903:
904: if (delta != -1)
905: goto invalid_value;
906:
907: pset = (ipc_pset_t) entry->ie_object;
908: assert(pset != IPS_NULL);
909:
910: entry->ie_object = IO_NULL;
911: ipc_entry_dealloc(space, name, entry);
912:
913: ips_lock(pset);
914: assert(ips_active(pset));
915: is_write_unlock(space);
916:
917: ipc_pset_destroy(pset); /* consumes ref, unlocks */
918: break;
919: }
920:
921: case MACH_PORT_RIGHT_RECEIVE: {
922: ipc_port_t port;
923: ipc_port_t dnrequest = IP_NULL;
924:
925: if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
926: goto invalid_right;
927:
928: if (delta == 0)
929: goto success;
930:
931: if (delta != -1)
932: goto invalid_value;
933:
934: if (bits & IE_BITS_MAREQUEST) {
935: bits &= ~IE_BITS_MAREQUEST;
936:
937: ipc_marequest_cancel(space, name);
938: }
939:
940: port = (ipc_port_t) entry->ie_object;
941: assert(port != IP_NULL);
942:
943: /*
944: * The port lock is needed for ipc_right_dncancel;
945: * otherwise, we wouldn't have to take the lock
946: * until just before dropping the space lock.
947: */
948:
949: ip_lock(port);
950: assert(ip_active(port));
951: assert(port->ip_receiver_name == name);
952: assert(port->ip_receiver == space);
953:
954: if (bits & MACH_PORT_TYPE_SEND) {
955: assert(IE_BITS_TYPE(bits) ==
956: MACH_PORT_TYPE_SEND_RECEIVE);
957: assert(IE_BITS_UREFS(bits) > 0);
958: assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
959: assert(port->ip_srights > 0);
960:
961: /*
962: * The remaining send right turns into a
963: * dead name. Notice we don't decrement
964: * ip_srights, generate a no-senders notif,
965: * or use ipc_right_dncancel, because the
966: * port is destroyed "first".
967: */
968:
969: bits &= ~IE_BITS_TYPE_MASK;
970: bits |= MACH_PORT_TYPE_DEAD_NAME;
971:
972: if (entry->ie_request != 0) {
973: entry->ie_request = 0;
974: bits++; /* increment urefs */
975: }
976:
977: entry->ie_bits = bits;
978: entry->ie_object = IO_NULL;
979: } else {
980: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
981: assert(IE_BITS_UREFS(bits) == 0);
982:
983: dnrequest = ipc_right_dncancel_macro(space, port,
984: name, entry);
985:
986: entry->ie_object = IO_NULL;
987: ipc_entry_dealloc(space, name, entry);
988: }
989: is_write_unlock(space);
990:
991: ipc_port_clear_receiver(port);
992: ipc_port_destroy(port); /* consumes ref, unlocks */
993:
994: if (dnrequest != IP_NULL)
995: ipc_notify_port_deleted(dnrequest, name);
996: break;
997: }
998:
999: case MACH_PORT_RIGHT_SEND_ONCE: {
1000: ipc_port_t port, dnrequest;
1001:
1002: if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0)
1003: goto invalid_right;
1004:
1005: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1006: assert(IE_BITS_UREFS(bits) == 1);
1007: assert((bits & IE_BITS_MAREQUEST) == 0);
1008:
1009: if ((delta > 0) || (delta < -1))
1010: goto invalid_value;
1011:
1012: port = (ipc_port_t) entry->ie_object;
1013: assert(port != IP_NULL);
1014:
1015: if (ipc_right_check(space, port, name, entry)) {
1016: assert(!(entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE));
1017: goto invalid_right;
1018: }
1019: /* port is locked and active */
1020:
1021: assert(port->ip_sorights > 0);
1022:
1023: if (delta == 0) {
1024: ip_unlock(port);
1025: goto success;
1026: }
1027:
1028: dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
1029: ip_unlock(port);
1030:
1031: entry->ie_object = IO_NULL;
1032: ipc_entry_dealloc(space, name, entry);
1033: is_write_unlock(space);
1034:
1035: ipc_notify_send_once(port);
1036:
1037: if (dnrequest != IP_NULL)
1038: ipc_notify_port_deleted(dnrequest, name);
1039: break;
1040: }
1041:
1042: case MACH_PORT_RIGHT_DEAD_NAME: {
1043: mach_port_urefs_t urefs;
1044:
1045: if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
1046: ipc_port_t port;
1047:
1048: port = (ipc_port_t) entry->ie_object;
1049: assert(port != IP_NULL);
1050:
1051: if (!ipc_right_check(space, port, name, entry)) {
1052: /* port is locked and active */
1053: ip_unlock(port);
1054: goto invalid_right;
1055: }
1056:
1057: bits = entry->ie_bits;
1058: } else if ((bits & MACH_PORT_TYPE_DEAD_NAME) == 0)
1059: goto invalid_right;
1060:
1061: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1062: assert(IE_BITS_UREFS(bits) > 0);
1063: assert((bits & IE_BITS_MAREQUEST) == 0);
1064: assert(entry->ie_object == IO_NULL);
1065: assert(entry->ie_request == 0);
1066:
1067: urefs = IE_BITS_UREFS(bits);
1068: if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta))
1069: goto invalid_value;
1070: if (MACH_PORT_UREFS_OVERFLOW(urefs, delta))
1071: goto urefs_overflow;
1072:
1073: if ((urefs + delta) == 0)
1074: ipc_entry_dealloc(space, name, entry);
1075: else
1076: entry->ie_bits = bits + delta;
1077:
1078: is_write_unlock(space);
1079: break;
1080: }
1081:
1082: case MACH_PORT_RIGHT_SEND: {
1083: mach_port_urefs_t urefs;
1084: ipc_port_t port;
1085: ipc_port_t dnrequest = IP_NULL;
1086: ipc_port_t nsrequest = IP_NULL;
1087: mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
1088:
1089: if ((bits & MACH_PORT_TYPE_SEND) == 0)
1090: goto invalid_right;
1091:
1092: /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1093:
1094: urefs = IE_BITS_UREFS(bits);
1095: if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta))
1096: goto invalid_value;
1097: if (MACH_PORT_UREFS_OVERFLOW(urefs+1, delta))
1098: goto urefs_overflow;
1099:
1100: port = (ipc_port_t) entry->ie_object;
1101: assert(port != IP_NULL);
1102:
1103: if (ipc_right_check(space, port, name, entry)) {
1104: assert((entry->ie_bits & MACH_PORT_TYPE_SEND) == 0);
1105: goto invalid_right;
1106: }
1107: /* port is locked and active */
1108:
1109: assert(port->ip_srights > 0);
1110:
1111: if ((urefs + delta) == 0) {
1112: if (--port->ip_srights == 0) {
1113: nsrequest = port->ip_nsrequest;
1114: if (nsrequest != IP_NULL) {
1115: port->ip_nsrequest = IP_NULL;
1116: mscount = port->ip_mscount;
1117: }
1118: }
1119:
1120: if (bits & MACH_PORT_TYPE_RECEIVE) {
1121: assert(port->ip_receiver_name == name);
1122: assert(port->ip_receiver == space);
1123: assert(IE_BITS_TYPE(bits) ==
1124: MACH_PORT_TYPE_SEND_RECEIVE);
1125:
1126: entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|
1127: MACH_PORT_TYPE_SEND);
1128: } else {
1129: assert(IE_BITS_TYPE(bits) ==
1130: MACH_PORT_TYPE_SEND);
1131:
1132: dnrequest = ipc_right_dncancel_macro(
1133: space, port, name, entry);
1134:
1.1.1.5 ! root 1135: ipc_reverse_remove(space, (ipc_object_t) port);
1.1 root 1136:
1137: if (bits & IE_BITS_MAREQUEST)
1138: ipc_marequest_cancel(space, name);
1139:
1140: ip_release(port);
1141: entry->ie_object = IO_NULL;
1142: ipc_entry_dealloc(space, name, entry);
1143: }
1144: } else
1145: entry->ie_bits = bits + delta;
1146:
1147: ip_unlock(port); /* even if dropped a ref, port is active */
1148: is_write_unlock(space);
1149:
1150: if (nsrequest != IP_NULL)
1151: ipc_notify_no_senders(nsrequest, mscount);
1152:
1153: if (dnrequest != IP_NULL)
1154: ipc_notify_port_deleted(dnrequest, name);
1155: break;
1156: }
1157:
1158: default:
1159: #if MACH_ASSERT
1160: assert(!"ipc_right_delta: strange right");
1161: #else
1162: panic("ipc_right_delta: strange right");
1163: #endif
1164: }
1165:
1166: return KERN_SUCCESS;
1167:
1168: success:
1169: is_write_unlock(space);
1170: return KERN_SUCCESS;
1171:
1172: invalid_right:
1173: is_write_unlock(space);
1174: return KERN_INVALID_RIGHT;
1175:
1176: invalid_value:
1177: is_write_unlock(space);
1178: return KERN_INVALID_VALUE;
1179:
1180: urefs_overflow:
1181: is_write_unlock(space);
1182: return KERN_UREFS_OVERFLOW;
1183: }
1184:
1185: /*
1186: * Routine: ipc_right_info
1187: * Purpose:
1188: * Retrieves information about the right.
1189: * Conditions:
1190: * The space is write-locked, and is unlocked upon return
1191: * if the call is unsuccessful. The space must be active.
1192: * Returns:
1193: * KERN_SUCCESS Retrieved info; space still locked.
1194: */
1195:
1196: kern_return_t
1197: ipc_right_info(
1198: ipc_space_t space,
1199: mach_port_t name,
1200: ipc_entry_t entry,
1201: mach_port_type_t *typep,
1202: mach_port_urefs_t *urefsp)
1203: {
1204: ipc_entry_bits_t bits = entry->ie_bits;
1205: ipc_port_request_index_t request;
1206: mach_port_type_t type;
1207:
1208: if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
1209: ipc_port_t port = (ipc_port_t) entry->ie_object;
1210:
1211: if (ipc_right_check(space, port, name, entry)) {
1212: bits = entry->ie_bits;
1213: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1214: } else
1215: ip_unlock(port);
1216: }
1217:
1218: type = IE_BITS_TYPE(bits);
1219: request = entry->ie_request;
1220:
1221: if (request != 0)
1222: type |= MACH_PORT_TYPE_DNREQUEST;
1223: if (bits & IE_BITS_MAREQUEST)
1224: type |= MACH_PORT_TYPE_MAREQUEST;
1225:
1226: *typep = type;
1227: *urefsp = IE_BITS_UREFS(bits);
1228: return KERN_SUCCESS;
1229: }
1230:
1231: /*
1232: * Routine: ipc_right_copyin_check
1233: * Purpose:
1234: * Check if a subsequent ipc_right_copyin would succeed.
1235: * Conditions:
1236: * The space is locked (read or write) and active.
1237: */
1238:
1239: boolean_t
1240: ipc_right_copyin_check(
1241: ipc_space_t space,
1242: mach_port_t name,
1243: ipc_entry_t entry,
1244: mach_msg_type_name_t msgt_name)
1245: {
1246: ipc_entry_bits_t bits = entry->ie_bits;
1247:
1248: assert(space->is_active);
1249:
1250: switch (msgt_name) {
1251: case MACH_MSG_TYPE_MAKE_SEND:
1252: case MACH_MSG_TYPE_MAKE_SEND_ONCE:
1253: case MACH_MSG_TYPE_MOVE_RECEIVE:
1254: if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1255: return FALSE;
1256:
1257: break;
1258:
1259: case MACH_MSG_TYPE_COPY_SEND:
1260: case MACH_MSG_TYPE_MOVE_SEND:
1261: case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
1262: ipc_port_t port;
1263: boolean_t active;
1264:
1265: if (bits & MACH_PORT_TYPE_DEAD_NAME)
1266: break;
1267:
1268: if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1269: return FALSE;
1270:
1271: port = (ipc_port_t) entry->ie_object;
1272: assert(port != IP_NULL);
1273:
1274: ip_lock(port);
1275: active = ip_active(port);
1276: ip_unlock(port);
1277:
1278: if (!active) {
1279: break;
1280: }
1281:
1282: if (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE) {
1283: if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0)
1284: return FALSE;
1285: } else {
1286: if ((bits & MACH_PORT_TYPE_SEND) == 0)
1287: return FALSE;
1288: }
1289:
1290: break;
1291: }
1292:
1293: default:
1294: #if MACH_ASSERT
1295: assert(!"ipc_right_copyin_check: strange rights");
1296: #else
1297: panic("ipc_right_copyin_check: strange rights");
1298: #endif
1299: }
1300:
1301: return TRUE;
1302: }
1303:
1304: /*
1305: * Routine: ipc_right_copyin
1306: * Purpose:
1307: * Copyin a capability from a space.
1308: * If successful, the caller gets a ref
1309: * for the resulting object, unless it is IO_DEAD,
1310: * and possibly a send-once right which should
1311: * be used in a port-deleted notification.
1312: *
1313: * If deadok is not TRUE, the copyin operation
1314: * will fail instead of producing IO_DEAD.
1315: *
1316: * The entry is never deallocated (except
1317: * when KERN_INVALID_NAME), so the caller
1318: * should deallocate the entry if its type
1319: * is MACH_PORT_TYPE_NONE.
1320: * Conditions:
1321: * The space is write-locked and active.
1322: * Returns:
1323: * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1324: * KERN_INVALID_RIGHT Name doesn't denote correct right.
1325: */
1326:
1327: kern_return_t
1328: ipc_right_copyin(
1329: ipc_space_t space,
1330: mach_port_t name,
1331: ipc_entry_t entry,
1332: mach_msg_type_name_t msgt_name,
1333: boolean_t deadok,
1334: ipc_object_t *objectp,
1335: ipc_port_t *sorightp)
1336: {
1337: ipc_entry_bits_t bits = entry->ie_bits;
1338:
1339: assert(space->is_active);
1340:
1341: switch (msgt_name) {
1342: case MACH_MSG_TYPE_MAKE_SEND: {
1343: ipc_port_t port;
1344:
1345: if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1346: goto invalid_right;
1347:
1348: port = (ipc_port_t) entry->ie_object;
1349: assert(port != IP_NULL);
1350:
1351: ip_lock(port);
1352: assert(ip_active(port));
1353: assert(port->ip_receiver_name == name);
1354: assert(port->ip_receiver == space);
1355:
1356: port->ip_mscount++;
1357: port->ip_srights++;
1358: ip_reference(port);
1359: ip_unlock(port);
1360:
1361: *objectp = (ipc_object_t) port;
1362: *sorightp = IP_NULL;
1363: break;
1364: }
1365:
1366: case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
1367: ipc_port_t port;
1368:
1369: if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1370: goto invalid_right;
1371:
1372: port = (ipc_port_t) entry->ie_object;
1373: assert(port != IP_NULL);
1374:
1375: ip_lock(port);
1376: assert(ip_active(port));
1377: assert(port->ip_receiver_name == name);
1378: assert(port->ip_receiver == space);
1379:
1380: port->ip_sorights++;
1381: ip_reference(port);
1382: ip_unlock(port);
1383:
1384: *objectp = (ipc_object_t) port;
1385: *sorightp = IP_NULL;
1386: break;
1387: }
1388:
1389: case MACH_MSG_TYPE_MOVE_RECEIVE: {
1390: ipc_port_t port;
1391: ipc_port_t dnrequest = IP_NULL;
1392:
1393: if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
1394: goto invalid_right;
1395:
1396: port = (ipc_port_t) entry->ie_object;
1397: assert(port != IP_NULL);
1398:
1399: ip_lock(port);
1400: assert(ip_active(port));
1401: assert(port->ip_receiver_name == name);
1402: assert(port->ip_receiver == space);
1403:
1404: if (bits & MACH_PORT_TYPE_SEND) {
1405: assert(IE_BITS_TYPE(bits) ==
1406: MACH_PORT_TYPE_SEND_RECEIVE);
1407: assert(IE_BITS_UREFS(bits) > 0);
1408: assert(port->ip_srights > 0);
1409:
1.1.1.5 ! root 1410: entry->ie_name = name;
! 1411: ipc_reverse_insert(space, (ipc_object_t) port, entry);
1.1 root 1412:
1413: ip_reference(port);
1414: } else {
1415: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
1416: assert(IE_BITS_UREFS(bits) == 0);
1417:
1418: dnrequest = ipc_right_dncancel_macro(space, port,
1419: name, entry);
1420:
1421: if (bits & IE_BITS_MAREQUEST)
1422: ipc_marequest_cancel(space, name);
1423:
1424: entry->ie_object = IO_NULL;
1425: }
1426: entry->ie_bits = bits &~ MACH_PORT_TYPE_RECEIVE;
1427:
1428: ipc_port_clear_receiver(port);
1429:
1430: port->ip_receiver_name = MACH_PORT_NULL;
1431: port->ip_destination = IP_NULL;
1.1.1.4 root 1432:
1433: /*
1434: * Clear the protected payload field to retain
1435: * the behavior of mach_msg.
1436: */
1437: ipc_port_flag_protected_payload_clear(port);
1.1 root 1438: ip_unlock(port);
1439:
1440: *objectp = (ipc_object_t) port;
1441: *sorightp = dnrequest;
1442: break;
1443: }
1444:
1445: case MACH_MSG_TYPE_COPY_SEND: {
1446: ipc_port_t port;
1447:
1448: if (bits & MACH_PORT_TYPE_DEAD_NAME)
1449: goto copy_dead;
1450:
1451: /* allow for dead send-once rights */
1452:
1453: if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1454: goto invalid_right;
1455:
1456: assert(IE_BITS_UREFS(bits) > 0);
1457:
1458: port = (ipc_port_t) entry->ie_object;
1459: assert(port != IP_NULL);
1460:
1461: if (ipc_right_check(space, port, name, entry)) {
1462: bits = entry->ie_bits;
1463: goto copy_dead;
1464: }
1465: /* port is locked and active */
1466:
1467: if ((bits & MACH_PORT_TYPE_SEND) == 0) {
1468: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1469: assert(port->ip_sorights > 0);
1470:
1471: ip_unlock(port);
1472: goto invalid_right;
1473: }
1474:
1475: assert(port->ip_srights > 0);
1476:
1477: port->ip_srights++;
1478: ip_reference(port);
1479: ip_unlock(port);
1480:
1481: *objectp = (ipc_object_t) port;
1482: *sorightp = IP_NULL;
1483: break;
1484: }
1485:
1486: case MACH_MSG_TYPE_MOVE_SEND: {
1487: ipc_port_t port;
1488: ipc_port_t dnrequest = IP_NULL;
1489:
1490: if (bits & MACH_PORT_TYPE_DEAD_NAME)
1491: goto move_dead;
1492:
1493: /* allow for dead send-once rights */
1494:
1495: if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1496: goto invalid_right;
1497:
1498: assert(IE_BITS_UREFS(bits) > 0);
1499:
1500: port = (ipc_port_t) entry->ie_object;
1501: assert(port != IP_NULL);
1502:
1503: if (ipc_right_check(space, port, name, entry)) {
1504: bits = entry->ie_bits;
1505: goto move_dead;
1506: }
1507: /* port is locked and active */
1508:
1509: if ((bits & MACH_PORT_TYPE_SEND) == 0) {
1510: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1511: assert(port->ip_sorights > 0);
1512:
1513: ip_unlock(port);
1514: goto invalid_right;
1515: }
1516:
1517: assert(port->ip_srights > 0);
1518:
1519: if (IE_BITS_UREFS(bits) == 1) {
1520: if (bits & MACH_PORT_TYPE_RECEIVE) {
1521: assert(port->ip_receiver_name == name);
1522: assert(port->ip_receiver == space);
1523: assert(IE_BITS_TYPE(bits) ==
1524: MACH_PORT_TYPE_SEND_RECEIVE);
1525:
1526: ip_reference(port);
1527: } else {
1528: assert(IE_BITS_TYPE(bits) ==
1529: MACH_PORT_TYPE_SEND);
1530:
1531: dnrequest = ipc_right_dncancel_macro(
1532: space, port, name, entry);
1533:
1.1.1.5 ! root 1534: ipc_reverse_remove(space, (ipc_object_t) port);
1.1 root 1535:
1536: if (bits & IE_BITS_MAREQUEST)
1537: ipc_marequest_cancel(space, name);
1538:
1539: entry->ie_object = IO_NULL;
1540: }
1541: entry->ie_bits = bits &~
1542: (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND);
1543: } else {
1544: port->ip_srights++;
1545: ip_reference(port);
1546: entry->ie_bits = bits-1; /* decrement urefs */
1547: }
1548:
1549: ip_unlock(port);
1550:
1551: *objectp = (ipc_object_t) port;
1552: *sorightp = dnrequest;
1553: break;
1554: }
1555:
1556: case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
1557: ipc_port_t port;
1558: ipc_port_t dnrequest;
1559:
1560: if (bits & MACH_PORT_TYPE_DEAD_NAME)
1561: goto move_dead;
1562:
1563: /* allow for dead send rights */
1564:
1565: if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
1566: goto invalid_right;
1567:
1568: assert(IE_BITS_UREFS(bits) > 0);
1569:
1570: port = (ipc_port_t) entry->ie_object;
1571: assert(port != IP_NULL);
1572:
1573: if (ipc_right_check(space, port, name, entry)) {
1574: bits = entry->ie_bits;
1575: goto move_dead;
1576: }
1577: /* port is locked and active */
1578:
1579: if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) {
1580: assert(bits & MACH_PORT_TYPE_SEND);
1581: assert(port->ip_srights > 0);
1582:
1583: ip_unlock(port);
1584: goto invalid_right;
1585: }
1586:
1587: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
1588: assert(IE_BITS_UREFS(bits) == 1);
1589: assert((bits & IE_BITS_MAREQUEST) == 0);
1590: assert(port->ip_sorights > 0);
1591:
1592: dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
1593: ip_unlock(port);
1594:
1595: entry->ie_object = IO_NULL;
1596: entry->ie_bits = bits &~ MACH_PORT_TYPE_SEND_ONCE;
1597:
1598: *objectp = (ipc_object_t) port;
1599: *sorightp = dnrequest;
1600: break;
1601: }
1602:
1603: default:
1604: #if MACH_ASSERT
1605: assert(!"ipc_right_copyin: strange rights");
1606: #else
1607: panic("ipc_right_copyin: strange rights");
1608: #endif
1609: }
1610:
1611: return KERN_SUCCESS;
1612:
1613: copy_dead:
1614: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1615: assert(IE_BITS_UREFS(bits) > 0);
1616: assert((bits & IE_BITS_MAREQUEST) == 0);
1617: assert(entry->ie_request == 0);
1618: assert(entry->ie_object == 0);
1619:
1620: if (!deadok)
1621: goto invalid_right;
1622:
1623: *objectp = IO_DEAD;
1624: *sorightp = IP_NULL;
1625: return KERN_SUCCESS;
1626:
1627: move_dead:
1628: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
1629: assert(IE_BITS_UREFS(bits) > 0);
1630: assert((bits & IE_BITS_MAREQUEST) == 0);
1631: assert(entry->ie_request == 0);
1632: assert(entry->ie_object == 0);
1633:
1634: if (!deadok)
1635: goto invalid_right;
1636:
1637: if (IE_BITS_UREFS(bits) == 1)
1638: entry->ie_bits = bits &~ MACH_PORT_TYPE_DEAD_NAME;
1639: else
1640: entry->ie_bits = bits-1; /* decrement urefs */
1641:
1642: *objectp = IO_DEAD;
1643: *sorightp = IP_NULL;
1644: return KERN_SUCCESS;
1645:
1646: invalid_right:
1647: return KERN_INVALID_RIGHT;
1648: }
1649:
1650: /*
1651: * Routine: ipc_right_copyin_undo
1652: * Purpose:
1653: * Undoes the effects of an ipc_right_copyin
1654: * of a send/send-once right that is dead.
1655: * (Object is either IO_DEAD or a dead port.)
1656: * Conditions:
1657: * The space is write-locked and active.
1658: */
1659:
1660: void
1661: ipc_right_copyin_undo(
1662: ipc_space_t space,
1663: mach_port_t name,
1664: ipc_entry_t entry,
1665: mach_msg_type_name_t msgt_name,
1666: ipc_object_t object,
1667: ipc_port_t soright)
1668: {
1669: ipc_entry_bits_t bits = entry->ie_bits;
1670:
1671: assert(space->is_active);
1672:
1673: assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1674: (msgt_name == MACH_MSG_TYPE_COPY_SEND) ||
1675: (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
1676:
1677: if (soright != IP_NULL) {
1678: assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1679: (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
1680: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
1681: assert(entry->ie_object == IO_NULL);
1682: assert(object != IO_DEAD);
1683:
1684: entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) |
1685: MACH_PORT_TYPE_DEAD_NAME | 2);
1686: } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE) {
1687: assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1688: (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
1689: assert(entry->ie_object == IO_NULL);
1690:
1691: entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) |
1692: MACH_PORT_TYPE_DEAD_NAME | 1);
1693: } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME) {
1694: assert(entry->ie_object == IO_NULL);
1695: assert(object == IO_DEAD);
1696: assert(IE_BITS_UREFS(bits) > 0);
1697:
1698: if (msgt_name != MACH_MSG_TYPE_COPY_SEND) {
1699: assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
1700:
1701: entry->ie_bits = bits+1; /* increment urefs */
1702: }
1703: } else {
1704: assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
1705: (msgt_name == MACH_MSG_TYPE_COPY_SEND));
1706: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
1707: assert(object != IO_DEAD);
1708: assert(entry->ie_object == object);
1709: assert(IE_BITS_UREFS(bits) > 0);
1710:
1711: if (msgt_name != MACH_MSG_TYPE_COPY_SEND) {
1712: assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX-1);
1713:
1714: entry->ie_bits = bits+1; /* increment urefs */
1715: }
1716:
1717: /*
1718: * May as well convert the entry to a dead name.
1719: * (Or if it is a compat entry, destroy it.)
1720: */
1721:
1722: (void) ipc_right_check(space, (ipc_port_t) object,
1723: name, entry);
1724: /* object is dead so it is not locked */
1725: }
1726:
1727: /* release the reference acquired by copyin */
1728:
1729: if (object != IO_DEAD)
1730: ipc_object_release(object);
1731: }
1732:
1733: /*
1734: * Routine: ipc_right_copyin_two
1735: * Purpose:
1736: * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
1737: * and deadok == FALSE, except that this moves two
1738: * send rights at once.
1739: * Conditions:
1740: * The space is write-locked and active.
1741: * The object is returned with two refs/send rights.
1742: * Returns:
1743: * KERN_SUCCESS Acquired an object.
1744: * KERN_INVALID_RIGHT Name doesn't denote correct right.
1745: */
1746:
1747: kern_return_t
1748: ipc_right_copyin_two(
1749: ipc_space_t space,
1750: mach_port_t name,
1751: ipc_entry_t entry,
1752: ipc_object_t *objectp,
1753: ipc_port_t *sorightp)
1754: {
1755: ipc_entry_bits_t bits = entry->ie_bits;
1756: mach_port_urefs_t urefs;
1757: ipc_port_t port;
1758: ipc_port_t dnrequest = IP_NULL;
1759:
1760: assert(space->is_active);
1761:
1762: if ((bits & MACH_PORT_TYPE_SEND) == 0)
1763: goto invalid_right;
1764:
1765: urefs = IE_BITS_UREFS(bits);
1766: if (urefs < 2)
1767: goto invalid_right;
1768:
1769: port = (ipc_port_t) entry->ie_object;
1770: assert(port != IP_NULL);
1771:
1772: if (ipc_right_check(space, port, name, entry)) {
1773: goto invalid_right;
1774: }
1775: /* port is locked and active */
1776:
1777: assert(port->ip_srights > 0);
1778:
1779: if (urefs == 2) {
1780: if (bits & MACH_PORT_TYPE_RECEIVE) {
1781: assert(port->ip_receiver_name == name);
1782: assert(port->ip_receiver == space);
1783: assert(IE_BITS_TYPE(bits) ==
1784: MACH_PORT_TYPE_SEND_RECEIVE);
1785:
1786: port->ip_srights++;
1787: ip_reference(port);
1788: ip_reference(port);
1789: } else {
1790: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
1791:
1792: dnrequest = ipc_right_dncancel_macro(space, port,
1793: name, entry);
1794:
1.1.1.5 ! root 1795: ipc_reverse_remove(space, (ipc_object_t) port);
1.1 root 1796:
1797: if (bits & IE_BITS_MAREQUEST)
1798: ipc_marequest_cancel(space, name);
1799:
1800: port->ip_srights++;
1801: ip_reference(port);
1802: entry->ie_object = IO_NULL;
1803: }
1804: entry->ie_bits = bits &~
1805: (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND);
1806: } else {
1807: port->ip_srights += 2;
1808: ip_reference(port);
1809: ip_reference(port);
1810: entry->ie_bits = bits-2; /* decrement urefs */
1811: }
1812: ip_unlock(port);
1813:
1814: *objectp = (ipc_object_t) port;
1815: *sorightp = dnrequest;
1816: return KERN_SUCCESS;
1817:
1818: invalid_right:
1819: return KERN_INVALID_RIGHT;
1820: }
1821:
1822: /*
1823: * Routine: ipc_right_copyout
1824: * Purpose:
1825: * Copyout a capability to a space.
1826: * If successful, consumes a ref for the object.
1827: *
1828: * Always succeeds when given a newly-allocated entry,
1829: * because user-reference overflow isn't a possibility.
1830: *
1831: * If copying out the object would cause the user-reference
1832: * count in the entry to overflow, and overflow is TRUE,
1833: * then instead the user-reference count is left pegged
1834: * to its maximum value and the copyout succeeds anyway.
1835: * Conditions:
1836: * The space is write-locked and active.
1837: * The object is locked and active.
1838: * The object is unlocked; the space isn't.
1839: * Returns:
1840: * KERN_SUCCESS Copied out capability.
1841: * KERN_UREFS_OVERFLOW User-refs would overflow;
1842: * guaranteed not to happen with a fresh entry
1843: * or if overflow=TRUE was specified.
1844: */
1845:
1846: kern_return_t
1847: ipc_right_copyout(
1848: ipc_space_t space,
1849: mach_port_t name,
1850: ipc_entry_t entry,
1851: mach_msg_type_name_t msgt_name,
1852: boolean_t overflow,
1853: ipc_object_t object)
1854: {
1855: ipc_entry_bits_t bits = entry->ie_bits;
1856: ipc_port_t port;
1857:
1858: assert(IO_VALID(object));
1859: assert(io_otype(object) == IOT_PORT);
1860: assert(io_active(object));
1861: assert(entry->ie_object == object);
1862:
1863: port = (ipc_port_t) object;
1864:
1865: switch (msgt_name) {
1866: case MACH_MSG_TYPE_PORT_SEND_ONCE:
1867: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
1868: assert(port->ip_sorights > 0);
1869:
1870: /* transfer send-once right and ref to entry */
1871: ip_unlock(port);
1872:
1873: entry->ie_bits = bits | (MACH_PORT_TYPE_SEND_ONCE | 1);
1874: break;
1875:
1876: case MACH_MSG_TYPE_PORT_SEND:
1877: assert(port->ip_srights > 0);
1878:
1879: if (bits & MACH_PORT_TYPE_SEND) {
1880: mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
1881:
1882: assert(port->ip_srights > 1);
1883: assert(urefs > 0);
1884: assert(urefs < MACH_PORT_UREFS_MAX);
1885:
1886: if (urefs+1 == MACH_PORT_UREFS_MAX) {
1887: if (overflow) {
1888: /* leave urefs pegged to maximum */
1889:
1890: port->ip_srights--;
1891: ip_release(port);
1892: ip_unlock(port);
1893: return KERN_SUCCESS;
1894: }
1895:
1896: ip_unlock(port);
1897: return KERN_UREFS_OVERFLOW;
1898: }
1899:
1900: port->ip_srights--;
1901: ip_release(port);
1902: ip_unlock(port);
1903: } else if (bits & MACH_PORT_TYPE_RECEIVE) {
1904: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
1905: assert(IE_BITS_UREFS(bits) == 0);
1906:
1907: /* transfer send right to entry */
1908: ip_release(port);
1909: ip_unlock(port);
1910: } else {
1911: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
1912: assert(IE_BITS_UREFS(bits) == 0);
1913:
1914: /* transfer send right and ref to entry */
1915: ip_unlock(port);
1916:
1917: /* entry is locked holding ref, so can use port */
1918:
1.1.1.5 ! root 1919: entry->ie_name = name;
! 1920: ipc_reverse_insert(space, (ipc_object_t) port, entry);
1.1 root 1921: }
1922:
1923: entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1;
1924: break;
1925:
1926: case MACH_MSG_TYPE_PORT_RECEIVE: {
1927: ipc_port_t dest;
1928:
1929: assert(port->ip_mscount == 0);
1930: assert(port->ip_receiver_name == MACH_PORT_NULL);
1931: dest = port->ip_destination;
1932:
1933: port->ip_receiver_name = name;
1934: port->ip_receiver = space;
1935:
1.1.1.4 root 1936: /*
1937: * Clear the protected payload field to retain
1938: * the behavior of mach_msg.
1939: */
1940: ipc_port_flag_protected_payload_clear(port);
1941:
1.1 root 1942: assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
1943:
1944: if (bits & MACH_PORT_TYPE_SEND) {
1945: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
1946: assert(IE_BITS_UREFS(bits) > 0);
1947: assert(port->ip_srights > 0);
1948:
1949: ip_release(port);
1950: ip_unlock(port);
1951:
1952: /* entry is locked holding ref, so can use port */
1953:
1.1.1.5 ! root 1954: ipc_reverse_remove(space, (ipc_object_t) port);
1.1 root 1955: } else {
1956: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
1957: assert(IE_BITS_UREFS(bits) == 0);
1958:
1959: /* transfer ref to entry */
1960: ip_unlock(port);
1961: }
1962:
1963: entry->ie_bits = bits | MACH_PORT_TYPE_RECEIVE;
1964:
1965: if (dest != IP_NULL)
1966: ipc_port_release(dest);
1967: break;
1968: }
1969:
1970: default:
1971: #if MACH_ASSERT
1972: assert(!"ipc_right_copyout: strange rights");
1973: #else
1974: panic("ipc_right_copyout: strange rights");
1975: #endif
1976: }
1977:
1978: return KERN_SUCCESS;
1979: }
1980:
1981: #if 0
1982: /*XXX same, but allows multiple duplicate send rights */
1983: kern_return_t
1984: ipc_right_copyout_multiname(space, name, entry, object)
1985: ipc_space_t space;
1986: mach_port_t name;
1987: ipc_entry_t entry;
1988: ipc_object_t object;
1989: {
1990: ipc_entry_bits_t bits = entry->ie_bits;
1991: ipc_port_t port;
1992:
1993: assert(IO_VALID(object));
1994: assert(io_otype(object) == IOT_PORT);
1995: assert(io_active(object));
1996: assert(entry->ie_object == object);
1997:
1998: port = (ipc_port_t) object;
1999:
2000: assert(port->ip_srights > 0);
2001:
2002: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
2003: assert(IE_BITS_UREFS(bits) == 0);
2004:
2005: /* transfer send right and ref to entry */
2006: ip_unlock(port);
2007:
2008: /* entry is locked holding ref, so can use port */
2009:
2010: entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1;
2011:
2012: return KERN_SUCCESS;
2013: }
2014: #endif
2015:
2016: /*
2017: * Routine: ipc_right_rename
2018: * Purpose:
2019: * Transfer an entry from one name to another.
2020: * The old entry is deallocated.
2021: * Conditions:
2022: * The space is write-locked and active.
2023: * The new entry is unused. Upon return,
2024: * the space is unlocked.
2025: * Returns:
2026: * KERN_SUCCESS Moved entry to new name.
2027: */
2028:
2029: kern_return_t
2030: ipc_right_rename(
2031: ipc_space_t space,
2032: mach_port_t oname,
2033: ipc_entry_t oentry,
2034: mach_port_t nname,
2035: ipc_entry_t nentry)
2036: {
2037: ipc_entry_bits_t bits = oentry->ie_bits;
2038: ipc_port_request_index_t request = oentry->ie_request;
2039: ipc_object_t object = oentry->ie_object;
2040:
2041: assert(space->is_active);
2042: assert(oname != nname);
2043:
2044: /*
2045: * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2046: * if the port is dead. (This would foil ipc_port_destroy.)
2047: * Instead we should fail because oentry shouldn't exist.
2048: * Note IE_BITS_COMPAT implies ie_request != 0.
2049: */
2050:
2051: if (request != 0) {
2052: ipc_port_t port;
2053:
2054: assert(bits & MACH_PORT_TYPE_PORT_RIGHTS);
2055: port = (ipc_port_t) object;
2056: assert(port != IP_NULL);
2057:
2058: if (ipc_right_check(space, port, oname, oentry)) {
2059: bits = oentry->ie_bits;
2060: assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
2061: assert(oentry->ie_request == 0);
2062: request = 0;
2063: assert(oentry->ie_object == IO_NULL);
2064: object = IO_NULL;
2065: } else {
2066: /* port is locked and active */
2067:
2068: ipc_port_dnrename(port, request, oname, nname);
2069: ip_unlock(port);
2070: oentry->ie_request = 0;
2071: }
2072: }
2073:
2074: if (bits & IE_BITS_MAREQUEST) {
2075: assert(bits & MACH_PORT_TYPE_SEND_RECEIVE);
2076:
2077: ipc_marequest_rename(space, oname, nname);
2078: }
2079:
1.1.1.5 ! root 2080: /* initialize nentry before letting ipc_reverse_insert see it */
1.1 root 2081:
2082: assert((nentry->ie_bits & IE_BITS_RIGHT_MASK) == 0);
2083: nentry->ie_bits |= bits & IE_BITS_RIGHT_MASK;
2084: nentry->ie_request = request;
2085: nentry->ie_object = object;
2086:
2087: switch (IE_BITS_TYPE(bits)) {
2088: case MACH_PORT_TYPE_SEND: {
2089: ipc_port_t port;
2090:
2091: port = (ipc_port_t) object;
2092: assert(port != IP_NULL);
2093:
1.1.1.5 ! root 2094: ipc_reverse_remove(space, (ipc_object_t) port);
! 2095: nentry->ie_name = nname;
! 2096: ipc_reverse_insert(space, (ipc_object_t) port, nentry);
1.1 root 2097: break;
2098: }
2099:
2100: case MACH_PORT_TYPE_RECEIVE:
2101: case MACH_PORT_TYPE_SEND_RECEIVE: {
2102: ipc_port_t port;
2103:
2104: port = (ipc_port_t) object;
2105: assert(port != IP_NULL);
2106:
2107: ip_lock(port);
2108: assert(ip_active(port));
2109: assert(port->ip_receiver_name == oname);
2110: assert(port->ip_receiver == space);
2111:
2112: port->ip_receiver_name = nname;
2113: ip_unlock(port);
2114: break;
2115: }
2116:
2117: case MACH_PORT_TYPE_PORT_SET: {
2118: ipc_pset_t pset;
2119:
2120: pset = (ipc_pset_t) object;
2121: assert(pset != IPS_NULL);
2122:
2123: ips_lock(pset);
2124: assert(ips_active(pset));
2125: assert(pset->ips_local_name == oname);
2126:
2127: pset->ips_local_name = nname;
2128: ips_unlock(pset);
2129: break;
2130: }
2131:
2132: case MACH_PORT_TYPE_SEND_ONCE:
2133: case MACH_PORT_TYPE_DEAD_NAME:
2134: break;
2135:
2136: default:
2137: #if MACH_ASSERT
2138: assert(!"ipc_right_rename: strange rights");
2139: #else
2140: panic("ipc_right_rename: strange rights");
2141: #endif
2142: }
2143:
2144: assert(oentry->ie_request == 0);
2145: oentry->ie_object = IO_NULL;
2146: ipc_entry_dealloc(space, oname, oentry);
2147: is_write_unlock(space);
2148:
2149: return KERN_SUCCESS;
2150: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.