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