about summary refs log tree commit diff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-05-08T13·42+0200
committerEelco Dolstra <edolstra@gmail.com>2017-05-08T13·42+0200
commit00b286275c1a77458e45bd73528c9ca729cca7f6 (patch)
tree3e252f2668f428538bf08030bad1bfbb249dcd8e /src/libstore/build.cc
parentebfceeb333120411af46d0af4805f3e7d557159f (diff)
Linux sandbox: Fix compatibility with older kernels
Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc38
1 files changed, 23 insertions, 15 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index dc9b9e023c..270500d81c 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -2390,17 +2390,14 @@ void DerivationGoal::runChild()
             /* Bind-mount all the directories from the "host"
                filesystem that we want in the chroot
                environment. */
-            for (auto & i : dirsInChroot) {
-                struct stat st;
-                Path source = i.second.source;
-                Path target = chrootRootDir + i.first;
-                if (source == "/proc") continue; // backwards compatibility
+            auto doBind = [&](const Path & source, const Path & target, bool optional = false) {
                 debug(format("bind mounting ‘%1%’ to ‘%2%’") % source % target);
+                struct stat st;
                 if (stat(source.c_str(), &st) == -1) {
-                    if (i.second.optional && errno == ENOENT)
-                        continue;
+                    if (optional && errno == ENOENT)
+                        return;
                     else
-                        throw SysError(format("getting attributes of path ‘%1%’") % source);
+                        throw SysError("getting attributes of path ‘%1%’", source);
                 }
                 if (S_ISDIR(st.st_mode))
                     createDirs(target);
@@ -2409,7 +2406,12 @@ void DerivationGoal::runChild()
                     writeFile(target, "");
                 }
                 if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
-                    throw SysError(format("bind mount from ‘%1%’ to ‘%2%’ failed") % source % target);
+                    throw SysError("bind mount from ‘%1%’ to ‘%2%’ failed", source, target);
+            };
+
+            for (auto & i : dirsInChroot) {
+                if (i.second.source == "/proc") continue; // backwards compatibility
+                doBind(i.second.source, chrootRootDir + i.first, i.second.optional);
             }
 
             /* Bind a new instance of procfs on /proc. */
@@ -2431,13 +2433,19 @@ void DerivationGoal::runChild()
                 !pathExists(chrootRootDir + "/dev/ptmx")
                 && !dirsInChroot.count("/dev/pts"))
             {
-                if (mount("none", (chrootRootDir + "/dev/pts").c_str(), "devpts", 0, "newinstance,mode=0620") == -1)
-                    throw SysError("mounting /dev/pts");
-                createSymlink("/dev/pts/ptmx", chrootRootDir + "/dev/ptmx");
+                if (mount("none", (chrootRootDir + "/dev/pts").c_str(), "devpts", 0, "newinstance,mode=0620") == 0)
+                {
+                    createSymlink("/dev/pts/ptmx", chrootRootDir + "/dev/ptmx");
 
-                /* Make sure /dev/pts/ptmx is world-writable.  With some
-                   Linux versions, it is created with permissions 0.  */
-                chmod_(chrootRootDir + "/dev/pts/ptmx", 0666);
+                    /* Make sure /dev/pts/ptmx is world-writable.  With some
+                       Linux versions, it is created with permissions 0.  */
+                    chmod_(chrootRootDir + "/dev/pts/ptmx", 0666);
+                } else {
+                    if (errno != EINVAL)
+                        throw SysError("mounting /dev/pts");
+                    doBind("/dev/pts", "/dev/pts");
+                    doBind("/dev/ptmx", "/dev/ptmx");
+                }
             }
 
             /* Do the chroot(). */