From c82d21271656400f5e87e0baf46e61224fe1aaa9 Mon Sep 17 00:00:00 2001 From: aszlig Date: Thu, 28 Sep 2017 21:29:58 +0200 Subject: pkgs/sandbox: Include basic runtime paths These paths are things such as /etc and /run but also the .Xauthority file, which contains the cookie to connect to the X server. What is still missing is access to the DRI libraries, which is a bit trickier, because we need to add those store paths at runtime and we need to also mount all of the dependencies. Signed-off-by: aszlig --- pkgs/games/build-support/build-sandbox/default.nix | 4 +- pkgs/games/build-support/build-sandbox/sandbox.c | 126 ++++++++++++++++++--- 2 files changed, 112 insertions(+), 18 deletions(-) (limited to 'pkgs/games/build-support') diff --git a/pkgs/games/build-support/build-sandbox/default.nix b/pkgs/games/build-support/build-sandbox/default.nix index 615f5358..2b45f3e5 100644 --- a/pkgs/games/build-support/build-sandbox/default.nix +++ b/pkgs/games/build-support/build-sandbox/default.nix @@ -33,10 +33,10 @@ stdenv.mkDerivation ({ echo 'static bool setup_app_paths(void) {' > params.c for dep in $runtimeDeps; do - echo 'if (!bind_mount("'"$dep"'", true)) return false;' >> params.c + echo 'if (!bind_mount("'"$dep"'", true, true)) return false;' >> params.c done - ${lib.concatMapStrings (extra: let + ${lib.concatMapStringsSep "\n" (extra: let escaped = lib.escapeShellArg (lib.escape ["\\" "\""] extra); result = "echo 'if (!extra_mount(\"'${escaped}'\")) return false;'"; in "${result} >> params.c") extraSandboxPaths} diff --git a/pkgs/games/build-support/build-sandbox/sandbox.c b/pkgs/games/build-support/build-sandbox/sandbox.c index 3f54378b..9df02296 100644 --- a/pkgs/games/build-support/build-sandbox/sandbox.c +++ b/pkgs/games/build-support/build-sandbox/sandbox.c @@ -109,33 +109,86 @@ static bool makedirs(const char *path) return true; } -static bool bind_mount(const char *path, bool restricted) +static char *get_mount_target(const char *path) +{ + size_t pathlen = strlen(path), rootdir_len = strlen(FS_ROOT_DIR); + char *target; + + if ((target = malloc(rootdir_len + pathlen + 1)) == NULL) { + perror("malloc mount target"); + return NULL; + } + + memcpy(target, FS_ROOT_DIR, rootdir_len); + memcpy(target + rootdir_len, path, pathlen + 1); + return target; +} + +static bool bind_mount(const char *path, bool restricted, bool resolve) { int mflags = MS_BIND | MS_REC; - size_t srclen, rootdir_len = strlen(FS_ROOT_DIR); - char src[PATH_MAX], target[PATH_MAX]; + char src[PATH_MAX], *target; if (restricted) mflags |= MS_NOSUID | MS_NODEV | MS_NOATIME; - if (realpath(path, src) == NULL) { - fprintf(stderr, "realpath of %s: %s\n", path, strerror(errno)); + if (resolve) { + if (realpath(path, src) == NULL) { + fprintf(stderr, "realpath of %s: %s\n", path, strerror(errno)); + return false; + } + } + + if ((target = get_mount_target(resolve ? src : path)) == NULL) + return false; + + if (!makedirs(target)) { + free(target); return false; } - if ((srclen = strlen(src)) > PATH_MAX - rootdir_len) { - fprintf(stderr, "`" FS_ROOT_DIR "%s' doesn't fit in PATH_MAX.\n", src); + if (mount(resolve ? src : path, target, "", mflags, NULL) == -1) { + fprintf(stderr, "mount %s to %s: %s\n", + resolve ? src : path, target, strerror(errno)); + free(target); return false; } - memcpy(target, FS_ROOT_DIR, rootdir_len); - memcpy(target + rootdir_len, src, srclen + 1); + free(target); + return true; +} + +static bool bind_file(const char *path) +{ + char *target, *tmp; + + if ((target = get_mount_target(path)) == NULL) + return false; + + if ((tmp = strdup(target)) == NULL) { + perror("strdup bind file target path"); + free(target); + return false; + } + + if (!makedirs(dirname(tmp))) { + free(target); + free(tmp); + return false; + } + + free(tmp); - if (!makedirs(target)) + if (creat(target, 0666) == -1) { + fprintf(stderr, "unable to create %s: %s\n", target, strerror(errno)); + free(target); return false; + } - if (mount(src, target, "", mflags, NULL) == -1) { - fprintf(stderr, "mount %s to %s: %s\n", src, target, strerror(errno)); + if (mount(path, target, "", MS_BIND, NULL) == -1) { + fprintf(stderr, "mount file %s to %s: %s\n", + path, target, strerror(errno)); + free(target); return false; } @@ -388,7 +441,7 @@ static bool extra_mount(const char *path) if ((expanded = replace_env(path)) == NULL) return false; - if (!bind_mount(expanded, true)) { + if (!bind_mount(expanded, true, true)) { free(expanded); return false; } @@ -397,6 +450,35 @@ static bool extra_mount(const char *path) return true; } +static bool setup_xauthority(void) +{ + char *xauth, *home; + bool result; + size_t homelen; + + if ((xauth = getenv("XAUTHORITY")) != NULL) + return bind_file(xauth); + + if ((home = getenv("HOME")) == NULL) { + fputs("Unable find $HOME.\n", stderr); + return false; + } + + homelen = strlen(home); + + if ((xauth = malloc(homelen + 13)) == NULL) { + perror("malloc xauth file path"); + return false; + } + + memcpy(xauth, home, homelen); + memcpy(xauth + homelen, "/.Xauthority", 13); + + result = bind_file(xauth); + free(xauth); + return result; +} + #include PARAMS_FILE static bool setup_chroot(void) @@ -410,13 +492,22 @@ static bool setup_chroot(void) return false; } - if (!bind_mount("/dev", false)) + if (!bind_mount("/etc", true, false)) + return false; + + if (!bind_mount("/dev", false, false)) return false; - if (!bind_mount("/proc", false)) + if (!bind_mount("/proc", false, false)) return false; - if (!bind_mount("/sys", false)) + if (!bind_mount("/sys", false, false)) + return false; + + if (!bind_mount("/run", false, false)) + return false; + + if (!bind_mount("/var/run", false, false)) return false; if (!bind_mount("/tmp", true, false)) @@ -425,6 +516,9 @@ static bool setup_chroot(void) if (!setup_app_paths()) return false; + if (!setup_xauthority()) + return false; + if (chroot(FS_ROOT_DIR) == -1) { perror("chroot"); return false; -- cgit 1.4.1