Example #1
0
int ipc_cld_join_callback (IPC_CALLBACK_ARGS)
{
    BEGIN_PROFILE_INTERVAL();
    debug("ipc callback from %u: IPC_CLD_JOIN\n", msg->src);
    add_ipc_port(port, msg->src, IPC_PORT_DIRCLD, NULL);
    SAVE_PROFILE_INTERVAL(ipc_cld_join_callback);
    return 0;
}
Example #2
0
int ipc_cld_exit_callback (IPC_CALLBACK_ARGS)
{
    BEGIN_PROFILE_INTERVAL();
    struct shim_ipc_cld_exit * msgin =
                (struct shim_ipc_cld_exit *) &msg->msg;

    debug("ipc callback from %u: IPC_CLD_EXIT(%u, %d)\n",
          msg->src, msgin->tid, msgin->exitcode);

    int ret = ipc_thread_exit(msg->src, msgin->tid, msgin->exitcode);
    SAVE_PROFILE_INTERVAL(ipc_cld_exit_callback);
    return ret;
}
Example #3
0
int ipc_cld_exit_send (IDTYPE tid, unsigned int exitcode)
{
    BEGIN_PROFILE_INTERVAL();
    int ret = 0;

    struct shim_ipc_msg * msg =
            create_ipc_msg_on_stack(IPC_CLD_EXIT,
                                    sizeof(struct shim_ipc_cld_exit), 0);
    struct shim_ipc_cld_exit * msgin =
                (struct shim_ipc_cld_exit *) &msg->msg;
    msgin->tid = tid;
    msgin->exitcode = exitcode;

    debug("ipc broadcast: IPC_CLD_EXIT(%u, %d)\n", tid, exitcode);

    ret = broadcast_ipc(msg, NULL, 0, IPC_PORT_DIRPRT|IPC_PORT_DIRCLD);
    SAVE_PROFILE_INTERVAL(ipc_cld_exit_send);
    return ret;
}
Example #4
0
static int migrate_execve (struct shim_cp_store * cpstore,
                           struct shim_process * process,
                           struct shim_thread * thread, va_list ap)
{
    struct shim_handle_map * handle_map = NULL;
    int ret;
    const char ** envp = va_arg (ap, const char **);
    size_t envsize = va_arg (ap, size_t);

    BEGIN_PROFILE_INTERVAL();

    if ((ret = dup_handle_map(&handle_map, thread->handle_map)) < 0)
        return ret;

    set_handle_map(thread, handle_map);

    if ((ret = close_cloexec_handle(handle_map)) < 0)
        return ret;

    SAVE_PROFILE_INTERVAL(close_CLOEXEC_files_for_exec);

    /* Now we start to migrate bookkeeping for exec.
       The data we need to migrate are:
            1. cur_threadrent thread
            2. cur_threadrent filesystem
            3. handle mapping
            4. each handle              */
    BEGIN_MIGRATION_DEF(execve, struct shim_process * proc,
                        struct shim_thread * thread,
                        const char ** envp, size_t envsize)
    {
        store->use_gipc = true;
        DEFINE_MIGRATE(process, proc, sizeof(struct shim_process), false);
        DEFINE_MIGRATE(all_mounts, NULL, 0, false);
        DEFINE_MIGRATE(running_thread, thread, sizeof(struct shim_thread),
                       false);
        DEFINE_MIGRATE(handle_map, thread->handle_map,
                       sizeof (struct shim_handle_map), true);
        DEFINE_MIGRATE(migratable, NULL, 0, false);
        DEFINE_MIGRATE(environ, envp, envsize, true);
    }
Example #5
0
int add_sysv_msg (struct shim_msg_handle * msgq,
                  long type, int size, const void * data,
                  struct sysv_client * src)
{
    BEGIN_PROFILE_INTERVAL();

    struct shim_handle * hdl = MSG_TO_HANDLE(msgq);
    int ret = 0;
    lock(hdl->lock);

