Merge branch 'test-sandboxing' of https://github.com/matthewbauer/nix
This commit is contained in:
commit
e5b397b2c7
|
@ -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();
|
||||||
|
|
|
@ -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"}};
|
||||||
|
|
|
@ -199,7 +199,10 @@ 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)
|
||||||
throw SysError("setting up a private mount namespace");
|
/* 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");
|
||||||
|
|
||||||
/* Bind-mount realStoreDir on /nix/store. If the latter mount
|
/* Bind-mount realStoreDir on /nix/store. If the latter mount
|
||||||
point doesn't already exists, we have to create a chroot
|
point doesn't already exists, we have to create a chroot
|
||||||
|
|
Loading…
Reference in a new issue