aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authorAlexander Bantyev <balsoft@balsoft.ru>2020-05-14 17:00:54 +0300
committerAlexander Bantyev <balsoft@balsoft.ru>2020-05-14 17:00:54 +0300
commit183dd28266e0292116da6cfbc3e2643577adbfbe (patch)
tree05e2be867ca4dea78bfb6bf10d7fe49ac7f80799 /src/libstore
parent772e5db828c9924c803b4d126bca72d7e123614b (diff)
Don't lock a user while doing remote builds
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build.cc88
1 files changed, 49 insertions, 39 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index a8c1cd565..f7fc23b35 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -507,6 +507,7 @@ private:
Path fnUserLock;
AutoCloseFD fdUserLock;
+ bool isEnabled;
string user;
uid_t uid;
gid_t gid;
@@ -524,7 +525,7 @@ public:
bool findFreeUser();
- bool enabled() { return uid != 0; }
+ bool enabled() { return isEnabled; }
};
@@ -535,9 +536,11 @@ UserLock::UserLock()
createDirs(settings.nixStateDir + "/userpool");
/* Mark that user is not enabled by default */
uid = 0;
+ isEnabled = false;
}
bool UserLock::findFreeUser() {
+ if (enabled()) return true;
/* Get the members of the build-users-group. */
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
@@ -597,6 +600,7 @@ bool UserLock::findFreeUser() {
supplementaryGIDs.resize(ngroups);
#endif
+ isEnabled = true;
return true;
}
}
@@ -931,6 +935,7 @@ private:
void closureRepaired();
void inputsRealised();
void tryToBuild();
+ void tryLocalBuild();
void buildDone();
/* Is the build hook willing to perform the build? */
@@ -1002,6 +1007,8 @@ private:
Goal::amDone(result);
}
+ void started();
+
void done(BuildResult::Status status, const string & msg = "");
StorePathSet exportReferences(const StorePathSet & storePaths);
@@ -1389,35 +1396,24 @@ void DerivationGoal::inputsRealised()
result = BuildResult();
}
+void DerivationGoal::started() {
+ auto msg = fmt(
+ buildMode == bmRepair ? "repairing outputs of '%s'" :
+ buildMode == bmCheck ? "checking outputs of '%s'" :
+ nrRounds > 1 ? "building '%s' (round %d/%d)" :
+ "building '%s'", worker.store.printStorePath(drvPath), curRound, nrRounds);
+ fmt("building '%s'", worker.store.printStorePath(drvPath));
+ if (hook) msg += fmt(" on '%s'", machineName);
+ act = std::make_unique<Activity>(*logger, lvlInfo, actBuild, msg,
+ Logger::Fields{worker.store.printStorePath(drvPath), hook ? machineName : "", curRound, nrRounds});
+ mcRunningBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.runningBuilds);
+ worker.updateProgress();
+}
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
@@ -1464,20 +1460,6 @@ void DerivationGoal::tryToBuild()
supported for local builds. */
bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally();
- auto started = [&]() {
- auto msg = fmt(
- buildMode == bmRepair ? "repairing outputs of '%s'" :
- buildMode == bmCheck ? "checking outputs of '%s'" :
- nrRounds > 1 ? "building '%s' (round %d/%d)" :
- "building '%s'", worker.store.printStorePath(drvPath), curRound, nrRounds);
- fmt("building '%s'", worker.store.printStorePath(drvPath));
- if (hook) msg += fmt(" on '%s'", machineName);
- act = std::make_unique<Activity>(*logger, lvlInfo, actBuild, msg,
- Logger::Fields{worker.store.printStorePath(drvPath), hook ? machineName : "", curRound, nrRounds});
- mcRunningBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.runningBuilds);
- worker.updateProgress();
- };
-
/* Is the build hook willing to accept this job? */
if (!buildLocally) {
switch (tryBuildHook()) {
@@ -1510,6 +1492,34 @@ void DerivationGoal::tryToBuild()
return;
}
+ state = &DerivationGoal::tryLocalBuild;
+ worker.wakeUp(shared_from_this());
+}
+
+void DerivationGoal::tryLocalBuild() {
+
+ /* 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->findFreeUser()) {
+ /* Make sure that no other processes are executing under this
+ uid. */
+ buildUser->kill();
+ } else {
+ debug("waiting for build users");
+ worker.waitForAWhile(shared_from_this());
+ return;
+ }
+#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
+ }
+
try {
/* Okay, we have to build. */