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

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.1.4 ! root       40: #include <kern/ipc_mig.h>
1.1       root       41: #include <vm/vm_map.h>
                     42: #include <vm/vm_user.h>
                     43: #include <ipc/port.h>
                     44: #include <ipc/ipc_kmsg.h>
                     45: #include <ipc/ipc_entry.h>
                     46: #include <ipc/ipc_object.h>
                     47: #include <ipc/ipc_mqueue.h>
                     48: #include <ipc/ipc_space.h>
                     49: #include <ipc/ipc_port.h>
                     50: #include <ipc/ipc_pset.h>
                     51: #include <ipc/ipc_thread.h>
1.1.1.3   root       52: #include <ipc/mach_port.h>
                     53: #include <device/dev_hdr.h>
1.1       root       54: #include <device/device_types.h>
1.1.1.3   root       55: #include <device/ds_routines.h>
1.1       root       56: 
                     57: /*
                     58:  *     Routine:        mach_msg_send_from_kernel
                     59:  *     Purpose:
                     60:  *             Send a message from the kernel.
                     61:  *
                     62:  *             This is used by the client side of KernelUser interfaces
                     63:  *             to implement SimpleRoutines.  Currently, this includes
                     64:  *             device_reply and memory_object messages.
                     65:  *     Conditions:
                     66:  *             Nothing locked.
                     67:  *     Returns:
                     68:  *             MACH_MSG_SUCCESS        Sent the message.
                     69:  *             MACH_SEND_INVALID_DATA  Bad destination port.
                     70:  */
                     71: 
                     72: mach_msg_return_t
                     73: mach_msg_send_from_kernel(
                     74:        mach_msg_header_t       *msg,
                     75:        mach_msg_size_t         send_size)
                     76: {
                     77:        ipc_kmsg_t kmsg;
                     78:        mach_msg_return_t mr;
                     79: 
                     80:        if (!MACH_PORT_VALID(msg->msgh_remote_port))
                     81:                return MACH_SEND_INVALID_DEST;
                     82: 
                     83:        mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
                     84:        if (mr != MACH_MSG_SUCCESS)
                     85:                panic("mach_msg_send_from_kernel");
                     86: 
                     87:        ipc_kmsg_copyin_from_kernel(kmsg);
                     88:        ipc_mqueue_send_always(kmsg);
                     89: 
                     90:        return MACH_MSG_SUCCESS;
                     91: }
                     92: 
                     93: mach_msg_return_t
                     94: mach_msg_rpc_from_kernel(msg, send_size, reply_size)
1.1.1.4 ! root       95:        const mach_msg_header_t *msg;
1.1       root       96:        mach_msg_size_t send_size;
                     97:        mach_msg_size_t reply_size;
                     98: {
                     99:        panic("mach_msg_rpc_from_kernel"); /*XXX*/
                    100: }
                    101: 
                    102: /*
                    103:  *     Routine:        mach_msg_abort_rpc
                    104:  *     Purpose:
                    105:  *             Destroy the thread's ith_rpc_reply port.
                    106:  *             This will interrupt a mach_msg_rpc_from_kernel
                    107:  *             with a MACH_RCV_PORT_DIED return code.
                    108:  *     Conditions:
                    109:  *             Nothing locked.
                    110:  */
                    111: 
                    112: void
1.1.1.4 ! root      113: mach_msg_abort_rpc(ipc_thread_t thread)
1.1       root      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
1.1.1.4 ! root      143: mach_msg(
        !           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)
1.1       root      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:  *
1.1.1.4 ! root      274:  * mig_strncpy -- Bounded string copy.  Does what the library routine
        !           275:  * strncpy does: Copies the (null terminated) string in src into dest,
        !           276:  * a buffer of length len.  Returns the length of the destination
        !           277:  * string excluding the terminating null.