    if (msgq->deleted) {
        ret = -EIDRM;
        goto out_locked;
    }

    if (!msgq->owned) {
        unlock(hdl->lock);
        ret = ipc_sysv_msgsnd_send(src->port, src->vmid, msgq->msqid,
                                   type, data, size, src->seq);
        goto out;
    }

    struct msg_type * mtype = __add_msg_type(type, &msgq->types,
                                             &msgq->ntypes,
                                             &msgq->maxtypes);

    if ((ret = __store_msg_qobjs(msgq, mtype, size, data)) < 0)
        goto out_locked;

    if (msgq->owned)
        __balance_sysv_score(&msg_policy, hdl, msgq->scores, MAX_SYSV_CLIENTS,
                             src, MSG_SND_SCORE);

    DkEventSet(msgq->event);
    ret  = 0;
out_locked:
    unlock(hdl->lock);
out:
    SAVE_PROFILE_INTERVAL(add_sysv_msg);
    return ret;
}
Example #6
0
int ipc_cld_join_send (IDTYPE dest)
{
    BEGIN_PROFILE_INTERVAL();
    struct shim_ipc_port * port = dest ?
                                  lookup_ipc_port(dest, IPC_PORT_DIRPRT) :
                                  get_parent_port(&dest);
    if (!port)
        return -ESRCH;

    struct shim_ipc_msg * msg =
                create_ipc_msg_on_stack(IPC_CLD_JOIN, 0, dest);

    debug("ipc send to %u: IPC_CLD_JOIN\n", dest);

    int ret = send_ipc_message(msg, port);

    add_ipc_port(port, dest, IPC_PORT_DIRPRT, NULL);
    put_ipc_port(port);
    SAVE_PROFILE_INTERVAL(ipc_cld_join_send);
    return ret;
}
Example #7
0
int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
                         const char ** envp)
{
    BEGIN_PROFILE_INTERVAL();

    struct shim_thread * cur_thread = get_cur_thread();
    int ret;

    if ((ret = close_cloexec_handle(cur_thread->handle_map)) < 0)
        return ret;

    SAVE_PROFILE_INTERVAL(close_CLOEXEC_files_for_exec);

    void * tcb = malloc(sizeof(__libc_tcb_t));
    if (!tcb)
        return -ENOMEM;

    populate_tls(tcb, false);
    __disable_preempt(&((__libc_tcb_t *) tcb)->shim_tcb); // Temporarily disable preemption
                                                          // during execve().
    debug("set tcb to %p\n", tcb);

    put_handle(cur_thread->exec);
    get_handle(hdl);
    cur_thread->exec = hdl;

    old_stack_top = cur_thread->stack_top;
    old_stack     = cur_thread->stack;
    old_stack_red = cur_thread->stack_red;
    cur_thread->stack_top = NULL;
    cur_thread->stack     = NULL;
    cur_thread->stack_red = NULL;

    initial_envp = NULL;
    new_argc = 0;
    for (const char ** a = argv ; *a ; a++, new_argc++);

    new_argcp = &new_argc;
    if ((ret = init_stack(argv, envp, &new_argcp, &new_argp,
                          REQUIRED_ELF_AUXV, &new_auxp)) < 0)
        return ret;

    SAVE_PROFILE_INTERVAL(alloc_new_stack_for_exec);

    SWITCH_STACK(new_argp);
    cur_thread = get_cur_thread();

    UPDATE_PROFILE_INTERVAL();

    DkVirtualMemoryFree(old_stack, old_stack_top - old_stack);
    DkVirtualMemoryFree(old_stack_red, old_stack - old_stack_red);

    if (bkeep_munmap(old_stack, old_stack_top - old_stack, 0) < 0 ||
        bkeep_munmap(old_stack_red, old_stack - old_stack_red, 0) < 0)
        BUG();

    remove_loaded_libraries();
    clean_link_map_list();
    SAVE_PROFILE_INTERVAL(unmap_loaded_binaries_for_exec);

    reset_brk();

    size_t count = DEFAULT_VMA_COUNT;
    struct shim_vma_val * vmas = malloc(sizeof(struct shim_vma_val) * count);

    if (!vmas)
        return -ENOMEM;

retry_dump_vmas:
    ret = dump_all_vmas(vmas, count);

    if (ret == -EOVERFLOW) {
        struct shim_vma_val * new_vmas
                = malloc(sizeof(struct shim_vma_val) * count * 2);
        if (!new_vmas) {
            free(vmas);
            return -ENOMEM;
        }
        free(vmas);
        vmas = new_vmas;
        count *= 2;
        goto retry_dump_vmas;
    }

    if (ret < 0) {
        free(vmas);
        return ret;
    }

    count = ret;
    for (struct shim_vma_val * vma = vmas ; vma < vmas + count ; vma++) {
        /* Don't free the current stack */
        if (vma->addr == cur_thread->stack)
            continue;

        /* Free all the mapped VMAs */
        if (!(vma->flags & VMA_UNMAPPED))
            DkVirtualMemoryFree(vma->addr, vma->length);

        /* Remove the VMAs */
        bkeep_munmap(vma->addr, vma->length, vma->flags);
    }

    free_vma_val_array(vmas, count);

    SAVE_PROFILE_INTERVAL(unmap_all_vmas_for_exec);

    if ((ret = load_elf_object(cur_thread->exec, NULL, 0)) < 0)
        shim_terminate(ret);

    init_brk_from_executable(cur_thread->exec);
    load_elf_interp(cur_thread->exec);

    SAVE_PROFILE_INTERVAL(load_new_executable_for_exec);

    cur_thread->robust_list = NULL;

#ifdef PROFILE
    if (ENTER_TIME)
        SAVE_PROFILE_INTERVAL_SINCE(syscall_execve, ENTER_TIME);
#endif

    debug("execve: start execution\n");
    execute_elf_object(cur_thread->exec, new_argcp, new_argp,
                       REQUIRED_ELF_AUXV, new_auxp);

    return 0;
}
Example #8
0
int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
                         const char ** envp)
{
    BEGIN_PROFILE_INTERVAL();

    struct shim_thread * cur_thread = get_cur_thread();
    int ret;

    if ((ret = close_cloexec_handle(cur_thread->handle_map)) < 0)
        return ret;

    SAVE_PROFILE_INTERVAL(close_CLOEXEC_files_for_exec);

    void * tcb = malloc(sizeof(__libc_tcb_t));
    if (!tcb)
        return -ENOMEM;

    populate_tls(tcb);

    put_handle(cur_thread->exec);
    get_handle(hdl);
    cur_thread->exec = hdl;

    old_stack_top = cur_thread->stack_top;
    old_stack     = cur_thread->stack;
    old_stack_red = cur_thread->stack_red;
    cur_thread->stack_top = NULL;
    cur_thread->stack     = NULL;
    cur_thread->stack_red = NULL;

    initial_envp = NULL;
    new_argc = 0;
    for (const char ** a = argv ; *a ; a++, new_argc++);

    if ((ret = init_stack(argv, envp, &new_argp,
                          REQUIRED_ELF_AUXV, &new_auxp)) < 0)
        return ret;

    SAVE_PROFILE_INTERVAL(alloc_new_stack_for_exec);

    switch_stack(new_argp);
    cur_thread = get_cur_thread();

    UPDATE_PROFILE_INTERVAL();

    DkVirtualMemoryFree(old_stack, old_stack_top - old_stack);
    DkVirtualMemoryFree(old_stack_red, old_stack - old_stack_red);
    int flags = VMA_INTERNAL;
    bkeep_munmap(old_stack, old_stack_top - old_stack, &flags);
    bkeep_munmap(old_stack_red, old_stack - old_stack_red, &flags);

    remove_loaded_libraries();
    clean_link_map_list();
    SAVE_PROFILE_INTERVAL(unmap_loaded_binaries_for_exec);

    init_brk();
    unmap_all_vmas();
    SAVE_PROFILE_INTERVAL(unmap_all_vmas_for_exec);

    if ((ret = load_elf_object(cur_thread->exec, NULL, 0)) < 0)
        shim_terminate();

    load_elf_interp(cur_thread->exec);

    SAVE_PROFILE_INTERVAL(load_new_executable_for_exec);

    debug("execve: start execution\n");
    execute_elf_object(cur_thread->exec, new_argc, new_argp,
                       REQUIRED_ELF_AUXV, new_auxp);

    return 0;
}
Example #9
0
int get_sysv_msg (struct shim_msg_handle * msgq,
                  long type, int size, void * data, int flags,
                  struct sysv_client * src)
{
    BEGIN_PROFILE_INTERVAL();
    int ret = 0;
    struct shim_handle * hdl = MSG_TO_HANDLE(msgq);
    struct msg_item * msg = NULL;
    struct msg_type * alltypes = NULL, * mtype = NULL;
    lock(hdl->lock);

