diff options
Diffstat (limited to 'pkgs/games/build-support/build-sandbox')
-rw-r--r-- | pkgs/games/build-support/build-sandbox/default.nix | 31 | ||||
-rw-r--r-- | pkgs/games/build-support/build-sandbox/src/setup.c | 29 | ||||
-rw-r--r-- | pkgs/games/build-support/build-sandbox/src/setup.h | 2 |
3 files changed, 40 insertions, 22 deletions
diff --git a/pkgs/games/build-support/build-sandbox/default.nix b/pkgs/games/build-support/build-sandbox/default.nix index e4826405..fa4bac57 100644 --- a/pkgs/games/build-support/build-sandbox/default.nix +++ b/pkgs/games/build-support/build-sandbox/default.nix @@ -1,8 +1,23 @@ { stdenv, lib, pkgconfig, nix }: -drv: { extraSandboxPaths ? [], runtimePathVars ? [], ... }@attrs: - -stdenv.mkDerivation ({ +drv: { paths ? {}, ... }@attrs: + +let + # Extra paths that are required so they are created prior to bind-mounting. + pathsRequired = paths.required or []; + # Extra paths that are skipped if they don't exist. + pathsWanted = paths.wanted or []; + # Paths extracted from PATH-like environment variables, eg. LD_LIBRARY_PATH. + pathsRuntimeVars = paths.runtimeVars or []; + + # Create code snippets for params.c to add extra_mount() calls. + mkExtraMountParams = isRequired: lib.concatMapStringsSep "\n" (extra: let + escaped = lib.escape ["\\" "\""] extra; + reqBool = if isRequired then "true" else "false"; + code = "if (!extra_mount(\"${escaped}\", ${reqBool})) return false;"; + in "echo ${lib.escapeShellArg code} >> params.c"); + +in stdenv.mkDerivation ({ name = "${drv.name}-sandboxed"; src = ./src; @@ -37,10 +52,8 @@ stdenv.mkDerivation ({ echo 'if (!bind_mount("'"$dep"'", true, true)) return false;' >> params.c done - ${lib.concatMapStringsSep "\n" (extra: let - escaped = lib.escapeShellArg (lib.escape ["\\" "\""] extra); - result = "echo 'if (!extra_mount(\"'${escaped}'\")) return false;'"; - in "${result} >> params.c") extraSandboxPaths} + ${mkExtraMountParams true pathsRequired} + ${mkExtraMountParams false pathsWanted} echo 'return true; }' >> params.c @@ -50,7 +63,7 @@ stdenv.mkDerivation ({ escaped = lib.escapeShellArg (lib.escape ["\\" "\""] pathvar); fun = "mount_from_path_var"; result = "echo 'if (!${fun}(qs, \"'${escaped}'\")) return false;'"; - in "${result} >> params.c") runtimePathVars} + in "${result} >> params.c") pathsRuntimeVars} echo 'return true; }' >> params.c ''; @@ -59,4 +72,4 @@ stdenv.mkDerivation ({ buildInputs = [ nix ]; makeFlags = [ "BINDIR=${drv}/bin" ]; -} // removeAttrs attrs [ "extraSandboxPaths" "runtimePathVars" ]) +} // removeAttrs attrs [ "paths" ]) diff --git a/pkgs/games/build-support/build-sandbox/src/setup.c b/pkgs/games/build-support/build-sandbox/src/setup.c index 0b582e92..f351ce19 100644 --- a/pkgs/games/build-support/build-sandbox/src/setup.c +++ b/pkgs/games/build-support/build-sandbox/src/setup.c @@ -91,7 +91,7 @@ bool write_maps(pid_t parent_pid) return true; } -static bool makedirs(const char *path) +static bool makedirs(const char *path, bool do_cache) { char *tmp, *segment; @@ -103,13 +103,13 @@ static bool makedirs(const char *path) segment = dirname(tmp); if (!(segment[0] == '/' && segment[1] == '\0')) { - if (!makedirs(segment)) { + if (!makedirs(segment, do_cache)) { free(tmp); return false; } } - if (cache_path(cached_paths, path)) + if (!do_cache || cache_path(cached_paths, path)) (void)mkdir(path, 0755); free(tmp); return true; @@ -138,17 +138,14 @@ bool bind_mount(const char *path, bool restricted, bool resolve) if (restricted) mflags |= MS_NOSUID | MS_NODEV | MS_NOATIME; - if (resolve) { - if (realpath(path, src) == NULL) { - fprintf(stderr, "realpath of %s: %s\n", path, strerror(errno)); - return false; - } - } + if (resolve ? realpath(path, src) == NULL : access(path, F_OK) == -1) + // Skip missing mount source + return true; if ((target = get_mount_target(resolve ? src : path)) == NULL) return false; - if (!makedirs(target)) { + if (!makedirs(target, false)) { free(target); return false; } @@ -173,6 +170,10 @@ static bool bind_file(const char *path) { char *target, *tmp; + if (access(path, R_OK) == -1) + // Skip missing mount source + return true; + if ((target = get_mount_target(path)) == NULL) return false; @@ -182,7 +183,7 @@ static bool bind_file(const char *path) return false; } - if (!makedirs(dirname(tmp))) { + if (!makedirs(dirname(tmp), true)) { free(target); free(tmp); return false; @@ -452,12 +453,16 @@ static char *replace_env(const char *path) return replace_env_offset_free(path, base); } -bool extra_mount(const char *path) +bool extra_mount(const char *path, bool is_required) { char *expanded; + if ((expanded = replace_env(path)) == NULL) return false; + if (is_required && !makedirs(expanded, false)) + return false; + if (!bind_mount(expanded, true, true)) { free(expanded); return false; diff --git a/pkgs/games/build-support/build-sandbox/src/setup.h b/pkgs/games/build-support/build-sandbox/src/setup.h index c3b69699..fe882dc5 100644 --- a/pkgs/games/build-support/build-sandbox/src/setup.h +++ b/pkgs/games/build-support/build-sandbox/src/setup.h @@ -7,7 +7,7 @@ bool write_maps(pid_t parent_pid); bool bind_mount(const char *path, bool restricted, bool resolve); -bool extra_mount(const char *path); +bool extra_mount(const char *path, bool is_required); bool mount_from_path_var(struct query_state *qs, const char *name); bool setup_sandbox(void); |