Annotation of kernel/ipc/ipc_object.c, revision 1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.