Annotation of XNU/osfmk/kern/ipc_mig.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 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: #include <norma_vm.h>
                     54: #include <mach_rt.h>
                     55: #include <dipc.h>
                     56: 
                     57: #include <mach/boolean.h>
                     58: #include <mach/port.h>
                     59: #include <mach/thread_status.h>
                     60: #include <mach/mig_errors.h>
                     61: #include <mach/mach_types.h>
                     62: #include <mach/mach_traps.h>
                     63: #include <kern/ast.h>
                     64: #include <kern/ipc_mig.h>
                     65: #include <kern/task.h>
                     66: #include <kern/thread.h>
                     67: #include <kern/ipc_kobject.h>
                     68: #include <kern/misc_protos.h>
                     69: #include <vm/vm_map.h>
                     70: #include <vm/vm_user.h>
                     71: #include <ipc/port.h>
                     72: #include <ipc/ipc_kmsg.h>
                     73: #include <ipc/ipc_entry.h>
                     74: #include <ipc/ipc_object.h>
                     75: #include <ipc/ipc_mqueue.h>
                     76: #include <ipc/ipc_space.h>
                     77: #include <ipc/ipc_port.h>
                     78: #include <ipc/ipc_pset.h>
                     79: 
                     80: /* Default (zeroed) template for qos */
                     81: 
                     82: static mach_port_qos_t qos_template;
                     83: 
                     84: /*
                     85:  *     Routine:        mach_msg_send_from_kernel
                     86:  *     Purpose:
                     87:  *             Send a message from the kernel.
                     88:  *
                     89:  *             This is used by the client side of KernelUser interfaces
                     90:  *             to implement SimpleRoutines.  Currently, this includes
                     91:  *             memory_object messages.
                     92:  *     Conditions:
                     93:  *             Nothing locked.
                     94:  *     Returns:
                     95:  *             MACH_MSG_SUCCESS        Sent the message.
                     96:  *             MACH_SEND_INVALID_DATA  Bad destination port.
                     97:  */
                     98: 
                     99: mach_msg_return_t
                    100: mach_msg_send_from_kernel(
                    101:        mach_msg_header_t       *msg,
                    102:        mach_msg_size_t         send_size)
                    103: {
                    104:        ipc_kmsg_t kmsg;
                    105:        mach_msg_return_t mr;
                    106: 
                    107:        if (!MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port))
                    108:                return MACH_SEND_INVALID_DEST;
                    109: 
                    110:        mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
                    111:        if (mr != MACH_MSG_SUCCESS)
                    112:                panic("mach_msg_send_from_kernel");
                    113: 
                    114:        ipc_kmsg_copyin_from_kernel(kmsg);
                    115:        ipc_kmsg_send_always(kmsg);
                    116: 
                    117:        return MACH_MSG_SUCCESS;
                    118: }
                    119: 
                    120: /*
                    121:  *     Routine:        mach_msg_rpc_from_kernel
                    122:  *     Purpose:
                    123:  *             Send a message from the kernel and receive a reply.
                    124:  *             Uses ith_rpc_reply for the reply port.
                    125:  *
                    126:  *             This is used by the client side of KernelUser interfaces
                    127:  *             to implement Routines.
                    128:  *     Conditions:
                    129:  *             Nothing locked.
                    130:  *     Returns:
                    131:  *             MACH_MSG_SUCCESS        Sent the message.
                    132:  *             MACH_RCV_PORT_DIED      The reply port was deallocated.
                    133:  */
                    134: 
                    135: mach_msg_return_t
                    136: mach_msg_rpc_from_kernel(
                    137:        mach_msg_header_t       *msg,
                    138:        mach_msg_size_t         send_size,
                    139:        mach_msg_size_t         rcv_size)
                    140: {
                    141:        thread_t self = current_thread();
                    142:        ipc_port_t reply;
                    143:        ipc_kmsg_t kmsg;
                    144:        mach_port_seqno_t seqno;
                    145:        mach_msg_return_t mr;
                    146: 
                    147:        assert(MACH_PORT_VALID((mach_port_name_t)msg->msgh_remote_port));
                    148:        assert(msg->msgh_local_port == MACH_PORT_NULL);
                    149: 
                    150:        self->ith_scatter_list = MACH_MSG_BODY_NULL;
                    151: 
                    152:        mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
                    153:        if (mr != MACH_MSG_SUCCESS)
                    154:                panic("mach_msg_rpc_from_kernel");
                    155: 
                    156:        rpc_lock(self);
                    157: 
                    158:        reply = self->ith_rpc_reply;
                    159:        if (reply == IP_NULL) {
                    160:                rpc_unlock(self);
                    161:                reply = ipc_port_alloc_reply();
                    162:                rpc_lock(self);
                    163:                if ((reply == IP_NULL) ||
                    164:                    (self->ith_rpc_reply != IP_NULL))
                    165:                        panic("mach_msg_rpc_from_kernel");
                    166:                self->ith_rpc_reply = reply;
                    167:        }
                    168: 
                    169:        /* insert send-once right for the reply port */
                    170:        kmsg->ikm_header.msgh_local_port = reply;
                    171:        kmsg->ikm_header.msgh_bits |=
                    172:                MACH_MSGH_BITS(0, MACH_MSG_TYPE_MAKE_SEND_ONCE);
                    173: 
                    174:        ipc_port_reference(reply);
                    175:        rpc_unlock(self);
                    176: 
                    177:        ipc_kmsg_copyin_from_kernel(kmsg);
                    178: 
                    179:        ipc_kmsg_send_always(kmsg);
                    180: 
                    181:        for (;;) {
                    182:                ipc_mqueue_t mqueue;
                    183: 
                    184:                ip_lock(reply);
                    185:                if ( !ip_active(reply)) {
                    186:                        ip_unlock(reply);
                    187:                        ipc_port_release(reply);
                    188:                        return MACH_RCV_PORT_DIED;
                    189:                }
                    190:                if (!self->top_act || !self->top_act->active) {
                    191:                        ip_unlock(reply);
                    192:                        ipc_port_release(reply);
                    193:                        return MACH_RCV_INTERRUPTED;
                    194:                }
                    195: 
                    196:                assert(reply->ip_pset_count == 0);
                    197:                mqueue = &reply->ip_messages;
                    198:                ip_unlock(reply);
                    199: 
                    200:                mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
                    201:                                        MACH_MSG_SIZE_MAX,
                    202:                                        MACH_MSG_TIMEOUT_NONE,
                    203:                                        THREAD_INTERRUPTIBLE,
                    204:                                        &kmsg, &seqno);
                    205:                if (mr == MACH_MSG_SUCCESS)
                    206:                  {
                    207:                        break;
                    208:                  }
                    209: 
                    210:                assert(mr == MACH_RCV_INTERRUPTED);
                    211: 
                    212:                if (self->top_act && self->top_act->handlers) {
                    213:                        ipc_port_release(reply);
                    214:                        return(mr);
                    215:                }
                    216:        }
                    217:        ipc_port_release(reply);
                    218: 
                    219:        /*
                    220:         * XXXXX  Set manually for now ...
                    221:         *      No, why even bother, since the effort is wasted?
                    222:         *
                    223:        { mach_msg_format_0_trailer_t *trailer = (mach_msg_format_0_trailer_t *)
                    224:                ((vm_offset_t)&kmsg->ikm_header + kmsg->ikm_header.msgh_size);
                    225:        trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
                    226:        trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
                    227:        }
                    228:         *****/
                    229: 
                    230:        if (rcv_size < kmsg->ikm_header.msgh_size) {
                    231:                ipc_kmsg_copyout_dest(kmsg, ipc_space_reply);
                    232:                ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
                    233:                return MACH_RCV_TOO_LARGE;
                    234:        }
                    235: 
                    236:        /*
                    237:         *      We want to preserve rights and memory in reply!
                    238:         *      We don't have to put them anywhere; just leave them
                    239:         *      as they are.
                    240:         */
                    241: 
                    242:        ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply);
                    243:        ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
                    244:        return MACH_MSG_SUCCESS;
                    245: }
                    246: 
                    247: 
                    248: /************** These Calls are set up for kernel-loaded tasks   **************/
                    249: /************** Apple does not plan on supporting that. These    **************/
                    250: /************** need to be reworked to deal with the kernel      **************/
                    251: /************** proper to eliminate the kernel specific code MIG **************/
                    252: /************** must generate.                                   **************/
                    253: 
                    254: 
                    255: /*
                    256:  *     Routine:        mach_msg
                    257:  *     Purpose:
                    258:  *             Like mach_msg_overwrite_trap except that message buffers
                    259:  *             live in kernel space.  Doesn't handle any options.
                    260:  *
                    261:  *             This is used by in-kernel server threads to make
                    262:  *             kernel calls, to receive request messages, and
                    263:  *             to send reply messages.
                    264:  *     Conditions:
                    265:  *             Nothing locked.
                    266:  *     Returns:
                    267:  */
                    268: 
                    269: mach_msg_return_t
                    270: mach_msg_overwrite(
                    271:        mach_msg_header_t       *msg,
                    272:        mach_msg_option_t       option,
                    273:        mach_msg_size_t         send_size,
                    274:        mach_msg_size_t         rcv_size,
                    275:        mach_port_name_t        rcv_name,
                    276:        mach_msg_timeout_t      timeout,
                    277:        mach_port_name_t        notify,
                    278:        mach_msg_header_t       *rcv_msg,
                    279:         mach_msg_size_t                rcv_msg_size)
                    280: {
                    281:        ipc_space_t space = current_space();
                    282:        vm_map_t map = current_map();
                    283:        ipc_kmsg_t kmsg;
                    284:        mach_port_seqno_t seqno;
                    285:        mach_msg_return_t mr;
                    286:        mach_msg_format_0_trailer_t *trailer;
                    287: 
                    288:        if (option & MACH_SEND_MSG) {
                    289:                mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
                    290:                if (mr != MACH_MSG_SUCCESS)
                    291:                        panic("mach_msg");
                    292: 
                    293:                mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
                    294:                if (mr != MACH_MSG_SUCCESS) {
                    295:                        ikm_free(kmsg);
                    296:                        return mr;
                    297:                }
                    298: 
                    299:                do
                    300:                        mr = ipc_kmsg_send(kmsg, MACH_MSG_OPTION_NONE,
                    301:                                             MACH_MSG_TIMEOUT_NONE);
                    302:                while (mr == MACH_SEND_INTERRUPTED);
                    303:                assert(mr == MACH_MSG_SUCCESS);
                    304:        }
                    305: 
                    306:        if (option & MACH_RCV_MSG) {
                    307:                thread_t self = current_thread();
                    308: 
                    309:                self->ith_scatter_list = MACH_MSG_BODY_NULL;
                    310:                do {
                    311:                        ipc_object_t object;
                    312:                        ipc_mqueue_t mqueue;
                    313: 
                    314:                        mr = ipc_mqueue_copyin(space, rcv_name,
                    315:                                               &mqueue, &object);
                    316:                        if (mr != MACH_MSG_SUCCESS)
                    317:                                return mr;
                    318:                        /* hold ref for object */
                    319: 
                    320:                        mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
                    321:                                                MACH_MSG_SIZE_MAX,
                    322:                                                MACH_MSG_TIMEOUT_NONE,
                    323:                                                THREAD_ABORTSAFE,
                    324:                                                &kmsg, &seqno);
                    325:                        ipc_object_release(object);
                    326: 
                    327:                } while (mr == MACH_RCV_INTERRUPTED);
                    328:                if (mr != MACH_MSG_SUCCESS)
                    329:                        return mr;
                    330: 
                    331:                trailer = (mach_msg_format_0_trailer_t *) 
                    332:                    ((vm_offset_t)&kmsg->ikm_header + kmsg->ikm_header.msgh_size);
                    333:                if (option & MACH_RCV_TRAILER_MASK) {
                    334:                        trailer->msgh_seqno = seqno;
                    335:                        trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option);
                    336:                }
                    337: 
                    338:                if (rcv_size < (kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size)) {
                    339:                        ipc_kmsg_copyout_dest(kmsg, space);
                    340:                        ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
                    341:                        return MACH_RCV_TOO_LARGE;
                    342:                }
                    343: 
                    344:                mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL,
                    345:                                      MACH_MSG_BODY_NULL);
                    346:                if (mr != MACH_MSG_SUCCESS) {
                    347:                        if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
                    348:                                ipc_kmsg_put_to_kernel(msg, kmsg,
                    349:                                                kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size);
                    350:                        } else {
                    351:                                ipc_kmsg_copyout_dest(kmsg, space);
                    352:                                ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
                    353:                        }
                    354: 
                    355:                        return mr;
                    356:                }
                    357: 
                    358:                ipc_kmsg_put_to_kernel(msg, kmsg, 
                    359:                      kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size);
                    360:        }
                    361: 
                    362:        return MACH_MSG_SUCCESS;
                    363: }
                    364: 
                    365: /*
                    366:  *     Routine:        mig_get_reply_port
                    367:  *     Purpose:
                    368:  *             Called by client side interfaces living in the kernel
                    369:  *             to get a reply port.  This port is used for
                    370:  *             mach_msg() calls which are kernel calls.
                    371:  */
                    372: mach_port_t
                    373: mig_get_reply_port(void)
                    374: {
                    375:        thread_t self = current_thread();
                    376: 
                    377:        assert(self->ith_mig_reply == (mach_port_t)0);
                    378: 
                    379:        /* 
                    380:         * JMM - for now we have no real clients of this under the kernel
                    381:         * loaded server model because we only have one of those.  In order
                    382:         * to avoid MIG changes, we just return null here - and return]
                    383:         * references to ipc_port_t's instead of names.
                    384:         *
                    385:         * if (self->ith_mig_reply == MACH_PORT_NULL)
                    386:         *      self->ith_mig_reply = mach_reply_port();
                    387:         */
                    388:        return self->ith_mig_reply;
                    389: }
                    390: 
                    391: /*
                    392:  *     Routine:        mig_dealloc_reply_port
                    393:  *     Purpose:
                    394:  *             Called by client side interfaces to get rid of a reply port.
                    395:  *             Shouldn't ever be called inside the kernel, because
                    396:  *             kernel calls shouldn't prompt Mig to call it.
                    397:  */
                    398: 
                    399: void
                    400: mig_dealloc_reply_port(
                    401:        mach_port_t reply_port)
                    402: {
                    403:        panic("mig_dealloc_reply_port");
                    404: }
                    405: 
                    406: /*
                    407:  *     Routine:        mig_put_reply_port
                    408:  *     Purpose:
                    409:  *             Called by client side interfaces after each RPC to 
                    410:  *             let the client recycle the reply port if it wishes.
                    411:  */
                    412: void
                    413: mig_put_reply_port(
                    414:        mach_port_t reply_port)
                    415: {
                    416: }
                    417: 
                    418: /*
                    419:  * mig_strncpy.c - by Joshua Block
                    420:  *
                    421:  * mig_strncp -- Bounded string copy.  Does what the library routine strncpy
                    422:  * OUGHT to do:  Copies the (null terminated) string in src into dest, a 
                    423:  * buffer of length len.  Assures that the copy is still null terminated
                    424:  * and doesn't overflow the buffer, truncating the copy if necessary.
                    425:  *
                    426:  * Parameters:
                    427:  * 
                    428:  *     dest - Pointer to destination buffer.
                    429:  * 
                    430:  *     src - Pointer to source string.
                    431:  * 
                    432:  *     len - Length of destination buffer.
                    433:  */
                    434: int 
                    435: mig_strncpy(
                    436:        char    *dest,
                    437:        char    *src,
                    438:        int     len)
                    439: {
                    440:     int i;
                    441: 
                    442:     if (len <= 0)
                    443:        return 0;
                    444: 
                    445:     for (i=1; i<len; i++)
                    446:        if (! (*dest++ = *src++))
                    447:            return i;
                    448: 
                    449:     *dest = '\0';
                    450:     return i;
                    451: }
                    452: 
                    453: char *
                    454: mig_user_allocate(
                    455:        vm_size_t       size)
                    456: {
                    457:        return (char *)kalloc(size);
                    458: }
                    459: 
                    460: void
                    461: mig_user_deallocate(
                    462:        char            *data,
                    463:        vm_size_t       size)
                    464: {
                    465:        kfree((vm_offset_t)data, size);
                    466: }
                    467: 
                    468: thread_act_t
                    469: port_name_to_act(
                    470:        mach_port_name_t        name)
                    471: {
                    472:        thread_act_t thr_act;
                    473:        ipc_port_t kern_port;
                    474:        kern_return_t kr;
                    475: 
                    476:        if (MACH_PORT_VALID(name)) {
                    477:                kr = ipc_object_copyin(current_space(), name,
                    478:                                       MACH_MSG_TYPE_COPY_SEND,
                    479:                                       (ipc_object_t *) &kern_port);
                    480:                if (kr != KERN_SUCCESS)
                    481:                        return THR_ACT_NULL;
                    482: 
                    483:                thr_act = convert_port_to_act(kern_port);
                    484:                
                    485:                if (IP_VALID(kern_port))
                    486:                        ipc_port_release_send(kern_port);
                    487:        }
                    488:        return thr_act;
                    489: }
                    490: 
                    491: task_t
                    492: port_name_to_task(
                    493:        mach_port_name_t name)
                    494: {
                    495:        ipc_port_t kern_port;
                    496:        kern_return_t kr;
                    497:        task_t task = TASK_NULL;
                    498: 
                    499:        if (MACH_PORT_VALID(name)) {
                    500:                kr = ipc_object_copyin(current_space(), name,
                    501:                                       MACH_MSG_TYPE_COPY_SEND,
                    502:                                       (ipc_object_t *) &kern_port);
                    503:                if (kr != KERN_SUCCESS)
                    504:                        return TASK_NULL;
                    505: 
                    506:                task = convert_port_to_task(kern_port);
                    507: 
                    508:                if (IP_VALID(kern_port))
                    509:                        ipc_port_release_send(kern_port);
                    510:        }
                    511:        return task;
                    512: }

unix.superglobalmegacorp.com

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