1.1       root      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:  */
1.1.1.4 ! root      287: vm_size_t
        !           288: mig_strncpy(dest, src, len)
        !           289:        char *dest;
        !           290:        const char *src;
        !           291:        int len;
        !           292: {
        !           293:        char *dest_ = dest;
        !           294:        int i;
        !           295: 
        !           296:        if (len <= 0)
        !           297:                return 0;
        !           298: 
        !           299:        for (i = 0; i < len; i++) {
        !           300:                if (! (*dest = *src))
        !           301:                        break;
        !           302:                dest++;
        !           303:                src++;
        !           304:        }
1.1       root      305: 
1.1.1.4 ! root      306:        return dest - dest_;
1.1       root      307: }
                    308: 
                    309: #define        fast_send_right_lookup(name, port, abort)                       \
                    310: MACRO_BEGIN                                                            \
1.1.1.4 ! root      311:        ipc_space_t space = current_space();                            \
        !           312:        ipc_entry_t entry;                                              \
        !           313:        mach_port_index_t index = MACH_PORT_INDEX(name);                \
1.1       root      314:                                                                        \
                    315:        is_read_lock(space);                                            \
                    316:        assert(space->is_active);                                       \
                    317:                                                                        \
                    318:        if ((index >= space->is_table_size) ||                          \
                    319:            (((entry = &space->is_table[index])->ie_bits &              \
                    320:              (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) !=                \
                    321:             (MACH_PORT_GEN(name) | MACH_PORT_TYPE_SEND))) {            \
                    322:                is_read_unlock(space);                                  \
                    323:                abort;                                                  \
                    324:        }                                                               \
                    325:                                                                        \
                    326:        port = (ipc_port_t) entry->ie_object;                           \
                    327:        assert(port != IP_NULL);                                        \
                    328:                                                                        \
                    329:        ip_lock(port);                                                  \
                    330:        /* can safely unlock space now that port is locked */           \
                    331:        is_read_unlock(space);                                          \
                    332: MACRO_END
                    333: 
                    334: device_t
1.1.1.4 ! root      335: port_name_to_device(mach_port_t name)
1.1       root      336: {
1.1.1.4 ! root      337:        ipc_port_t port;
        !           338:        device_t device;
1.1.1.2   root      339: 
1.1       root      340:        fast_send_right_lookup(name, port, goto abort);
                    341:        /* port is locked */
1.1.1.2   root      342: 
1.1       root      343:        /*
                    344:         * Now map the port object to a device object.
                    345:         * This is an inline version of dev_port_lookup().
                    346:         */
                    347:        if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
                    348:                device = (device_t) port->ip_kobject;
                    349:                device_reference(device);
                    350:                ip_unlock(port);
1.1.1.2   root      351:                return device;
1.1       root      352:        }
1.1.1.2   root      353: 
1.1       root      354:        ip_unlock(port);
                    355:        return DEVICE_NULL;
1.1.1.2   root      356: 
1.1       root      357:        /*
                    358:         * The slow case.  The port wasn't easily accessible.
                    359:         */
                    360:     abort: {
                    361:            ipc_port_t kern_port;
                    362:            kern_return_t kr;
1.1.1.2   root      363: 
1.1       root      364:            kr = ipc_object_copyin(current_space(), name,
                    365:                                   MACH_MSG_TYPE_COPY_SEND,
                    366:                                   (ipc_object_t *) &kern_port);
                    367:            if (kr != KERN_SUCCESS)
                    368:                    return DEVICE_NULL;
1.1.1.2   root      369: 
1.1       root      370:            device = dev_port_lookup(kern_port);
                    371:            if (IP_VALID(kern_port))
                    372:                    ipc_port_release_send(kern_port);
                    373:            return device;
                    374:     }
                    375: }
                    376: 
                    377: thread_t
