Annotation of Gnu-Mach/kern/ipc_mig.c, revision 1.1.1.3

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
1.1.1.2   root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: 
                     27: #include <mach/boolean.h>
                     28: #include <mach/port.h>
                     29: #include <mach/message.h>
                     30: #include <mach/thread_status.h>
1.1.1.3 ! root       31: #include <machine/locore.h>
1.1       root       32: #include <kern/ast.h>
1.1.1.3 ! root       33: #include <kern/debug.h>
1.1       root       34: #include <kern/ipc_tt.h>
1.1.1.3 ! root       35: #include <kern/syscall_subr.h>
1.1       root       36: #include <kern/thread.h>
                     37: #include <kern/task.h>
                     38: #include <kern/ipc_kobject.h>
1.1.1.3 ! root       39: #include <kern/ipc_tt.h>
1.1       root       40: #include <vm/vm_map.h>
                     41: #include <vm/vm_user.h>
                     42: #include <ipc/port.h>
                     43: #include <ipc/ipc_kmsg.h>
                     44: #include <ipc/ipc_entry.h>
                     45: #include <ipc/ipc_object.h>
                     46: #include <ipc/ipc_mqueue.h>
                     47: #include <ipc/ipc_space.h>
                     48: #include <ipc/ipc_port.h>
                     49: #include <ipc/ipc_pset.h>
                     50: #include <ipc/ipc_thread.h>
1.1.1.3 ! root       51: #include <ipc/mach_port.h>
        !            52: #include <device/dev_hdr.h>
