aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
authorBen Burdette <bburdette@gmail.com>2020-05-29 09:51:37 -0600
committerBen Burdette <bburdette@gmail.com>2020-05-29 09:51:37 -0600
commit734283d636318b6dfc249afe1ddbb20bb4d02ed4 (patch)
tree1528b42a7c0017b674caec2deccaaa99ca9b856d /src/libstore/build.cc
parent92123c6c798682f3a7c1f19984dcd3a06ad6be92 (diff)
parentf60ce4fa207a210e23a1142d3a8ead611526e6e1 (diff)
Merge remote-tracking branch 'upstream/master' into errors-phase-2
Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc123
1 files changed, 73 insertions, 50 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 64bc9c4b8..4630432c9 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -513,9 +513,10 @@ private:
Path fnUserLock;
AutoCloseFD fdUserLock;
+ bool isEnabled = false;
string user;
- uid_t uid;
- gid_t gid;
+ uid_t uid = 0;
+ gid_t gid = 0;
std::vector<gid_t> supplementaryGIDs;
public:
@@ -528,7 +529,9 @@ public:
uid_t getGID() { assert(gid); return gid; }
std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }
- bool enabled() { return uid != 0; }
+ bool findFreeUser();
+
+ bool enabled() { return isEnabled; }
};
@@ -536,6 +539,11 @@ public:
UserLock::UserLock()
{
assert(settings.buildUsersGroup != "");
+ createDirs(settings.nixStateDir + "/userpool");
+}
+
+bool UserLock::findFreeUser() {
+ if (enabled()) return true;
/* Get the members of the build-users-group. */
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
@@ -565,7 +573,6 @@ UserLock::UserLock()
throw Error("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();
@@ -596,16 +603,14 @@ UserLock::UserLock()
supplementaryGIDs.resize(ngroups);
#endif
- return;
+ isEnabled = true;
+ return true;
}
}
- throw Error("all build users are currently in use; "
- "consider creating additional users and adding them to the '%1%' group",
- settings.buildUsersGroup);
+ return false;
}
-
void UserLock::kill()
{
killUser(uid);
@@ -934,6 +939,7 @@ private:
void closureRepaired();
void inputsRealised();
void tryToBuild();
+ void tryLocalBuild();
void buildDone();
/* Is the build hook willing to perform the build? */
@@ -1005,6 +1011,8 @@ private:
Goal::amDone(result);
}
+ void started();
+
void done(BuildResult::Status status, const string & msg = "");
StorePathSet exportReferences(const StorePathSet & storePaths);
@@ -1406,6 +1414,19 @@ 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()
{
@@ -1457,20 +1478,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()) {
@@ -1503,6 +1510,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. */
@@ -1968,22 +2003,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. */
tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);
@@ -2740,7 +2759,7 @@ struct RestrictedStore : public LocalFSStore
{ throw Error("queryPathFromHashPart"); }
StorePath addToStore(const string & name, const Path & srcPath,
- bool recursive = true, HashType hashAlgo = htSHA256,
+ FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter, RepairFlag repair = NoRepair) override
{ throw Error("addToStore"); }
@@ -2753,9 +2772,9 @@ struct RestrictedStore : public LocalFSStore
}
StorePath addToStoreFromDump(const string & dump, const string & name,
- bool recursive = true, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair) override
+ FileIngestionMethod method = FileIngestionMethod::Recursive, HashType hashAlgo = htSHA256, RepairFlag repair = NoRepair) override
{
- auto path = next->addToStoreFromDump(dump, name, recursive, hashAlgo, repair);
+ auto path = next->addToStoreFromDump(dump, name, method, hashAlgo, repair);
goal.addDependency(path);
return path;
}
@@ -3702,10 +3721,10 @@ void DerivationGoal::registerOutputs()
if (fixedOutput) {
- bool recursive; Hash h;
- i.second.parseHashInfo(recursive, h);
+ FileIngestionMethod outputHashMode; Hash h;
+ i.second.parseHashInfo(outputHashMode, h);
- if (!recursive) {
+ if (outputHashMode == FileIngestionMethod::Flat) {
/* The output path should be a regular file without execute permission. */
if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0)
throw BuildError(
@@ -3716,9 +3735,11 @@ void DerivationGoal::registerOutputs()
/* Check the hash. In hash mode, move the path produced by
the derivation to its content-addressed location. */
- Hash h2 = recursive ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath);
+ Hash h2 = outputHashMode == FileIngestionMethod::Recursive
+ ? hashPath(h.type, actualPath).first
+ : hashFile(h.type, actualPath);
- auto dest = worker.store.makeFixedOutputPath(recursive, h2, i.second.path.name());
+ auto dest = worker.store.makeFixedOutputPath(outputHashMode, h2, i.second.path.name());
if (h != h2) {
@@ -3747,7 +3768,7 @@ void DerivationGoal::registerOutputs()
else
assert(worker.store.parseStorePath(path) == dest);
- ca = makeFixedOutputCA(recursive, h2);
+ ca = makeFixedOutputCA(outputHashMode, h2);
}
/* Get rid of all weird permissions. This also checks that
@@ -3974,7 +3995,9 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs)
auto spec = parseReferenceSpecifiers(worker.store, *drv, *value);
- auto used = recursive ? cloneStorePathSet(getClosure(info.path).first) : cloneStorePathSet(info.references);
+ auto used = recursive
+ ? cloneStorePathSet(getClosure(info.path).first)
+ : cloneStorePathSet(info.references);
if (recursive && checks.ignoreSelfRefs)
used.erase(info.path);
@@ -4861,7 +4884,7 @@ void Worker::waitForInput()
if (!waitingForAWhile.empty()) {
useTimeout = true;
if (lastWokenUp == steady_time_point::min())
- printInfo("waiting for locks or build slots...");
+ printInfo("waiting for locks, build slots or build users...");
if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before;
timeout = std::max(1L,
(long) std::chrono::duration_cast<std::chrono::seconds>(