1.1.1.4 ! root      378: port_name_to_thread(mach_port_t name)
1.1       root      379: {
1.1.1.4 ! root      380:        ipc_port_t port;
1.1       root      381: 
                    382:        fast_send_right_lookup(name, port, goto abort);
                    383:        /* port is locked */
                    384: 
                    385:        if (ip_active(port) &&
                    386:            (ip_kotype(port) == IKOT_THREAD)) {
1.1.1.4 ! root      387:                thread_t thread;
1.1       root      388: 
                    389:                thread = (thread_t) port->ip_kobject;
                    390:                assert(thread != THREAD_NULL);
                    391: 
                    392:                /* thread referencing is a bit complicated,
                    393:                   so don't bother to expand inline */
                    394:                thread_reference(thread);
                    395:                ip_unlock(port);
                    396: 
                    397:                return thread;
                    398:        }
                    399: 
                    400:        ip_unlock(port);
                    401:        return THREAD_NULL;
                    402: 
                    403:     abort: {
                    404:        thread_t thread;
                    405:        ipc_port_t kern_port;
                    406:        kern_return_t kr;
                    407: 
                    408:        kr = ipc_object_copyin(current_space(), name,
                    409:                               MACH_MSG_TYPE_COPY_SEND,
                    410:                               (ipc_object_t *) &kern_port);
                    411:        if (kr != KERN_SUCCESS)
                    412:                return THREAD_NULL;
                    413: 
                    414:        thread = convert_port_to_thread(kern_port);
                    415:        if (IP_VALID(kern_port))
                    416:                ipc_port_release_send(kern_port);
                    417: 
                    418:        return thread;
                    419:     }
                    420: }
                    421: 
                    422: task_t
