Don't block while waiting for build users

This commit is contained in:
Alexander Bantyev 2020-05-08 12:22:39 +03:00
parent 04967dee9d
commit 14073fb76b
No known key found for this signature in database
GPG key ID: E081FF12ADCB4AD5

View file

@ -507,9 +507,6 @@ private:
Path fnUserLock; Path fnUserLock;
AutoCloseFD fdUserLock; AutoCloseFD fdUserLock;
bool findFreeUser();
string user; string user;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
@ -525,20 +522,19 @@ public:
uid_t getGID() { assert(gid); return gid; } uid_t getGID() { assert(gid); return gid; }
std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; } std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }
bool findFreeUser();
bool enabled() { return uid != 0; } bool enabled() { return uid != 0; }
}; };
UserLock::UserLock() UserLock::UserLock()
{ {
assert(settings.buildUsersGroup != ""); assert(settings.buildUsersGroup != "");
createDirs(settings.nixStateDir + "/userpool"); createDirs(settings.nixStateDir + "/userpool");
/* Mark that user is not enabled by default */
if (findFreeUser()) return; uid = 0;
printError("waiting for build users");
do std::this_thread::sleep_for(std::chrono::seconds(2)); while (! findFreeUser());
} }
bool UserLock::findFreeUser() { bool UserLock::findFreeUser() {
@ -1398,6 +1394,30 @@ void DerivationGoal::tryToBuild()
{ {
trace("trying to build"); trace("trying to build");
/* If `build-users-group' is not empty, then we have to build as
one of the members of that group. */
if (settings.buildUsersGroup != "" && getuid() == 0) {
#if defined(__linux__) || defined(__APPLE__)
if (!buildUser) buildUser = std::make_unique<UserLock>();
if (!buildUser->enabled()) {
if (!buildUser->findFreeUser()) {
debug("waiting for build users");
worker.waitForAWhile(shared_from_this());
return;
}
/* Make sure that no other processes are executing under this
uid. */
buildUser->kill();
}
#else
/* Don't know how to block the creation of setuid/setgid
binaries on this platform. */
throw Error("build users are not supported on this platform for security reasons");
#endif
}
/* Obtain locks on all output paths. The locks are automatically /* Obtain locks on all output paths. The locks are automatically
released when we exit this function or Nix crashes. If we released when we exit this function or Nix crashes. If we
can't acquire the lock, then continue; hopefully some other can't acquire the lock, then continue; hopefully some other
@ -1950,22 +1970,6 @@ void DerivationGoal::startBuilder()
#endif #endif
} }
/* If `build-users-group' is not empty, then we have to build as
one of the members of that group. */
if (settings.buildUsersGroup != "" && getuid() == 0) {
#if defined(__linux__) || defined(__APPLE__)
buildUser = std::make_unique<UserLock>();
/* Make sure that no other processes are executing under this
uid. */
buildUser->kill();
#else
/* Don't know how to block the creation of setuid/setgid
binaries on this platform. */
throw Error("build users are not supported on this platform for security reasons");
#endif
}
/* Create a temporary directory where the build will take /* Create a temporary directory where the build will take
place. */ place. */
tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700); tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);