From d39692e6b3275c6f54c066554d2915e4b857bc3e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Oct 2021 14:07:51 +0200 Subject: [PATCH] Make builtins.{path,filterSource} work with chroot stores --- src/libexpr/eval.cc | 10 ++++++++-- src/libexpr/eval.hh | 4 ++++ src/libexpr/flake/flake.cc | 2 +- src/libexpr/primops.cc | 13 +++++++------ src/libexpr/primops/fetchMercurial.cc | 2 +- src/libexpr/primops/fetchTree.cc | 8 +++----- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 2483132f6..3ae05a8d8 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -445,7 +445,7 @@ EvalState::EvalState( StorePathSet closure; store->computeFSClosure(store->toStorePath(r.second).first, closure); for (auto & path : closure) - allowPath(store->printStorePath(path)); + allowPath(path); } catch (InvalidPath &) { allowPath(r.second); } @@ -488,6 +488,12 @@ void EvalState::allowPath(const Path & path) allowedPaths->insert(path); } +void EvalState::allowPath(const StorePath & storePath) +{ + if (allowedPaths) + allowedPaths->insert(store->toRealPath(storePath)); +} + Path EvalState::checkSourcePath(const Path & path_) { if (!allowedPaths) return path_; @@ -1895,9 +1901,9 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path) ? store->computeStorePathForPath(std::string(baseNameOf(path)), checkSourcePath(path)).first : store->addToStore(std::string(baseNameOf(path)), checkSourcePath(path), FileIngestionMethod::Recursive, htSHA256, defaultPathFilter, repair); dstPath = store->printStorePath(p); + allowPath(p); srcToStore.insert_or_assign(path, std::move(p)); printMsg(lvlChatty, "copied source '%1%' -> '%2%'", path, dstPath); - allowPath(dstPath); } context.insert(dstPath); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index f8c9cf5a7..7cc16ef0a 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -153,6 +153,10 @@ public: /* Allow access to a path. */ void allowPath(const Path & path); + /* Allow access to a store path. Note that this gets remapped to + the real store path if `store` is a chroot store. */ + void allowPath(const StorePath & storePath); + /* Check whether access to a path is allowed and throw an error if not. Otherwise return the canonicalised path. */ Path checkSourcePath(const Path & path); diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index abb0fb0be..43bfc3644 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -64,7 +64,7 @@ static std::tuple fetchOrSubstituteTree( debug("got tree '%s' from '%s'", state.store->printStorePath(tree.storePath), lockedRef); - state.allowPath(tree.actualPath); + state.allowPath(tree.storePath); assert(!originalRef.input.getNarHash() || tree.storePath == originalRef.input.computeStorePath(*state.store)); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 94e196d62..f27331534 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1859,18 +1859,19 @@ static void addPath( // be rewritten to the actual output). state.realiseContext(context); - path = evalSettings.pureEval && expectedHash - ? path - : state.checkSourcePath(path); - if (state.store->isInStore(path)) { - auto storePath = state.store->toStorePath(path).first; + auto [storePath, subPath] = state.store->toStorePath(path); auto info = state.store->queryPathInfo(storePath); if (!info->references.empty()) throw EvalError("store path '%s' is not allowed to have references", state.store->printStorePath(storePath)); + path = state.store->toRealPath(storePath) + subPath; } + path = evalSettings.pureEval && expectedHash + ? path + : state.checkSourcePath(path); + PathFilter filter = filterFun ? ([&](const Path & path) { auto st = lstat(path); @@ -1911,7 +1912,7 @@ static void addPath( mkString(v, dstPath, {dstPath}); - state.allowPath(v.string.s); + state.allowPath(dstPath); } catch (Error & e) { e.addTrace(pos, "while adding path '%s'", path); diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc index b51b155f7..1cd481243 100644 --- a/src/libexpr/primops/fetchMercurial.cc +++ b/src/libexpr/primops/fetchMercurial.cc @@ -84,7 +84,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *revCount); v.attrs->sort(); - state.allowPath(tree.actualPath); + state.allowPath(tree.storePath); } static RegisterPrimOp r_fetchMercurial("fetchMercurial", 1, prim_fetchMercurial); diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 44f726f9b..f570f19ae 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -169,7 +169,7 @@ static void fetchTree( auto [tree, input2] = input.fetch(state.store); - state.allowPath(tree.actualPath); + state.allowPath(tree.storePath); emitTreeAttrs(state, tree, input2, v, params.emptyRevFallback, false); } @@ -233,18 +233,16 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, ? fetchers::downloadTarball(state.store, *url, name, (bool) expectedHash).first.storePath : fetchers::downloadFile(state.store, *url, name, (bool) expectedHash).storePath; - auto realPath = state.store->toRealPath(storePath); - if (expectedHash) { auto hash = unpack ? state.store->queryPathInfo(storePath)->narHash - : hashFile(htSHA256, realPath); + : hashFile(htSHA256, state.store->toRealPath(storePath)); if (hash != *expectedHash) throw Error((unsigned int) 102, "hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s", *url, expectedHash->to_string(Base32, true), hash.to_string(Base32, true)); } - state.allowPath(realPath); + state.allowPath(storePath); auto path = state.store->printStorePath(storePath); mkString(v, path, PathSet({path}));