Annotation of kernel/kern/ipc_kobject.c, revision 1.1.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.