Example #1
0
static inline int init_tty_handle (struct shim_handle * hdl, bool write)
{
    struct shim_dentry * dent = NULL;
    int ret;

    if ((ret = path_lookupat(NULL, "/dev/tty", LOOKUP_OPEN, &dent)) < 0)
        return ret;

    int flags = (write ? O_WRONLY : O_RDONLY)|O_APPEND;
    struct shim_mount * fs = dent->fs;
    ret = fs->d_ops->open(hdl, dent, flags);
    if (ret < 0)
        return ret;

    set_handle_fs(hdl, fs);
    hdl->dentry = dent;
    hdl->flags = O_RDWR|O_APPEND|0100000;

    int size;
    char * path = dentry_get_path(dent, true, &size);
    if (path)
        qstrsetstr(&hdl->path, path, size);
    else
        qstrsetstr(&hdl->path, "/dev/tty", 8);

    return 0;
}
Example #2
0
int shim_do_readlink (const char * file, char * buf, int bufsize)
{
    if (!file)
        return -EFAULT;

    if (bufsize <= 0)
        return -EINVAL;

    /* The correct behavior is to return -EINVAL if file is not a
       symbolic link */
    return -EINVAL;

#if 0
    int ret;
    struct shim_dentry * dent = NULL;

    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent)) < 0)
        return ret;

    char * relpath;
    int len;

    relpath = dentry_get_path(dent, true, &len);
    if (len > bufsize)
        len = bufsize;
    memcpy(buf, relpath, len);
    put_dentry(dent);
    return len;
#endif
}
Example #3
0
int shim_do_truncate (const char * path, loff_t length)
{
    struct shim_dentry * dent = NULL;
    int ret = 0;

    if (!path || test_user_string(path))
        return -EFAULT;

    if ((ret = path_lookupat(NULL, path, 0, &dent, NULL)) < 0)
        return ret;

    struct shim_mount * fs = dent->fs;

    if (!fs || !fs->d_ops || !fs->d_ops->open) {
        ret = -EBADF;
        goto out;
    }

    if (!fs->fs_ops->truncate) {
        ret = -EROFS;
        goto out;
    }

    struct shim_handle * hdl = get_new_handle();

    if (!hdl) {
        ret = -ENOMEM;
        goto out;
    }

    hdl->fs = fs;

    if ((ret = fs->d_ops->open(hdl, dent, O_WRONLY)) < 0)
        goto out_handle;

    ret = fs->fs_ops->truncate(hdl, length);
    flush_handle(hdl);
out_handle:
    put_handle(hdl);
out:
    return ret;
}
Example #4
0
int shim_do_lstat (const char * file, struct stat * stat)
{
    if (!file)
        return -EFAULT;

    int ret;
    struct shim_dentry * dent = NULL;

    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent)) < 0)
        goto out;

    struct shim_mount * fs = dent->fs;

    if (!fs->d_ops || !fs->d_ops->stat) {
        ret = -EACCES;
        goto out_dentry;
    }

    ret = fs->d_ops->stat(dent, stat);
out_dentry:
    put_dentry(dent);
out:
    return ret;
}
Example #5
0
static int find_thread_link (const char * name, struct shim_qstr * link,
                             struct shim_dentry ** dentptr,
                             struct shim_thread ** threadptr)
{
    const char * next, * nextnext;
    int next_len;
    int pid = parse_thread_name(name, &next, &next_len, &nextnext);
    if (pid < 0)
        return pid;

    struct shim_thread * thread = lookup_thread(pid);
    struct shim_dentry * dent = NULL;
    int ret = 0;

    if (!thread)
        return -ENOENT;

    if (!thread->in_vm) {
        ret = -ENOENT;
        goto out;
    }

    lock(&thread->lock);

    if (next_len == static_strlen("root") && !memcmp(next, "root", next_len)) {
        dent = thread->root;
        get_dentry(dent);
    }

    if (next_len == static_strlen("cwd") && !memcmp(next, "cwd", next_len)) {
        dent = thread->cwd;
        get_dentry(dent);
    }

    if (next_len == static_strlen("exe") && !memcmp(next, "exe", next_len)) {
        struct shim_handle * exec = thread->exec;
        if (!exec->dentry) {
            unlock(&thread->lock);
            ret = -EINVAL;
            goto out;
        }
        dent = exec->dentry;
        get_dentry(dent);
    }

    unlock(&thread->lock);

    if (nextnext) {
        struct shim_dentry * next_dent = NULL;

        ret = path_lookupat(dent, nextnext, 0, &next_dent, dent->fs);
        if (ret < 0)
            goto out;

        put_dentry(dent);
        dent = next_dent;
    }

