1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 01:51:47 +02:00

Support optional sandbox paths

For example, you can now set

  build-sandbox-paths = /dev/nvidiactl?

to specify that /dev/nvidiactl should only be mounted in the sandbox
if it exists in the host filesystem. This is useful e.g. for EC2
images that should support both CUDA and non-CUDA instances.

(cherry picked from commit 18b7363a69)
This commit is contained in:
Eelco Dolstra 2016-10-31 17:09:52 +01:00
parent fd9fc15c0c
commit 2eb840eefa
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
2 changed files with 36 additions and 10 deletions

View file

@ -268,7 +268,12 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
to mount a path in a different location in the sandbox; for
instance, <literal>/bin=/nix-bin</literal> will mount the path
<literal>/nix-bin</literal> as <literal>/bin</literal> inside the
sandbox.</para>
sandbox. If <replaceable>source</replaceable> is followed by
<literal>?</literal>, then it is not an error if
<replaceable>source</replaceable> does not exist; for example,
<literal>/dev/nvidiactl?</literal> specifies that
<filename>/dev/nvidiactl</filename> will only be mounted in the
sandbox if it exists in the host filesystem.</para>
<para>Depending on how Nix was built, the default value for this option
may be empty or provide <filename>/bin/sh</filename> as a

View file

@ -761,7 +761,14 @@ private:
GoalState state;
/* Stuff we need to pass to initChild(). */
typedef map<Path, Path> DirsInChroot; // maps target path to source path
struct ChrootPath {
Path source;
bool optional;
ChrootPath(Path source = "", bool optional = false)
: source(source), optional(optional)
{ }
};
typedef map<Path, ChrootPath> DirsInChroot; // maps target path to source path
DirsInChroot dirsInChroot;
typedef map<string, string> Environment;
Environment env;
@ -1924,20 +1931,30 @@ void DerivationGoal::startBuilder()
dirsInChroot.clear();
for (auto & i : dirs) {
for (auto i : dirs) {
if (i.empty()) continue;
bool optional = false;
if (i[i.size() - 1] == '?') {
optional = true;
i.pop_back();
}
size_t p = i.find('=');
if (p == string::npos)
dirsInChroot[i] = i;
dirsInChroot[i] = {i, optional};
else
dirsInChroot[string(i, 0, p)] = string(i, p + 1);
dirsInChroot[string(i, 0, p)] = {string(i, p + 1), optional};
}
dirsInChroot[tmpDirInSandbox] = tmpDir;
/* Add the closure of store paths to the chroot. */
PathSet closure;
for (auto & i : dirsInChroot)
if (isInStore(i.second))
computeFSClosure(worker.store, toStorePath(i.second), closure);
try {
if (isInStore(i.second.source))
computeFSClosure(worker.store, toStorePath(i.second.source), closure);
} catch (Error & e) {
throw Error(format("while processing build-sandbox-paths: %s") % e.what());
}
for (auto & i : closure)
dirsInChroot[i] = i;
@ -2328,12 +2345,16 @@ void DerivationGoal::runChild()
environment. */
for (auto & i : dirsInChroot) {
struct stat st;
Path source = i.second;
Path source = i.second.source;
Path target = chrootRootDir + i.first;
if (source == "/proc") continue; // backwards compatibility
debug(format("bind mounting %1% to %2%") % source % target);
if (stat(source.c_str(), &st) == -1)
throw SysError(format("getting attributes of path %1%") % source);
if (stat(source.c_str(), &st) == -1) {
if (i.second.optional && errno == ENOENT)
continue;
else
throw SysError(format("getting attributes of path %1%") % source);
}
if (S_ISDIR(st.st_mode))
createDirs(target);
else {