mirror of
https://github.com/NixOS/nix
synced 2025-06-25 10:41:16 +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/abstract-setting-to-json.hh"
|
||||||
#include "nix/util/compute-levels.hh"
|
#include "nix/util/compute-levels.hh"
|
||||||
#include "nix/util/signals.hh"
|
#include "nix/util/signals.hh"
|
||||||
|
#include "nix/util/types.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
|
@ -697,14 +697,7 @@ public:
|
||||||
|
|
||||||
Setting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
|
Setting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
|
||||||
R"(
|
R"(
|
||||||
The directory on the host, in which derivations' temporary build directories are created.
|
Override the `build-dir` store setting for all stores that have this setting.
|
||||||
|
|
||||||
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).
|
|
||||||
)"};
|
)"};
|
||||||
|
|
||||||
Setting<PathSet> allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps",
|
Setting<PathSet> allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps",
|
||||||
|
|
|
@ -34,7 +34,38 @@ struct OptimiseStats
|
||||||
uint64_t bytesFreed = 0;
|
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;
|
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
|
ref<Store> LocalStore::Config::openStore() const
|
||||||
{
|
{
|
||||||
return make_ref<LocalStore>(ref{shared_from_this()});
|
return make_ref<LocalStore>(ref{shared_from_this()});
|
||||||
|
|
|
@ -725,9 +725,13 @@ void DerivationBuilderImpl::startBuilder()
|
||||||
throw BuildError(msg);
|
throw BuildError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto buildDir = getLocalStore(store).config->getBuildDir();
|
||||||
|
|
||||||
|
createDirs(buildDir);
|
||||||
|
|
||||||
/* Create a temporary directory where the build will take
|
/* Create a temporary directory where the build will take
|
||||||
place. */
|
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();
|
setBuildTmpDir();
|
||||||
assert(!tmpDir.empty());
|
assert(!tmpDir.empty());
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ requiresUnprivilegedUserNamespaces
|
||||||
[[ $busybox =~ busybox ]] || skipTest "no busybox"
|
[[ $busybox =~ busybox ]] || skipTest "no busybox"
|
||||||
|
|
||||||
unset NIX_STORE_DIR
|
unset NIX_STORE_DIR
|
||||||
unset NIX_STATE_DIR
|
|
||||||
|
|
||||||
# We first build a dependency of the derivation we eventually want to
|
# We first build a dependency of the derivation we eventually want to
|
||||||
# build.
|
# build.
|
||||||
|
|
|
@ -9,7 +9,6 @@ requiresUnprivilegedUserNamespaces
|
||||||
[[ "$busybox" =~ busybox ]] || skipTest "no busybox"
|
[[ "$busybox" =~ busybox ]] || skipTest "no busybox"
|
||||||
|
|
||||||
unset NIX_STORE_DIR
|
unset NIX_STORE_DIR
|
||||||
unset NIX_STATE_DIR
|
|
||||||
|
|
||||||
remoteDir=$TEST_ROOT/remote
|
remoteDir=$TEST_ROOT/remote
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ requiresUnprivilegedUserNamespaces
|
||||||
|
|
||||||
# Avoid store dir being inside sandbox build-dir
|
# Avoid store dir being inside sandbox build-dir
|
||||||
unset NIX_STORE_DIR
|
unset NIX_STORE_DIR
|
||||||
unset NIX_STATE_DIR
|
|
||||||
|
|
||||||
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
|
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
|
# Avoid store dir being inside sandbox build-dir
|
||||||
unset NIX_STORE_DIR
|
unset NIX_STORE_DIR
|
||||||
unset NIX_STATE_DIR
|
|
||||||
|
|
||||||
setLocalStore () {
|
setLocalStore () {
|
||||||
export NIX_REMOTE=\$TEST_ROOT/\$1
|
export NIX_REMOTE=\$TEST_ROOT/\$1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue