Annotation of XNU/osfmk/ipc/ipc_object.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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