about summary refs log tree commit diff
path: root/pkgs/games/build-support
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2017-09-28 21:29:58 +0200
committeraszlig <aszlig@redmoonstudios.org>2017-10-03 23:41:28 +0200
commitc82d21271656400f5e87e0baf46e61224fe1aaa9 (patch)
tree2bf2eec304bc90f84cbbd1366c2e324b699f8bb4 /pkgs/games/build-support
parent8d77ca6a9a94d4547a0abc8f27753fb7755e69cd (diff)
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 <aszlig@redmoonstudios.org>
Diffstat (limited to 'pkgs/games/build-support')
-rw-r--r--pkgs/games/build-support/build-sandbox/default.nix4
-rw-r--r--pkgs/games/build-support/build-sandbox/sandbox.c126
2 files changed, 112 insertions, 18 deletions
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;