aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc43
1 files changed, 30 insertions, 13 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 0972d6e19..1840fb7b2 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -45,7 +45,7 @@
#include <sched.h>
#endif
-#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(CLONE_NEWNS)
+#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS)
#if CHROOT_ENABLED
#include <sys/socket.h>
@@ -604,18 +604,17 @@ void getOwnership(const Path & path)
}
-void deletePathWrapped(const Path & path,
- unsigned long long & bytesFreed, unsigned long long & blocksFreed)
+void deletePathWrapped(const Path & path, unsigned long long & bytesFreed)
{
try {
/* First try to delete it ourselves. */
- deletePath(path, bytesFreed, blocksFreed);
+ deletePath(path, bytesFreed);
} catch (SysError & e) {
/* If this failed due to a permission error, then try it with
the setuid helper. */
if (settings.buildUsersGroup != "" && !amPrivileged()) {
getOwnership(path);
- deletePath(path, bytesFreed, blocksFreed);
+ deletePath(path, bytesFreed);
} else
throw;
}
@@ -624,8 +623,8 @@ void deletePathWrapped(const Path & path,
void deletePathWrapped(const Path & path)
{
- unsigned long long dummy1, dummy2;
- deletePathWrapped(path, dummy1, dummy2);
+ unsigned long long dummy1;
+ deletePathWrapped(path, dummy1);
}
@@ -1470,9 +1469,9 @@ HookReply DerivationGoal::tryBuildHook()
}
-void chmod(const Path & path, mode_t mode)
+void chmod_(const Path & path, mode_t mode)
{
- if (::chmod(path.c_str(), 01777) == -1)
+ if (chmod(path.c_str(), mode) == -1)
throw SysError(format("setting permissions on `%1%'") % path);
}
@@ -1674,7 +1673,7 @@ void DerivationGoal::startBuilder()
instead.) */
Path chrootTmpDir = chrootRootDir + "/tmp";
createDirs(chrootTmpDir);
- chmod(chrootTmpDir, 01777);
+ chmod_(chrootTmpDir, 01777);
/* Create a /etc/passwd with entries for the build user and the
nobody account. The latter is kind of a hack to support
@@ -1710,7 +1709,7 @@ void DerivationGoal::startBuilder()
precaution, make the fake Nix store only writable by the
build user. */
createDirs(chrootRootDir + settings.nixStore);
- chmod(chrootRootDir + settings.nixStore, 01777);
+ chmod_(chrootRootDir + settings.nixStore, 01777);
foreach (PathSet::iterator, i, inputPaths) {
struct stat st;
@@ -1844,22 +1843,40 @@ void DerivationGoal::initChild()
char domainname[] = "(none)"; // kernel default
setdomainname(domainname, sizeof(domainname));
+ /* Make all filesystems private. This is necessary
+ because subtrees may have been mounted as "shared"
+ (MS_SHARED). (Systemd does this, for instance.) Even
+ though we have a private mount namespace, mounting
+ filesystems on top of a shared subtree still propagates
+ outside of the namespace. Making a subtree private is
+ local to the namespace, though, so setting MS_PRIVATE
+ does not affect the outside world. */
+ Strings mounts = tokenizeString(readFile("/proc/self/mountinfo", true), "\n");
+ foreach (Strings::iterator, i, mounts) {
+ Strings fields = tokenizeString(*i, " ");
+ assert(fields.size() >= 5);
+ Strings::iterator j = fields.begin();
+ std::advance(j, 4);
+ if (mount(0, j->c_str(), 0, MS_PRIVATE, 0) == -1)
+ throw SysError(format("unable to make filesystem `%1%' private") % *j);
+ }
+
/* Bind-mount all the directories from the "host"
filesystem that we want in the chroot
environment. */
foreach (PathSet::iterator, i, dirsInChroot) {
Path source = *i;
Path target = chrootRootDir + source;
+ if (source == "/proc") continue; // backwards compatibility
debug(format("bind mounting `%1%' to `%2%'") % source % target);
-
createDirs(target);
-
if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1)
throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target);
}
/* Bind a new instance of procfs on /proc to reflect our
private PID namespace. */
+ createDirs(chrootRootDir + "/proc");
if (mount("none", (chrootRootDir + "/proc").c_str(), "proc", 0, 0) == -1)
throw SysError("mounting /proc");