Fix showing an appropriate RestrictedPathError

This commit is contained in:
Eelco Dolstra 2022-05-18 14:20:24 +02:00
parent c1a202c348
commit 1970d6db12
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
4 changed files with 29 additions and 11 deletions

View file

@ -461,10 +461,18 @@ EvalState::EvalState(
, sPrefix(symbols.create("prefix")) , sPrefix(symbols.create("prefix"))
, repair(NoRepair) , repair(NoRepair)
, emptyBindings(0) , emptyBindings(0)
, rootFS(makeFSInputAccessor(CanonPath::root, , rootFS(
makeFSInputAccessor(
CanonPath::root,
evalSettings.restrictEval || evalSettings.pureEval evalSettings.restrictEval || evalSettings.pureEval
? std::optional<std::set<CanonPath>>(std::set<CanonPath>()) ? std::optional<std::set<CanonPath>>(std::set<CanonPath>())
: std::nullopt)) : std::nullopt,
[](const CanonPath & path) -> RestrictedPathError {
auto modeInformation = evalSettings.pureEval
? "in pure eval mode (use '--impure' to override)"
: "in restricted mode";
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
}))
, corepkgsFS(makeMemoryInputAccessor()) , corepkgsFS(makeMemoryInputAccessor())
, store(store) , store(store)
, buildStore(buildStore ? buildStore : store) , buildStore(buildStore ? buildStore : store)

View file

@ -20,7 +20,6 @@ MakeError(Abort, EvalError);
MakeError(TypeError, EvalError); MakeError(TypeError, EvalError);
MakeError(UndefinedVarError, Error); MakeError(UndefinedVarError, Error);
MakeError(MissingArgumentError, EvalError); MakeError(MissingArgumentError, EvalError);
MakeError(RestrictedPathError, Error);
/* Position objects. */ /* Position objects. */

View file

@ -104,10 +104,15 @@ struct FSInputAccessorImpl : FSInputAccessor
{ {
CanonPath root; CanonPath root;
std::optional<std::set<CanonPath>> allowedPaths; std::optional<std::set<CanonPath>> allowedPaths;
MakeNotAllowedError makeNotAllowedError;
FSInputAccessorImpl(const CanonPath & root, std::optional<std::set<CanonPath>> && allowedPaths) FSInputAccessorImpl(
const CanonPath & root,
std::optional<std::set<CanonPath>> && allowedPaths,
MakeNotAllowedError && makeNotAllowedError)
: root(root) : root(root)
, allowedPaths(allowedPaths) , allowedPaths(std::move(allowedPaths))
, makeNotAllowedError(std::move(makeNotAllowedError))
{ } { }
std::string readFile(const CanonPath & path) override std::string readFile(const CanonPath & path) override
@ -171,9 +176,9 @@ struct FSInputAccessorImpl : FSInputAccessor
void checkAllowed(const CanonPath & absPath) override void checkAllowed(const CanonPath & absPath) override
{ {
if (!isAllowed(absPath)) if (!isAllowed(absPath))
// FIXME: for Git trees, show a custom error message like throw makeNotAllowedError
// "file is not under version control or does not exist" ? makeNotAllowedError(absPath)
throw Error("access to path '%s' is forbidden", absPath); : RestrictedPathError("access to path '%s' is forbidden", absPath);
} }
bool isAllowed(const CanonPath & absPath) bool isAllowed(const CanonPath & absPath)
@ -209,9 +214,10 @@ struct FSInputAccessorImpl : FSInputAccessor
ref<FSInputAccessor> makeFSInputAccessor( ref<FSInputAccessor> makeFSInputAccessor(
const CanonPath & root, const CanonPath & root,
std::optional<std::set<CanonPath>> && allowedPaths) std::optional<std::set<CanonPath>> && allowedPaths,
MakeNotAllowedError && makeNotAllowedError)
{ {
return make_ref<FSInputAccessorImpl>(root, std::move(allowedPaths)); return make_ref<FSInputAccessorImpl>(root, std::move(allowedPaths), std::move(makeNotAllowedError));
} }
std::ostream & operator << (std::ostream & str, const SourcePath & path) std::ostream & operator << (std::ostream & str, const SourcePath & path)

View file

@ -7,6 +7,8 @@
namespace nix { namespace nix {
MakeError(RestrictedPathError, Error);
struct InputAccessor struct InputAccessor
{ {
const size_t number; const size_t number;
@ -68,9 +70,12 @@ struct FSInputAccessor : InputAccessor
virtual bool hasAccessControl() = 0; virtual bool hasAccessControl() = 0;
}; };
typedef std::function<RestrictedPathError(const CanonPath & path)> MakeNotAllowedError;
ref<FSInputAccessor> makeFSInputAccessor( ref<FSInputAccessor> makeFSInputAccessor(
const CanonPath & root, const CanonPath & root,
std::optional<std::set<CanonPath>> && allowedPaths = {}); std::optional<std::set<CanonPath>> && allowedPaths = {},
MakeNotAllowedError && makeNotAllowedError = {});
struct MemoryInputAccessor : InputAccessor struct MemoryInputAccessor : InputAccessor
{ {