aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build
diff options
context:
space:
mode:
authorLas Safin <me@las.rs>2021-10-08 22:55:08 +0000
committerLas Safin <me@las.rs>2021-11-25 11:15:11 +0000
commit8388d2c7c662e37470240cfde798956fe8e36a6f (patch)
tree887bf67a7bf545cb0aac41317af3c60eeaf2338e /src/libstore/build
parentd58f149140582330bc994d215e54b2a4fc1149ff (diff)
Make recursive-nix work even when not privileged
Before this, `setns` would fail when switching to the mount namespace, since we did not have the privileges to do so when not root. Closes #5360
Diffstat (limited to 'src/libstore/build')
-rw-r--r--src/libstore/build/local-derivation-goal.cc11
-rw-r--r--src/libstore/build/local-derivation-goal.hh3
2 files changed, 11 insertions, 3 deletions
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index c9a4a31e7..ebcb561c2 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -260,6 +260,7 @@ void LocalDerivationGoal::cleanupHookFinally()
void LocalDerivationGoal::cleanupPreChildKill()
{
sandboxMountNamespace = -1;
+ sandboxUserNamespace = -1;
}
@@ -906,11 +907,14 @@ void LocalDerivationGoal::startBuilder()
"nobody:x:65534:65534:Nobody:/:/noshell\n",
sandboxUid(), sandboxGid(), settings.sandboxBuildDir));
- /* Save the mount namespace of the child. We have to do this
+ /* Save the mount- and user namespace of the child. We have to do this
*before* the child does a chroot. */
sandboxMountNamespace = open(fmt("/proc/%d/ns/mnt", (pid_t) pid).c_str(), O_RDONLY);
if (sandboxMountNamespace.get() == -1)
throw SysError("getting sandbox mount namespace");
+ sandboxUserNamespace = open(fmt("/proc/%d/ns/user", (pid_t) pid).c_str(), O_RDONLY);
+ if (sandboxUserNamespace.get() == -1)
+ throw SysError("getting sandbox user namespace");
/* Signal the builder that we've updated its user namespace. */
writeFull(userNamespaceSync.writeSide.get(), "1");
@@ -1423,7 +1427,7 @@ void LocalDerivationGoal::addDependency(const StorePath & path)
Path source = worker.store.Store::toRealPath(path);
Path target = chrootRootDir + worker.store.printStorePath(path);
- debug("bind-mounting %s -> %s", target, source);
+ debug("bind-mounting %s -> %s", source, target);
if (pathExists(target))
throw Error("store path '%s' already exists in the sandbox", worker.store.printStorePath(path));
@@ -1438,6 +1442,9 @@ void LocalDerivationGoal::addDependency(const StorePath & path)
child process.*/
Pid child(startProcess([&]() {
+ if (usingUserNamespace && (setns(sandboxUserNamespace.get(), 0) == -1))
+ throw SysError("entering sandbox user namespace");
+
if (setns(sandboxMountNamespace.get(), 0) == -1)
throw SysError("entering sandbox mount namespace");
diff --git a/src/libstore/build/local-derivation-goal.hh b/src/libstore/build/local-derivation-goal.hh
index 088a57209..bfdf91d89 100644
--- a/src/libstore/build/local-derivation-goal.hh
+++ b/src/libstore/build/local-derivation-goal.hh
@@ -27,9 +27,10 @@ struct LocalDerivationGoal : public DerivationGoal
/* Pipe for synchronising updates to the builder namespaces. */
Pipe userNamespaceSync;
- /* The mount namespace of the builder, used to add additional
+ /* The mount namespace and user namespace of the builder, used to add additional
paths to the sandbox as a result of recursive Nix calls. */
AutoCloseFD sandboxMountNamespace;
+ AutoCloseFD sandboxUserNamespace;
/* On Linux, whether we're doing the build in its own user
namespace. */