mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
libstore: Don't default build-dir to temp-dir, store setting
If a build directory is accessible to other users it is possible to smuggle data in and out of build directories. Usually this is only a build purity problem, but in combination with other issues it can be used to break out of a build sandbox. to prevent this we default to using a subdirectory of nixStateDir (which is more restrictive). (cherry picked from pennae Lix commit 55b416f6897fb0d8a9315a530a9b7f0914458ded) (store setting done by roberth)
This commit is contained in:
parent
9af4c267c6
commit
88b7db1ba4
11 changed files with 62 additions and 15 deletions
9
doc/manual/rl-next/build-dir-mandatory.md
Normal file
9
doc/manual/rl-next/build-dir-mandatory.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
synopsis: "`build-dir` no longer defaults to `$TMPDIR`"
|
||||
---
|
||||
|
||||
The directory in which temporary build directories are created no longer defaults
|
||||
to `TMPDIR` or `/tmp`, to avoid builders making their directories
|
||||
world-accessible. This behavior allowed escaping 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).
|
|
@ -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 -
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "nix/util/abstract-setting-to-json.hh"
|
||||
#include "nix/util/compute-levels.hh"
|
||||
#include "nix/util/signals.hh"
|
||||
#include "nix/util/types.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
|
|
@ -697,14 +697,7 @@ public:
|
|||
|
||||
Setting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
|
||||
R"(
|
||||
The directory on the host, in which derivations' temporary build directories are created.
|
||||
|
||||
If not set, Nix uses 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.
|
||||
|
||||
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 contains this directory instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir).
|
||||
Override the `build-dir` store setting for all stores that have this setting.
|
||||
)"};
|
||||
|
||||
Setting<PathSet> allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps",
|
||||
|
|
|
@ -34,7 +34,38 @@ struct OptimiseStats
|
|||
uint64_t bytesFreed = 0;
|
||||
};
|
||||
|
||||
struct LocalStoreConfig : std::enable_shared_from_this<LocalStoreConfig>, virtual LocalFSStoreConfig
|
||||
struct LocalBuildStoreConfig : virtual LocalFSStoreConfig {
|
||||
|
||||
private:
|
||||
/**
|
||||
Input for computing the build directory. See `getBuildDir()`.
|
||||
*/
|
||||
Setting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
|
||||
R"(
|
||||
The directory on the host, in which derivations' temporary build directories are created.
|
||||
|
||||
If not set, Nix will use the `builds` subdirectory of its configured state directory.
|
||||
|
||||
Note that builds are often performed by the Nix daemon, so its `build-dir` applies.
|
||||
|
||||
Nix 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).
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> `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.
|
||||
)"};
|
||||
public:
|
||||
Path getBuildDir() const;
|
||||
};
|
||||
|
||||
struct LocalStoreConfig : std::enable_shared_from_this<LocalStoreConfig>, virtual LocalFSStoreConfig, virtual LocalBuildStoreConfig
|
||||
{
|
||||
using LocalFSStoreConfig::LocalFSStoreConfig;
|
||||
|
||||
|
|
|
@ -77,6 +77,18 @@ std::string LocalStoreConfig::doc()
|
|||
;
|
||||
}
|
||||
|
||||
Path LocalBuildStoreConfig::getBuildDir() const
|
||||
{
|
||||
if (settings.buildDir.get().has_value()) {
|
||||
return *settings.buildDir.get();
|
||||
}
|
||||
if (buildDir.get().has_value()) {
|
||||
return *buildDir.get();
|
||||
}
|
||||
|
||||
return stateDir.get() + "/builds";
|
||||
}
|
||||
|
||||
ref<Store> LocalStore::Config::openStore() const
|
||||
{
|
||||
return make_ref<LocalStore>(ref{shared_from_this()});
|
||||
|
|
|
@ -725,9 +725,13 @@ void DerivationBuilderImpl::startBuilder()
|
|||
throw BuildError(msg);
|
||||
}
|
||||
|
||||
auto buildDir = getLocalStore(store).config->getBuildDir();
|
||||
|
||||
createDirs(buildDir);
|
||||
|
||||
/* Create a temporary directory where the build will take
|
||||
place. */
|
||||
topTmpDir = createTempDir(settings.buildDir.get().value_or(""), "nix-build-" + std::string(drvPath.name()), 0700);
|
||||
topTmpDir = createTempDir(buildDir, "nix-build-" + std::string(drvPath.name()), 0700);
|
||||
setBuildTmpDir();
|
||||
assert(!tmpDir.empty());
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ requiresUnprivilegedUserNamespaces
|
|||
[[ $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.
|
||||
|
|
|
@ -9,7 +9,6 @@ requiresUnprivilegedUserNamespaces
|
|||
[[ "$busybox" =~ busybox ]] || skipTest "no busybox"
|
||||
|
||||
unset NIX_STORE_DIR
|
||||
unset NIX_STATE_DIR
|
||||
|
||||
remoteDir=$TEST_ROOT/remote
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ requiresUnprivilegedUserNamespaces
|
|||
|
||||
# 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}"; }
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ execUnshare <<EOF
|
|||
|
||||
# Avoid store dir being inside sandbox build-dir
|
||||
unset NIX_STORE_DIR
|
||||
unset NIX_STATE_DIR
|
||||
|
||||
setLocalStore () {
|
||||
export NIX_REMOTE=\$TEST_ROOT/\$1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue