From e8838713df29d94529ea4d7865180e936393340b Mon Sep 17 00:00:00 2001 From: aszlig Date: Fri, 11 Nov 2016 04:59:48 +0100 Subject: [PATCH] Run builds as root in user namespace again This reverts commit ff0c0b645cc1448959126185bb2fafe41cf0bddf. We're going to use seccomp to allow "cp -p" and force chown-related syscalls to always return 0. Signed-off-by: aszlig --- src/libstore/build.cc | 45 +++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 61286ceac..ed9d48378 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -811,9 +811,6 @@ private: result. */ ValidPathInfos prevInfos; - const uid_t sandboxUid = 1000; - const gid_t sandboxGid = 100; - public: DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal); @@ -1956,18 +1953,14 @@ void DerivationGoal::startBuilder() createDirs(chrootRootDir + "/etc"); writeFile(chrootRootDir + "/etc/passwd", - (format( - "root:x:0:0:Nix build user:/:/noshell\n" - "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" - "nobody:x:65534:65534:Nobody:/:/noshell\n") % sandboxUid % sandboxGid).str()); + "root:x:0:0:Nix build user:/:/noshell\n" + "nobody:x:65534:65534:Nobody:/:/noshell\n"); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ writeFile(chrootRootDir + "/etc/group", - (format( - "root:x:0:\n" - "nixbld:!:%1%:\n" - "nogroup:x:65534:\n") % sandboxGid).str()); + "root:x:0:\n" + "nobody:x:65534:\n"); /* Create /etc/hosts with localhost entry. */ if (!fixedOutput) @@ -2149,12 +2142,7 @@ void DerivationGoal::startBuilder() Pid helper = startProcess([&]() { /* Drop additional groups here because we can't do it - after we've created the new user namespace. FIXME: - this means that if we're not root in the parent - namespace, we can't drop additional groups; they will - be mapped to nogroup in the child namespace. There does - not seem to be a workaround for this. (But who can tell - from reading user_namespaces(7)?)*/ + after we've created the new user namespace. */ if (getuid() == 0 && setgroups(0, 0) == -1) throw SysError("setgroups failed"); @@ -2187,19 +2175,19 @@ void DerivationGoal::startBuilder() if (!string2Int(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.enabled() ? buildUser.getUID() : getuid(); - uid_t hostGid = buildUser.enabled() ? buildUser.getGID() : getgid(); + /* Set the UID/GID mapping of the builder's user + namespace such that root maps to the build user, or to the + calling user (if build users are disabled). */ + uid_t targetUid = buildUser.enabled() ? buildUser.getUID() : getuid(); + uid_t targetGid = buildUser.enabled() ? buildUser.getGID() : getgid(); writeFile("/proc/" + std::to_string(pid) + "/uid_map", - (format("%d %d 1") % sandboxUid % hostUid).str()); + (format("0 %d 1") % targetUid).str()); writeFile("/proc/" + std::to_string(pid) + "/setgroups", "deny"); writeFile("/proc/" + std::to_string(pid) + "/gid_map", - (format("%d %d 1") % sandboxGid % hostGid).str()); + (format("0 %d 1") % targetGid).str()); /* Signal the builder that we've updated its user namespace. */ @@ -2409,12 +2397,11 @@ void DerivationGoal::runChild() if (rmdir("real-root") == -1) throw SysError("cannot remove real-root directory"); - /* Switch to the sandbox uid/gid in the user namespace, - which corresponds to the build user or calling user in - the parent namespace. */ - if (setgid(sandboxGid) == -1) + /* Become root in the user namespace, which corresponds to + the build user or calling user in the parent namespace. */ + if (setgid(0) == -1) throw SysError("setgid failed"); - if (setuid(sandboxUid) == -1) + if (setuid(0) == -1) throw SysError("setuid failed"); setUser = false;