|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1995, 1994, 1993, 1992, 1991, 1990
27: * Open Software Foundation, Inc.
28: *
29: * Permission to use, copy, modify, and distribute this software and
30: * its documentation for any purpose and without fee is hereby granted,
31: * provided that the above copyright notice appears in all copies and
32: * that both the copyright notice and this permission notice appear in
33: * supporting documentation, and that the name of ("OSF") or Open Software
34: * Foundation not be used in advertising or publicity pertaining to
35: * distribution of the software without specific, written prior permission.
36: *
37: * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
38: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
39: * FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL OSF BE LIABLE FOR ANY
40: * SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42: * ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING
43: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
44: */
45: /*
46: * OSF Research Institute MK6.1 (unencumbered) 1/31/1995
47: */
48: /*
49: * Mach Operating System
50: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
51: * All Rights Reserved.
52: *
53: * Permission to use, copy, modify and distribute this software and its
54: * documentation is hereby granted, provided that both the copyright
55: * notice and this permission notice appear in all copies of the
56: * software, derivative works or modified versions, and any portions
57: * thereof, and that both notices appear in supporting documentation.
58: *
59: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
60: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
61: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
62: *
63: * Carnegie Mellon requests users of this software to return to
64: *
65: * Software Distribution Coordinator or [email protected]
66: * School of Computer Science
67: * Carnegie Mellon University
68: * Pittsburgh PA 15213-3890
69: *
70: * any improvements or extensions that they make and grant Carnegie Mellon
71: * the rights to redistribute these changes.
72: */
73: /*
74: * File: ipc/ipc_object.c
75: * Author: Rich Draves
76: * Date: 1989
77: *
78: * Functions to manipulate IPC objects.
79: */
80:
81: #import <mach/features.h>
82:
83: #include <mach/boolean.h>
84: #include <mach/kern_return.h>
85: #include <mach/port.h>
86: #include <mach/message.h>
87: #include <ipc/port.h>
88: #include <ipc/ipc_space.h>
89: #include <ipc/ipc_entry.h>
90: #include <ipc/ipc_object.h>
91: #include <ipc/ipc_hash.h>
92: #include <ipc/ipc_right.h>
93: #include <ipc/ipc_notify.h>
94:
95: zone_t ipc_object_zones[IOT_NUMBER];
96:
97: /*
98: * Routine: ipc_object_reference
99: * Purpose:
100: * Take a reference to an object.
101: */
102:
103: void
104: ipc_object_reference(
105: ipc_object_t object)
106: {
107: io_lock(object);
108: assert(object->io_references > 0);
109: io_reference(object);
110: io_unlock(object);
111: }
112:
113: /*
114: * Routine: ipc_object_release
115: * Purpose:
116: * Release a reference to an object.
117: */
118:
119: void
120: ipc_object_release(
121: ipc_object_t object)
122: {
123: io_lock(object);
124: assert(object->io_references > 0);
125: io_release(object);
126: io_check_unlock(object);
127: }
128:
129: /*
130: * Routine: ipc_object_translate
131: * Purpose:
132: * Look up an object in a space.
133: * Conditions:
134: * Nothing locked before. If successful, the object
135: * is returned locked. The caller doesn't get a ref.
136: * Returns:
137: * KERN_SUCCESS Objected returned locked.
138: * KERN_INVALID_TASK The space is dead.
139: * KERN_INVALID_NAME The name doesn't denote a right.
140: * KERN_INVALID_RIGHT Name doesn't denote the correct right.
141: */
142:
143: kern_return_t
144: ipc_object_translate(
145: ipc_space_t space,
146: mach_port_t name,
147: mach_port_right_t right,
148: ipc_object_t *objectp)
149: {
150: ipc_entry_t entry;
151: ipc_object_t object;
152: kern_return_t kr;
153:
154: kr = ipc_right_lookup_read(space, name, &entry);
155: if (kr != KERN_SUCCESS)
156: return kr;
157: /* space is read-locked and active */
158:
159: if ((entry->ie_bits & MACH_PORT_TYPE(right)) == 0) {
160: is_read_unlock(space);
161: return KERN_INVALID_RIGHT;
162: }
163:
164: object = entry->ie_object;
165: assert(object != IO_NULL);
166:
167: io_lock(object);
168: is_read_unlock(space);
169:
170: *objectp = object;
171: return KERN_SUCCESS;
172: }
173:
174: /*
175: * Routine: ipc_object_alloc_dead
176: * Purpose:
177: * Allocate a dead-name entry.
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_NO_SPACE No room for an entry in the space.
184: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
185: */
186:
187: kern_return_t
188: ipc_object_alloc_dead(
189: ipc_space_t space,
190: mach_port_t *namep)
191: {
192: ipc_entry_t entry;
193: kern_return_t kr;
194:
195: kr = ipc_entry_alloc(space, namep, &entry);
196: if (kr != KERN_SUCCESS)
197: return kr;
198: /* space is write-locked */
199:
200: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
201:
202: assert(entry->ie_object == IO_NULL);
203: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
204:
205: is_write_unlock(space);
206: return KERN_SUCCESS;
207: }
208:
209: /*
210: * Routine: ipc_object_alloc_dead_name
211: * Purpose:
212: * Allocate a dead-name entry, with a specific name.
213: * Conditions:
214: * Nothing locked.
215: * Returns:
216: * KERN_SUCCESS The dead name is allocated.
217: * KERN_INVALID_TASK The space is dead.
218: * KERN_NAME_EXISTS The name already denotes a right.
219: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
220: */
221:
222: kern_return_t
223: ipc_object_alloc_dead_name(
224: ipc_space_t space,
225: mach_port_t name)
226: {
227: ipc_entry_t entry;
228: kern_return_t kr;
229:
230: kr = ipc_entry_alloc_name(space, name, &entry);
231: if (kr != KERN_SUCCESS)
232: return kr;
233: /* space is write-locked */
234:
235: if (ipc_right_inuse(space, name, entry))
236: return KERN_NAME_EXISTS;
237:
238: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
239:
240: assert(entry->ie_object == IO_NULL);
241: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
242:
243: is_write_unlock(space);
244: return KERN_SUCCESS;
245: }
246:
247: /*
248: * Routine: ipc_object_alloc
249: * Purpose:
250: * Allocate an object.
251: * Conditions:
252: * Nothing locked. If successful, the object is returned locked.
253: * The caller doesn't get a reference for the object.
254: * Returns:
255: * KERN_SUCCESS The object is allocated.
256: * KERN_INVALID_TASK The space is dead.
257: * KERN_NO_SPACE No room for an entry in the space.
258: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
259: */
260:
261: kern_return_t
262: ipc_object_alloc(
263: ipc_space_t space,
264: ipc_object_type_t otype,
265: mach_port_type_t type,
266: mach_port_urefs_t urefs,
267: mach_port_t *namep,
268: ipc_object_t *objectp)
269: {
270: ipc_object_t object;
271: ipc_entry_t entry;
272: kern_return_t kr;
273:
274: assert(otype < IOT_NUMBER);
275: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
276: assert(type != MACH_PORT_TYPE_NONE);
277: assert(urefs <= MACH_PORT_UREFS_MAX);
278:
279: object = io_alloc(otype);
280: if (object == IO_NULL)
281: return KERN_RESOURCE_SHORTAGE;
282:
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_init(object);
294: io_lock(object);
295: is_write_unlock(space);
296:
297: object->io_references = 1; /* for entry, not caller */
298: object->io_bits = io_makebits(TRUE, otype, 0);
299:
300: *objectp = object;
301: return KERN_SUCCESS;
302: }
303:
304: /*
305: * Routine: ipc_object_alloc_name
306: * Purpose:
307: * Allocate an object, with a specific name.
308: * Conditions:
309: * Nothing locked. If successful, the object is returned locked.
310: * The caller doesn't get a reference for the object.
311: * Returns:
312: * KERN_SUCCESS The object is allocated.
313: * KERN_INVALID_TASK The space is dead.
314: * KERN_NAME_EXISTS The name already denotes a right.
315: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
316: */
317:
318: kern_return_t
319: ipc_object_alloc_name(
320: ipc_space_t space,
321: ipc_object_type_t otype,
322: mach_port_type_t type,
323: mach_port_urefs_t urefs,
324: mach_port_t name,
325: ipc_object_t *objectp)
326: {
327: ipc_object_t object;
328: ipc_entry_t entry;
329: kern_return_t kr;
330:
331: assert(otype < IOT_NUMBER);
332: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
333: assert(type != MACH_PORT_TYPE_NONE);
334: assert(urefs <= MACH_PORT_UREFS_MAX);
335:
336: object = io_alloc(otype);
337: if (object == IO_NULL)
338: return KERN_RESOURCE_SHORTAGE;
339:
340: kr = ipc_entry_alloc_name(space, name, &entry);
341: if (kr != KERN_SUCCESS) {
342: io_free(otype, object);
343: return kr;
344: }
345: /* space is write-locked */
346:
347: if (ipc_right_inuse(space, name, entry)) {
348: io_free(otype, object);
349: return KERN_NAME_EXISTS;
350: }
351:
352: entry->ie_bits |= type | urefs;
353: entry->ie_object = object;
354:
355: io_lock_init(object);
356: io_lock(object);
357: is_write_unlock(space);
358:
359: object->io_references = 1; /* for entry, not caller */
360: object->io_bits = io_makebits(TRUE, otype, 0);
361:
362: *objectp = object;
363: return KERN_SUCCESS;
364: }
365:
366: /*
367: * Routine: ipc_object_copyin_type
368: * Purpose:
369: * Convert a send type name to a received type name.
370: */
371: mach_msg_type_name_t
372: ipc_object_copyin_type(
373: mach_msg_type_name_t msgt_name)
374: {
375: switch (msgt_name) {
376: case 0:
377: return 0;
378:
379: case MACH_MSG_TYPE_MOVE_RECEIVE:
380: return MACH_MSG_TYPE_PORT_RECEIVE;
381:
382: case MACH_MSG_TYPE_MOVE_SEND_ONCE:
383: case MACH_MSG_TYPE_MAKE_SEND_ONCE:
384: return MACH_MSG_TYPE_PORT_SEND_ONCE;
385:
386: case MACH_MSG_TYPE_MOVE_SEND:
387: case MACH_MSG_TYPE_MAKE_SEND:
388: case MACH_MSG_TYPE_COPY_SEND:
389: return MACH_MSG_TYPE_PORT_SEND;
390:
391: #if MACH_IPC_COMPAT
392: case MSG_TYPE_PORT:
393: return MACH_MSG_TYPE_PORT_SEND;
394:
395: case MSG_TYPE_PORT_ALL:
396: return MACH_MSG_TYPE_PORT_RECEIVE;
397: #endif MACH_IPC_COMPAT
398:
399: default:
400: panic("ipc_object_copyin_type: strange rights");
401: }
402: }
403:
404: /*
405: * Routine: ipc_object_copyin
406: * Purpose:
407: * Copyin a capability from a space.
408: * If successful, the caller gets a ref
409: * for the resulting object, unless it is IO_DEAD.
410: * Conditions:
411: * Nothing locked.
412: * Returns:
413: * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
414: * KERN_INVALID_TASK The space is dead.
415: * KERN_INVALID_NAME Name doesn't exist in space.
416: * KERN_INVALID_RIGHT Name doesn't denote correct right.
417: */
418:
419: kern_return_t
420: ipc_object_copyin(
421: ipc_space_t space,
422: mach_port_t name,
423: mach_msg_type_name_t msgt_name,
424: ipc_object_t *objectp)
425: {
426: ipc_entry_t entry;
427: ipc_port_t soright;
428: kern_return_t kr;
429:
430: /*
431: * Could first try a read lock when doing
432: * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
433: * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
434: */
435:
436: kr = ipc_right_lookup_write(space, name, &entry);
437: if (kr != KERN_SUCCESS)
438: return kr;
439: /* space is write-locked and active */
440:
441: kr = ipc_right_copyin(space, name, entry,
442: msgt_name, TRUE,
443: objectp, &soright);
444: if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
445: ipc_entry_dealloc(space, name, entry);
446: is_write_unlock(space);
447:
448: if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
449: ipc_notify_port_deleted(soright, name);
450:
451: return kr;
452: }
453:
454: /*
455: * Routine: ipc_object_copyin_from_kernel
456: * Purpose:
457: * Copyin a naked capability from the kernel.
458: *
459: * MACH_MSG_TYPE_MOVE_RECEIVE
460: * The receiver must be ipc_space_kernel.
461: * Consumes the naked receive right.
462: * MACH_MSG_TYPE_COPY_SEND
463: * A naked send right must be supplied.
464: * The port gains a reference, and a send right
465: * if the port is still active.
466: * MACH_MSG_TYPE_MAKE_SEND
467: * The receiver must be ipc_space_kernel.
468: * The port gains a reference and a send right.
469: * MACH_MSG_TYPE_MOVE_SEND
470: * Consumes a naked send right.
471: * MACH_MSG_TYPE_MAKE_SEND_ONCE
472: * The receiver must be ipc_space_kernel.
473: * The port gains a reference and a send-once right.
474: * MACH_MSG_TYPE_MOVE_SEND_ONCE
475: * Consumes a naked send-once right.
476: * Conditions:
477: * Nothing locked.
478: */
479:
480: void
481: ipc_object_copyin_from_kernel(
482: ipc_object_t object,
483: mach_msg_type_name_t msgt_name)
484: {
485: assert(IO_VALID(object));
486:
487: switch (msgt_name) {
488: #if MACH_IPC_COMPAT
489: case MSG_TYPE_PORT_ALL:
490: #endif
491: case MACH_MSG_TYPE_MOVE_RECEIVE: {
492: ipc_port_t port = (ipc_port_t) object;
493:
494: ip_lock(port);
495: assert(ip_active(port));
496: assert(port->ip_receiver_name != MACH_PORT_NULL);
497: assert(port->ip_receiver == ipc_space_kernel);
498:
499: /* relevant part of ipc_port_clear_receiver */
500: ipc_port_set_mscount(port, 0);
501:
502: port->ip_receiver_name = MACH_PORT_NULL;
503: port->ip_destination = IP_NULL;
504: ip_unlock(port);
505: break;
506: }
507:
508: #if MACH_IPC_COMPAT
509: case MSG_TYPE_PORT:
510: #endif
511: case MACH_MSG_TYPE_COPY_SEND: {
512: ipc_port_t port = (ipc_port_t) object;
513:
514: ip_lock(port);
515: if (ip_active(port)) {
516: assert(port->ip_srights > 0);
517: port->ip_srights++;
518: }
519: ip_reference(port);
520: ip_unlock(port);
521: break;
522: }
523:
524: case MACH_MSG_TYPE_MAKE_SEND: {
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_mscount++;
534: port->ip_srights++;
535: ip_unlock(port);
536: break;
537: }
538:
539: case MACH_MSG_TYPE_MOVE_SEND:
540: /* move naked send right into the message */
541: break;
542:
543: case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
544: ipc_port_t port = (ipc_port_t) object;
545:
546: ip_lock(port);
547: assert(ip_active(port));
548: assert(port->ip_receiver_name != MACH_PORT_NULL);
549: assert(port->ip_receiver == ipc_space_kernel);
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:
584: switch (msgt_name) {
585: case MACH_MSG_TYPE_PORT_SEND:
586: assert(io_otype(object) == IOT_PORT);
587: ipc_port_release_send((ipc_port_t) object);
588: break;
589:
590: case MACH_MSG_TYPE_PORT_SEND_ONCE:
591: assert(io_otype(object) == IOT_PORT);
592: ipc_notify_send_once((ipc_port_t) object);
593: break;
594:
595: case MACH_MSG_TYPE_PORT_RECEIVE:
596: assert(io_otype(object) == IOT_PORT);
597: ipc_port_release_receive((ipc_port_t) object);
598: break;
599:
600: default:
601: panic("ipc_object_copyout_dest: strange rights");
602: }
603: }
604:
605: /*
606: * Routine: ipc_object_copyout
607: * Purpose:
608: * Copyout a capability, placing it into a space.
609: * If successful, consumes a ref for the object.
610: * Conditions:
611: * Nothing locked.
612: * Returns:
613: * KERN_SUCCESS Copied out object, consumed ref.
614: * KERN_INVALID_TASK The space is dead.
615: * KERN_INVALID_CAPABILITY The object is dead.
616: * KERN_NO_SPACE No room in space for another right.
617: * KERN_RESOURCE_SHORTAGE No memory available.
618: * KERN_UREFS_OVERFLOW Urefs limit exceeded
619: * and overflow wasn't specified.
620: */
621:
622: kern_return_t
623: ipc_object_copyout(
624: ipc_space_t space,
625: ipc_object_t object,
626: mach_msg_type_name_t msgt_name,
627: boolean_t overflow,
628: mach_port_t *namep)
629: {
630: mach_port_t name;
631: ipc_entry_t entry;
632: kern_return_t kr;
633:
634: assert(IO_VALID(object));
635: assert(io_otype(object) == IOT_PORT);
636:
637: is_write_lock(space);
638:
639: for (;;) {
640: if (!space->is_active) {
641: is_write_unlock(space);
642: return KERN_INVALID_TASK;
643: }
644:
645: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
646: ipc_right_reverse(space, object, &name, &entry)) {
647: /* object is locked and active */
648:
649: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
650: break;
651: }
652:
653: kr = ipc_entry_get(space, &name, &entry);
654: if (kr != KERN_SUCCESS) {
655: /* unlocks/locks space, so must start again */
656:
657: kr = ipc_entry_grow_table(space, ITS_SIZE_NONE);
658: if (kr != KERN_SUCCESS)
659: return kr; /* space is unlocked */
660:
661: continue;
662: }
663:
664: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
665: assert(entry->ie_object == IO_NULL);
666:
667: io_lock(object);
668: if (!io_active(object)) {
669: io_unlock(object);
670: ipc_entry_dealloc(space, name, entry);
671: is_write_unlock(space);
672: return KERN_INVALID_CAPABILITY;
673: }
674:
675: entry->ie_object = object;
676: break;
677: }
678:
679: /* space is write-locked and active, object is locked and active */
680:
681: kr = ipc_right_copyout(space, name, entry,
682: msgt_name, overflow, object);
683: /* object is unlocked */
684: is_write_unlock(space);
685:
686: if (kr == KERN_SUCCESS)
687: *namep = name;
688: return kr;
689: }
690:
691: /*
692: * Routine: ipc_object_copyout_name
693: * Purpose:
694: * Copyout a capability, placing it into a space.
695: * The specified name is used for the capability.
696: * If successful, consumes a ref for the object.
697: * Conditions:
698: * Nothing locked.
699: * Returns:
700: * KERN_SUCCESS Copied out object, consumed ref.
701: * KERN_INVALID_TASK The space is dead.
702: * KERN_INVALID_CAPABILITY The object is dead.
703: * KERN_RESOURCE_SHORTAGE No memory available.
704: * KERN_UREFS_OVERFLOW Urefs limit exceeded
705: * and overflow wasn't specified.
706: * KERN_RIGHT_EXISTS Space has rights under another name.
707: * KERN_NAME_EXISTS Name is already used.
708: */
709:
710: kern_return_t
711: ipc_object_copyout_name(
712: ipc_space_t space,
713: ipc_object_t object,
714: mach_msg_type_name_t msgt_name,
715: boolean_t overflow,
716: mach_port_t name)
717: {
718: mach_port_t oname;
719: ipc_entry_t oentry;
720: ipc_entry_t entry;
721: kern_return_t kr;
722:
723: assert(IO_VALID(object));
724: assert(io_otype(object) == IOT_PORT);
725:
726: kr = ipc_entry_alloc_name(space, name, &entry);
727: if (kr != KERN_SUCCESS)
728: return kr;
729: /* space is write-locked and active */
730:
731: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
732: ipc_right_reverse(space, object, &oname, &oentry)) {
733: /* object is locked and active */
734:
735: if (name != oname) {
736: io_unlock(object);
737:
738: if (IE_BITS_TYPE(entry->ie_bits)
739: == 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_t *namep)
794: {
795: mach_port_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: assert(port->ip_srights > 0);
816: if (--port->ip_srights == 0) {
817: nsrequest = port->ip_nsrequest;
818: if (nsrequest != IP_NULL) {
819: port->ip_nsrequest = IP_NULL;
820: mscount = port->ip_mscount;
821: }
822: }
823:
824: if (port->ip_receiver == space)
825: name = port->ip_receiver_name;
826: else
827: name = MACH_PORT_NULL;
828:
829: ip_unlock(port);
830:
831: if (nsrequest != IP_NULL)
832: ipc_notify_no_senders(nsrequest, mscount);
833:
834: break;
835: }
836:
837: case MACH_MSG_TYPE_PORT_SEND_ONCE: {
838: ipc_port_t port = (ipc_port_t) object;
839:
840: assert(port->ip_sorights > 0);
841:
842: if (port->ip_receiver == space) {
843: /* quietly consume the send-once right */
844:
845: port->ip_sorights--;
846: name = port->ip_receiver_name;
847: ip_unlock(port);
848: } else {
849: /*
850: * A very bizarre case. The message
851: * was received, but before this copyout
852: * happened the space lost receive rights.
853: * We can't quietly consume the soright
854: * out from underneath some other task,
855: * so generate a send-once notification.
856: */
857:
858: ip_reference(port); /* restore ref */
859: ip_unlock(port);
860:
861: ipc_notify_send_once(port);
862: name = MACH_PORT_NULL;
863: }
864:
865: break;
866: }
867:
868: default:
869: panic("ipc_object_copyout_dest: strange rights");
870: }
871:
872: *namep = name;
873: }
874:
875: /*
876: * Routine: ipc_object_rename
877: * Purpose:
878: * Rename an entry in a space.
879: * Conditions:
880: * Nothing locked.
881: * Returns:
882: * KERN_SUCCESS Renamed the entry.
883: * KERN_INVALID_TASK The space was dead.
884: * KERN_INVALID_NAME oname didn't denote an entry.
885: * KERN_NAME_EXISTS nname already denoted an entry.
886: * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
887: */
888:
889: kern_return_t
890: ipc_object_rename(
891: ipc_space_t space,
892: mach_port_t oname,
893: mach_port_t nname)
894: {
895: ipc_entry_t oentry, nentry;
896: kern_return_t kr;
897:
898: kr = ipc_entry_alloc_name(space, nname, &nentry);
899: if (kr != KERN_SUCCESS)
900: return kr;
901: /* space is write-locked and active */
902:
903: if (ipc_right_inuse(space, nname, nentry)) {
904: /* space is unlocked */
905: return KERN_NAME_EXISTS;
906: }
907:
908: /* don't let ipc_entry_lookup see the uninitialized new entry */
909:
910: if ((oname == nname) ||
911: ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
912: ipc_entry_dealloc(space, nname, nentry);
913: is_write_unlock(space);
914: return KERN_INVALID_NAME;
915: }
916:
917: kr = ipc_right_rename(space, oname, oentry, nname, nentry);
918: /* space is unlocked */
919: return kr;
920: }
921:
922: #if MACH_IPC_COMPAT
923:
924: /*
925: * Routine: ipc_object_copyout_type_compat
926: * Purpose:
927: * Convert a carried type name to an old type name.
928: */
929:
930: mach_msg_type_name_t
931: ipc_object_copyout_type_compat(
932: mach_msg_type_name_t msgt_name)
933: {
934: switch (msgt_name) {
935: case MACH_MSG_TYPE_PORT_SEND:
936: case MACH_MSG_TYPE_PORT_SEND_ONCE:
937: return MSG_TYPE_PORT;
938:
939: case MACH_MSG_TYPE_PORT_RECEIVE:
940: return MSG_TYPE_PORT_ALL;
941:
942: default:
943: panic("ipc_object_copyout_type_compat: strange rights");
944: }
945: }
946:
947: /*
948: * Routine: ipc_object_copyin_compat
949: * Purpose:
950: * Copyin a capability from a space.
951: * If successful, the caller gets a ref
952: * for the resulting object, which is always valid.
953: * Conditions:
954: * Nothing locked.
955: * Returns:
956: * KERN_SUCCESS Acquired a valid object.
957: * KERN_INVALID_TASK The space is dead.
958: * KERN_INVALID_NAME Name doesn't exist in space.
959: * KERN_INVALID_RIGHT Name doesn't denote correct right.
960: */
961:
962: kern_return_t
963: ipc_object_copyin_compat(
964: ipc_space_t space,
965: mach_port_t name,
966: mach_msg_type_name_t msgt_name,
967: boolean_t dealloc,
968: ipc_object_t *objectp)
969: {
970: ipc_entry_t entry;
971: kern_return_t kr;
972:
973: kr = ipc_right_lookup_write(space, name, &entry);
974: if (kr != KERN_SUCCESS)
975: return kr;
976: /* space is write-locked and active */
977:
978: kr = ipc_right_copyin_compat(space, name, entry,
979: msgt_name, dealloc, objectp);
980: /* space is unlocked */
981: return kr;
982: }
983:
984: /*
985: * Routine: ipc_object_copyin_header
986: * Purpose:
987: * Copyin a capability from a space.
988: * If successful, the caller gets a ref
989: * for the resulting object, which is always valid.
990: * The type of the acquired capability is returned.
991: * Conditions:
992: * Nothing locked.
993: * Returns:
994: * KERN_SUCCESS Acquired a valid object.
995: * KERN_INVALID_TASK The space is dead.
996: * KERN_INVALID_NAME Name doesn't exist in space.
997: * KERN_INVALID_RIGHT Name doesn't denote correct right.
998: */
999:
1000: kern_return_t
1001: ipc_object_copyin_header(
1002: ipc_space_t space,
1003: mach_port_t name,
1004: ipc_object_t *objectp,
1005: mach_msg_type_name_t *msgt_namep)
1006: {
1007: ipc_entry_t entry;
1008: kern_return_t kr;
1009:
1010: kr = ipc_right_lookup_write(space, name, &entry);
1011: if (kr != KERN_SUCCESS)
1012: return kr;
1013: /* space is write-locked and active */
1014:
1015: kr = ipc_right_copyin_header(space, name, entry,
1016: objectp, msgt_namep);
1017: /* space is unlocked */
1018: return kr;
1019: }
1020:
1021: /*
1022: * Routine: ipc_object_copyout_compat
1023: * Purpose:
1024: * Copyout a capability, placing it into a space.
1025: * If successful, consumes a ref for the object.
1026: *
1027: * Marks new entries with IE_BITS_COMPAT.
1028: * Conditions:
1029: * Nothing locked.
1030: * Returns:
1031: * KERN_SUCCESS Copied out object, consumed ref.
1032: * KERN_INVALID_TASK The space is dead.
1033: * KERN_INVALID_CAPABILITY The object is dead.
1034: * KERN_NO_SPACE No room in space for another right.
1035: * KERN_RESOURCE_SHORTAGE No memory available.
1036: */
1037:
1038: kern_return_t
1039: ipc_object_copyout_compat(
1040: ipc_space_t space,
1041: ipc_object_t object,
1042: mach_msg_type_name_t msgt_name,
1043: mach_port_t *namep)
1044: {
1045: mach_port_t name;
1046: ipc_entry_t entry;
1047: ipc_port_t port;
1048: kern_return_t kr;
1049:
1050: assert(IO_VALID(object));
1051: assert(io_otype(object) == IOT_PORT);
1052: port = (ipc_port_t) object;
1053:
1054: is_write_lock(space);
1055:
1056: for (;;) {
1057: ipc_port_request_index_t request;
1058:
1059: if (!space->is_active) {
1060: is_write_unlock(space);
1061: return KERN_INVALID_TASK;
1062: }
1063:
1064: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
1065: ipc_right_reverse(space, (ipc_object_t) port,
1066: &name, &entry)) {
1067: /* port is locked and active */
1068:
1069: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
1070: break;
1071: }
1072:
1073: kr = ipc_entry_get(space, &name, &entry);
1074: if (kr != KERN_SUCCESS) {
1075: /* unlocks/locks space, so must start again */
1076:
1077: kr = ipc_entry_grow_table(space, ITS_SIZE_NONE);
1078: if (kr != KERN_SUCCESS)
1079: return kr; /* space is unlocked */
1080:
1081: continue;
1082: }
1083:
1084: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
1085: assert(entry->ie_object == IO_NULL);
1086:
1087: ip_lock(port);
1088: if (!ip_active(port)) {
1089: ip_unlock(port);
1090: ipc_entry_dealloc(space, name, entry);
1091: is_write_unlock(space);
1092: return KERN_INVALID_CAPABILITY;
1093: }
1094:
1095: kr = ipc_port_dnrequest(port, name, ipr_spacem(space),
1096: &request);
1097: if (kr != KERN_SUCCESS) {
1098: ipc_entry_dealloc(space, name, entry);
1099: is_write_unlock(space);
1100:
1101: kr = ipc_port_dngrow(port, ITS_SIZE_NONE);
1102: /* port is unlocked */
1103: if (kr != KERN_SUCCESS)
1104: return kr;
1105:
1106: is_write_lock(space);
1107: continue;
1108: }
1109:
1110: is_reference(space); /* for dnrequest */
1111: entry->ie_object = (ipc_object_t) port;
1112: entry->ie_request = request;
1113: entry->ie_bits |= IE_BITS_COMPAT;
1114: break;
1115: }
1116:
1117: /* space is write-locked and active, port is locked and active */
1118:
1119: kr = ipc_right_copyout(space, name, entry,
1120: msgt_name, TRUE, (ipc_object_t) port);
1121: /* object is unlocked */
1122: is_write_unlock(space);
1123:
1124: if (kr == KERN_SUCCESS)
1125: *namep = name;
1126: return kr;
1127: }
1128:
1129: /*
1130: * Routine: ipc_object_copyout_name_compat
1131: * Purpose:
1132: * Copyout a capability, placing it into a space.
1133: * The specified name is used for the capability.
1134: * If successful, consumes a ref for the object.
1135: *
1136: * Like ipc_object_copyout_name, except that
1137: * the name can't be in use at all, even for the same
1138: * port, and IE_BITS_COMPAT gets turned on.
1139: * Conditions:
1140: * Nothing locked.
1141: * Returns:
1142: * KERN_SUCCESS Copied out object, consumed ref.
1143: * KERN_INVALID_TASK The space is dead.
1144: * KERN_INVALID_CAPABILITY The object is dead.
1145: * KERN_RESOURCE_SHORTAGE No memory available.
1146: * KERN_RIGHT_EXISTS Space has rights under another name.
1147: * KERN_NAME_EXISTS Name is already used.
1148: */
1149:
1150: kern_return_t
1151: ipc_object_copyout_name_compat(
1152: ipc_space_t space,
1153: ipc_object_t object,
1154: mach_msg_type_name_t msgt_name,
1155: mach_port_t name)
1156: {
1157: ipc_entry_t entry;
1158: ipc_port_t port;
1159: kern_return_t kr;
1160:
1161: assert(IO_VALID(object));
1162: assert(io_otype(object) == IOT_PORT);
1163: port = (ipc_port_t) object;
1164:
1165: for (;;) {
1166: mach_port_t oname;
1167: ipc_entry_t oentry;
1168: ipc_port_request_index_t request;
1169:
1170: kr = ipc_entry_alloc_name(space, name, &entry);
1171: if (kr != KERN_SUCCESS)
1172: return kr;
1173: /* space is write-locked and active */
1174:
1175: if (ipc_right_inuse(space, name, entry))
1176: return KERN_NAME_EXISTS; /* space is unlocked */
1177:
1178: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
1179: assert(entry->ie_object == IO_NULL);
1180:
1181: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
1182: ipc_right_reverse(space, (ipc_object_t) port,
1183: &oname, &oentry)) {
1184: /* port is locked and active */
1185:
1186: ip_unlock(port);
1187: ipc_entry_dealloc(space, name, entry);
1188: is_write_unlock(space);
1189: return KERN_RIGHT_EXISTS;
1190: }
1191:
1192: ip_lock(port);
1193: if (!ip_active(port)) {
1194: ip_unlock(port);
1195: ipc_entry_dealloc(space, name, entry);
1196: is_write_unlock(space);
1197: return KERN_INVALID_CAPABILITY;
1198: }
1199:
1200: kr = ipc_port_dnrequest(port, name, ipr_spacem(space),
1201: &request);
1202: if (kr != KERN_SUCCESS) {
1203: ipc_entry_dealloc(space, name, entry);
1204: is_write_unlock(space);
1205:
1206: kr = ipc_port_dngrow(port, ITS_SIZE_NONE);
1207: /* port is unlocked */
1208: if (kr != KERN_SUCCESS)
1209: return kr;
1210:
1211: continue;
1212: }
1213:
1214: is_reference(space); /* for dnrequest */
1215: entry->ie_object = (ipc_object_t) port;
1216: entry->ie_request = request;
1217: entry->ie_bits |= IE_BITS_COMPAT;
1218: break;
1219: }
1220:
1221: /* space is write-locked and active, port is locked and active */
1222:
1223: kr = ipc_right_copyout(space, name, entry,
1224: msgt_name, TRUE, (ipc_object_t) port);
1225: /* object is unlocked */
1226: is_write_unlock(space);
1227:
1228: assert(kr == KERN_SUCCESS);
1229: return kr;
1230: }
1231:
1232: #endif /* MACH_IPC_COMPAT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.