diff --git a/src/libstore/restricted-store.cc b/src/libstore/restricted-store.cc index 643dc5239..42e81765d 100644 --- a/src/libstore/restricted-store.cc +++ b/src/libstore/restricted-store.cc @@ -71,44 +71,15 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual In return next->getUri(); } - StorePathSet queryAllValidPaths() override - { - StorePathSet paths; - for (auto & p : goal.originalPaths()) - paths.insert(p); - for (auto & p : goal.addedPaths) - paths.insert(p); - return paths; - } + StorePathSet queryAllValidPaths() override; void queryPathInfoUncached( - const StorePath & path, Callback> callback) noexcept override - { - if (goal.isAllowed(path)) { - try { - /* Censor impure information. */ - auto info = std::make_shared(*next->queryPathInfo(path)); - info->deriver.reset(); - info->registrationTime = 0; - info->ultimate = false; - info->sigs.clear(); - callback(info); - } catch (InvalidPath &) { - callback(nullptr); - } - } else - callback(nullptr); - }; + const StorePath & path, Callback> callback) noexcept override; - void queryReferrers(const StorePath & path, StorePathSet & referrers) override {} + void queryReferrers(const StorePath & path, StorePathSet & referrers) override; std::map> - queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore = nullptr) override - { - if (!goal.isAllowed(path)) - throw InvalidPath("cannot query output map for unknown path '%s' in recursive Nix", printStorePath(path)); - return next->queryPartialDerivationOutputMap(path, evalStore); - } + queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore = nullptr) override; std::optional queryPathFromHashPart(const std::string & hashPart) override { @@ -131,11 +102,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual In const ValidPathInfo & info, Source & narSource, RepairFlag repair = NoRepair, - CheckSigsFlag checkSigs = CheckSigs) override - { - next->addToStore(info, narSource, repair, checkSigs); - goal.addDependency(info.path); - } + CheckSigsFlag checkSigs = CheckSigs) override; StorePath addToStoreFromDump( Source & dump, @@ -144,88 +111,24 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual In ContentAddressMethod hashMethod, HashAlgorithm hashAlgo, const StorePathSet & references, - RepairFlag repair) override - { - auto path = next->addToStoreFromDump(dump, name, dumpMethod, hashMethod, hashAlgo, references, repair); - goal.addDependency(path); - return path; - } + RepairFlag repair) override; - void narFromPath(const StorePath & path, Sink & sink) override - { - if (!goal.isAllowed(path)) - throw InvalidPath("cannot dump unknown path '%s' in recursive Nix", printStorePath(path)); - LocalFSStore::narFromPath(path, sink); - } + void narFromPath(const StorePath & path, Sink & sink) override; - void ensurePath(const StorePath & path) override - { - if (!goal.isAllowed(path)) - throw InvalidPath("cannot substitute unknown path '%s' in recursive Nix", printStorePath(path)); - /* Nothing to be done; 'path' must already be valid. */ - } + void ensurePath(const StorePath & path) override; - void registerDrvOutput(const Realisation & info) override - // XXX: This should probably be allowed as a no-op if the realisation - // corresponds to an allowed derivation - { - throw Error("registerDrvOutput"); - } + void registerDrvOutput(const Realisation & info) override; void queryRealisationUncached( - const DrvOutput & id, Callback> callback) noexcept override - // XXX: This should probably be allowed if the realisation corresponds to - // an allowed derivation - { - if (!goal.isAllowed(id)) - callback(nullptr); - next->queryRealisation(id, std::move(callback)); - } + const DrvOutput & id, Callback> callback) noexcept override; void - buildPaths(const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) override - { - for (auto & result : buildPathsWithResults(paths, buildMode, evalStore)) - if (!result.success()) - result.rethrow(); - } + buildPaths(const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) override; std::vector buildPathsWithResults( const std::vector & paths, BuildMode buildMode = bmNormal, - std::shared_ptr evalStore = nullptr) override - { - assert(!evalStore); - - if (buildMode != bmNormal) - throw Error("unsupported build mode"); - - StorePathSet newPaths; - std::set newRealisations; - - for (auto & req : paths) { - if (!goal.isAllowed(req)) - throw InvalidPath("cannot build '%s' in recursive Nix because path is unknown", req.to_string(*next)); - } - - auto results = next->buildPathsWithResults(paths, buildMode); - - for (auto & result : results) { - for (auto & [outputName, output] : result.builtOutputs) { - newPaths.insert(output.outPath); - newRealisations.insert(output); - } - } - - StorePathSet closure; - next->computeFSClosure(newPaths, closure); - for (auto & path : closure) - goal.addDependency(path); - for (auto & real : Realisation::closure(*next, newRealisations)) - goal.addedDrvOutputs.insert(real.id); - - return results; - } + std::shared_ptr evalStore = nullptr) override; BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildMode buildMode = bmNormal) override @@ -255,22 +158,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual In StorePathSet & willSubstitute, StorePathSet & unknown, uint64_t & downloadSize, - uint64_t & narSize) override - { - /* This is slightly impure since it leaks information to the - client about what paths will be built/substituted or are - already present. Probably not a big deal. */ - - std::vector allowed; - for (auto & req : targets) { - if (goal.isAllowed(req)) - allowed.emplace_back(req); - else - unknown.insert(pathPartOfReq(req)); - } - - next->queryMissing(allowed, willBuild, willSubstitute, unknown, downloadSize, narSize); - } + uint64_t & narSize) override; virtual std::optional getBuildLogExact(const StorePath & path) override { @@ -293,4 +181,161 @@ ref makeRestrictedStore(const Store::Params & params, ref nex return make_ref(params, next, context); } +StorePathSet RestrictedStore::queryAllValidPaths() +{ + StorePathSet paths; + for (auto & p : goal.originalPaths()) + paths.insert(p); + for (auto & p : goal.addedPaths) + paths.insert(p); + return paths; +} + +void RestrictedStore::queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept +{ + if (goal.isAllowed(path)) { + try { + /* Censor impure information. */ + auto info = std::make_shared(*next->queryPathInfo(path)); + info->deriver.reset(); + info->registrationTime = 0; + info->ultimate = false; + info->sigs.clear(); + callback(info); + } catch (InvalidPath &) { + callback(nullptr); + } + } else + callback(nullptr); +}; + +void RestrictedStore::queryReferrers(const StorePath & path, StorePathSet & referrers) {} + +std::map> +RestrictedStore::queryPartialDerivationOutputMap(const StorePath & path, Store * evalStore) +{ + if (!goal.isAllowed(path)) + throw InvalidPath("cannot query output map for unknown path '%s' in recursive Nix", printStorePath(path)); + return next->queryPartialDerivationOutputMap(path, evalStore); +} + +void RestrictedStore::addToStore( + const ValidPathInfo & info, Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs) +{ + next->addToStore(info, narSource, repair, checkSigs); + goal.addDependency(info.path); +} + +StorePath RestrictedStore::addToStoreFromDump( + Source & dump, + std::string_view name, + FileSerialisationMethod dumpMethod, + ContentAddressMethod hashMethod, + HashAlgorithm hashAlgo, + const StorePathSet & references, + RepairFlag repair) +{ + auto path = next->addToStoreFromDump(dump, name, dumpMethod, hashMethod, hashAlgo, references, repair); + goal.addDependency(path); + return path; +} + +void RestrictedStore::narFromPath(const StorePath & path, Sink & sink) +{ + if (!goal.isAllowed(path)) + throw InvalidPath("cannot dump unknown path '%s' in recursive Nix", printStorePath(path)); + LocalFSStore::narFromPath(path, sink); +} + +void RestrictedStore::ensurePath(const StorePath & path) +{ + if (!goal.isAllowed(path)) + throw InvalidPath("cannot substitute unknown path '%s' in recursive Nix", printStorePath(path)); + /* Nothing to be done; 'path' must already be valid. */ +} + +void RestrictedStore::registerDrvOutput(const Realisation & info) +// XXX: This should probably be allowed as a no-op if the realisation +// corresponds to an allowed derivation +{ + throw Error("registerDrvOutput"); +} + +void RestrictedStore::queryRealisationUncached( + const DrvOutput & id, Callback> callback) noexcept +// XXX: This should probably be allowed if the realisation corresponds to +// an allowed derivation +{ + if (!goal.isAllowed(id)) + callback(nullptr); + next->queryRealisation(id, std::move(callback)); +} + +void RestrictedStore::buildPaths( + const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) +{ + for (auto & result : buildPathsWithResults(paths, buildMode, evalStore)) + if (!result.success()) + result.rethrow(); +} + +std::vector RestrictedStore::buildPathsWithResults( + const std::vector & paths, BuildMode buildMode, std::shared_ptr evalStore) +{ + assert(!evalStore); + + if (buildMode != bmNormal) + throw Error("unsupported build mode"); + + StorePathSet newPaths; + std::set newRealisations; + + for (auto & req : paths) { + if (!goal.isAllowed(req)) + throw InvalidPath("cannot build '%s' in recursive Nix because path is unknown", req.to_string(*next)); + } + + auto results = next->buildPathsWithResults(paths, buildMode); + + for (auto & result : results) { + for (auto & [outputName, output] : result.builtOutputs) { + newPaths.insert(output.outPath); + newRealisations.insert(output); + } + } + + StorePathSet closure; + next->computeFSClosure(newPaths, closure); + for (auto & path : closure) + goal.addDependency(path); + for (auto & real : Realisation::closure(*next, newRealisations)) + goal.addedDrvOutputs.insert(real.id); + + return results; +} + +void RestrictedStore::queryMissing( + const std::vector & targets, + StorePathSet & willBuild, + StorePathSet & willSubstitute, + StorePathSet & unknown, + uint64_t & downloadSize, + uint64_t & narSize) +{ + /* This is slightly impure since it leaks information to the + client about what paths will be built/substituted or are + already present. Probably not a big deal. */ + + std::vector allowed; + for (auto & req : targets) { + if (goal.isAllowed(req)) + allowed.emplace_back(req); + else + unknown.insert(pathPartOfReq(req)); + } + + next->queryMissing(allowed, willBuild, willSubstitute, unknown, downloadSize, narSize); +} + }