Merge branch 'test-sandboxing' of https://github.com/matthewbauer/nix

This commit is contained in:
Eelco Dolstra 2019-08-27 20:58:47 +02:00
commit e5b397b2c7
3 changed files with 31 additions and 4 deletions

View file

@ -2357,17 +2357,37 @@ void DerivationGoal::startBuilder()
flags |= CLONE_NEWNET; flags |= CLONE_NEWNET;
pid_t child = clone(childEntry, stack + stackSize, flags, this); pid_t child = clone(childEntry, stack + stackSize, flags, this);
if (child == -1 && errno == EINVAL) if (child == -1 && errno == EINVAL) {
/* Fallback for Linux < 2.13 where CLONE_NEWPID and /* Fallback for Linux < 2.13 where CLONE_NEWPID and
CLONE_PARENT are not allowed together. */ CLONE_PARENT are not allowed together. */
child = clone(childEntry, stack + stackSize, flags & ~CLONE_NEWPID, this); flags &= ~CLONE_NEWPID;
child = clone(childEntry, stack + stackSize, flags, this);
}
if (child == -1 && (errno == EPERM || errno == EINVAL)) {
/* Some distros patch Linux to not allow unpriveleged
* user namespaces. If we get EPERM or EINVAL, try
* without CLONE_NEWUSER and see if that works.
*/
flags &= ~CLONE_NEWUSER;
child = clone(childEntry, stack + stackSize, flags, this);
}
/* Otherwise exit with EPERM so we can handle this in the
parent. This is only done when sandbox-fallback is set
to true (the default). */
if (child == -1 && (errno == EPERM || errno == EINVAL) && settings.sandboxFallback)
_exit(1);
if (child == -1) throw SysError("cloning builder process"); if (child == -1) throw SysError("cloning builder process");
writeFull(builderOut.writeSide.get(), std::to_string(child) + "\n"); writeFull(builderOut.writeSide.get(), std::to_string(child) + "\n");
_exit(0); _exit(0);
}, options); }, options);
if (helper.wait() != 0) int res = helper.wait();
if (res != 0 && settings.sandboxFallback) {
useChroot = false;
tmpDirInSandbox = tmpDir;
goto fallback;
} else if (res != 0)
throw Error("unable to start build process"); throw Error("unable to start build process");
userNamespaceSync.readSide = -1; userNamespaceSync.readSide = -1;
@ -2398,6 +2418,7 @@ void DerivationGoal::startBuilder()
} else } else
#endif #endif
{ {
fallback:
options.allowVfork = !buildUser && !drv->isBuiltin(); options.allowVfork = !buildUser && !drv->isBuiltin();
pid = startProcess([&]() { pid = startProcess([&]() {
runChild(); runChild();

View file

@ -209,6 +209,9 @@ public:
"The paths to make available inside the build sandbox.", "The paths to make available inside the build sandbox.",
{"build-chroot-dirs", "build-sandbox-paths"}}; {"build-chroot-dirs", "build-sandbox-paths"}};
Setting<bool> sandboxFallback{this, true, "sandbox-fallback",
"Whether to disable sandboxing when the kernel doesn't allow it."};
Setting<PathSet> extraSandboxPaths{this, {}, "extra-sandbox-paths", Setting<PathSet> extraSandboxPaths{this, {}, "extra-sandbox-paths",
"Additional paths to make available inside the build sandbox.", "Additional paths to make available inside the build sandbox.",
{"build-extra-chroot-dirs", "build-extra-sandbox-paths"}}; {"build-extra-chroot-dirs", "build-extra-sandbox-paths"}};

View file

@ -199,6 +199,9 @@ void chrootHelper(int argc, char * * argv)
uid_t gid = getgid(); uid_t gid = getgid();
if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1) if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1)
/* Try with just CLONE_NEWNS in case user namespaces are
specifically disabled. */
if (unshare(CLONE_NEWNS) == -1)
throw SysError("setting up a private mount namespace"); throw SysError("setting up a private mount namespace");
/* Bind-mount realStoreDir on /nix/store. If the latter mount /* Bind-mount realStoreDir on /nix/store. If the latter mount