Properly return false on builtins.pathExists /someNonAllowedPath

Follow-up from https://github.com/NixOS/nix/pull/5807 to fix https://github.com/NixOS/nix/pull/5807#issuecomment-1000135394
This commit is contained in:
regnat 2021-12-23 10:35:09 +01:00
parent 7feb741e00
commit dc89dfa7b3
2 changed files with 25 additions and 7 deletions

View file

@ -89,18 +89,28 @@ StringMap EvalState::realiseContext(const PathSet & context)
return res; return res;
} }
static Path realisePath(EvalState & state, const Pos & pos, Value & v, bool requireAbsolutePath = true) struct RealisePathFlags {
// Whether to check whether the path is a valid absolute path
bool requireAbsolutePath = true;
// Whether to check that the path is allowed in pure eval mode
bool checkForPureEval = true;
};
static Path realisePath(EvalState & state, const Pos & pos, Value & v, const RealisePathFlags flags = {})
{ {
PathSet context; PathSet context;
Path path = requireAbsolutePath Path path = flags.requireAbsolutePath
? state.coerceToPath(pos, v, context) ? state.coerceToPath(pos, v, context)
: state.coerceToString(pos, v, context, false, false); : state.coerceToString(pos, v, context, false, false);
StringMap rewrites = state.realiseContext(context); StringMap rewrites = state.realiseContext(context);
return state.checkSourcePath( auto realPath = state.toRealPath(rewriteStrings(path, rewrites), context);
state.toRealPath(rewriteStrings(path, rewrites), context));
return flags.checkForPureEval
? state.checkSourcePath(realPath)
: realPath;
} }
/* Add and attribute to the given attribute map from the output name to /* Add and attribute to the given attribute map from the output name to
@ -1371,7 +1381,12 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args,
{ {
Path path; Path path;
try { try {
path = realisePath(state, pos, *args[0]); // We dont check the path right now, because we dont want to throw if
// the path isnt allowed, but just return false
// (and we cant just catch the exception here because we still want to
// throw if something in the evaluation of `*args[0]` tries to access an
// unauthorized path)
path = realisePath(state, pos, *args[0], { .checkForPureEval = false });
} catch (InvalidPathError & e) { } catch (InvalidPathError & e) {
throw EvalError({ throw EvalError({
.msg = hintfmt( .msg = hintfmt(
@ -1382,7 +1397,7 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args,
} }
try { try {
mkBool(v, pathExists(path)); mkBool(v, pathExists(state.checkSourcePath(path)));
} catch (SysError & e) { } catch (SysError & e) {
/* Don't give away info from errors while canonicalising /* Don't give away info from errors while canonicalising
path in restricted mode. */ path in restricted mode. */
@ -1496,7 +1511,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
Path path; Path path;
try { try {
path = realisePath(state, pos, *i->value, false); path = realisePath(state, pos, *i->value, { .requireAbsolutePath = false });
} catch (InvalidPathError & e) { } catch (InvalidPathError & e) {
throw EvalError({ throw EvalError({
.msg = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path), .msg = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path),

View file

@ -11,6 +11,9 @@ missingImpureErrorMsg=$(! nix eval --expr 'builtins.readFile ./pure-eval.sh' 2>&
echo "$missingImpureErrorMsg" | grep -q -- --impure || \ echo "$missingImpureErrorMsg" | grep -q -- --impure || \
fail "The error message should mention the “--impure” flag to unblock users" fail "The error message should mention the “--impure” flag to unblock users"
[[ $(nix eval --expr 'builtins.pathExists ./pure-eval.sh') == false ]] || \
fail "Calling 'pathExists' on a non-authorised path should return false"
(! nix eval --expr builtins.currentTime) (! nix eval --expr builtins.currentTime)
(! nix eval --expr builtins.currentSystem) (! nix eval --expr builtins.currentSystem)