summary refs log tree commit diff
path: root/nix
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-02-23 15:41:41 +0100
committerLudovic Courtès <ludo@gnu.org>2015-06-03 21:55:59 +0200
commit67af480244250409c8cf41e66a4995258b8ccc9b (patch)
tree81b5e81b65629515ef8a8b65ac98df73ba86909f /nix
parent638f3675e140af1214b82ff162baadd3ef1bb6e6 (diff)
downloadguix-67af480244250409c8cf41e66a4995258b8ccc9b.tar.gz
Use chroots for all derivations
If ‘build-use-chroot’ is set to ‘true’, fixed-output derivations are
now also chrooted. However, unlike normal derivations, they don't get
a private network namespace, so they can still access the
network. Also, the use of the ‘__noChroot’ derivation attribute is
no longer allowed.

Setting ‘build-use-chroot’ to ‘relaxed’ gives the old behaviour.

Note for Guix: unlike Nix commit 99897f6, we keep 'settings.useChroot'.
Diffstat (limited to 'nix')
-rw-r--r--nix/libstore/build.cc38
1 files changed, 21 insertions, 17 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index 6276937b0e..7153c85788 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -1752,19 +1752,8 @@ void DerivationGoal::startBuilder()
             throw SysError(format("cannot change ownership of '%1%'") % tmpDir);
     }
 
-
-    /* Are we doing a chroot build?  Note that fixed-output
-       derivations are never done in a chroot, mainly so that
-       functions like fetchurl (which needs a proper /etc/resolv.conf)
-       work properly.  Purity checking for fixed-output derivations
-       is somewhat pointless anyway. */
     useChroot = settings.useChroot;
 
-    if (fixedOutput) useChroot = false;
-
-    /* Hack to allow derivations to disable chroot builds. */
-    if (get(drv.env, "__noChroot") == "1") useChroot = false;
-
     if (useChroot) {
 #if CHROOT_ENABLED
         /* Create a temporary directory in which we set up the chroot
@@ -1805,7 +1794,8 @@ void DerivationGoal::startBuilder()
                 % (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
 
         /* Create /etc/hosts with localhost entry. */
-        writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n");
+        if (!fixedOutput)
+            writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n");
 
         /* Bind-mount a user-configurable set of directories from the
            host file system. */
@@ -1938,9 +1928,12 @@ void DerivationGoal::startBuilder()
     */
 #if CHROOT_ENABLED
     if (useChroot) {
-        char stack[32 * 1024];
-        pid = clone(childEntry, stack + sizeof(stack) - 8,
-            CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD, this);
+	char stack[32 * 1024];
+	int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD;
+	if (!fixedOutput) flags |= CLONE_NEWNET;
+	pid = clone(childEntry, stack + sizeof(stack) - 8, flags, this);
+	if (pid == -1)
+	    throw SysError("cloning builder process");
     } else
 #endif
     {
@@ -2026,10 +2019,10 @@ void DerivationGoal::runChild()
 
             /* Set up a nearly empty /dev, unless the user asked to
                bind-mount the host /dev. */
+            Strings ss;
             if (dirsInChroot.find("/dev") == dirsInChroot.end()) {
                 createDirs(chrootRootDir + "/dev/shm");
                 createDirs(chrootRootDir + "/dev/pts");
-                Strings ss;
                 ss.push_back("/dev/full");
 #ifdef __linux__
                 if (pathExists("/dev/kvm"))
@@ -2040,13 +2033,24 @@ void DerivationGoal::runChild()
                 ss.push_back("/dev/tty");
                 ss.push_back("/dev/urandom");
                 ss.push_back("/dev/zero");
-                foreach (Strings::iterator, i, ss) dirsInChroot[*i] = *i;
                 createSymlink("/proc/self/fd", chrootRootDir + "/dev/fd");
                 createSymlink("/proc/self/fd/0", chrootRootDir + "/dev/stdin");
                 createSymlink("/proc/self/fd/1", chrootRootDir + "/dev/stdout");
                 createSymlink("/proc/self/fd/2", chrootRootDir + "/dev/stderr");
             }
 
+            /* Fixed-output derivations typically need to access the
+               network, so give them access to /etc/resolv.conf and so
+               on. */
+            if (fixedOutput) {
+                ss.push_back("/etc/resolv.conf");
+                ss.push_back("/etc/nsswitch.conf");
+                ss.push_back("/etc/services");
+                ss.push_back("/etc/hosts");
+            }
+
+            for (auto & i : ss) dirsInChroot[i] = i;
+
             /* Bind-mount all the directories from the "host"
                filesystem that we want in the chroot
                environment. */