forked from lix-project/lix
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:
parent
38b87dea62
commit
5c34d66538
|
@ -259,7 +259,7 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
v.attrs->sort();
|
v.attrs->sort();
|
||||||
|
|
||||||
if (state.allowedPaths)
|
if (state.allowedPaths)
|
||||||
state.allowedPaths->insert(gitInfo.storePath);
|
state.allowedPaths->insert(state.store->toRealPath(gitInfo.storePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r("fetchGit", 1, prim_fetchGit);
|
static RegisterPrimOp r("fetchGit", 1, prim_fetchGit);
|
||||||
|
|
|
@ -214,7 +214,7 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
||||||
v.attrs->sort();
|
v.attrs->sort();
|
||||||
|
|
||||||
if (state.allowedPaths)
|
if (state.allowedPaths)
|
||||||
state.allowedPaths->insert(hgInfo.storePath);
|
state.allowedPaths->insert(state.store->toRealPath(hgInfo.storePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp r("fetchMercurial", 1, prim_fetchMercurial);
|
static RegisterPrimOp r("fetchMercurial", 1, prim_fetchMercurial);
|
||||||
|
|
|
@ -248,7 +248,7 @@ static SourceInfo fetchFlake(EvalState & state, const FlakeRef & flakeRef, bool
|
||||||
FlakeRef ref(resolvedRef.baseRef());
|
FlakeRef ref(resolvedRef.baseRef());
|
||||||
ref.rev = Hash(std::string(*result.etag, 1, result.etag->size() - 2), htSHA1);
|
ref.rev = Hash(std::string(*result.etag, 1, result.etag->size() - 2), htSHA1);
|
||||||
SourceInfo info(ref);
|
SourceInfo info(ref);
|
||||||
info.storePath = result.path;
|
info.storePath = result.storePath;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -294,21 +294,22 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef, bool impureIsAllowe
|
||||||
state.store->assertStorePath(sourceInfo.storePath);
|
state.store->assertStorePath(sourceInfo.storePath);
|
||||||
|
|
||||||
if (state.allowedPaths)
|
if (state.allowedPaths)
|
||||||
state.allowedPaths->insert(sourceInfo.storePath);
|
state.allowedPaths->insert(state.store->toRealPath(sourceInfo.storePath));
|
||||||
|
|
||||||
// Guard against symlink attacks.
|
// Guard against symlink attacks.
|
||||||
Path flakeFile = canonPath(sourceInfo.storePath + "/" + resolvedRef.subdir + "/flake.nix");
|
Path flakeFile = canonPath(sourceInfo.storePath + "/" + resolvedRef.subdir + "/flake.nix");
|
||||||
if (!isInDir(flakeFile, sourceInfo.storePath))
|
Path realFlakeFile = state.store->toRealPath(flakeFile);
|
||||||
throw Error("flake file '%s' escapes from '%s'", resolvedRef, sourceInfo.storePath);
|
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 flake(flakeRef, sourceInfo);
|
||||||
flake.hash = state.store->queryPathInfo(sourceInfo.storePath)->narHash;
|
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);
|
throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", resolvedRef, resolvedRef.subdir);
|
||||||
|
|
||||||
Value vInfo;
|
Value vInfo;
|
||||||
state.evalFile(flakeFile, vInfo); // FIXME: symlink attack
|
state.evalFile(realFlakeFile, vInfo); // FIXME: symlink attack
|
||||||
|
|
||||||
state.forceAttrs(vInfo);
|
state.forceAttrs(vInfo);
|
||||||
|
|
||||||
|
|
|
@ -804,6 +804,7 @@ CachedDownloadResult Downloader::downloadCached(ref<Store> store, const string &
|
||||||
expectedStorePath = store->makeFixedOutputPath(unpack, expectedHash, name);
|
expectedStorePath = store->makeFixedOutputPath(unpack, expectedHash, name);
|
||||||
if (store->isValidPath(expectedStorePath)) {
|
if (store->isValidPath(expectedStorePath)) {
|
||||||
CachedDownloadResult result;
|
CachedDownloadResult result;
|
||||||
|
result.storePath = expectedStorePath;
|
||||||
result.path = store->toRealPath(expectedStorePath);
|
result.path = store->toRealPath(expectedStorePath);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -912,6 +913,7 @@ CachedDownloadResult Downloader::downloadCached(ref<Store> store, const string &
|
||||||
url, expectedHash.to_string(), gotHash.to_string());
|
url, expectedHash.to_string(), gotHash.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.storePath = storePath;
|
||||||
result.path = store->toRealPath(storePath);
|
result.path = store->toRealPath(storePath);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,9 @@ struct DownloadResult
|
||||||
|
|
||||||
struct CachedDownloadResult
|
struct CachedDownloadResult
|
||||||
{
|
{
|
||||||
|
// Note: 'storePath' may be different from 'path' when using a
|
||||||
|
// chroot store.
|
||||||
|
Path storePath;
|
||||||
Path path;
|
Path path;
|
||||||
std::optional<std::string> etag;
|
std::optional<std::string> etag;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue