diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build-remote/build-remote.cc | 43 | ||||
-rw-r--r-- | src/libstore/daemon.cc | 2 | ||||
-rw-r--r-- | src/libstore/store-api.cc | 43 | ||||
-rw-r--r-- | src/libstore/store-api.hh | 27 | ||||
-rw-r--r-- | src/nix/daemon.cc | 26 |
5 files changed, 113 insertions, 28 deletions
diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 0559aeaf4..72752d624 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -248,6 +248,8 @@ static int main_build_remote(int argc, char * * argv) connected: close(5); + assert(sshStore); + std::cerr << "# accept\n" << storeUri << "\n"; auto inputs = readStrings<PathSet>(source); @@ -268,31 +270,39 @@ connected: auto substitute = settings.buildersUseSubstitutes ? Substitute : NoSubstitute; + auto copyStorePathImpl = sshStore->isTrusting ? copyStorePathAdapter : copyOrBuildStorePath; + { Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri)); - copyPaths(*store, *sshStore, store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute); + copyPaths(*store, *sshStore, store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute, copyStorePathImpl); } uploadLock = -1; auto drv = store->readDerivation(*drvPath); - auto outputHashes = staticOutputHashes(*store, drv); - - // Hijack the inputs paths of the derivation to include all the paths - // that come from the `inputDrvs` set. - // We don’t do that for the derivations whose `inputDrvs` is empty - // because - // 1. It’s not needed - // 2. Changing the `inputSrcs` set changes the associated output ids, - // which break CA derivations - if (!drv.inputDrvs.empty()) - drv.inputSrcs = store->parseStorePathSet(inputs); - auto result = sshStore->buildDerivation(*drvPath, drv); + std::optional<BuildResult> optResult; + if (sshStore->isTrusting || derivationIsCA(drv.type())) { + // Hijack the inputs paths of the derivation to include all the paths + // that come from the `inputDrvs` set. + // We don’t do that for the derivations whose `inputDrvs` is empty + // because + // 1. It’s not needed + // 2. Changing the `inputSrcs` set changes the associated output ids, + // which break CA derivations + if (!drv.inputDrvs.empty()) + drv.inputSrcs = store->parseStorePathSet(inputs); + optResult = sshStore->buildDerivation(*drvPath, (const BasicDerivation &) drv); + auto & result = *optResult; + if (!result.success()) + throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg); + } else { + copyPaths(*store, *sshStore, StorePathSet {*drvPath}, NoRepair, NoCheckSigs, substitute, copyStorePathImpl); + sshStore->buildPaths({ DerivedPath::Built { *drvPath, {} } }); + } - if (!result.success()) - throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg); + auto outputHashes = staticOutputHashes(*store, drv); std::set<Realisation> missingRealisations; StorePathSet missingPaths; if (settings.isExperimentalFeatureEnabled("ca-derivations") && !derivationHasKnownOutputPaths(drv.type())) { @@ -301,6 +311,8 @@ connected: auto thisOutputId = DrvOutput{ thisOutputHash, outputName }; if (!store->queryRealisation(thisOutputId)) { debug("missing output %s", outputName); + assert(optResult); + auto & result = *optResult; assert(result.builtOutputs.count(thisOutputId)); auto newRealisation = result.builtOutputs.at(thisOutputId); missingRealisations.insert(newRealisation); @@ -321,6 +333,7 @@ connected: if (auto localStore = store.dynamic_pointer_cast<LocalStore>()) for (auto & path : missingPaths) localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */ + /* No `copyStorePathImpl` because we always trust ourselves. */ copyPaths(*sshStore, *store, missingPaths, NoRepair, NoCheckSigs, NoSubstitute); } // XXX: Should be done as part of `copyPaths` diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 164a9b2be..bfcdb8d95 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -987,6 +987,8 @@ void processConnection( opCount++; + debug("performing daemon worker op: %d", op); + try { performOp(tunnelLogger, store, trusted, recursive, clientVersion, from, to, op); } catch (Error & e) { diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index b5ff3dccf..49bc91614 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -847,13 +847,47 @@ void copyStorePath( } +void copyStorePathAdapter(Store & srcStore, Store & dstStore, + const ValidPathInfo & info, RepairFlag repair, CheckSigsFlag checkSigs) +{ + copyStorePath(srcStore, dstStore, info.path, repair, checkSigs); +} + +void copyOrBuildStorePath(Store & srcStore, Store & dstStore, + const ValidPathInfo & info, RepairFlag repair, CheckSigsFlag checkSigs) +{ + auto storePath = info.path; + if (dstStore.isTrusting || info.ca) { + copyStorePath(srcStore, dstStore, storePath, repair, checkSigs); + } else if (info.deriver && dstStore.storeDir == srcStore.storeDir) { + auto drvPath = *info.deriver; + auto outputMap = srcStore.queryDerivationOutputMap(drvPath); + auto p = std::find_if(outputMap.begin(), outputMap.end(), [&](auto & i) { + return i.second == storePath; + }); + // drv file is always CA + srcStore.ensurePath(drvPath); + copyStorePath(srcStore, dstStore, drvPath, repair, checkSigs); + dstStore.buildPaths({ + DerivedPath::Built { + .drvPath = drvPath, + .outputs = p != outputMap.end() ? StringSet { p->first } : StringSet {}, + }, + }); + } else { + dstStore.ensurePath(storePath); + } +} + + std::map<StorePath, StorePath> copyPaths( Store & srcStore, Store & dstStore, const RealisedPath::Set & paths, RepairFlag repair, CheckSigsFlag checkSigs, - SubstituteFlag substitute) + SubstituteFlag substitute, + std::function<void(Store &, Store &, const ValidPathInfo &, RepairFlag, CheckSigsFlag)> copyStorePathImpl) { StorePathSet storePaths; std::set<Realisation> toplevelRealisations; @@ -864,7 +898,7 @@ std::map<StorePath, StorePath> copyPaths( toplevelRealisations.insert(*realisation); } } - auto pathsMap = copyPaths(srcStore, dstStore, storePaths, repair, checkSigs, substitute); + auto pathsMap = copyPaths(srcStore, dstStore, storePaths, repair, checkSigs, substitute, copyStorePathImpl); ThreadPool pool; @@ -907,7 +941,8 @@ std::map<StorePath, StorePath> copyPaths( const StorePathSet & storePaths, RepairFlag repair, CheckSigsFlag checkSigs, - SubstituteFlag substitute) + SubstituteFlag substitute, + std::function<void(Store &, Store &, const ValidPathInfo &, RepairFlag, CheckSigsFlag)> copyStorePathImpl) { auto valid = dstStore.queryValidPaths(storePaths, substitute); @@ -1007,7 +1042,7 @@ std::map<StorePath, StorePath> copyPaths( MaintainCount<decltype(nrRunning)> mc(nrRunning); showProgress(); try { - copyStorePath(srcStore, dstStore, storePath, repair, checkSigs); + copyStorePathImpl(srcStore, dstStore, *info, repair, checkSigs); } catch (Error &e) { nrFailed++; if (!settings.keepGoing) diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 54471bdf2..24b9228f9 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -192,7 +192,9 @@ struct StoreConfig : public Config const Setting<int> pathInfoCacheSize{this, 65536, "path-info-cache-size", "size of the in-memory store path information cache"}; - const Setting<bool> isTrusted{this, false, "trusted", "whether paths from this store can be used as substitutes even when they lack trusted signatures"}; + const Setting<bool> isTrusted{this, false, "trusted", "whether paths from this store can be used as substitutes even when they lack trusted signatures. Compare \"trusting\""}; + + Setting<bool> isTrusting{this, true, "trusting", "whether (we think) paths can be added to this store even when they lack trusted signatures. Compare \"trusted\""}; Setting<int> priority{this, 0, "priority", "priority of this substituter (lower value means higher priority)"}; @@ -767,25 +769,42 @@ void copyStorePath( CheckSigsFlag checkSigs = CheckSigs); +/* copyStorePath wrapped to be used with `copyPaths`. */ +void copyStorePathAdapter(Store & srcStore, Store & dstStore, + const ValidPathInfo & info, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); + +/* The more liberal alternative to `copyStorePathAdapter`, useful for remote + stores that do not trust us. */ +void copyOrBuildStorePath(Store & srcStore, Store & dstStore, + const ValidPathInfo & info, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); + /* Copy store paths from one store to another. The paths may be copied in parallel. They are copied in a topologically sorted order (i.e. if A is a reference of B, then A is copied before B), but the set of store paths is not automatically closed; use copyClosure() for that. Returns a map of what each path was copied to the dstStore - as. */ + as. + + The `copyStorePathImpl` parameter allows doing something other than just + copying. For example, this is used with the build hook to allow the other + side to build dependencies we don't have permission to copy. This behavior + isn't just the default that way `nix copy` etc. still can be relied upon to + not build anything. */ std::map<StorePath, StorePath> copyPaths( Store & srcStore, Store & dstStore, const RealisedPath::Set &, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, - SubstituteFlag substitute = NoSubstitute); + SubstituteFlag substitute = NoSubstitute, + std::function<void(Store &, Store &, const ValidPathInfo &, RepairFlag, CheckSigsFlag)> copyStorePathImpl = copyStorePathAdapter); std::map<StorePath, StorePath> copyPaths( Store & srcStore, Store & dstStore, const StorePathSet & paths, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs, - SubstituteFlag substitute = NoSubstitute); + SubstituteFlag substitute = NoSubstitute, + std::function<void(Store &, Store &, const ValidPathInfo &, RepairFlag, CheckSigsFlag)> copyStorePathImpl = copyStorePathAdapter); /* Copy the closure of `paths` from `srcStore` to `dstStore`. */ void copyClosure( diff --git a/src/nix/daemon.cc b/src/nix/daemon.cc index 6a40a0bd3..da8d91029 100644 --- a/src/nix/daemon.cc +++ b/src/nix/daemon.cc @@ -265,10 +265,16 @@ static void daemonLoop() } } -static void runDaemon(bool stdio) +static void runDaemon(bool stdio, std::optional<TrustedFlag> isTrustedOpt = {}) { + auto ensureNoTrustedFlag = [&]() { + if (isTrustedOpt) + throw Error("--trust and --no-trust flags are only for use with --stdio when this nix-daemon process is not proxying another"); + }; + if (stdio) { if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) { + ensureNoTrustedFlag(); auto conn = store->openConnectionWrapper(); int from = conn->from.fd; int to = conn->to.fd; @@ -302,16 +308,20 @@ static void runDaemon(bool stdio) /* Auth hook is empty because in this mode we blindly trust the standard streams. Limiting access to those is explicitly not `nix-daemon`'s responsibility. */ - processConnection(openUncachedStore(), from, to, Trusted, NotRecursive, [&](Store & _){}); + auto isTrusted = isTrustedOpt.value_or(Trusted); + processConnection(openUncachedStore(), from, to, isTrusted, NotRecursive, [&](Store & _){}); } - } else + } else { + ensureNoTrustedFlag(); daemonLoop(); + } } static int main_nix_daemon(int argc, char * * argv) { { auto stdio = false; + std::optional<TrustedFlag> isTrustedOpt; parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--daemon") @@ -322,11 +332,17 @@ static int main_nix_daemon(int argc, char * * argv) printVersion("nix-daemon"); else if (*arg == "--stdio") stdio = true; - else return false; + else if (*arg == "--trust") { + settings.requireExperimentalFeature("nix-testing"); + isTrustedOpt = Trusted; + } else if (*arg == "--no-trust") { + settings.requireExperimentalFeature("nix-testing"); + isTrustedOpt = NotTrusted; + } else return false; return true; }); - runDaemon(stdio); + runDaemon(stdio, isTrustedOpt); return 0; } |