|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52: /*
53: * File: ipc/ipc_object.c
54: * Author: Rich Draves
55: * Date: 1989
56: *
57: * Functions to manipulate IPC objects.
58: */
59:
60: #include <dipc.h>
61: #include <mach_rt.h>
62:
63: #include <mach/boolean.h>
64: #include <mach/kern_return.h>
65: #include <mach/port.h>
66: #include <mach/message.h>
67: #include <kern/misc_protos.h>
68: #include <ipc/port.h>
69: #include <ipc/ipc_space.h>
70: #include <ipc/ipc_entry.h>
71: #include <ipc/ipc_object.h>
72: #include <ipc/ipc_hash.h>
73: #include <ipc/ipc_right.h>
74: #include <ipc/ipc_notify.h>
75: #include <ipc/ipc_pset.h>
76:
77: zone_t ipc_object_zones[IOT_NUMBER];
78:
79: /*
80: * Routine: ipc_object_reference
81: * Purpose:
82: * Take a reference to an object.
83: */
84:
85: void
86: ipc_object_reference(
87: ipc_object_t object)
88: {
89: io_lock(object);
90: assert(object->io_references > 0);
91: io_reference(object);
92: io_unlock(object);
93: }
94:
95: /*
96: * Routine: ipc_object_release
97: * Purpose:
98: * Release a reference to an object.
99: */
100:
101: void
102: ipc_object_release(
103: ipc_object_t object)
104: {
105: io_lock(object);
106: assert(object->io_references > 0);
107: io_release(object);
108: io_check_unlock(object);
109: }
110:
111: /*
112: * Routine: ipc_object_translate
113: * Purpose:
114: * Look up an object in a space.
115: * Conditions:
116: * Nothing locked before. If successful, the object
117: * is returned locked. The caller doesn't get a ref.
118: * Returns:
119: * KERN_SUCCESS Objected returned locked.
120: * KERN_INVALID_TASK The space is dead.
121: * KERN_INVALID_NAME The name doesn't denote a right.
122: * KERN_INVALID_RIGHT Name doesn't denote the correct right.
123: */
124:
125: kern_return_t
126: ipc_object_translate(
127: ipc_space_t space,
128: mach_port_name_t name,
129: mach_port_right_t right,
130: ipc_object_t *objectp)
131: {
132: ipc_entry_t entry;
133: ipc_object_t object;
134: kern_return_t kr;
135:
136: kr = ipc_right_lookup_read(space, name, &entry);
137: if (kr != KERN_SUCCESS)
138: return kr;
139: /* space is read-locked and active */
140:
141: if ((entry->ie_bits & MACH_PORT_TYPE(right)) == MACH_PORT_TYPE_NONE) {
142: is_read_unlock(space);
143: return KERN_INVALID_RIGHT;
144: }
145:
146: object = entry->ie_object;
147: assert(object != IO_NULL);
148:
149: io_lock(object);
150: is_read_unlock(space);
151:
152: *objectp = object;
153: return KERN_SUCCESS;
154: }
155:
156: /*
157: * Routine: ipc_object_alloc_dead
158: * Purpose:
159: * Allocate a dead-name entry.
160: * Conditions:
161: * Nothing locked.
162: * Returns:
163: * KERN_SUCCESS The dead name is allocated.
164: * KERN_INVALID_TASK The space is dead.
165: * KERN_NO_SPACE No room for an entry in the space.
166: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
167: */
168:
169: kern_return_t
170: ipc_object_alloc_dead(
171: ipc_space_t space,
172: mach_port_name_t *namep)
173: {
174: ipc_entry_t entry;
175: kern_return_t kr;
176:
177: int i;
178:
179:
180: kr = ipc_entry_alloc(space, namep, &entry);
181: if (kr != KERN_SUCCESS)
182: return kr;
183: /* space is write-locked */
184:
185: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
186:
187: assert(entry->ie_object == IO_NULL);
188: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
189:
190: is_write_unlock(space);
191: return KERN_SUCCESS;
192: }
193:
194: /*
195: * Routine: ipc_object_alloc_dead_name
196: * Purpose:
197: * Allocate a dead-name entry, with a specific name.
198: * Conditions:
199: * Nothing locked.
200: * Returns:
201: * KERN_SUCCESS The dead name is allocated.
202: * KERN_INVALID_TASK The space is dead.
203: * KERN_NAME_EXISTS The name already denotes a right.
204: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
205: */
206:
207: kern_return_t
208: ipc_object_alloc_dead_name(
209: ipc_space_t space,
210: mach_port_name_t name)
211: {
212: ipc_entry_t entry;
213: kern_return_t kr;
214:
215: int i;
216:
217:
218: kr = ipc_entry_alloc_name(space, name, &entry);
219: if (kr != KERN_SUCCESS)
220: return kr;
221: /* space is write-locked */
222:
223: if (ipc_right_inuse(space, name, entry))
224: return KERN_NAME_EXISTS;
225:
226: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
227:
228: assert(entry->ie_object == IO_NULL);
229: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
230:
231: is_write_unlock(space);
232: return KERN_SUCCESS;
233: }
234:
235: /*
236: * Routine: ipc_object_alloc
237: * Purpose:
238: * Allocate an object.
239: * Conditions:
240: * Nothing locked. If successful, the object is returned locked.
241: * The caller doesn't get a reference for the object.
242: * Returns:
243: * KERN_SUCCESS The object is allocated.
244: * KERN_INVALID_TASK The space is dead.
245: * KERN_NO_SPACE No room for an entry in the space.
246: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
247: */
248:
249: kern_return_t
250: ipc_object_alloc(
251: ipc_space_t space,
252: ipc_object_type_t otype,
253: mach_port_type_t type,
254: mach_port_urefs_t urefs,
255: mach_port_name_t *namep,
256: ipc_object_t *objectp)
257: {
258: ipc_object_t object;
259: ipc_entry_t entry;
260: kern_return_t kr;
261:
262: assert(otype < IOT_NUMBER);
263: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
264: assert(type != MACH_PORT_TYPE_NONE);
265: assert(urefs <= MACH_PORT_UREFS_MAX);
266:
267: object = io_alloc(otype);
268: if (object == IO_NULL)
269: return KERN_RESOURCE_SHORTAGE;
270:
271: if (otype == IOT_PORT) {
272: ipc_port_t port = (ipc_port_t)object;
273:
274: bzero((char *)port, sizeof(*port));
275: } else if (otype == IOT_PORT_SET) {
276: ipc_pset_t pset = (ipc_pset_t)object;
277:
278: bzero((char *)pset, sizeof(*pset));
279: }
280:
281: io_lock_init(object);
282: *namep = (mach_port_name_t)object;
283: kr = ipc_entry_alloc(space, namep, &entry);
284: if (kr != KERN_SUCCESS) {
285: io_free(otype, object);
286: return kr;
287: }
288: /* space is write-locked */
289:
290: entry->ie_bits |= type | urefs;
291: entry->ie_object = object;
292:
293: io_lock(object);
294: is_write_unlock(space);
295:
296: object->io_references = 1; /* for entry, not caller */
297: object->io_bits = io_makebits(TRUE, otype, 0);
298:
299: *objectp = object;
300: return KERN_SUCCESS;
301: }
302:
303: /*
304: * Routine: ipc_object_alloc_name
305: * Purpose:
306: * Allocate an object, with a specific name.
307: * Conditions:
308: * Nothing locked. If successful, the object is returned locked.
309: * The caller doesn't get a reference for the object.
310: * Returns:
311: * KERN_SUCCESS The object is allocated.
312: * KERN_INVALID_TASK The space is dead.
313: * KERN_NAME_EXISTS The name already denotes a right.
314: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
315: */
316:
317: kern_return_t
318: ipc_object_alloc_name(
319: ipc_space_t space,
320: ipc_object_type_t otype,
321: mach_port_type_t type,
322: mach_port_urefs_t urefs,
323: mach_port_name_t name,
324: ipc_object_t *objectp)
325: {
326: ipc_object_t object;
327: ipc_entry_t entry;
328: kern_return_t kr;
329:
330: assert(otype < IOT_NUMBER);
331: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
332: assert(type != MACH_PORT_TYPE_NONE);
333: assert(urefs <= MACH_PORT_UREFS_MAX);
334:
335: object = io_alloc(otype);
336: if (object == IO_NULL)
337: return KERN_RESOURCE_SHORTAGE;
338:
339: if (otype == IOT_PORT) {
340: ipc_port_t port = (ipc_port_t)object;
341:
342: bzero((char *)port, sizeof(*port));
343: } else if (otype == IOT_PORT_SET) {
344: ipc_pset_t pset = (ipc_pset_t)object;
345:
346: bzero((char *)pset, sizeof(*pset));
347: }
348:
349: io_lock_init(object);
350: kr = ipc_entry_alloc_name(space, name, &entry);
351: if (kr != KERN_SUCCESS) {
352: io_free(otype, object);
353: return kr;
354: }
355: /* space is write-locked */
356:
357: if (ipc_right_inuse(space, name, entry)) {
358: io_free(otype, object);
359: return KERN_NAME_EXISTS;
360: }
361:
362: entry->ie_bits |= type | urefs;
363: entry->ie_object = object;
364:
365: io_lock(object);
366: is_write_unlock(space);
367:
368: object->io_references = 1; /* for entry, not caller */
369: object->io_bits = io_makebits(TRUE, otype, 0);
370:
371: *objectp = object;
372: return KERN_SUCCESS;
373: }
374:
375: /*
376: * Routine: ipc_object_copyin_type
377: * Purpose:
378: * Convert a send type name to a received type name.
379: */
380:
381: mach_msg_type_name_t
382: ipc_object_copyin_type(
383: mach_msg_type_name_t msgt_name)
384: {
385: switch (msgt_name) {
386: case 0:
387: return 0;
388:
389: case MACH_MSG_TYPE_MOVE_RECEIVE:
390: case MACH_MSG_TYPE_COPY_RECEIVE:
391: return MACH_MSG_TYPE_PORT_RECEIVE;
392:
393: case MACH_MSG_TYPE_MOVE_SEND_ONCE:
394: case MACH_MSG_TYPE_MAKE_SEND_ONCE:
395: return MACH_MSG_TYPE_PORT_SEND_ONCE;
396:
397: case MACH_MSG_TYPE_MOVE_SEND:
398: case MACH_MSG_TYPE_MAKE_SEND:
399: case MACH_MSG_TYPE_COPY_SEND:
400: return MACH_MSG_TYPE_PORT_SEND;
401:
402: default:
403: panic("ipc_object_copyin_type: strange rights");
404: return (mach_msg_type_name_t) 0; /* Shut up the compiler */
405: }
406: }
407:
408: /*
409: * Routine: ipc_object_copyin
410: * Purpose:
411: * Copyin a capability from a space.
412: * If successful, the caller gets a ref
413: * for the resulting object, unless it is IO_DEAD.
414: * Conditions:
415: * Nothing locked.
416: * Returns:
417: * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
418: * KERN_INVALID_TASK The space is dead.
419: * KERN_INVALID_NAME Name doesn't exist in space.
420: * KERN_INVALID_RIGHT Name doesn't denote correct right.
421: */
422:
423: kern_return_t
424: ipc_object_copyin(
425: ipc_space_t space,
426: mach_port_name_t name,
427: mach_msg_type_name_t msgt_name,
428: ipc_object_t *objectp)
429: {
430: ipc_entry_t entry;
431: ipc_port_t soright;
432: kern_return_t kr;
433:
434: int i;
435:
436: /*
437: * Could first try a read lock when doing
438: * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
439: * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
440: */
441:
442: kr = ipc_right_lookup_write(space, name, &entry);
443: if (kr != KERN_SUCCESS)
444: return kr;
445: /* space is write-locked and active */
446:
447: kr = ipc_right_copyin(space, name, entry,
448: msgt_name, TRUE,
449: objectp, &soright);
450: if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
451: ipc_entry_dealloc(space, name, entry);
452: is_write_unlock(space);
453:
454: if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
455: ipc_notify_port_deleted(soright, name);
456:
457: return kr;
458: }
459:
460: /*
461: * Routine: ipc_object_copyin_from_kernel
462: * Purpose:
463: * Copyin a naked capability from the kernel.
464: *
465: * MACH_MSG_TYPE_MOVE_RECEIVE
466: * The receiver must be ipc_space_kernel.
467: * Consumes the naked receive right.
468: * MACH_MSG_TYPE_COPY_SEND
469: * A naked send right must be supplied.
470: * The port gains a reference, and a send right
471: * if the port is still active.
472: * MACH_MSG_TYPE_MAKE_SEND
473: * The receiver must be ipc_space_kernel.
474: * The port gains a reference and a send right.
475: * MACH_MSG_TYPE_MOVE_SEND
476: * Consumes a naked send right.
477: * MACH_MSG_TYPE_MAKE_SEND_ONCE
478: * The port gains a reference and a send-once right.
479: * Receiver also be the caller of device subsystem,
480: * so no assertion.
481: * MACH_MSG_TYPE_MOVE_SEND_ONCE
482: * Consumes a naked send-once right.
483: * Conditions:
484: * Nothing locked.
485: */
486:
487: void
488: ipc_object_copyin_from_kernel(
489: ipc_object_t object,
490: mach_msg_type_name_t msgt_name)
491: {
492: assert(IO_VALID(object));
493:
494: switch (msgt_name) {
495: case MACH_MSG_TYPE_MOVE_RECEIVE: {
496: ipc_port_t port = (ipc_port_t) object;
497:
498: ip_lock(port);
499: assert(ip_active(port));
500: assert(port->ip_receiver_name != MACH_PORT_NULL);
501: assert(port->ip_receiver == ipc_space_kernel);
502:
503: /* relevant part of ipc_port_clear_receiver */
504: ipc_port_set_mscount(port, 0);
505:
506: port->ip_receiver_name = MACH_PORT_NULL;
507: port->ip_destination = IP_NULL;
508: ip_unlock(port);
509: break;
510: }
511:
512: case MACH_MSG_TYPE_COPY_SEND: {
513: ipc_port_t port = (ipc_port_t) object;
514:
515: ip_lock(port);
516: if (ip_active(port)) {
517: assert(port->ip_srights > 0);
518: port->ip_srights++;
519: }
520: ip_reference(port);
521: ip_unlock(port);
522: break;
523: }
524:
525: case MACH_MSG_TYPE_MAKE_SEND: {
526: ipc_port_t port = (ipc_port_t) object;
527:
528: ip_lock(port);
529: assert(ip_active(port));
530: assert(port->ip_receiver_name != MACH_PORT_NULL);
531: assert(port->ip_receiver == ipc_space_kernel);
532:
533: ip_reference(port);
534: port->ip_mscount++;
535: port->ip_srights++;
536: ip_unlock(port);
537: break;
538: }
539:
540: case MACH_MSG_TYPE_MOVE_SEND:
541: /* move naked send right into the message */
542: break;
543:
544: case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
545: ipc_port_t port = (ipc_port_t) object;
546:
547: ip_lock(port);
548: assert(ip_active(port));
549: assert(port->ip_receiver_name != MACH_PORT_NULL);
550:
551: ip_reference(port);
552: port->ip_sorights++;
553: ip_unlock(port);
554: break;
555: }
556:
557: case MACH_MSG_TYPE_MOVE_SEND_ONCE:
558: /* move naked send-once right into the message */
559: break;
560:
561: default:
562: panic("ipc_object_copyin_from_kernel: strange rights");
563: }
564: }
565:
566: /*
567: * Routine: ipc_object_destroy
568: * Purpose:
569: * Destroys a naked capability.
570: * Consumes a ref for the object.
571: *
572: * A receive right should be in limbo or in transit.
573: * Conditions:
574: * Nothing locked.
575: */
576:
577: void
578: ipc_object_destroy(
579: ipc_object_t object,
580: mach_msg_type_name_t msgt_name)
581: {
582: assert(IO_VALID(object));
583: assert(io_otype(object) == IOT_PORT);
584:
585: switch (msgt_name) {
586: case MACH_MSG_TYPE_PORT_SEND:
587: ipc_port_release_send((ipc_port_t) object);
588: break;
589:
590: case MACH_MSG_TYPE_PORT_SEND_ONCE:
591: ipc_notify_send_once((ipc_port_t) object);
592: break;
593:
594: case MACH_MSG_TYPE_PORT_RECEIVE:
595: ipc_port_release_receive((ipc_port_t) object);
596: break;
597:
598: default:
599: panic("ipc_object_destroy: strange rights");
600: }
601: }
602:
603: /*
604: * Routine: ipc_object_copyout
605: * Purpose:
606: * Copyout a capability, placing it into a space.
607: * If successful, consumes a ref for the object.
608: * Conditions:
609: * Nothing locked.
610: * Returns:
611: * KERN_SUCCESS Copied out object, consumed ref.
612: * KERN_INVALID_TASK The space is dead.
613: * KERN_INVALID_CAPABILITY The object is dead.
614: * KERN_NO_SPACE No room in space for another right.
615: * KERN_RESOURCE_SHORTAGE No memory available.
616: * KERN_UREFS_OVERFLOW Urefs limit exceeded
617: * and overflow wasn't specified.
618: */
619:
620: kern_return_t
621: ipc_object_copyout(
622: ipc_space_t space,
623: ipc_object_t object,
624: mach_msg_type_name_t msgt_name,
625: boolean_t overflow,
626: mach_port_name_t *namep)
627: {
628: mach_port_name_t name;
629: ipc_entry_t entry;
630: kern_return_t kr;
631:
632: assert(IO_VALID(object));
633: assert(io_otype(object) == IOT_PORT);
634:
635: is_write_lock(space);
636:
637: for (;;) {
638: if (!space->is_active) {
639: is_write_unlock(space);
640: return KERN_INVALID_TASK;
641: }
642:
643: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
644: ipc_right_reverse(space, object, &name, &entry)) {
645: /* object is locked and active */
646:
647: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
648: break;
649: }
650:
651: name = (mach_port_name_t)object;
652: kr = ipc_entry_get(space, &name, &entry);
653: if (kr != KERN_SUCCESS) {
654: /* unlocks/locks space, so must start again */
655:
656: kr = ipc_entry_grow_table(space, ITS_SIZE_NONE);
657: if (kr != KERN_SUCCESS)
658: return kr; /* space is unlocked */
659:
660: continue;
661: }
662:
663: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
664: assert(entry->ie_object == IO_NULL);
665:
666: io_lock(object);
667: if (!io_active(object)) {
668: io_unlock(object);
669: ipc_entry_dealloc(space, name, entry);
670: is_write_unlock(space);
671: return KERN_INVALID_CAPABILITY;
672: }
673:
674: entry->ie_object = object;
675: break;
676: }
677:
678: /* space is write-locked and active, object is locked and active */
679:
680: kr = ipc_right_copyout(space, name, entry,
681: msgt_name, overflow, object);
682: /* object is unlocked */
683: is_write_unlock(space);
684:
685: if (kr == KERN_SUCCESS)
686: *namep = name;
687: return kr;
688: }
689:
690: /*
691: * Routine: ipc_object_copyout_name
692: * Purpose:
693: * Copyout a capability, placing it into a space.
694: * The specified name is used for the capability.
695: * If successful, consumes a ref for the object.
696: * Conditions:
697: * Nothing locked.
698: * Returns:
699: * KERN_SUCCESS Copied out object, consumed ref.
700: * KERN_INVALID_TASK The space is dead.
701: * KERN_INVALID_CAPABILITY The object is dead.
702: * KERN_RESOURCE_SHORTAGE No memory available.
703: * KERN_UREFS_OVERFLOW Urefs limit exceeded
704: * and overflow wasn't specified.
705: * KERN_RIGHT_EXISTS Space has rights under another name.
706: * KERN_NAME_EXISTS Name is already used.
707: */
708:
709: kern_return_t
710: ipc_object_copyout_name(
711: ipc_space_t space,
712: ipc_object_t object,
713: mach_msg_type_name_t msgt_name,
714: boolean_t overflow,
715: mach_port_name_t name)
716: {
717: mach_port_name_t oname;
718: ipc_entry_t oentry;
719: ipc_entry_t entry;
720: kern_return_t kr;
721:
722: int i;
723:
724: assert(IO_VALID(object));
725: assert(io_otype(object) == IOT_PORT);
726:
727: kr = ipc_entry_alloc_name(space, name, &entry);
728: if (kr != KERN_SUCCESS)
729: return kr;
730: /* space is write-locked and active */
731:
732: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
733: ipc_right_reverse(space, object, &oname, &oentry)) {
734: /* object is locked and active */
735:
736: if (name != oname) {
737: io_unlock(object);
738:
739: if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
740: ipc_entry_dealloc(space, name, entry);
741:
742: is_write_unlock(space);
743: return KERN_RIGHT_EXISTS;
744: }
745:
746: assert(entry == oentry);
747: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
748: } else {
749: if (ipc_right_inuse(space, name, entry))
750: return KERN_NAME_EXISTS;
751:
752: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
753: assert(entry->ie_object == IO_NULL);
754:
755: io_lock(object);
756: if (!io_active(object)) {
757: io_unlock(object);
758: ipc_entry_dealloc(space, name, entry);
759: is_write_unlock(space);
760: return KERN_INVALID_CAPABILITY;
761: }
762:
763: entry->ie_object = object;
764: }
765:
766: /* space is write-locked and active, object is locked and active */
767:
768: kr = ipc_right_copyout(space, name, entry,
769: msgt_name, overflow, object);
770: /* object is unlocked */
771: is_write_unlock(space);
772: return kr;
773: }
774:
775: /*
776: * Routine: ipc_object_copyout_dest
777: * Purpose:
778: * Translates/consumes the destination right of a message.
779: * This is unlike normal copyout because the right is consumed
780: * in a funny way instead of being given to the receiving space.
781: * The receiver gets his name for the port, if he has receive
782: * rights, otherwise MACH_PORT_NULL.
783: * Conditions:
784: * The object is locked and active. Nothing else locked.
785: * The object is unlocked and loses a reference.
786: */
787:
788: void
789: ipc_object_copyout_dest(
790: ipc_space_t space,
791: ipc_object_t object,
792: mach_msg_type_name_t msgt_name,
793: mach_port_name_t *namep)
794: {
795: mach_port_name_t name;
796:
797: assert(IO_VALID(object));
798: assert(io_active(object));
799:
800: io_release(object);
801:
802: /*
803: * If the space is the receiver/owner of the object,
804: * then we quietly consume the right and return
805: * the space's name for the object. Otherwise
806: * we destroy the right and return MACH_PORT_NULL.
807: */
808:
809: switch (msgt_name) {
810: case MACH_MSG_TYPE_PORT_SEND: {
811: ipc_port_t port = (ipc_port_t) object;
812: ipc_port_t nsrequest = IP_NULL;
813: mach_port_mscount_t mscount;
814:
815: if (port->ip_receiver == space)
816: name = port->ip_receiver_name;
817: else
818: name = MACH_PORT_NULL;
819:
820: assert(port->ip_srights > 0);
821: if (--port->ip_srights == 0 &&
822: port->ip_nsrequest != IP_NULL) {
823: nsrequest = port->ip_nsrequest;
824: port->ip_nsrequest = IP_NULL;
825: mscount = port->ip_mscount;
826: ip_unlock(port);
827: ipc_notify_no_senders(nsrequest, mscount);
828: } else
829: ip_unlock(port);
830: break;
831: }
832:
833: case MACH_MSG_TYPE_PORT_SEND_ONCE: {
834: ipc_port_t port = (ipc_port_t) object;
835:
836: assert(port->ip_sorights > 0);
837:
838: if (port->ip_receiver == space) {
839: /* quietly consume the send-once right */
840:
841: port->ip_sorights--;
842: name = port->ip_receiver_name;
843: ip_unlock(port);
844: } else {
845: /*
846: * A very bizarre case. The message
847: * was received, but before this copyout
848: * happened the space lost receive rights.
849: * We can't quietly consume the soright
850: * out from underneath some other task,
851: * so generate a send-once notification.
852: */
853:
854: ip_reference(port); /* restore ref */
855: ip_unlock(port);
856:
857: ipc_notify_send_once(port);
858: name = MACH_PORT_NULL;
859: }
860:
861: break;
862: }
863:
864: default:
865: panic("ipc_object_copyout_dest: strange rights");
866: }
867:
868: *namep = name;
869: }
870:
871: /*
872: * Routine: ipc_object_rename
873: * Purpose:
874: * Rename an entry in a space.
875: * Conditions:
876: * Nothing locked.
877: * Returns:
878: * KERN_SUCCESS Renamed the entry.
879: * KERN_INVALID_TASK The space was dead.
880: * KERN_INVALID_NAME oname didn't denote an entry.
881: * KERN_NAME_EXISTS nname already denoted an entry.
882: * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
883: */
884:
885: kern_return_t
886: ipc_object_rename(
887: ipc_space_t space,
888: mach_port_name_t oname,
889: mach_port_name_t nname)
890: {
891: ipc_entry_t oentry, nentry;
892: kern_return_t kr;
893:
894: int i;
895:
896: kr = ipc_entry_alloc_name(space, nname, &nentry);
897: if (kr != KERN_SUCCESS)
898: return kr;
899:
900: /* space is write-locked and active */
901:
902: if (ipc_right_inuse(space, nname, nentry)) {
903: /* space is unlocked */
904: return KERN_NAME_EXISTS;
905: }
906:
907: /* don't let ipc_entry_lookup see the uninitialized new entry */
908:
909: if ((oname == nname) ||
910: ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
911: ipc_entry_dealloc(space, nname, nentry);
912: is_write_unlock(space);
913: return KERN_INVALID_NAME;
914: }
915:
916: kr = ipc_right_rename(space, oname, oentry, nname, nentry);
917: /* space is unlocked */
918: return kr;
919: }
920:
921: #if MACH_ASSERT
922: /*
923: * Check whether the object is a port if so, free it. But
924: * keep track of that fact.
925: */
926: void
927: io_free(
928: unsigned int otype,
929: ipc_object_t object)
930: {
931: ipc_port_t port;
932:
933: if (otype == IOT_PORT) {
934: port = (ipc_port_t) object;
935: #if MACH_ASSERT
936: ipc_port_track_dealloc(port);
937: #endif /* MACH_ASSERT */
938: }
939: zfree(ipc_object_zones[otype], (vm_offset_t) object);
940: }
941: #endif /* MACH_ASSERT */
942:
943: #if MACH_RT
944: /*
945: * Routine: ipc_object_is_rt
946: * Purpose:
947: * Determine if an object is a real-time object.
948: * Conditions:
949: * Nothing locked.
950: */
951:
952: boolean_t
953: ipc_object_is_rt(
954: ipc_object_t object)
955: {
956: assert(IO_VALID(object));
957:
958: switch (io_otype(object)) {
959: case IOT_PORT:
960: return IP_RT((ipc_port_t) object);
961: case IOT_PORT_SET:
962: return FALSE;
963: default:
964: #if MACH_ASSERT
965: assert(FALSE);
966: #else
967: panic("ipc_object_is_rt: strange object type");
968: #endif
969: }
970: return FALSE;
971: }
972: #endif /* MACH_RT */
973:
974: #include <mach_kdb.h>
975: #if MACH_KDB
976:
977: #include <ddb/db_output.h>
978:
979: #define printf kdbprintf
980:
981: /*
982: * Routine: ipc_object_print
983: * Purpose:
984: * Pretty-print an object for kdb.
985: */
986:
987: char *ikot_print_array[IKOT_MAX_TYPE] = {
988: "(NONE) ",
989: "(THREAD) ",
990: "(TASK) ",
991: "(HOST) ",
992: "(HOST_PRIV) ",
993: "(PROCESSOR) ",
994: "(PSET) ",
995: "(PSET_NAME) ",
996: "(PAGER) ",
997: "(PAGER_REQUEST) ",
998: "(DEVICE) ", /* 10 */
999: "(XMM_OBJECT) ",
1000: "(XMM_PAGER) ",
1001: "(XMM_KERNEL) ",
1002: "(XMM_REPLY) ",
1003: "(PAGER_TERMINATING)",
1004: "(PAGING_NAME) ",
1005: "(HOST_SECURITY) ",
1006: "(LEDGER) ",
1007: "(MASTER_DEVICE) ",
1008: "(ACTIVATION) ", /* 20 */
1009: "(SUBSYSTEM) ",
1010: "(IO_DONE_QUEUE) ",
1011: "(SEMAPHORE) ",
1012: "(LOCK_SET) ",
1013: "(CLOCK) ",
1014: "(CLOCK_CTRL) ", /* 26 */
1015: "(IOKIT) ", /* 27 */
1016: "(NAMED_MEM_ENTRY) ", /* 28 */
1017: /* << new entries here */
1018: "(UNKNOWN) " /* magic catchall */
1019: }; /* Please keep in sync with kern/ipc_kobject.h */
1020:
1021: void
1022: ipc_object_print(
1023: ipc_object_t object)
1024: {
1025: int kotype;
1026:
1027: iprintf("%s", io_active(object) ? "active" : "dead");
1028: printf(", refs=%d", object->io_references);
1029: printf(", otype=%d", io_otype(object));
1030: kotype = io_kotype(object);
1031: if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
1032: printf(", kotype=%d %s\n", io_kotype(object),
1033: ikot_print_array[kotype]);
1034: else
1035: printf(", kotype=0x%x %s\n", io_kotype(object),
1036: ikot_print_array[IKOT_UNKNOWN]);
1037: }
1038:
1039: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.