1.1       root       53: #include <device/device_types.h>
1.1.1.3 ! root       54: #include <device/ds_routines.h>
1.1       root       55: 
                     56: /*
                     57:  *     Routine:        mach_msg_send_from_kernel
                     58:  *     Purpose:
                     59:  *             Send a message from the kernel.
                     60:  *
                     61:  *             This is used by the client side of KernelUser interfaces
                     62:  *             to implement SimpleRoutines.  Currently, this includes
                     63:  *             device_reply and memory_object messages.
                     64:  *     Conditions:
                     65:  *             Nothing locked.
                     66:  *     Returns:
                     67:  *             MACH_MSG_SUCCESS        Sent the message.
                     68:  *             MACH_SEND_INVALID_DATA  Bad destination port.
                     69:  */
                     70: 
                     71: mach_msg_return_t
                     72: mach_msg_send_from_kernel(
                     73:        mach_msg_header_t       *msg,
                     74:        mach_msg_size_t         send_size)
                     75: {
                     76:        ipc_kmsg_t kmsg;
                     77:        mach_msg_return_t mr;
                     78: 
                     79:        if (!MACH_PORT_VALID(msg->msgh_remote_port))
                     80:                return MACH_SEND_INVALID_DEST;
                     81: 
                     82:        mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
                     83:        if (mr != MACH_MSG_SUCCESS)
                     84:                panic("mach_msg_send_from_kernel");
                     85: 
                     86:        ipc_kmsg_copyin_from_kernel(kmsg);
                     87:        ipc_mqueue_send_always(kmsg);
                     88: 
                     89:        return MACH_MSG_SUCCESS;
                     90: }
                     91: 
                     92: mach_msg_return_t
                     93: mach_msg_rpc_from_kernel(msg, send_size, reply_size)
                     94:        mach_msg_header_t *msg;
                     95:        mach_msg_size_t send_size;
                     96:        mach_msg_size_t reply_size;
                     97: {
                     98:        panic("mach_msg_rpc_from_kernel"); /*XXX*/
                     99: }
                    100: 
                    101: /*
                    102:  *     Routine:        mach_msg_abort_rpc
                    103:  *     Purpose:
                    104:  *             Destroy the thread's ith_rpc_reply port.
                    105:  *             This will interrupt a mach_msg_rpc_from_kernel
                    106:  *             with a MACH_RCV_PORT_DIED return code.
                    107:  *     Conditions:
                    108:  *             Nothing locked.
                    109:  */
                    110: 
                    111: void
                    112: mach_msg_abort_rpc(thread)
                    113:        ipc_thread_t thread;
                    114: {
                    115:        ipc_port_t reply = IP_NULL;
                    116: 
                    117:        ith_lock(thread);
                    118:        if (thread->ith_self != IP_NULL) {
                    119:                reply = thread->ith_rpc_reply;
                    120:                thread->ith_rpc_reply = IP_NULL;
                    121:        }
                    122:        ith_unlock(thread);
                    123: 
                    124:        if (reply != IP_NULL)
                    125:                ipc_port_dealloc_reply(reply);
                    126: }
                    127: 
                    128: /*
                    129:  *     Routine:        mach_msg
                    130:  *     Purpose:
                    131:  *             Like mach_msg_trap except that message buffers
                    132:  *             live in kernel space.  Doesn't handle any options.
                    133:  *
                    134:  *             This is used by in-kernel server threads to make
                    135:  *             kernel calls, to receive request messages, and
                    136:  *             to send reply messages.
                    137:  *     Conditions:
                    138:  *             Nothing locked.
                    139:  *     Returns:
                    140:  */
                    141: 
                    142: mach_msg_return_t
                    143: mach_msg(msg, option, send_size, rcv_size, rcv_name, time_out, notify)
                    144:        mach_msg_header_t *msg;
                    145:        mach_msg_option_t option;
                    146:        mach_msg_size_t send_size;
                    147:        mach_msg_size_t rcv_size;
                    148:        mach_port_t rcv_name;
                    149:        mach_msg_timeout_t time_out;
                    150:        mach_port_t notify;
                    151: {
                    152:        ipc_space_t space = current_space();
                    153:        vm_map_t map = current_map();
                    154:        ipc_kmsg_t kmsg;
                    155:        mach_port_seqno_t seqno;
                    156:        mach_msg_return_t mr;
                    157: 
                    158:        if (option & MACH_SEND_MSG) {
                    159:                mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
                    160:                if (mr != MACH_MSG_SUCCESS)
                    161:                        panic("mach_msg");
                    162: 
                    163:                mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
                    164:                if (mr != MACH_MSG_SUCCESS) {
                    165:                        ikm_free(kmsg);
                    166:                        return mr;
                    167:                }
                    168: 
                    169:                do
                    170:                        mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
                    171:                                             MACH_MSG_TIMEOUT_NONE);
                    172:                while (mr == MACH_SEND_INTERRUPTED);
                    173:                assert(mr == MACH_MSG_SUCCESS);
                    174:        }
                    175: 
                    176:        if (option & MACH_RCV_MSG) {
                    177:                do {
                    178:                        ipc_object_t object;
                    179:                        ipc_mqueue_t mqueue;
                    180: 
                    181:                        mr = ipc_mqueue_copyin(space, rcv_name,
                    182:                                               &mqueue, &object);
                    183:                        if (mr != MACH_MSG_SUCCESS)
                    184:                                return mr;
                    185:                        /* hold ref for object; mqueue is locked */
                    186: 
                    187:                        mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
                    188:                                                MACH_MSG_SIZE_MAX,
                    189:                                                MACH_MSG_TIMEOUT_NONE,
                    190:                                                FALSE, IMQ_NULL_CONTINUE,
                    191:                                                &kmsg, &seqno);
                    192:                        /* mqueue is unlocked */
                    193:                        ipc_object_release(object);
                    194:                } while (mr == MACH_RCV_INTERRUPTED);
                    195:                if (mr != MACH_MSG_SUCCESS)
                    196:                        return mr;
                    197: 
                    198:                kmsg->ikm_header.msgh_seqno = seqno;
                    199: 
                    200:                if (rcv_size < kmsg->ikm_header.msgh_size) {
                    201:                        ipc_kmsg_copyout_dest(kmsg, space);
                    202:                        ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
                    203:                        return MACH_RCV_TOO_LARGE;
                    204:                }
                    205: 
                    206:                mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
                    207:                if (mr != MACH_MSG_SUCCESS) {
                    208:                        if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
                    209:                                ipc_kmsg_put_to_kernel(msg, kmsg,
                    210:                                                kmsg->ikm_header.msgh_size);
                    211:                        } else {
                    212:                                ipc_kmsg_copyout_dest(kmsg, space);
                    213:                                ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
                    214:                        }
                    215: 
                    216:                        return mr;
                    217:                }
                    218: 
                    219:                ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
                    220:        }
                    221: 
                    222:        return MACH_MSG_SUCCESS;
                    223: }
                    224: 
                    225: /*
                    226:  *     Routine:        mig_get_reply_port
                    227:  *     Purpose:
                    228:  *             Called by client side interfaces living in the kernel
                    229:  *             to get a reply port.  This port is used for
                    230:  *             mach_msg() calls which are kernel calls.
                    231:  */
                    232: 
                    233: mach_port_t
                    234: mig_get_reply_port(void)
                    235: {
                    236:        ipc_thread_t self = current_thread();
                    237: 
                    238:        if (self->ith_mig_reply == MACH_PORT_NULL)
                    239:                self->ith_mig_reply = mach_reply_port();
                    240: 
                    241:        return self->ith_mig_reply;
                    242: }
                    243: 
                    244: /*
                    245:  *     Routine:        mig_dealloc_reply_port
                    246:  *     Purpose:
                    247:  *             Called by client side interfaces to get rid of a reply port.
                    248:  *             Shouldn't ever be called inside the kernel, because
                    249:  *             kernel calls shouldn't prompt Mig to call it.
                    250:  */
                    251: 
                    252: void
                    253: mig_dealloc_reply_port(
                    254:        mach_port_t     reply_port)
                    255: {
                    256:        panic("mig_dealloc_reply_port");
                    257: }
                    258: 
                    259: /*
                    260:  *     Routine:        mig_put_reply_port
                    261:  *     Purpose:
1.1.1.2   root      262:  *             Called by client side interfaces after each RPC to
1.1       root      263:  *             let the client recycle the reply port if it wishes.
                    264:  */
                    265: void
                    266: mig_put_reply_port(
                    267:        mach_port_t     reply_port)
                    268: {
                    269: }
                    270: 
                    271: /*
                    272:  * mig_strncpy.c - by Joshua Block
                    273:  *
                    274:  * mig_strncp -- Bounded string copy.  Does what the library routine strncpy
1.1.1.2   root      275:  * OUGHT to do:  Copies the (null terminated) string in src into dest, a
1.1       root      276:  * buffer of length len.  Assures that the copy is still null terminated
                    277:  * and doesn't overflow the buffer, truncating the copy if necessary.
                    278:  *
                    279:  * Parameters:
1.1.1.2   root      280:  *
1.1       root      281:  *     dest - Pointer to destination buffer.
1.1.1.2   root      282:  *
1.1       root      283:  *     src - Pointer to source string.
1.1.1.2   root      284:  *
1.1       root      285:  *     len - Length of destination buffer.
                    286:  */
                    287: void mig_strncpy(dest, src, len)
                    288: char *dest, *src;
                    289: int len;
                    290: {
                    291:     int i;
                    292: 
                    293:     if (len <= 0)
                    294:        return;
                    295: 
                    296:     for (i=1; i<len; i++)
                    297:        if (! (*dest++ = *src++))
                    298:            return;
                    299: 
                    300:     *dest = '\0';
                    301:     return;
                    302: }
                    303: 
                    304: #define        fast_send_right_lookup(name, port, abort)                       \
                    305: MACRO_BEGIN                                                            \
                    306:        register ipc_space_t space = current_space();                   \
                    307:        register ipc_entry_t entry;                                     \
                    308:        register mach_port_index_t index = MACH_PORT_INDEX(name);       \
                    309:                                                                        \
                    310:        is_read_lock(space);                                            \
                    311:        assert(space->is_active);                                       \
                    312:                                                                        \
                    313:        if ((index >= space->is_table_size) ||                          \
                    314:            (((entry = &space->is_table[index])->ie_bits &              \
                    315:              (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) !=                \
                    316:             (MACH_PORT_GEN(name) | MACH_PORT_TYPE_SEND))) {            \
                    317:                is_read_unlock(space);                                  \
                    318:                abort;                                                  \
                    319:        }                                                               \
                    320:                                                                        \
                    321:        port = (ipc_port_t) entry->ie_object;                           \
                    322:        assert(port != IP_NULL);                                        \
                    323:                                                                        \
                    324:        ip_lock(port);                                                  \
                    325:        /* can safely unlock space now that port is locked */           \
                    326:        is_read_unlock(space);                                          \
                    327: MACRO_END
                    328: 
                    329: device_t
                    330: port_name_to_device(name)
                    331:        mach_port_t name;
                    332: {
                    333:        register ipc_port_t port;
                    334:        register device_t device;
1.1.1.2   root      335: 
1.1       root      336:        fast_send_right_lookup(name, port, goto abort);
                    337:        /* port is locked */
1.1.1.2   root      338: 
1.1       root      339:        /*
                    340:         * Now map the port object to a device object.
                    341:         * This is an inline version of dev_port_lookup().
                    342:         */
                    343:        if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
                    344:                device = (device_t) port->ip_kobject;
                    345:                device_reference(device);
                    346:                ip_unlock(port);
1.1.1.2   root      347:                return device;
1.1       root      348:        }
1.1.1.2   root      349: 
1.1       root      350:        ip_unlock(port);
                    351:        return DEVICE_NULL;
1.1.1.2   root      352: 
1.1       root      353:        /*
                    354:         * The slow case.  The port wasn't easily accessible.
                    355:         */
                    356:     abort: {
                    357:            ipc_port_t kern_port;
                    358:            kern_return_t kr;
1.1.1.2   root      359: 
1.1       root      360:            kr = ipc_object_copyin(current_space(), name,
                    361:                                   MACH_MSG_TYPE_COPY_SEND,
                    362:                                   (ipc_object_t *) &kern_port);
                    363:            if (kr != KERN_SUCCESS)
                    364:                    return DEVICE_NULL;
1.1.1.2   root      365: 
1.1       root      366:            device = dev_port_lookup(kern_port);
                    367:            if (IP_VALID(kern_port))
                    368:                    ipc_port_release_send(kern_port);
                    369:            return device;
                    370:     }
                    371: }
                    372: 
                    373: thread_t
                    374: port_name_to_thread(name)
                    375:        mach_port_t name;
                    376: {
                    377:        register ipc_port_t port;
                    378: 
                    379:        fast_send_right_lookup(name, port, goto abort);
                    380:        /* port is locked */
                    381: 
                    382:        if (ip_active(port) &&
                    383:            (ip_kotype(port) == IKOT_THREAD)) {
                    384:                register thread_t thread;
                    385: 
                    386:                thread = (thread_t) port->ip_kobject;
                    387:                assert(thread != THREAD_NULL);
                    388: 
                    389:                /* thread referencing is a bit complicated,
                    390:                   so don't bother to expand inline */
                    391:                thread_reference(thread);
                    392:                ip_unlock(port);
                    393: 
                    394:                return thread;
                    395:        }
                    396: 
                    397:        ip_unlock(port);
                    398:        return THREAD_NULL;
                    399: 
                    400:     abort: {
                    401:        thread_t thread;
                    402:        ipc_port_t kern_port;
                    403:        kern_return_t kr;
                    404: 
                    405:        kr = ipc_object_copyin(current_space(), name,
                    406:                               MACH_MSG_TYPE_COPY_SEND,
                    407:                               (ipc_object_t *) &kern_port);
                    408:        if (kr != KERN_SUCCESS)
                    409:                return THREAD_NULL;
                    410: 
                    411:        thread = convert_port_to_thread(kern_port);
                    412:        if (IP_VALID(kern_port))
                    413:                ipc_port_release_send(kern_port);
                    414: 
                    415:        return thread;
                    416:     }
                    417: }
                    418: 
                    419: task_t
                    420: port_name_to_task(name)
                    421:        mach_port_t name;
                    422: {
                    423:        register ipc_port_t port;
                    424: 
                    425:        fast_send_right_lookup(name, port, goto abort);
                    426:        /* port is locked */
                    427: 
                    428:        if (ip_active(port) &&
                    429:            (ip_kotype(port) == IKOT_TASK)) {
                    430:                register task_t task;
                    431: 
                    432:                task = (task_t) port->ip_kobject;
                    433:                assert(task != TASK_NULL);
                    434: 
                    435:                task_lock(task);
                    436:                /* can safely unlock port now that task is locked */
                    437:                ip_unlock(port);
                    438: 
                    439:                task->ref_count++;
                    440:                task_unlock(task);
                    441: 
                    442:                return task;
                    443:        }
                    444: 
                    445:        ip_unlock(port);
                    446:        return TASK_NULL;
                    447: 
                    448:     abort: {
                    449:        task_t task;
                    450:        ipc_port_t kern_port;
                    451:        kern_return_t kr;
                    452: 
                    453:        kr = ipc_object_copyin(current_space(), name,
                    454:                               MACH_MSG_TYPE_COPY_SEND,
                    455:                               (ipc_object_t *) &kern_port);
                    456:        if (kr != KERN_SUCCESS)
                    457:                return TASK_NULL;
                    458: 
                    459:        task = convert_port_to_task(kern_port);
                    460:        if (IP_VALID(kern_port))
                    461:                ipc_port_release_send(kern_port);
                    462: 
                    463:        return task;
                    464:     }
                    465: }
                    466: 
                    467: vm_map_t
                    468: port_name_to_map(
                    469:        mach_port_t     name)
                    470: {
                    471:        register ipc_port_t port;
                    472: 
                    473:        fast_send_right_lookup(name, port, goto abort);
                    474:        /* port is locked */
                    475: 
                    476:        if (ip_active(port) &&
                    477:            (ip_kotype(port) == IKOT_TASK)) {
                    478:                register vm_map_t map;
                    479: 
                    480:                map = ((task_t) port->ip_kobject)->map;
                    481:                assert(map != VM_MAP_NULL);
                    482: 
                    483:                simple_lock(&map->ref_lock);
                    484:                /* can safely unlock port now that map is locked */
                    485:                ip_unlock(port);
                    486: 
                    487:                map->ref_count++;
                    488:                simple_unlock(&map->ref_lock);
                    489: 
                    490:                return map;
                    491:        }
                    492: 
                    493:        ip_unlock(port);
                    494:        return VM_MAP_NULL;
                    495: 
                    496:     abort: {
                    497:        vm_map_t map;
                    498:        ipc_port_t kern_port;
                    499:        kern_return_t kr;
                    500: 
                    501:        kr = ipc_object_copyin(current_space(), name,
                    502:                               MACH_MSG_TYPE_COPY_SEND,
                    503:                               (ipc_object_t *) &kern_port);
                    504:        if (kr != KERN_SUCCESS)
                    505:                return VM_MAP_NULL;
                    506: 
                    507:        map = convert_port_to_map(kern_port);
                    508:        if (IP_VALID(kern_port))
                    509:                ipc_port_release_send(kern_port);
                    510: 
                    511:        return map;
                    512:     }
                    513: }
                    514: 
                    515: ipc_space_t
                    516: port_name_to_space(name)
                    517:        mach_port_t name;
                    518: {
                    519:        register ipc_port_t port;
                    520: 
                    521:        fast_send_right_lookup(name, port, goto abort);
                    522:        /* port is locked */
                    523: 
                    524:        if (ip_active(port) &&
                    525:            (ip_kotype(port) == IKOT_TASK)) {
                    526:                register ipc_space_t space;
                    527: 
                    528:                space = ((task_t) port->ip_kobject)->itk_space;
                    529:                assert(space != IS_NULL);
                    530: 
                    531:                simple_lock(&space->is_ref_lock_data);
                    532:                /* can safely unlock port now that space is locked */
                    533:                ip_unlock(port);
                    534: 
                    535:                space->is_references++;
                    536:                simple_unlock(&space->is_ref_lock_data);
                    537: 
                    538:                return space;
                    539:        }
                    540: 
                    541:        ip_unlock(port);
                    542:        return IS_NULL;
                    543: 
                    544:     abort: {
                    545:        ipc_space_t space;
                    546:        ipc_port_t kern_port;
                    547:        kern_return_t kr;
                    548: 
                    549:        kr = ipc_object_copyin(current_space(), name,
                    550:                               MACH_MSG_TYPE_COPY_SEND,
                    551:                               (ipc_object_t *) &kern_port);
                    552:        if (kr != KERN_SUCCESS)
                    553:                return IS_NULL;
                    554: 
                    555:        space = convert_port_to_space(kern_port);
                    556:        if (IP_VALID(kern_port))
                    557:                ipc_port_release_send(kern_port);
                    558: 
                    559:        return space;
                    560:     }
                    561: }
                    562: 
                    563: /*
                    564:  * Hack to translate a thread port to a thread pointer for calling
                    565:  * thread_get_state and thread_set_state.  This is only necessary
                    566:  * because the IPC message for these two operations overflows the
                    567:  * kernel stack.
                    568:  *
                    569:  * AARGH!
                    570:  */
                    571: 
                    572: kern_return_t thread_get_state_KERNEL(thread_port, flavor,
                    573:                        old_state, old_state_count)
                    574:        mach_port_t     thread_port;    /* port right for thread */
                    575:        int             flavor;
                    576:        thread_state_t  old_state;      /* pointer to OUT array */
                    577:        natural_t       *old_state_count;       /* IN/OUT */
                    578: {
                    579:        thread_t        thread;
                    580:        kern_return_t   result;
                    581: 
                    582:        thread = port_name_to_thread(thread_port);
                    583:        result = thread_get_state(thread, flavor, old_state, old_state_count);
                    584:        thread_deallocate(thread);
                    585: 
                    586:        return result;
                    587: }
                    588: 
                    589: kern_return_t thread_set_state_KERNEL(thread_port, flavor,
                    590:                        new_state, new_state_count)
                    591:        mach_port_t     thread_port;    /* port right for thread */
                    592:        int             flavor;
                    593:        thread_state_t  new_state;
                    594:        natural_t       new_state_count;
                    595: {
                    596:        thread_t        thread;
                    597:        kern_return_t   result;
                    598: 
                    599:        thread = port_name_to_thread(thread_port);
                    600:        result = thread_set_state(thread, flavor, new_state, new_state_count);
                    601:        thread_deallocate(thread);
                    602: 
                    603:        return result;
                    604: }
                    605: 
                    606: /*
                    607:  *     Things to keep in mind:
                    608:  *
                    609:  *     The idea here is to duplicate the semantics of the true kernel RPC.
                    610:  *     The destination port/object should be checked first, before anything
                    611:  *     that the user might notice (like ipc_object_copyin).  Return
                    612:  *     MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
                    613:  *     knows to fall back on an RPC.  For other return values, it won't
                    614:  *     retry with an RPC.  The retry might get a different (incorrect) rc.
                    615:  *     Return values are only set (and should only be set, with copyout)
                    616:  *     on successfull calls.
                    617:  */
                    618: 
                    619: kern_return_t
                    620: syscall_vm_map(
                    621:        mach_port_t     target_map,
                    622:        vm_offset_t     *address,
                    623:        vm_size_t       size,
                    624:        vm_offset_t     mask,
                    625:        boolean_t       anywhere,
                    626:        mach_port_t     memory_object,
                    627:        vm_offset_t     offset,
                    628:        boolean_t       copy,
                    629:        vm_prot_t       cur_protection,
                    630:        vm_prot_t       max_protection,
                    631:        vm_inherit_t    inheritance)
                    632: {
                    633:        vm_map_t                map;
                    634:        ipc_port_t              port;
                    635:        vm_offset_t             addr;
                    636:        kern_return_t           result;
                    637: 
                    638:        map = port_name_to_map(target_map);
                    639:        if (map == VM_MAP_NULL)
                    640:                return MACH_SEND_INTERRUPTED;
                    641: 
                    642:        if (MACH_PORT_VALID(memory_object)) {
                    643:                result = ipc_object_copyin(current_space(), memory_object,
                    644:                                           MACH_MSG_TYPE_COPY_SEND,
                    645:                                           (ipc_object_t *) &port);
                    646:                if (result != KERN_SUCCESS) {
                    647:                        vm_map_deallocate(map);
                    648:                        return result;
                    649:                }
                    650:        } else
                    651:                port = (ipc_port_t) memory_object;
                    652: 
                    653:        copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
                    654:        result = vm_map(map, &addr, size, mask, anywhere,
                    655:                        port, offset, copy,
                    656:                        cur_protection, max_protection, inheritance);
                    657:        if (result == KERN_SUCCESS)
                    658:                copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
                    659:        if (IP_VALID(port))
                    660:                ipc_port_release_send(port);
                    661:        vm_map_deallocate(map);
                    662: 
                    663:        return result;
                    664: }
                    665: 
                    666: kern_return_t syscall_vm_allocate(target_map, address, size, anywhere)
                    667:        mach_port_t             target_map;
                    668:        vm_offset_t             *address;
                    669:        vm_size_t               size;
                    670:        boolean_t               anywhere;
                    671: {
                    672:        vm_map_t                map;
                    673:        vm_offset_t             addr;
                    674:        kern_return_t           result;
                    675: 
                    676:        map = port_name_to_map(target_map);
                    677:        if (map == VM_MAP_NULL)
                    678:                return MACH_SEND_INTERRUPTED;
                    679: 
                    680:        copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
                    681:        result = vm_allocate(map, &addr, size, anywhere);
                    682:        if (result == KERN_SUCCESS)
                    683:                copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
                    684:        vm_map_deallocate(map);
                    685: 
                    686:        return result;
                    687: }
                    688: 
                    689: kern_return_t syscall_vm_deallocate(target_map, start, size)
                    690:        mach_port_t             target_map;
                    691:        vm_offset_t             start;
                    692:        vm_size_t               size;
                    693: {
                    694:        vm_map_t                map;
                    695:        kern_return_t           result;
                    696: 
                    697:        map = port_name_to_map(target_map);
                    698:        if (map == VM_MAP_NULL)
                    699:                return MACH_SEND_INTERRUPTED;
                    700: 
                    701:        result = vm_deallocate(map, start, size);
                    702:        vm_map_deallocate(map);
                    703: 
                    704:        return result;
                    705: }
                    706: 
                    707: kern_return_t syscall_task_create(parent_task, inherit_memory, child_task)
                    708:        mach_port_t     parent_task;
                    709:        boolean_t       inherit_memory;
                    710:        mach_port_t     *child_task;            /* OUT */
                    711: {
                    712:        task_t          t, c;
                    713:        ipc_port_t      port;
                    714:        mach_port_t     name;
                    715:        kern_return_t   result;
                    716: 
                    717:        t = port_name_to_task(parent_task);
                    718:        if (t == TASK_NULL)
                    719:                return MACH_SEND_INTERRUPTED;
                    720: 
                    721:        result = task_create(t, inherit_memory, &c);
                    722:        if (result == KERN_SUCCESS) {
                    723:                port = (ipc_port_t) convert_task_to_port(c);
                    724:                /* always returns a name, even for non-success return codes */
                    725:                (void) ipc_kmsg_copyout_object(current_space(),
                    726:                                               (ipc_object_t) port,
                    727:                                               MACH_MSG_TYPE_PORT_SEND, &name);
                    728:                copyout((char *)&name, (char *)child_task,
                    729:                        sizeof(mach_port_t));
                    730:        }
                    731:        task_deallocate(t);
                    732: 
                    733:        return result;
                    734: }
                    735: 
                    736: kern_return_t syscall_task_terminate(task)
                    737:        mach_port_t     task;
                    738: {
                    739:        task_t          t;
                    740:        kern_return_t   result;
                    741: 
                    742:        t = port_name_to_task(task);
                    743:        if (t == TASK_NULL)
                    744:                return MACH_SEND_INTERRUPTED;
                    745: 
                    746:        result = task_terminate(t);
                    747:        task_deallocate(t);
                    748: 
                    749:        return result;
                    750: }
                    751: 
                    752: kern_return_t syscall_task_suspend(task)
                    753:        mach_port_t     task;
                    754: {
                    755:        task_t          t;
                    756:        kern_return_t   result;
                    757: 
                    758:        t = port_name_to_task(task);
                    759:        if (t == TASK_NULL)
                    760:                return MACH_SEND_INTERRUPTED;
                    761: 
                    762:        result = task_suspend(t);
                    763:        task_deallocate(t);
                    764: 
                    765:        return result;
                    766: }
                    767: 
                    768: kern_return_t syscall_task_set_special_port(task, which_port, port_name)
                    769:        mach_port_t     task;
                    770:        int             which_port;
                    771:        mach_port_t     port_name;
                    772: {
                    773:        task_t          t;
                    774:        ipc_port_t      port;
                    775:        kern_return_t   result;
                    776: 
                    777:        t = port_name_to_task(task);
                    778:        if (t == TASK_NULL)
                    779:                return MACH_SEND_INTERRUPTED;
                    780: 
                    781:        if (MACH_PORT_VALID(port_name)) {
                    782:                result = ipc_object_copyin(current_space(), port_name,
                    783:                                           MACH_MSG_TYPE_COPY_SEND,
                    784:                                           (ipc_object_t *) &port);
                    785:                if (result != KERN_SUCCESS) {
                    786:                        task_deallocate(t);
                    787:                        return result;
                    788:                }
                    789:        } else
                    790:                port = (ipc_port_t) port_name;
                    791: 
                    792:        result = task_set_special_port(t, which_port, port);
                    793:        if ((result != KERN_SUCCESS) && IP_VALID(port))
                    794:                ipc_port_release_send(port);
                    795:        task_deallocate(t);
                    796: 
                    797:        return result;
                    798: }
                    799: 
                    800: kern_return_t
                    801: syscall_mach_port_allocate(task, right, namep)
                    802:        mach_port_t task;
                    803:        mach_port_right_t right;
                    804:        mach_port_t *namep;
                    805: {
                    806:        ipc_space_t space;
                    807:        mach_port_t name;
                    808:        kern_return_t kr;
                    809: 
                    810:        space = port_name_to_space(task);
                    811:        if (space == IS_NULL)
                    812:                return MACH_SEND_INTERRUPTED;
                    813: 
                    814:        kr = mach_port_allocate(space, right, &name);
                    815:        if (kr == KERN_SUCCESS)
                    816:                copyout((char *)&name, (char *)namep, sizeof(mach_port_t));
                    817:        is_release(space);
                    818: 
                    819:        return kr;
                    820: }
                    821: 
                    822: kern_return_t
                    823: syscall_mach_port_allocate_name(task, right, name)
                    824:        mach_port_t task;
                    825:        mach_port_right_t right;
                    826:        mach_port_t name;
                    827: {
                    828:        ipc_space_t space;
                    829:        kern_return_t kr;
                    830: 
                    831:        space = port_name_to_space(task);
                    832:        if (space == IS_NULL)
                    833:                return MACH_SEND_INTERRUPTED;
                    834: 
                    835:        kr = mach_port_allocate_name(space, right, name);
                    836:        is_release(space);
                    837: 
                    838:        return kr;
                    839: }
                    840: 
                    841: kern_return_t
                    842: syscall_mach_port_deallocate(task, name)
                    843:        mach_port_t task;
                    844:        mach_port_t name;
                    845: {
                    846:        ipc_space_t space;
                    847:        kern_return_t kr;
                    848: 
                    849:        space = port_name_to_space(task);
                    850:        if (space == IS_NULL)
                    851:                return MACH_SEND_INTERRUPTED;
                    852: 
                    853:        kr = mach_port_deallocate(space, name);
                    854:        is_release(space);
                    855: 
                    856:        return kr;
                    857: }
                    858: 
                    859: kern_return_t
                    860: syscall_mach_port_insert_right(task, name, right, rightType)
                    861:        mach_port_t task;
                    862:        mach_port_t name;
                    863:        mach_port_t right;
                    864:        mach_msg_type_name_t rightType;
                    865: {
                    866:        ipc_space_t space;
                    867:        ipc_object_t object;
                    868:        mach_msg_type_name_t newtype;
                    869:        kern_return_t kr;
                    870: 
                    871:        space = port_name_to_space(task);
                    872:        if (space == IS_NULL)
                    873:                return MACH_SEND_INTERRUPTED;
                    874: 
                    875:        if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
                    876:                is_release(space);
                    877:                return KERN_INVALID_VALUE;
                    878:        }
                    879: 
                    880:        if (MACH_PORT_VALID(right)) {
                    881:                kr = ipc_object_copyin(current_space(), right, rightType,
                    882:                                       &object);
                    883:                if (kr != KERN_SUCCESS) {
                    884:                        is_release(space);
                    885:                        return kr;
                    886:                }
                    887:        } else
                    888:                object = (ipc_object_t) right;
                    889:        newtype = ipc_object_copyin_type(rightType);
                    890: 
                    891:        kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype);
                    892:        if ((kr != KERN_SUCCESS) && IO_VALID(object))
                    893:                ipc_object_destroy(object, newtype);
                    894:        is_release(space);
                    895: 
                    896:        return kr;
                    897: }
                    898: 
                    899: kern_return_t syscall_thread_depress_abort(thread)
                    900:        mach_port_t     thread;
                    901: {
                    902:        thread_t        t;
                    903:        kern_return_t   result;
                    904: 
                    905:        t = port_name_to_thread(thread);
                    906:        if (t == THREAD_NULL)
                    907:                return MACH_SEND_INTERRUPTED;
                    908: 
                    909:        result = thread_depress_abort(t);
                    910:        thread_deallocate(t);
                    911: 
                    912:        return result;
                    913: }
                    914: 
                    915: /*
                    916:  * Device traps -- these are way experimental.
                    917:  */
                    918: 
                    919: extern io_return_t ds_device_write_trap();
                    920: extern io_return_t ds_device_writev_trap();
                    921: 
                    922: io_return_t
                    923: syscall_device_write_request(mach_port_t       device_name,
                    924:                             mach_port_t        reply_name,
                    925:                             dev_mode_t         mode,
                    926:                             recnum_t           recnum,
                    927:                             vm_offset_t        data,
                    928:                             vm_size_t          data_count)
                    929: {
                    930:        device_t        dev;
1.1.1.3 ! root      931:        /*ipc_port_t    reply_port;*/
1.1       root      932:        io_return_t     res;
                    933: 
                    934:        /*
                    935:         * First try to translate the device name.
                    936:         *
                    937:         * If this fails, return KERN_INVALID_CAPABILITY.
                    938:         * Caller knows that this most likely means that
                    939:         * device is not local to node and IPC should be used.
                    940:         *
                    941:         * If kernel doesn't do device traps, kern_invalid()
                    942:         * will be called instead of this function which will
                    943:         * return KERN_INVALID_ARGUMENT.
                    944:         */
                    945:        dev = port_name_to_device(device_name);
                    946:        if (dev == DEVICE_NULL)
                    947:                return KERN_INVALID_CAPABILITY;
                    948: 
                    949:        /*
                    950:         * Translate reply port.
                    951:         */
1.1.1.3 ! root      952:        /*if (reply_name == MACH_PORT_NULL)
1.1       root      953:                reply_port = IP_NULL;
1.1.1.3 ! root      954:        */
        !           955:        if (reply_name != MACH_PORT_NULL) {
1.1       root      956:                /* Homey don't play that. */
                    957:                device_deallocate(dev);
                    958:                return KERN_INVALID_RIGHT;
                    959:        }
                    960: 
                    961:        /* note: doesn't take reply_port arg yet. */
                    962:        res = ds_device_write_trap(dev, /*reply_port,*/
                    963:                                   mode, recnum,
                    964:                                   data, data_count);
                    965: 
                    966:        /*
                    967:         * Give up reference from port_name_to_device.
                    968:         */
                    969:        device_deallocate(dev);
                    970:        return res;
                    971: }
                    972: 
                    973: io_return_t
                    974: syscall_device_writev_request(mach_port_t      device_name,
                    975:                              mach_port_t       reply_name,
                    976:                              dev_mode_t        mode,
                    977:                              recnum_t          recnum,
                    978:                              io_buf_vec_t      *iovec,
                    979:                              vm_size_t         iocount)
                    980: {
                    981:        device_t        dev;
                    982:        ipc_port_t      reply_port;
                    983:        io_return_t     res;
                    984: 
                    985:        /*
                    986:         * First try to translate the device name.
                    987:         *
                    988:         * If this fails, return KERN_INVALID_CAPABILITY.
                    989:         * Caller knows that this most likely means that
                    990:         * device is not local to node and IPC should be used.
                    991:         *
                    992:         * If kernel doesn't do device traps, kern_invalid()
                    993:         * will be called instead of this function which will
                    994:         * return KERN_INVALID_ARGUMENT.
                    995:         */
                    996:        dev = port_name_to_device(device_name);
                    997:        if (dev == DEVICE_NULL)
                    998:                return KERN_INVALID_CAPABILITY;
                    999: 
                   1000:        /*
                   1001:         * Translate reply port.
                   1002:         */
                   1003:        if (reply_name == MACH_PORT_NULL)
                   1004:                reply_port = IP_NULL;
                   1005:        else {
                   1006:                /* Homey don't play that. */
                   1007:                device_deallocate(dev);
                   1008:                return KERN_INVALID_RIGHT;
                   1009:        }
                   1010: 
                   1011:        /* note: doesn't take reply_port arg yet. */
                   1012:        res = ds_device_writev_trap(dev, /*reply_port,*/
                   1013:                                    mode, recnum,
                   1014:                                    iovec, iocount);
                   1015: 
                   1016:        /*
                   1017:         * Give up reference from port_name_to_device.
                   1018:         */
                   1019:        device_deallocate(dev);
                   1020:        return res;
                   1021: }

unix.superglobalmegacorp.com

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