|
@@ -1,399 +0,0 @@
|
|
|
-/* Copyright (C) 2014 Stony Brook University
|
|
|
- This file is part of Graphene Library OS.
|
|
|
-
|
|
|
- Graphene Library OS is free software: you can redistribute it and/or
|
|
|
- modify it under the terms of the GNU Lesser General Public License
|
|
|
- as published by the Free Software Foundation, either version 3 of the
|
|
|
- License, or (at your option) any later version.
|
|
|
-
|
|
|
- Graphene Library OS is distributed in the hope that it will be useful,
|
|
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
- GNU Lesser General Public License for more details.
|
|
|
-
|
|
|
- You should have received a copy of the GNU Lesser General Public License
|
|
|
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
-
|
|
|
-/*
|
|
|
- * shim_sandbox.c
|
|
|
- */
|
|
|
-
|
|
|
-#include <shim_internal.h>
|
|
|
-#include <shim_table.h>
|
|
|
-#include <shim_fs.h>
|
|
|
-#include <shim_checkpoint.h>
|
|
|
-#include <shim_ipc.h>
|
|
|
-
|
|
|
-#include <pal.h>
|
|
|
-#include <pal_error.h>
|
|
|
-
|
|
|
-#include <errno.h>
|
|
|
-
|
|
|
-struct shim_sandbox {
|
|
|
- unsigned int sbid;
|
|
|
- unsigned int parent_sbid;
|
|
|
- IDTYPE parent_vmid;
|
|
|
-};
|
|
|
-
|
|
|
-static struct shim_sandbox sandbox_info __attribute_migratable;
|
|
|
-
|
|
|
-static inline void append_uri (char * uri, int prefix_len, char * append,
|
|
|
- int append_len)
|
|
|
-{
|
|
|
- if (prefix_len && uri[prefix_len - 1] == ':') {
|
|
|
- if (append[0] == '/')
|
|
|
- memcpy(uri + prefix_len, append + 1, append_len);
|
|
|
- else
|
|
|
- memcpy(uri + prefix_len, append, append_len + 1);
|
|
|
- } else {
|
|
|
- if (append[0] != '/')
|
|
|
- uri[prefix_len++] = '/';
|
|
|
- memcpy(uri + prefix_len, append, append_len + 1);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-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, NULL)) < 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
- if (!(dent->state & DENTRY_ISDIRECTORY)) {
|
|
|
- put_dentry(dent);
|
|
|
- return -ENOTDIR;
|
|
|
- }
|
|
|
-
|
|
|
- size_t dpath_len = 0;
|
|
|
- char * dpath = dentry_get_path(dent, true, &dpath_len);
|
|
|
- bool root_created = false;
|
|
|
- char t[CONFIG_MAX], u[CONFIG_MAX];
|
|
|
- ssize_t prefix_len;
|
|
|
-
|
|
|
- int nkeys;
|
|
|
- ssize_t keybuf_size;
|
|
|
- keybuf_size = get_config_entries_size(cfg, "fs.mount.other");
|
|
|
- if (keybuf_size <= 0)
|
|
|
- goto root;
|
|
|
-
|
|
|
- char * keybuf = __alloca(keybuf_size);
|
|
|
- nkeys = get_config_entries(cfg, "fs.mount.other", keybuf, keybuf_size);
|
|
|
-
|
|
|
- if (nkeys <= 0)
|
|
|
- goto root;
|
|
|
-
|
|
|
- char k[CONFIG_MAX], p[CONFIG_MAX];
|
|
|
- char * tmp = strcpy_static(k, "fs.mount.other.", CONFIG_MAX);
|
|
|
- const char * key = keybuf, * next = NULL;
|
|
|
-
|
|
|
- for (int n = 0 ; n < nkeys ; key = next, n++) {
|
|
|
- for (next = key ; *next ; next++);
|
|
|
- next++;
|
|
|
- size_t key_len = next - key - 1;
|
|
|
- memcpy(tmp, key, key_len);
|
|
|
- char * kp = tmp + key_len;
|
|
|
- ssize_t ulen, plen;
|
|
|
- bool is_chroot = false;
|
|
|
-
|
|
|
- /* Skip FS that are not chroot */
|
|
|
- strcpy_static(kp, ".type", (size_t) ((k + CONFIG_MAX) - kp));
|
|
|
- if (get_config(cfg, k, t, CONFIG_MAX) <= 0)
|
|
|
- continue;
|
|
|
- if (strpartcmp_static(t, "chroot"))
|
|
|
- is_chroot = true;
|
|
|
-
|
|
|
- strcpy_static(kp, ".uri", (size_t) ((k + CONFIG_MAX) - kp));
|
|
|
- if ((ulen = get_config(cfg, k, u, CONFIG_MAX)) <= 0)
|
|
|
- continue;
|
|
|
-
|
|
|
- strcpy_static(kp, ".path", (size_t) ((k + CONFIG_MAX) - kp));
|
|
|
- if ((plen = get_config(cfg, k, p, CONFIG_MAX)) <= 0)
|
|
|
- continue;
|
|
|
-
|
|
|
- if ((size_t) 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);
|
|
|
- strcpy_static(kp, ".type", (size_t) ((k + CONFIG_MAX) - kp));
|
|
|
- set_config(cfg, k, NULL);
|
|
|
- strcpy_static(kp, ".uri", (size_t) ((k + CONFIG_MAX) - kp));
|
|
|
- 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);
|
|
|
- strcpy_static(kp, "uri", (size_t) ((k + CONFIG_MAX) - kp));
|
|
|
- set_config(cfg, k, u);
|
|
|
- root_created = true;
|
|
|
- debug("added file rule: %s => %s\n", dpath, u);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-root:
|
|
|
- if ((prefix_len = get_config(cfg, "fs.mount.root.uri", u, CONFIG_MAX)) > 0) {
|
|
|
- if (get_config(cfg, "fs.mount.root.type", t, CONFIG_MAX) > 0 &&
|
|
|
- strcmp_static(t, "chroot")) {
|
|
|
- /* 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;
|
|
|
-}
|
|
|
-
|
|
|
-static int isolate_net (struct config_store * cfg, struct net_sb * sb)
|
|
|
-{
|
|
|
- int nkeys;
|
|
|
- ssize_t keybuf_size;
|
|
|
- char k[CONFIG_MAX], * keybuf;
|
|
|
-
|
|
|
- keybuf_size = get_config_entries_size(cfg, "net.rules");
|
|
|
- if (keybuf_size <= 0)
|
|
|
- goto add;
|
|
|
-
|
|
|
- keybuf = __alloca(keybuf_size);
|
|
|
- nkeys = get_config_entries(cfg, "net.rules", keybuf, keybuf_size);
|
|
|
-
|
|
|
- if (nkeys <= 0)
|
|
|
- goto add;
|
|
|
-
|
|
|
- const char * key = keybuf, * next = NULL;
|
|
|
- memcpy(k, "net.rules.", 10);
|
|
|
-
|
|
|
- for (int n = 0 ; n < nkeys ; key = next, n++) {
|
|
|
- for (next = key ; *next ; next++);
|
|
|
- next++;
|
|
|
- int key_len = next - key - 1;
|
|
|
- memcpy(k + 10, key, key_len);
|
|
|
- k[10 + key_len] = 0;
|
|
|
-
|
|
|
- set_config(cfg, k, NULL);
|
|
|
- }
|
|
|
-
|
|
|
-add:
|
|
|
- if (!sb)
|
|
|
- return 0;
|
|
|
-
|
|
|
- for (int i = 0 ; i < sb->nrules ; i++) {
|
|
|
- struct net_sb_rule * r = &sb->rules[i];
|
|
|
- char u[CONFIG_MAX];
|
|
|
- int ulen;
|
|
|
- int family = -1;
|
|
|
-
|
|
|
-undo:
|
|
|
- ulen = 0;
|
|
|
- for (int turn = 0 ; turn < 2 ; turn++) {
|
|
|
- struct sockaddr * addr = turn ? r->r_addr : r->l_addr;
|
|
|
-
|
|
|
- if (turn)
|
|
|
- u[ulen++] = ':';
|
|
|
-
|
|
|
- if (!addr) {
|
|
|
- if (family == -1 || family == AF_INET)
|
|
|
- ulen += snprintf(u + ulen, CONFIG_MAX - ulen,
|
|
|
- "0.0.0.0:0-65535");
|
|
|
- else
|
|
|
- ulen += snprintf(u + ulen, CONFIG_MAX - ulen,
|
|
|
- "[0:0:0:0:0:0:0:0]:0-65535]");
|
|
|
- } else {
|
|
|
- if (addr->sa_family == AF_INET) {
|
|
|
- if (family == AF_INET6)
|
|
|
- goto next;
|
|
|
- family = AF_INET;
|
|
|
- struct sockaddr_in * saddr = (void *) addr;
|
|
|
- unsigned char * a = (void *) &saddr->sin_addr.s_addr;
|
|
|
- ulen += snprintf(u + ulen, CONFIG_MAX - ulen,
|
|
|
- "%d.%d.%d.%d:%u",
|
|
|
- a[0], a[1], a[2], a[3],
|
|
|
- __ntohs(saddr->sin_port));
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if (addr->sa_family == AF_INET6) {
|
|
|
- if (family == AF_INET)
|
|
|
- goto next;
|
|
|
- if (turn && family == -1) {
|
|
|
- family = AF_INET6;
|
|
|
- goto undo;
|
|
|
- }
|
|
|
-
|
|
|
- family = AF_INET6;
|
|
|
- struct sockaddr_in6 * saddr = (void *) addr;
|
|
|
- unsigned short * a = (void *) &saddr->sin6_addr.s6_addr;
|
|
|
- ulen += snprintf(u + ulen, CONFIG_MAX - ulen,
|
|
|
- "[%d:%d:%d:%d:%d:%d:%d:%d]:%u",
|
|
|
- a[0], a[1], a[2], a[3],
|
|
|
- a[4], a[5], a[6], a[7],
|
|
|
- __ntohs(saddr->sin6_port));
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- goto next;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- snprintf(k + 10, CONFIG_MAX - 10, "%d", i + 1);
|
|
|
- set_config(cfg, k, u);
|
|
|
- debug("added net rule: %s\n", u);
|
|
|
-next:
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void * __malloc (size_t size)
|
|
|
-{
|
|
|
- return malloc(size);
|
|
|
-}
|
|
|
-
|
|
|
-static void __free (void * mem)
|
|
|
-{
|
|
|
- free(mem);
|
|
|
-}
|
|
|
-
|
|
|
-struct cfg_arg {
|
|
|
- PAL_HANDLE handle;
|
|
|
- int offset;
|
|
|
-};
|
|
|
-
|
|
|
-static int __write (void * f, void * buf, int len)
|
|
|
-{
|
|
|
- struct cfg_arg * arg = f;
|
|
|
-
|
|
|
- int bytes = DkStreamWrite(arg->handle, arg->offset, len, buf, NULL);
|
|
|
- if (!bytes)
|
|
|
- return -PAL_ERRNO;
|
|
|
-
|
|
|
- arg->offset += bytes;
|
|
|
- return bytes;
|
|
|
-}
|
|
|
-
|
|
|
-long shim_do_sandbox_create (int flags, const char * fs_sb,
|
|
|
- struct net_sb * net_sb)
|
|
|
-{
|
|
|
- unsigned int sbid;
|
|
|
- char uri[24];
|
|
|
- PAL_HANDLE handle = NULL;
|
|
|
-
|
|
|
- int ret = create_handle("file:sandbox-", uri, 24, &handle, &sbid);
|
|
|
- if (ret < 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
- debug("create manifest: %s\n", uri);
|
|
|
-
|
|
|
- struct config_store * newcfg = __alloca(sizeof(struct config_store));
|
|
|
- memset(newcfg, 0, sizeof(struct config_store));
|
|
|
- newcfg->malloc = __malloc;
|
|
|
- newcfg->free = __free;
|
|
|
-
|
|
|
- if ((ret = copy_config(root_config, newcfg)) < 0) {
|
|
|
- newcfg = NULL;
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- if (flags & SANDBOX_FS)
|
|
|
- if ((ret = isolate_fs(newcfg, fs_sb)) < 0)
|
|
|
- goto err;
|
|
|
-
|
|
|
- if (flags & SANDBOX_NET)
|
|
|
- if ((ret = isolate_net(newcfg, net_sb)) < 0)
|
|
|
- goto err;
|
|
|
-
|
|
|
- struct cfg_arg arg;
|
|
|
- arg.handle = handle;
|
|
|
- arg.offset = 0;
|
|
|
-
|
|
|
- if ((ret = write_config(&arg, __write, newcfg)) < 0)
|
|
|
- goto err;
|
|
|
-
|
|
|
- DkObjectClose(handle);
|
|
|
-
|
|
|
- PAL_BOL success = DkProcessSandboxCreate(uri, flags & SANDBOX_RPC ?
|
|
|
- PAL_SANDBOX_PIPE : 0);
|
|
|
-
|
|
|
- if (!success) {
|
|
|
- ret = -PAL_ERRNO;
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- if (sandbox_info.sbid) {
|
|
|
- if (!sandbox_info.parent_sbid ||
|
|
|
- sandbox_info.parent_vmid != cur_process.vmid) {
|
|
|
- sandbox_info.parent_sbid = sandbox_info.sbid;
|
|
|
- sandbox_info.parent_vmid = cur_process.vmid;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (flags & SANDBOX_RPC)
|
|
|
- del_all_ipc_ports();
|
|
|
-
|
|
|
- if ((ret = free_config(root_config)) < 0)
|
|
|
- goto err;
|
|
|
-
|
|
|
- handle = DkStreamOpen(uri, PAL_ACCESS_RDONLY, 0, 0, 0);
|
|
|
-
|
|
|
- if (!handle)
|
|
|
- return -PAL_ERRNO;
|
|
|
-
|
|
|
- root_config = newcfg;
|
|
|
- sandbox_info.sbid = sbid;
|
|
|
- return sbid;
|
|
|
-
|
|
|
-err:
|
|
|
- free_config(newcfg);
|
|
|
- DkStreamDelete(handle, 0);
|
|
|
- DkObjectClose(handle);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-int shim_do_sandbox_attach (unsigned int sbid)
|
|
|
-{
|
|
|
- __UNUSED(sbid);
|
|
|
- return -ENOSYS;
|
|
|
-}
|
|
|
-
|
|
|
-long shim_do_sandbox_current (void)
|
|
|
-{
|
|
|
- return sandbox_info.sbid;
|
|
|
-}
|