1.1.1.4 ! root      423: port_name_to_task(mach_port_t name)
1.1       root      424: {
1.1.1.4 ! root      425:        ipc_port_t port;
1.1       root      426: 
                    427:        fast_send_right_lookup(name, port, goto abort);
                    428:        /* port is locked */
                    429: 
                    430:        if (ip_active(port) &&
                    431:            (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 ! root      432:                task_t task;
1.1       root      433: 
                    434:                task = (task_t) port->ip_kobject;
                    435:                assert(task != TASK_NULL);
                    436: 
                    437:                task_lock(task);
                    438:                /* can safely unlock port now that task is locked */
                    439:                ip_unlock(port);
                    440: 
                    441:                task->ref_count++;
                    442:                task_unlock(task);
                    443: 
                    444:                return task;
                    445:        }
                    446: 
                    447:        ip_unlock(port);
                    448:        return TASK_NULL;
                    449: 
                    450:     abort: {
                    451:        task_t task;
                    452:        ipc_port_t kern_port;
                    453:        kern_return_t kr;
                    454: 
                    455:        kr = ipc_object_copyin(current_space(), name,
                    456:                               MACH_MSG_TYPE_COPY_SEND,
                    457:                               (ipc_object_t *) &kern_port);
                    458:        if (kr != KERN_SUCCESS)
                    459:                return TASK_NULL;
                    460: 
                    461:        task = convert_port_to_task(kern_port);
                    462:        if (IP_VALID(kern_port))
                    463:                ipc_port_release_send(kern_port);
                    464: 
                    465:        return task;
                    466:     }
                    467: }
                    468: 
                    469: vm_map_t
                    470: port_name_to_map(
                    471:        mach_port_t     name)
                    472: {
1.1.1.4 ! root      473:        ipc_port_t port;
1.1       root      474: 
                    475:        fast_send_right_lookup(name, port, goto abort);
                    476:        /* port is locked */
                    477: 
                    478:        if (ip_active(port) &&
                    479:            (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 ! root      480:                vm_map_t map;
1.1       root      481: 
                    482:                map = ((task_t) port->ip_kobject)->map;
                    483:                assert(map != VM_MAP_NULL);
                    484: 
                    485:                simple_lock(&map->ref_lock);
                    486:                /* can safely unlock port now that map is locked */
                    487:                ip_unlock(port);
                    488: 
                    489:                map->ref_count++;
                    490:                simple_unlock(&map->ref_lock);
                    491: 
                    492:                return map;
                    493:        }
                    494: 
                    495:        ip_unlock(port);
                    496:        return VM_MAP_NULL;
                    497: 
                    498:     abort: {
                    499:        vm_map_t map;
                    500:        ipc_port_t kern_port;
                    501:        kern_return_t kr;
                    502: 
                    503:        kr = ipc_object_copyin(current_space(), name,
                    504:                               MACH_MSG_TYPE_COPY_SEND,
                    505:                               (ipc_object_t *) &kern_port);
                    506:        if (kr != KERN_SUCCESS)
                    507:                return VM_MAP_NULL;
                    508: 
                    509:        map = convert_port_to_map(kern_port);
                    510:        if (IP_VALID(kern_port))
                    511:                ipc_port_release_send(kern_port);
                    512: 
                    513:        return map;
                    514:     }
                    515: }
                    516: 
                    517: ipc_space_t
1.1.1.4 ! root      518: port_name_to_space(mach_port_t name)
1.1       root      519: {
1.1.1.4 ! root      520:        ipc_port_t port;
1.1       root      521: 
                    522:        fast_send_right_lookup(name, port, goto abort);
                    523:        /* port is locked */
                    524: 
                    525:        if (ip_active(port) &&
                    526:            (ip_kotype(port) == IKOT_TASK)) {
1.1.1.4 ! root      527:                ipc_space_t space;
1.1       root      528: 
                    529:                space = ((task_t) port->ip_kobject)->itk_space;
                    530:                assert(space != IS_NULL);
                    531: 
                    532:                simple_lock(&space->is_ref_lock_data);
                    533:                /* can safely unlock port now that space is locked */
                    534:                ip_unlock(port);
                    535: 
                    536:                space->is_references++;
                    537:                simple_unlock(&space->is_ref_lock_data);
                    538: 
                    539:                return space;
                    540:        }
                    541: 
                    542:        ip_unlock(port);
                    543:        return IS_NULL;
                    544: 
                    545:     abort: {
                    546:        ipc_space_t space;
                    547:        ipc_port_t kern_port;
                    548:        kern_return_t kr;
                    549: 
                    550:        kr = ipc_object_copyin(current_space(), name,
                    551:                               MACH_MSG_TYPE_COPY_SEND,
                    552:                               (ipc_object_t *) &kern_port);
                    553:        if (kr != KERN_SUCCESS)
                    554:                return IS_NULL;
                    555: 
                    556:        space = convert_port_to_space(kern_port);
                    557:        if (IP_VALID(kern_port))
                    558:                ipc_port_release_send(kern_port);
                    559: 
                    560:        return space;
                    561:     }
                    562: }
                    563: 
                    564: /*
                    565:  * Hack to translate a thread port to a thread pointer for calling
                    566:  * thread_get_state and thread_set_state.  This is only necessary
                    567:  * because the IPC message for these two operations overflows the
                    568:  * kernel stack.
                    569:  *
                    570:  * AARGH!
                    571:  */
                    572: 
1.1.1.4 ! root      573: kern_return_t thread_get_state_KERNEL(
        !           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 */
1.1       root      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: 
1.1.1.4 ! root      589: kern_return_t thread_set_state_KERNEL(
        !           590:        mach_port_t     thread_port,    /* port right for thread */
        !           591:        int             flavor,
        !           592:        thread_state_t  new_state,
        !           593:        natural_t       new_state_count)
1.1       root      594: {
                    595:        thread_t        thread;
                    596:        kern_return_t   result;
                    597: 
                    598:        thread = port_name_to_thread(thread_port);
                    599:        result = thread_set_state(thread, flavor, new_state, new_state_count);
                    600:        thread_deallocate(thread);
                    601: 
                    602:        return result;
                    603: }
                    604: 
                    605: /*
                    606:  *     Things to keep in mind:
                    607:  *
                    608:  *     The idea here is to duplicate the semantics of the true kernel RPC.
                    609:  *     The destination port/object should be checked first, before anything
                    610:  *     that the user might notice (like ipc_object_copyin).  Return
                    611:  *     MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
                    612:  *     knows to fall back on an RPC.  For other return values, it won't
                    613:  *     retry with an RPC.  The retry might get a different (incorrect) rc.
                    614:  *     Return values are only set (and should only be set, with copyout)
1.1.1.4 ! root      615:  *     on successful calls.
1.1       root      616:  */
                    617: 
                    618: kern_return_t
                    619: syscall_vm_map(
                    620:        mach_port_t     target_map,
                    621:        vm_offset_t     *address,
                    622:        vm_size_t       size,
                    623:        vm_offset_t     mask,
                    624:        boolean_t       anywhere,
                    625:        mach_port_t     memory_object,
                    626:        vm_offset_t     offset,
                    627:        boolean_t       copy,
                    628:        vm_prot_t       cur_protection,
                    629:        vm_prot_t       max_protection,
                    630:        vm_inherit_t    inheritance)
                    631: {
                    632:        vm_map_t                map;
                    633:        ipc_port_t              port;
                    634:        vm_offset_t             addr;
                    635:        kern_return_t           result;
                    636: 
                    637:        map = port_name_to_map(target_map);
                    638:        if (map == VM_MAP_NULL)
                    639:                return MACH_SEND_INTERRUPTED;
                    640: 
                    641:        if (MACH_PORT_VALID(memory_object)) {
                    642:                result = ipc_object_copyin(current_space(), memory_object,
                    643:                                           MACH_MSG_TYPE_COPY_SEND,
                    644:                                           (ipc_object_t *) &port);
                    645:                if (result != KERN_SUCCESS) {
                    646:                        vm_map_deallocate(map);
                    647:                        return result;
                    648:                }
                    649:        } else
                    650:                port = (ipc_port_t) memory_object;
                    651: 
1.1.1.4 ! root      652:        copyin(address, &addr, sizeof(vm_offset_t));
1.1       root      653:        result = vm_map(map, &addr, size, mask, anywhere,
                    654:                        port, offset, copy,
                    655:                        cur_protection, max_protection, inheritance);
                    656:        if (result == KERN_SUCCESS)
1.1.1.4 ! root      657:                copyout(&addr, address, sizeof(vm_offset_t));
1.1       root      658:        if (IP_VALID(port))
                    659:                ipc_port_release_send(port);
                    660:        vm_map_deallocate(map);
                    661: 
                    662:        return result;
                    663: }
                    664: 
1.1.1.4 ! root      665: kern_return_t syscall_vm_allocate(
        !           666:        mach_port_t             target_map,
        !           667:        vm_offset_t             *address,
        !           668:        vm_size_t               size,
        !           669:        boolean_t               anywhere)
1.1       root      670: {
                    671:        vm_map_t                map;
                    672:        vm_offset_t             addr;
                    673:        kern_return_t           result;
                    674: 
                    675:        map = port_name_to_map(target_map);
                    676:        if (map == VM_MAP_NULL)
                    677:                return MACH_SEND_INTERRUPTED;
                    678: 
1.1.1.4 ! root      679:        copyin(address, &addr, sizeof(vm_offset_t));
1.1       root      680:        result = vm_allocate(map, &addr, size, anywhere);
                    681:        if (result == KERN_SUCCESS)
1.1.1.4 ! root      682:                copyout(&addr, address, sizeof(vm_offset_t));
1.1       root      683:        vm_map_deallocate(map);
                    684: 
                    685:        return result;
                    686: }
                    687: 
1.1.1.4 ! root      688: kern_return_t syscall_vm_deallocate(
        !           689:        mach_port_t             target_map,
        !           690:        vm_offset_t             start,
        !           691:        vm_size_t               size)
1.1       root      692: {
                    693:        vm_map_t                map;
                    694:        kern_return_t           result;
                    695: 
                    696:        map = port_name_to_map(target_map);
                    697:        if (map == VM_MAP_NULL)
                    698:                return MACH_SEND_INTERRUPTED;
                    699: 
                    700:        result = vm_deallocate(map, start, size);
                    701:        vm_map_deallocate(map);
                    702: 
                    703:        return result;
                    704: }
                    705: 
1.1.1.4 ! root      706: kern_return_t syscall_task_create(
        !           707:        mach_port_t     parent_task,
        !           708:        boolean_t       inherit_memory,
        !           709:        mach_port_t     *child_task)            /* OUT */
1.1       root      710: {
                    711:        task_t          t, c;
                    712:        ipc_port_t      port;
                    713:        mach_port_t     name;
                    714:        kern_return_t   result;
                    715: 
                    716:        t = port_name_to_task(parent_task);
                    717:        if (t == TASK_NULL)
                    718:                return MACH_SEND_INTERRUPTED;
                    719: 
                    720:        result = task_create(t, inherit_memory, &c);
                    721:        if (result == KERN_SUCCESS) {
                    722:                port = (ipc_port_t) convert_task_to_port(c);
                    723:                /* always returns a name, even for non-success return codes */
                    724:                (void) ipc_kmsg_copyout_object(current_space(),
                    725:                                               (ipc_object_t) port,
                    726:                                               MACH_MSG_TYPE_PORT_SEND, &name);
1.1.1.4 ! root      727:                copyout(&name, child_task,
1.1       root      728:                        sizeof(mach_port_t));
                    729:        }
                    730:        task_deallocate(t);
                    731: 
                    732:        return result;
                    733: }
                    734: 
1.1.1.4 ! root      735: kern_return_t syscall_task_terminate(mach_port_t task)
1.1       root      736: {
                    737:        task_t          t;
                    738:        kern_return_t   result;
                    739: 
                    740:        t = port_name_to_task(task);
                    741:        if (t == TASK_NULL)
                    742:                return MACH_SEND_INTERRUPTED;
                    743: 
                    744:        result = task_terminate(t);
                    745:        task_deallocate(t);
                    746: 
                    747:        return result;
                    748: }
                    749: 
1.1.1.4 ! root      750: kern_return_t syscall_task_suspend(mach_port_t task)
1.1       root      751: {
                    752:        task_t          t;
                    753:        kern_return_t   result;
                    754: 
                    755:        t = port_name_to_task(task);
                    756:        if (t == TASK_NULL)
                    757:                return MACH_SEND_INTERRUPTED;
                    758: 
                    759:        result = task_suspend(t);
                    760:        task_deallocate(t);
                    761: 
                    762:        return result;
                    763: }
                    764: 
1.1.1.4 ! root      765: kern_return_t syscall_task_set_special_port(
        !           766:        mach_port_t     task,
        !           767:        int             which_port,
        !           768:        mach_port_t     port_name)
1.1       root      769: {
                    770:        task_t          t;
                    771:        ipc_port_t      port;
                    772:        kern_return_t   result;
                    773: 
                    774:        t = port_name_to_task(task);
                    775:        if (t == TASK_NULL)
                    776:                return MACH_SEND_INTERRUPTED;
                    777: 
                    778:        if (MACH_PORT_VALID(port_name)) {
                    779:                result = ipc_object_copyin(current_space(), port_name,
                    780:                                           MACH_MSG_TYPE_COPY_SEND,
                    781:                                           (ipc_object_t *) &port);
                    782:                if (result != KERN_SUCCESS) {
                    783:                        task_deallocate(t);
                    784:                        return result;
                    785:                }
                    786:        } else
                    787:                port = (ipc_port_t) port_name;
                    788: 
                    789:        result = task_set_special_port(t, which_port, port);
                    790:        if ((result != KERN_SUCCESS) && IP_VALID(port))
                    791:                ipc_port_release_send(port);
                    792:        task_deallocate(t);
                    793: 
                    794:        return result;
                    795: }
                    796: 
                    797: kern_return_t
1.1.1.4 ! root      798: syscall_mach_port_allocate(
        !           799:        mach_port_t             task,
        !           800:        mach_port_right_t       right,
        !           801:        mach_port_t             *namep)
1.1       root      802: {
                    803:        ipc_space_t space;
                    804:        mach_port_t name;
                    805:        kern_return_t kr;
                    806: 
                    807:        space = port_name_to_space(task);
                    808:        if (space == IS_NULL)
                    809:                return MACH_SEND_INTERRUPTED;
                    810: 
                    811:        kr = mach_port_allocate(space, right, &name);
                    812:        if (kr == KERN_SUCCESS)
1.1.1.4 ! root      813:                copyout(&name, namep, sizeof(mach_port_t));
1.1       root      814:        is_release(space);
                    815: 
                    816:        return kr;
                    817: }
                    818: 
                    819: kern_return_t
1.1.1.4 ! root      820: syscall_mach_port_allocate_name(
        !           821:        mach_port_t             task,
        !           822:        mach_port_right_t       right,
        !           823:        mach_port_t             name)
1.1       root      824: {
                    825:        ipc_space_t space;
                    826:        kern_return_t kr;
                    827: 
                    828:        space = port_name_to_space(task);
                    829:        if (space == IS_NULL)
                    830:                return MACH_SEND_INTERRUPTED;
                    831: 
                    832:        kr = mach_port_allocate_name(space, right, name);
                    833:        is_release(space);
                    834: 
                    835:        return kr;
                    836: }
                    837: 
                    838: kern_return_t
1.1.1.4 ! root      839: syscall_mach_port_deallocate(
        !           840:        mach_port_t task,
        !           841:        mach_port_t name)
1.1       root      842: {
                    843:        ipc_space_t space;
                    844:        kern_return_t kr;
                    845: 
                    846:        space = port_name_to_space(task);
                    847:        if (space == IS_NULL)
                    848:                return MACH_SEND_INTERRUPTED;
                    849: 
                    850:        kr = mach_port_deallocate(space, name);
                    851:        is_release(space);
                    852: 
                    853:        return kr;
                    854: }
                    855: 
                    856: kern_return_t
1.1.1.4 ! root      857: syscall_mach_port_insert_right(
        !           858:        mach_port_t             task,
        !           859:        mach_port_t             name,
        !           860:        mach_port_t             right,
        !           861:        mach_msg_type_name_t    rightType)
1.1       root      862: {
                    863:        ipc_space_t space;
                    864:        ipc_object_t object;
                    865:        mach_msg_type_name_t newtype;
                    866:        kern_return_t kr;
                    867: 
                    868:        space = port_name_to_space(task);
                    869:        if (space == IS_NULL)
                    870:                return MACH_SEND_INTERRUPTED;
                    871: 
                    872:        if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
                    873:                is_release(space);
                    874:                return KERN_INVALID_VALUE;
                    875:        }
                    876: 
                    877:        if (MACH_PORT_VALID(right)) {
                    878:                kr = ipc_object_copyin(current_space(), right, rightType,
                    879:                                       &object);
                    880:                if (kr != KERN_SUCCESS) {
                    881:                        is_release(space);
                    882:                        return kr;
                    883:                }
                    884:        } else
                    885:                object = (ipc_object_t) right;
                    886:        newtype = ipc_object_copyin_type(rightType);
                    887: 
                    888:        kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype);
                    889:        if ((kr != KERN_SUCCESS) && IO_VALID(object))
                    890:                ipc_object_destroy(object, newtype);
                    891:        is_release(space);
                    892: 
                    893:        return kr;
                    894: }
                    895: 
1.1.1.4 ! root      896: kern_return_t syscall_thread_depress_abort(mach_port_t thread)
1.1       root      897: {
                    898:        thread_t        t;
                    899:        kern_return_t   result;
                    900: 
                    901:        t = port_name_to_thread(thread);
                    902:        if (t == THREAD_NULL)
                    903:                return MACH_SEND_INTERRUPTED;
                    904: 
                    905:        result = thread_depress_abort(t);
                    906:        thread_deallocate(t);
                    907: 
                    908:        return result;
                    909: }
                    910: 
                    911: /*
                    912:  * Device traps -- these are way experimental.
                    913:  */
                    914: io_return_t
                    915: syscall_device_write_request(mach_port_t       device_name,
                    916:                             mach_port_t        reply_name,
                    917:                             dev_mode_t         mode,
                    918:                             recnum_t           recnum,
                    919:                             vm_offset_t        data,
                    920:                             vm_size_t          data_count)
                    921: {
                    922:        device_t        dev;
1.1.1.3   root      923:        /*ipc_port_t    reply_port;*/
1.1       root      924:        io_return_t     res;
                    925: 
                    926:        /*
                    927:         * First try to translate the device name.
                    928:         *
                    929:         * If this fails, return KERN_INVALID_CAPABILITY.
                    930:         * Caller knows that this most likely means that
                    931:         * device is not local to node and IPC should be used.
                    932:         *
                    933:         * If kernel doesn't do device traps, kern_invalid()
                    934:         * will be called instead of this function which will
                    935:         * return KERN_INVALID_ARGUMENT.
                    936:         */
                    937:        dev = port_name_to_device(device_name);
                    938:        if (dev == DEVICE_NULL)
                    939:                return KERN_INVALID_CAPABILITY;
                    940: 
                    941:        /*
                    942:         * Translate reply port.
                    943:         */
1.1.1.3   root      944:        /*if (reply_name == MACH_PORT_NULL)
1.1       root      945:                reply_port = IP_NULL;
1.1.1.3   root      946:        */
                    947:        if (reply_name != MACH_PORT_NULL) {
1.1       root      948:                /* Homey don't play that. */
                    949:                device_deallocate(dev);
                    950:                return KERN_INVALID_RIGHT;
                    951:        }
                    952: 
                    953:        /* note: doesn't take reply_port arg yet. */
                    954:        res = ds_device_write_trap(dev, /*reply_port,*/
                    955:                                   mode, recnum,
                    956:                                   data, data_count);
                    957: 
                    958:        /*
                    959:         * Give up reference from port_name_to_device.
                    960:         */
                    961:        device_deallocate(dev);
                    962:        return res;
                    963: }
                    964: 
                    965: io_return_t
                    966: syscall_device_writev_request(mach_port_t      device_name,
                    967:                              mach_port_t       reply_name,
                    968:                              dev_mode_t        mode,
                    969:                              recnum_t          recnum,
                    970:                              io_buf_vec_t      *iovec,
                    971:                              vm_size_t         iocount)
                    972: {
                    973:        device_t        dev;
1.1.1.4 ! root      974:        /*ipc_port_t    reply_port;*/
1.1       root      975:        io_return_t     res;
                    976: 
                    977:        /*
                    978:         * First try to translate the device name.
                    979:         *
                    980:         * If this fails, return KERN_INVALID_CAPABILITY.
                    981:         * Caller knows that this most likely means that
                    982:         * device is not local to node and IPC should be used.
                    983:         *
                    984:         * If kernel doesn't do device traps, kern_invalid()
                    985:         * will be called instead of this function which will
                    986:         * return KERN_INVALID_ARGUMENT.
                    987:         */
                    988:        dev = port_name_to_device(device_name);
                    989:        if (dev == DEVICE_NULL)
                    990:                return KERN_INVALID_CAPABILITY;
                    991: 
                    992:        /*
                    993:         * Translate reply port.
                    994:         */
1.1.1.4 ! root      995:        /*if (reply_name == MACH_PORT_NULL)
1.1       root      996:                reply_port = IP_NULL;
1.1.1.4 ! root      997:        */
        !           998:        if (reply_name != MACH_PORT_NULL) {
1.1       root      999:                /* Homey don't play that. */
                   1000:                device_deallocate(dev);
                   1001:                return KERN_INVALID_RIGHT;
                   1002:        }
                   1003: 
                   1004:        /* note: doesn't take reply_port arg yet. */
                   1005:        res = ds_device_writev_trap(dev, /*reply_port,*/
                   1006:                                    mode, recnum,
                   1007:                                    iovec, iocount);
                   1008: 
                   1009:        /*
                   1010:         * Give up reference from port_name_to_device.
                   1011:         */
                   1012:        device_deallocate(dev);
                   1013:        return res;
                   1014: }

unix.superglobalmegacorp.com

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