Make flakes work with 'nix build --store ...'

It was getting confused between logical and real store paths.

Also, make fetchGit and fetchMercurial update allowedPaths properly.

(Maybe the evaluator, rather than the caller of the evaluator, should
apply toRealPath(), but that's a bigger change.)
This commit is contained in:
Eelco Dolstra 2019-05-15 15:38:24 +02:00
parent 38b87dea62
commit 5c34d66538
5 changed files with 14 additions and 8 deletions

View file

@ -259,7 +259,7 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
v.attrs->sort();
if (state.allowedPaths)
state.allowedPaths->insert(gitInfo.storePath);
state.allowedPaths->insert(state.store->toRealPath(gitInfo.storePath));
}
static RegisterPrimOp r("fetchGit", 1, prim_fetchGit);

View file

@ -214,7 +214,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
v.attrs->sort();
if (state.allowedPaths)
state.allowedPaths->insert(hgInfo.storePath);
state.allowedPaths->insert(state.store->toRealPath(hgInfo.storePath));
}
static RegisterPrimOp r("fetchMercurial", 1, prim_fetchMercurial);

View file

@ -248,7 +248,7 @@ static SourceInfo fetchFlake(EvalState & state, const FlakeRef & flakeRef, bool
FlakeRef ref(resolvedRef.baseRef());
ref.rev = Hash(std::string(*result.etag, 1, result.etag->size() - 2), htSHA1);
SourceInfo info(ref);
info.storePath = result.path;
info.storePath = result.storePath;
return info;
}
@ -294,21 +294,22 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef, bool impureIsAllowe
state.store->assertStorePath(sourceInfo.storePath);
if (state.allowedPaths)
state.allowedPaths->insert(sourceInfo.storePath);
state.allowedPaths->insert(state.store->toRealPath(sourceInfo.storePath));
// Guard against symlink attacks.
Path flakeFile = canonPath(sourceInfo.storePath + "/" + resolvedRef.subdir + "/flake.nix");
if (!isInDir(flakeFile, sourceInfo.storePath))
throw Error("flake file '%s' escapes from '%s'", resolvedRef, sourceInfo.storePath);
Path realFlakeFile = state.store->toRealPath(flakeFile);
if (!isInDir(realFlakeFile, state.store->toRealPath(sourceInfo.storePath)))
throw Error("'flake.nix' file of flake '%s' escapes from '%s'", resolvedRef, sourceInfo.storePath);
Flake flake(flakeRef, sourceInfo);
flake.hash = state.store->queryPathInfo(sourceInfo.storePath)->narHash;
if (!pathExists(flakeFile))
if (!pathExists(realFlakeFile))
throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", resolvedRef, resolvedRef.subdir);
Value vInfo;
state.evalFile(flakeFile, vInfo); // FIXME: symlink attack
state.evalFile(realFlakeFile, vInfo); // FIXME: symlink attack
state.forceAttrs(vInfo);

View file

@ -804,6 +804,7 @@ CachedDownloadResult Downloader::downloadCached(ref<Store> store, const string &
expectedStorePath = store->makeFixedOutputPath(unpack, expectedHash, name);
if (store->isValidPath(expectedStorePath)) {
CachedDownloadResult result;
result.storePath = expectedStorePath;
result.path = store->toRealPath(expectedStorePath);
return result;
}
@ -912,6 +913,7 @@ CachedDownloadResult Downloader::downloadCached(ref<Store> store, const string &
url, expectedHash.to_string(), gotHash.to_string());
}
result.storePath = storePath;
result.path = store->toRealPath(storePath);
return result;
}

View file

@ -43,6 +43,9 @@ struct DownloadResult
struct CachedDownloadResult
{
// Note: 'storePath' may be different from 'path' when using a
// chroot store.
Path storePath;
Path path;
std::optional<std::string> etag;
};