    if (link) {
        int size;
        char * path = dentry_get_path(dent, true, &size);
        qstrsetstr(link, path, size);
    }

    if (dentptr) {
        get_dentry(dent);
        *dentptr = dent;
    }

    if (threadptr) {
        get_thread(thread);
        *threadptr = thread;
    }

    ret = 0;
out:
    if (dent)
        put_dentry(dent);
    if (thread)
        put_thread(thread);
    return ret;
}
Example #6
0
static int isolate_fs (struct config_store * cfg, const char * path)
{
    struct shim_dentry * dent = NULL;
    int ret = 0;

    if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent)) < 0)
        return ret;

    if (!(dent->state & DENTRY_ISDIRECTORY)) {
        put_dentry(dent);
        return -ENOTDIR;
    }

    int dpath_len = 0;
    char * dpath = dentry_get_path(dent, true, &dpath_len);
    bool root_created = false;
    char t[CONFIG_MAX], u[CONFIG_MAX];

    int nkeys, keybuf_size = CONFIG_MAX;
    char * keybuf = __alloca(keybuf_size);

    while ((nkeys = get_config_entries(cfg, "fs.mount.other", keybuf,
                                       keybuf_size)) == -ENAMETOOLONG) {
        keybuf_size *= 2;
        keybuf = __alloca(keybuf_size);
    }

    if (nkeys <= 0)
        goto root;

    char k[CONFIG_MAX], p[CONFIG_MAX];
    memcpy(k, "fs.mount.other.", 15);
    const char * key = keybuf, * next = NULL;

    for (int n = 0 ; n < nkeys ; key = next, n++) {
        for (next = key ; *next ; next++);
        next++;
        int key_len = next - key - 1;
        memcpy(k + 15, key, key_len);
        char * kp = k + 15 + key_len;
        int ulen, plen;
        bool is_chroot = false;

        /* Skip FS that are not chroot */
        memcpy(kp, ".type", 6);
        if ((ret = get_config(cfg, k, t, CONFIG_MAX)) <= 0)
            continue;
        if (ret == 6 || !memcmp(t, "chroot", 6))
            is_chroot = true;

        memcpy(kp, ".uri", 5);
        if ((ulen = get_config(cfg, k, u, CONFIG_MAX)) <= 0)
            continue;

        memcpy(kp, ".path", 6);
        if ((plen = get_config(cfg, k, p, CONFIG_MAX)) <= 0)
            continue;

        if (plen >= dpath_len) {
            if (!memcmp(p, dpath, dpath_len)) {
                if (!p[dpath_len]) {
                    root_created = true;
                    debug("kept file rule: %s => %s\n", p, u);
                    continue;
                }
                if (p[dpath_len] != '/')
                    goto remove;
                /* keep this FS */
                continue;
            } else {
remove:
                if (!is_chroot) {
                    debug("kept file rule: %s => %s\n", p, u);
                    continue;
                }
                set_config(cfg, k, NULL);
                memcpy(kp, ".type", 6);
                set_config(cfg, k, NULL);
                memcpy(kp, ".uri", 5);
                set_config(cfg, k, NULL);
                debug("deleted file rule: %s => %s\n", p, u);
            }
        } else {
            if (memcmp(p, dpath, plen))
                goto remove;

            assert(dpath[plen]);
            if (dpath[plen] != '/')
                goto remove;
            if (!is_chroot) {
                root_created = true;
                debug("kept file rule: %s => %s\n", p, u);
                continue;
            }

            append_uri(u, ulen, dpath + plen, dpath_len - plen);
            set_config(cfg, k, dpath);
            memcpy(kp, "uri", 5);
            set_config(cfg, k, u);
            root_created = true;
            debug("added file rule: %s => %s\n", dpath, u);
        }
    }

root:
    if ((ret = get_config(cfg, "fs.mount.root.uri", u, CONFIG_MAX)) > 0) {
        int prefix_len = ret;

        if ((ret = get_config(cfg, "fs.mount.root.type", t, CONFIG_MAX)) > 0 &&
            ret == 6 && !memcmp(t, "chroot", 6)) {
            /* remove the root FS */
            set_config(cfg, "fs.mount.root.uri",  NULL);
            set_config(cfg, "fs.mount.root.type", NULL);
            debug("deleted file rule: root\n");


            /* add another FS as part of the original root FS */
            if (!root_created) {
                append_uri(u, prefix_len, dpath, dpath_len);
                set_config(cfg, "fs.mount.other.root.path", dpath);
                set_config(cfg, "fs.mount.other.root.uri",  u);
                set_config(cfg, "fs.mount.other.root.type", "chroot");
                debug("added file rule: %s => %s\n", dpath, u);
            }
        }
    }

    return 0;
}