diff --git a/doc/manual/rl-next/build-dir-mandatory.md b/doc/manual/rl-next/build-dir-mandatory.md new file mode 100644 index 000000000..ca5e808d6 --- /dev/null +++ b/doc/manual/rl-next/build-dir-mandatory.md @@ -0,0 +1,12 @@ +--- +synopsis: "`build-dir` no longer defaults to `temp-dir`" +cls: [3443] +category: "Fixes" +credits: [horrors] +--- + +The directory in which temporary build directories are created no longer defaults +to the value of the `temp-dir` setting to avoid builders making their directories +world-accessible. This behavior has been used to escape the build sandbox and can +cause build impurities even when not used maliciously. We now default to `builds` +in `NIX_STATE_DIR` (which is `/nix/var/nix/builds` in the default configuration). diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index b84af16aa..6e8d9480f 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -483,10 +483,12 @@ try { }); } + createDirs(settings.buildDir.get()); + /* Create a temporary directory where the build will take place. */ tmpDir = createTempDir( - settings.buildDir.get().value_or(""), + settings.buildDir.get(), "nix-build-" + std::string(drvPath.name()), false, false, diff --git a/lix/libstore/settings/build-dir.md b/lix/libstore/settings/build-dir.md index f518d52a5..738368622 100644 --- a/lix/libstore/settings/build-dir.md +++ b/lix/libstore/settings/build-dir.md @@ -1,14 +1,24 @@ --- name: build-dir internalName: buildDir -settingType: PathsSetting> -default: null +settingType: PathsSetting +defaultText: "`«nixStateDir»/builds`" +defaultExpr: nixStateDir + "/builds" --- The directory on the host, in which derivations' temporary build directories are created. -If not set, Nix will use the [`temp-dir`](#conf-temp-dir) setting if set, otherwise the system temporary directory indicated by the `TMPDIR` environment variable. -Note that builds are often performed by the Nix daemon, so its `TMPDIR` is used, and not that of the Nix command line interface. +If not set, Lix will use the `builds` subdirectory of its configured state directory. +Lix will create this directory automatically with suitable permissions if it does not +exist, otherwise its permissions must allow all users to traverse the directory (i.e. +it must have `o+x` set, in unix parlance) for non-sandboxed builds to work correctly. This is also the location where [`--keep-failed`](@docroot@/command-ref/opt-common.md#opt-keep-failed) leaves its files. If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir). + +> Important: +> +> `build-dir` must not be set to a world-writable directory. Placing temporary build +> directories in a world-writable place allows other users to access or modify build +> data that is currently in use. This alone is merely an impurity, but combined with +> another factor this has allowed malicious derivations to escape the build sandbox. diff --git a/misc/systemd/nix-daemon.conf.in b/misc/systemd/nix-daemon.conf.in index e7b264234..a0ddc4019 100644 --- a/misc/systemd/nix-daemon.conf.in +++ b/misc/systemd/nix-daemon.conf.in @@ -1 +1,2 @@ -d @localstatedir@/nix/daemon-socket 0755 root root - - +d @localstatedir@/nix/daemon-socket 0755 root root - - +d @localstatedir@/nix/builds 0755 root root 7d - diff --git a/tests/functional/build-remote-trustless-should-fail-0.sh b/tests/functional/build-remote-trustless-should-fail-0.sh index 1582a7b32..e938e63a2 100644 --- a/tests/functional/build-remote-trustless-should-fail-0.sh +++ b/tests/functional/build-remote-trustless-should-fail-0.sh @@ -8,7 +8,6 @@ requireSandboxSupport [[ $busybox =~ busybox ]] || skipTest "no busybox" unset NIX_STORE_DIR -unset NIX_STATE_DIR # We first build a dependency of the derivation we eventually want to # build. diff --git a/tests/functional/build-remote-trustless.sh b/tests/functional/build-remote-trustless.sh index 81e5253bf..a0733fd4a 100644 --- a/tests/functional/build-remote-trustless.sh +++ b/tests/functional/build-remote-trustless.sh @@ -2,7 +2,6 @@ requireSandboxSupport [[ $busybox =~ busybox ]] || skipTest "no busybox" unset NIX_STORE_DIR -unset NIX_STATE_DIR remoteDir=$TEST_ROOT/remote diff --git a/tests/functional/build-remote.sh b/tests/functional/build-remote.sh index d2a2132c1..36059d8a8 100644 --- a/tests/functional/build-remote.sh +++ b/tests/functional/build-remote.sh @@ -3,7 +3,6 @@ requireSandboxSupport # Avoid store dir being inside sandbox build-dir unset NIX_STORE_DIR -unset NIX_STATE_DIR function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; } diff --git a/tests/functional/check.sh b/tests/functional/check.sh index 653563971..cd5adc0ff 100644 --- a/tests/functional/check.sh +++ b/tests/functional/check.sh @@ -49,27 +49,6 @@ test_custom_build_dir() { } test_custom_build_dir -test_custom_temp_dir() { - # like test_custom_build_dir(), but uses the temp-dir setting instead - # build-dir inherits from temp-dir when build-dir is unset - local customTempDir="$TEST_ROOT/custom-temp-dir" - - mkdir "$customTempDir" - nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \ - --no-out-link --keep-failed --option temp-dir "$customTempDir" 2> $TEST_ROOT/log || status=$? - [ "$status" = "100" ] - [[ 1 == "$(count "$customTempDir/nix-build-"*)" ]] - local buildDir="$customTempDir/nix-build-"* - grep $checkBuildId $buildDir/checkBuildId - - # also check a separate code path that doesn't involve build-dir - # nix-shell uses temp-dir for its rcfile path - rcpath=$(NIX_BUILD_SHELL=$SHELL nix-shell check.nix -A deterministic --option temp-dir "$customTempDir" --run 'echo $0' 2> $TEST_ROOT/log) - # rcpath is /nix-shell-*/rc - [[ $rcpath = "$customTempDir"/* ]] -} -test_custom_temp_dir - test_shell_preserves_tmpdir() { # ensure commands that spawn interactive shells don't overwrite TMPDIR with temp-dir local envTempDir=$TEST_ROOT/shell-temp-dir-env diff --git a/tests/functional/supplementary-groups.sh b/tests/functional/supplementary-groups.sh index d18fb2414..c1a949eb4 100644 --- a/tests/functional/supplementary-groups.sh +++ b/tests/functional/supplementary-groups.sh @@ -10,7 +10,6 @@ unshare --mount --map-root-user bash <