Support user namespaces being disabled
If max_user_namespaces is set to 0, then don't run the build in a user namespace. Fixes #4092.
This commit is contained in:
parent
f66bbd8c7b
commit
6aa64627c8
|
@ -831,6 +831,10 @@ private:
|
|||
paths to the sandbox as a result of recursive Nix calls. */
|
||||
AutoCloseFD sandboxMountNamespace;
|
||||
|
||||
/* On Linux, whether we're doing the build in its own user
|
||||
namespace. */
|
||||
bool usingUserNamespace = true;
|
||||
|
||||
/* The build hook. */
|
||||
std::unique_ptr<HookInstance> hook;
|
||||
|
||||
|
@ -920,8 +924,8 @@ private:
|
|||
result. */
|
||||
std::map<Path, ValidPathInfo> prevInfos;
|
||||
|
||||
const uid_t sandboxUid = 1000;
|
||||
const gid_t sandboxGid = 100;
|
||||
uid_t sandboxUid = 1000;
|
||||
gid_t sandboxGid = 100;
|
||||
|
||||
const static Path homeDir;
|
||||
|
||||
|
@ -2629,6 +2633,24 @@ void DerivationGoal::startBuilder()
|
|||
|
||||
options.allowVfork = false;
|
||||
|
||||
Path maxUserNamespaces = "/proc/sys/user/max_user_namespaces";
|
||||
static bool userNamespacesEnabled =
|
||||
pathExists(maxUserNamespaces)
|
||||
&& trim(readFile(maxUserNamespaces)) != "0";
|
||||
|
||||
usingUserNamespace = userNamespacesEnabled;
|
||||
|
||||
if (usingUserNamespace) {
|
||||
sandboxUid = 1000;
|
||||
sandboxGid = 100;
|
||||
} else {
|
||||
debug("note: not using a user namespace");
|
||||
if (!buildUser)
|
||||
throw Error("cannot perform a sandboxed build because user namespaces are not enabled; check /proc/sys/user/max_user_namespaces");
|
||||
sandboxUid = buildUser->getUID();
|
||||
sandboxGid = buildUser->getGID();
|
||||
}
|
||||
|
||||
Pid helper = startProcess([&]() {
|
||||
|
||||
/* Drop additional groups here because we can't do it
|
||||
|
@ -2647,9 +2669,11 @@ void DerivationGoal::startBuilder()
|
|||
PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||
if (stack == MAP_FAILED) throw SysError("allocating stack");
|
||||
|
||||
int flags = CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD;
|
||||
int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD;
|
||||
if (privateNetwork)
|
||||
flags |= CLONE_NEWNET;
|
||||
if (usingUserNamespace)
|
||||
flags |= CLONE_NEWUSER;
|
||||
|
||||
pid_t child = clone(childEntry, stack + stackSize, flags, this);
|
||||
if (child == -1 && errno == EINVAL) {
|
||||
|
@ -2697,19 +2721,21 @@ void DerivationGoal::startBuilder()
|
|||
if (!string2Int<pid_t>(readLine(builderOut.readSide.get()), tmp)) abort();
|
||||
pid = tmp;
|
||||
|
||||
/* Set the UID/GID mapping of the builder's user namespace
|
||||
such that the sandbox user maps to the build user, or to
|
||||
the calling user (if build users are disabled). */
|
||||
uid_t hostUid = buildUser ? buildUser->getUID() : getuid();
|
||||
uid_t hostGid = buildUser ? buildUser->getGID() : getgid();
|
||||
if (usingUserNamespace) {
|
||||
/* Set the UID/GID mapping of the builder's user namespace
|
||||
such that the sandbox user maps to the build user, or to
|
||||
the calling user (if build users are disabled). */
|
||||
uid_t hostUid = buildUser ? buildUser->getUID() : getuid();
|
||||
uid_t hostGid = buildUser ? buildUser->getGID() : getgid();
|
||||
|
||||
writeFile("/proc/" + std::to_string(pid) + "/uid_map",
|
||||
(format("%d %d 1") % sandboxUid % hostUid).str());
|
||||
writeFile("/proc/" + std::to_string(pid) + "/uid_map",
|
||||
(format("%d %d 1") % sandboxUid % hostUid).str());
|
||||
|
||||
writeFile("/proc/" + std::to_string(pid) + "/setgroups", "deny");
|
||||
writeFile("/proc/" + std::to_string(pid) + "/setgroups", "deny");
|
||||
|
||||
writeFile("/proc/" + std::to_string(pid) + "/gid_map",
|
||||
(format("%d %d 1") % sandboxGid % hostGid).str());
|
||||
writeFile("/proc/" + std::to_string(pid) + "/gid_map",
|
||||
(format("%d %d 1") % sandboxGid % hostGid).str());
|
||||
}
|
||||
|
||||
/* Save the mount namespace of the child. We have to do this
|
||||
*before* the child does a chroot. */
|
||||
|
@ -2745,7 +2771,7 @@ void DerivationGoal::startBuilder()
|
|||
ex.addTrace({}, "while setting up the build environment");
|
||||
throw ex;
|
||||
}
|
||||
debug(msg);
|
||||
debug("sandbox setup: " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue