diff options
author | Las Safin <me@las.rs> | 2021-10-08 22:55:08 +0000 |
---|---|---|
committer | Las Safin <me@las.rs> | 2021-11-25 11:15:11 +0000 |
commit | 8388d2c7c662e37470240cfde798956fe8e36a6f (patch) | |
tree | 887bf67a7bf545cb0aac41317af3c60eeaf2338e /src/libstore/build | |
parent | d58f149140582330bc994d215e54b2a4fc1149ff (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.cc | 11 | ||||
-rw-r--r-- | src/libstore/build/local-derivation-goal.hh | 3 |
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. */ |