1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-08 02:43:54 +02:00

Merge pull request #9261 from flokli/backport-3564

[2.3-maintenance] Wait for build users when none are available
This commit is contained in:
John Ericson 2023-11-01 20:01:36 -04:00 committed by GitHub
commit f76990444c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -524,17 +524,24 @@ public:
uid_t getGID() { assert(gid); return gid; }
std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }
bool findFreeUser();
bool enabled() { return uid != 0; }
};
Sync<PathSet> UserLock::lockedPaths_;
UserLock::UserLock()
{
assert(settings.buildUsersGroup != "");
createDirs(settings.nixStateDir + "/userpool");
/* Mark that user is not enabled by default */
uid = 0;
}
bool UserLock::findFreeUser() {
/* Get the members of the build-users-group. */
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
@ -564,7 +571,6 @@ UserLock::UserLock()
throw Error(format("the user '%1%' in the group '%2%' does not exist")
% i % settings.buildUsersGroup);
createDirs(settings.nixStateDir + "/userpool");
fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
@ -605,20 +611,17 @@ UserLock::UserLock()
supplementaryGIDs.resize(ngroups);
#endif
return;
return true;
}
} catch (...) {
lockedPaths_.lock()->erase(fnUserLock);
return false;
}
}
throw Error(format("all build users are currently in use; "
"consider creating additional users and adding them to the '%1%' group")
% settings.buildUsersGroup);
return false;
}
UserLock::~UserLock()
{
auto lockedPaths(lockedPaths_.lock());
@ -626,7 +629,6 @@ UserLock::~UserLock()
lockedPaths->erase(fnUserLock);
}
void UserLock::kill()
{
killUser(uid);
@ -1415,6 +1417,30 @@ void DerivationGoal::tryToBuild()
{
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
released when we exit this function or Nix crashes. If we
can't acquire the lock, then continue; hopefully some other
@ -1931,22 +1957,6 @@ void DerivationGoal::startBuilder()
#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
place. */
auto drvName = storePathToName(drvPath);
@ -4465,7 +4475,7 @@ void Worker::waitForInput()
if (!waitingForAWhile.empty()) {
useTimeout = true;
if (lastWokenUp == steady_time_point::min())
printError("waiting for locks or build slots...");
printError("waiting for locks, build slots or build users...");
if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before;
timeout.tv_sec = std::max(1L,
(long) std::chrono::duration_cast<std::chrono::seconds>(