Annotation of kernel/kern/ipc_kobject.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:  * 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:  *     File:   kern/ipc_kobject.c
        !            52:  *     Author: Rich Draves
        !            53:  *     Date:   1989
        !            54:  *
        !            55:  *     Functions for letting a port represent a kernel object.
        !            56:  */
        !            57: 
        !            58: #import <mach/features.h>
        !            59: 
        !            60: #include <mach/port.h>
        !            61: #include <mach/kern_return.h>
        !            62: #include <mach/message.h>
        !            63: #include <mach/mig_errors.h>
        !            64: #include <mach/notify.h>
        !            65: #include <kern/ipc_kobject.h>
        !            66: #include <ipc/ipc_object.h>
        !            67: #include <ipc/ipc_kmsg.h>
        !            68: #include <ipc/ipc_port.h>
        !            69: #include <ipc/ipc_thread.h>
        !            70: 
        !            71: #if    MACH_MACHINE_ROUTINES
        !            72: #include <machine/machine_routines.h>
        !            73: #endif
        !            74: 
        !            75: /* Forward Declarations */
        !            76: 
        !            77: boolean_t
        !            78: ipc_kobject_notify(
        !            79:         mach_msg_header_t *request_header,
        !            80:         mach_msg_header_t *reply_header);
        !            81: 
        !            82: #include <mach/ndr.h>
        !            83: 
        !            84: /*
        !            85:  *     Routine:        ipc_kobject_server
        !            86:  *     Purpose:
        !            87:  *             Handle a message sent to the kernel.
        !            88:  *             Generates a reply message.
        !            89:  *     Conditions:
        !            90:  *             Nothing locked.
        !            91:  */
        !            92: 
        !            93: ipc_kmsg_t
        !            94: ipc_kobject_server(
        !            95:        ipc_kmsg_t      request)
        !            96: {
        !            97:        mach_msg_size_t reply_size;
        !            98:        ipc_kmsg_t reply;
        !            99:        kern_return_t kr;
        !           100:        mig_routine_t routine;
        !           101:        ipc_port_t *destp;
        !           102: 
        !           103:        if (request->ikm_header.msgh_bits & MACH_MSGH_BITS_OLD_FORMAT) {
        !           104:            reply_size = ikm_less_overhead(2048);
        !           105:            reply = ikm_alloc(reply_size);
        !           106:            if (reply == IKM_NULL) {
        !           107:                    printf("ipc_kobject_server: dropping request\n");
        !           108:                    ipc_kmsg_destroy(request);
        !           109:                    return IKM_NULL;
        !           110:            }
        !           111:            ikm_init(reply, reply_size);
        !           112:            
        !           113:            reply->ikm_sender = KERNEL_SECURITY_ID_VALUE;
        !           114: 
        !           115:            /*
        !           116:             * Initialize reply message.
        !           117:             */
        !           118:            {
        !           119: #define        InP     ((mach_msg_header_t *) &request->ikm_header)
        !           120: #define        OutP    ((mig_reply_header_t *) &reply->ikm_header)
        !           121: 
        !           122:                static mach_msg_type_t RetCodeType = {
        !           123:                    /* msgt_name = */           MACH_MSG_TYPE_INTEGER_32,
        !           124:                    /* msgt_size = */           32,
        !           125:                    /* msgt_number = */         1,
        !           126:                    /* msgt_inline = */         TRUE,
        !           127:                    /* msgt_longform = */       FALSE,
        !           128:                    /* msgt_unused = */         0
        !           129:                };
        !           130:                OutP->Head.msgh_bits =
        !           131:                    MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0) |
        !           132:                                        MACH_MSGH_BITS_OLD_FORMAT;
        !           133:                OutP->Head.msgh_size = sizeof(mig_reply_header_t);
        !           134:                OutP->Head.msgh_remote_port = InP->msgh_local_port;
        !           135:                OutP->Head.msgh_local_port = MACH_PORT_NULL;
        !           136:                OutP->Head.msgh_reserved = 0;
        !           137:                OutP->Head.msgh_id = InP->msgh_id + 100;
        !           138: 
        !           139:                OutP->RetCodeType = RetCodeType;
        !           140: 
        !           141: #undef InP
        !           142: #undef OutP
        !           143:            }
        !           144: 
        !           145:            /*
        !           146:             * Find the server routine to call, and call it
        !           147:             * to perform the kernel function
        !           148:             */
        !           149: #if    MACH_NET
        !           150:            if (netipc_msg_send(request))
        !           151:                ((mig_reply_header_t *)
        !           152:                        &reply->ikm_header)->RetCode = MIG_NO_REPLY;
        !           153:            else
        !           154: #endif
        !           155:            {
        !           156:                extern mig_routine_t    mach_server_routine(),
        !           157:                                        mach_port_server_routine(),
        !           158:                                        mach_host_server_routine();
        !           159: #if    DRIVERKIT
        !           160:                extern mig_routine_t    driverServer_server_routine();
        !           161: #endif
        !           162: 
        !           163: #if    MACH_MACHINE_ROUTINES
        !           164:                extern mig_routine_t    MACHINE_SERVER_ROUTINE();
        !           165: #endif
        !           166: 
        !           167:                if ((routine =
        !           168:                        mach_server_routine(&request->ikm_header)) != 0
        !           169:                || (routine =
        !           170:                        mach_host_server_routine(&request->ikm_header)) != 0
        !           171: #if    DRIVERKIT
        !           172:                || (routine =
        !           173:                        driverServer_server_routine(&request->ikm_header)) != 0
        !           174: #endif DRIVERKIT
        !           175: #if    MACH_MACHINE_ROUTINES
        !           176:                || (routine =
        !           177:                        MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0
        !           178: #endif MACH_MACHINE_ROUTINES
        !           179:                ) {
        !           180:                        (*routine)(&request->ikm_header, &reply->ikm_header);
        !           181:                }
        !           182:                else
        !           183:                if (!ipc_kobject_notify(
        !           184:                                &request->ikm_header,&reply->ikm_header)) {
        !           185:                        ((mig_reply_header_t *)
        !           186:                                &reply->ikm_header)->RetCode = MIG_BAD_ID;
        !           187: #if    MACH_IPC_TEST
        !           188:                printf("ipc_kobject_server: bogus kernel message, id=%d\n",
        !           189:                                                request->ikm_header.msgh_id);
        !           190: #endif MACH_IPC_TEST
        !           191:                }
        !           192:            }
        !           193: 
        !           194:            kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode;
        !           195:        }
        !           196:        else {
        !           197:            reply_size = ikm_less_overhead(2048);
        !           198:            reply = ikm_alloc(reply_size);
        !           199:            if (reply == IKM_NULL) {
        !           200:                    printf("ipc_kobject_server: dropping request\n");
        !           201:                    ipc_kmsg_destroy(request);
        !           202:                    return IKM_NULL;
        !           203:            }
        !           204:            ikm_init(reply, reply_size);
        !           205: 
        !           206:            reply->ikm_sender = KERNEL_SECURITY_ID_VALUE;
        !           207: 
        !           208:            /*
        !           209:             * Initialize reply message.
        !           210:             */
        !           211:            {
        !           212: #define        InP     ((mach_msg_header_t *) &request->ikm_header)
        !           213: #define        OutP    ((mig_reply_error_t *) &reply->ikm_header)
        !           214:     
        !           215:                OutP->NDR = NDR_record;
        !           216:                OutP->Head.msgh_size = sizeof(mig_reply_error_t);
        !           217:     
        !           218:                OutP->Head.msgh_bits =
        !           219:                    MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
        !           220:                OutP->Head.msgh_remote_port = InP->msgh_local_port;
        !           221:                OutP->Head.msgh_local_port  = MACH_PORT_NULL;
        !           222:                OutP->Head.msgh_reserved = 0;
        !           223:                OutP->Head.msgh_id = InP->msgh_id + 100;
        !           224:     
        !           225: #undef InP
        !           226: #undef OutP
        !           227:            }
        !           228: 
        !           229:            /*
        !           230:             * Find the server routine to call, and call it
        !           231:             * to perform the kernel function
        !           232:             */
        !           233:            {
        !           234:                extern mig_routine_t    mach_port_server_routine();
        !           235: #if    MACH_DEBUG
        !           236:                extern mig_routine_t    mach_debug_server_routine();
        !           237: #endif
        !           238: 
        !           239:                if ((routine =
        !           240:                        mach_port_server_routine(&request->ikm_header)) != 0
        !           241: #if    MACH_DEBUG
        !           242:                || (routine =
        !           243:                        mach_debug_server_routine(&request->ikm_header)) != 0
        !           244: #endif MACH_DEBUG
        !           245:                ) {
        !           246:                        (*routine)(&request->ikm_header, &reply->ikm_header);
        !           247:                }
        !           248:                else
        !           249:                if (!ipc_kobject_notify(
        !           250:                                &request->ikm_header,&reply->ikm_header)) {
        !           251:                        ((mig_reply_error_t *)
        !           252:                                &reply->ikm_header)->RetCode = MIG_BAD_ID;
        !           253: #if    MACH_IPC_TEST
        !           254:                printf("ipc_kobject_server: bogus kernel message, id=%d\n",
        !           255:                                                request->ikm_header.msgh_id);
        !           256: #endif MACH_IPC_TEST
        !           257:                }
        !           258:            }
        !           259: 
        !           260:            if (!(reply->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX))
        !           261:                kr = ((mig_reply_error_t *) &reply->ikm_header)->RetCode;
        !           262:            else
        !           263:                kr = KERN_SUCCESS;
        !           264:        }
        !           265: 
        !           266:        /*
        !           267:         *      Destroy destination. The following code differs from
        !           268:         *      ipc_object_destroy in that we release the send-once
        !           269:         *      right instead of generating a send-once notification
        !           270:         *      (which would bring us here again, creating a loop).
        !           271:         *      It also differs in that we only expect send or
        !           272:         *      send-once rights, never receive rights.
        !           273:         *
        !           274:         *      We set msgh_remote_port to IP_NULL so that the kmsg
        !           275:         *      destroy routines don't try to destroy the port twice.
        !           276:         */
        !           277:        destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
        !           278:        switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
        !           279:                case MACH_MSG_TYPE_PORT_SEND:
        !           280:                    ipc_port_release_send(*destp);
        !           281:                    break;
        !           282:                
        !           283:                case MACH_MSG_TYPE_PORT_SEND_ONCE:
        !           284:                    ipc_port_release_sonce(*destp);
        !           285:                    break;
        !           286:                
        !           287:                default:
        !           288:                    panic("ipc_object_destroy: strange destination rights");
        !           289:        }
        !           290:        *destp = IP_NULL;
        !           291: 
        !           292:        if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
        !           293:                /*
        !           294:                 *      The server function is responsible for the contents
        !           295:                 *      of the message.  The reply port right is moved
        !           296:                 *      to the reply message, and we have deallocated
        !           297:                 *      the destination port right, so we just need
        !           298:                 *      to free the kmsg.
        !           299:                 */
        !           300: 
        !           301:                /* like ipc_kmsg_put, but without the copyout */
        !           302: 
        !           303:                ikm_check_initialized(request, request->ikm_size);
        !           304:                if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
        !           305:                    (ikm_cache() == IKM_NULL))
        !           306:                        ikm_cache() = request;
        !           307:                else
        !           308:                        ikm_free(request);
        !           309:        } else {
        !           310:                /*
        !           311:                 *      The message contents of the request are intact.
        !           312:                 *      Destroy everthing except the reply port right,
        !           313:                 *      which is needed in the reply message.
        !           314:                 */
        !           315: 
        !           316:                request->ikm_header.msgh_local_port = MACH_PORT_NULL;
        !           317:                ipc_kmsg_destroy(request);
        !           318:        }
        !           319: 
        !           320:        if (kr == MIG_NO_REPLY) {
        !           321:                /*
        !           322:                 *      The server function will send a reply message
        !           323:                 *      using the reply port right, which it has saved.
        !           324:                 */
        !           325: 
        !           326:                ikm_free(reply);
        !           327:                return IKM_NULL;
        !           328:        } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
        !           329:                /*
        !           330:                 *      Can't queue the reply message if the destination
        !           331:                 *      (the reply port) isn't valid.
        !           332:                 */
        !           333: 
        !           334:                ipc_kmsg_destroy(reply);
        !           335:                return IKM_NULL;
        !           336:        }
        !           337: 
        !           338:        return reply;
        !           339: }
        !           340: 
        !           341: /*
        !           342:  *     Routine:        ipc_kobject_set
        !           343:  *     Purpose:
        !           344:  *             Make a port represent a kernel object of the given type.
        !           345:  *             The caller is responsible for handling refs for the
        !           346:  *             kernel object, if necessary.
        !           347:  *     Conditions:
        !           348:  *             Nothing locked.  The port must be active.
        !           349:  */
        !           350: 
        !           351: void
        !           352: ipc_kobject_set(
        !           353:        ipc_port_t              port,
        !           354:        ipc_kobject_t           kobject,
        !           355:        ipc_kobject_type_t      type)
        !           356: {
        !           357:        ip_lock(port);
        !           358:        assert(ip_active(port));
        !           359:        port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
        !           360:        port->ip_kobject = kobject;
        !           361:        ip_unlock(port);
        !           362: }
        !           363: 
        !           364: /*
        !           365:  *     Routine:        ipc_kobject_destroy
        !           366:  *     Purpose:
        !           367:  *             Release any kernel object resources associated
        !           368:  *             with the port, which is being destroyed.
        !           369:  *
        !           370:  *             This should only be needed when resources are
        !           371:  *             associated with a user's port.  In the normal case,
        !           372:  *             when the kernel is the receiver, the code calling
        !           373:  *             ipc_port_dealloc_kernel should clean up the resources.
        !           374:  *     Conditions:
        !           375:  *             The port is not locked, but it is dead.
        !           376:  */
        !           377: 
        !           378: void
        !           379: ipc_kobject_destroy(port)
        !           380:        ipc_port_t port;
        !           381: {
        !           382:        switch (ip_kotype(port)) {
        !           383: #if    MACH_NET
        !           384:            case IKOT_NETIPC:
        !           385:                netipc_ignore(IP_NULL, port);
        !           386:                break;
        !           387: #endif
        !           388: 
        !           389:            default:
        !           390: #if    MACH_ASSERT
        !           391:                printf("ipc_kobject_destroy: port 0x%x, kobj 0x%x, type %d\n",
        !           392:                       port, port->ip_kobject, ip_kotype(port));
        !           393: #endif MACH_ASSERT
        !           394:                break;
        !           395:        }
        !           396: }
        !           397: 
        !           398: /*
        !           399:  *     Routine:        ipc_kobject_notify
        !           400:  *     Purpose:
        !           401:  *             Deliver notifications to kobjects that care about them.
        !           402:  */
        !           403: 
        !           404: boolean_t
        !           405: ipc_kobject_notify(request_header, reply_header)
        !           406:        mach_msg_header_t *request_header;
        !           407:        mach_msg_header_t *reply_header;
        !           408: {
        !           409:        ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
        !           410: 
        !           411:        ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY;
        !           412:        switch (request_header->msgh_id) {
        !           413:                case MACH_NOTIFY_PORT_DELETED:
        !           414:                case MACH_NOTIFY_MSG_ACCEPTED:
        !           415:                case MACH_NOTIFY_PORT_DESTROYED:
        !           416:                case MACH_NOTIFY_NO_SENDERS:
        !           417:                case MACH_NOTIFY_SEND_ONCE:
        !           418:                case MACH_NOTIFY_DEAD_NAME:
        !           419:                break;
        !           420: 
        !           421:                default:
        !           422:                return FALSE;
        !           423:        }
        !           424:        switch (ip_kotype(port)) {
        !           425:                default:
        !           426:                return FALSE;
        !           427:        }
        !           428: }

unix.superglobalmegacorp.com

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