    if (msgq->deleted) {
        ret = -EIDRM;
        goto out_locked;
    }

    if (msgq->owned) {
        __balance_sysv_score(&msg_policy, hdl, msgq->scores, MAX_SYSV_CLIENTS,
                             src, MSG_RCV_SCORE);

        if (!msgq->owned && src) {
            struct shim_ipc_info * owner = msgq->owner;
            assert(owner);
            ret = ipc_sysv_movres_send(src, owner->vmid,
                                       qstrgetstr(&owner->uri), msgq->lease,
                                       msgq->msqid, SYSV_MSGQ);
            goto out_locked;
        }
    }

    if (!msgq->owned) {
        IDTYPE msqid = msgq->msqid;

        if (src) {
            struct shim_ipc_info * owner = msgq->owner;
            ret = owner ?
                  ipc_sysv_movres_send(src, owner->vmid,
                                       qstrgetstr(&owner->uri), msgq->lease,
                                       msgq->msqid, SYSV_MSGQ) :
                  -ECONNREFUSED;
            goto out_locked;
        }

unowned:
        unlock(hdl->lock);
        ret = ipc_sysv_msgrcv_send(msqid, type, flags, data, size);
        if (ret != -EAGAIN &&
            ret != -ECONNREFUSED)
            goto out;

        lock(hdl->lock);

        if (!msgq->owned)
            goto out_locked;
    }

    while (1) {
        if (alltypes != msgq->types || !mtype || mtype->type != type) {
            alltypes = msgq->types;
            mtype = __find_msg_type(type, alltypes, msgq->ntypes);
        }

        if (mtype && mtype->msgs) {
            msg = mtype->msgs;
            if (msg->size > size && !(flags & MSG_NOERROR)) {
                ret = -E2BIG;
                goto out;
            }
            break;
        }

        if (flags & IPC_NOWAIT || src)
            break;

        unlock(hdl->lock);
        while (!DkObjectsWaitAny(1, &msgq->event, NO_TIMEOUT));
        lock(hdl->lock);

        if (!msgq->owned)
            goto unowned;
    }

    if (!msg) {
        ret = (!(flags & IPC_NOWAIT) && src) ?
            __add_msg_req(msgq, mtype, size, flags, src) : -ENOMSG;
        goto out_locked;
    }

    if ((ret = __load_msg_qobjs(msgq, mtype, msg, data)) < 0)
        goto out_locked;;

    ret = msg->size;
out_locked:
    unlock(hdl->lock);
out:
    SAVE_PROFILE_INTERVAL(get_sysv_msg);
    return ret;
}