Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

pathExists: Return false on "/nix/store" in pure mode #10505

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

edolstra
Copy link
Member

Motivation

AllowListInputAccessor has the invariant that if a path is accessible, its parent directories are also considered accessible (though reading them only yields the allowed subdirectories). As a result builtins.pathExists "/nix/store" returns true.

However this wasn't the behaviour of previous path access control, where builtins.pathExists "/nix/store" returns false even if a subdirectory of the store is accessible.

Fixes #9672.

Context

Priorities and Process

Add 馃憤 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@edolstra edolstra requested a review from roberth as a code owner April 15, 2024 14:26
@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label Apr 15, 2024
@Ericson2314
Copy link
Member

Ericson2314 commented Apr 15, 2024

What about builtins.pathExists "/nix"? Can you test that too?

Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about builtins.readFileType?

AllowListInputAccessor has the invariant that if a path is accessible,
its parent directories are also considered accessible (though reading
them only yields the allowed subdirectories). As a result
`builtins.pathExists "/nix/store"` returns true.

However this wasn't the behaviour of previous path access control,
where `builtins.pathExists "/nix/store"` returns false even if a
subdirectory of the store is accessible.

Fixes NixOS#9672.
@roberth
Copy link
Member

roberth commented Apr 16, 2024

AllowListInputAccessor has the invariant

This seems like a good invariant in normal use when composing accessors and such.

However this wasn't the behaviour of previous path access control,

Maybe the system accessor should be a composition of AllowListAccessor and something like PartialAccessor?

Regardless of how the accessor is named and structured, this is better handled in the accessor abstraction than in the language frontend, as highlighted by John's observation; this behavior needs to be reflected in all operations. Then the builtins can just use that and not have to duplicate a "hack".

@github-actions github-actions bot added the fetching Networking with the outside (non-Nix) world label Apr 16, 2024
@edolstra
Copy link
Member Author

edolstra commented Apr 16, 2024

I removed the special case handling in pathExists and reverted to the old behaviour, i.e. access to a parent is forbidden unless it's explicitly permitted. To support this, AllowListInputAccessor now has a set of allowed prefixes and allowed paths.

Comment on lines +949 to +955
std::unordered_set<CanonPath> files{CanonPath::root};
for (auto path : wd.files) {
while (!path.isRoot()) {
if (!files.insert(path).second) break;
path.pop();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a generic solution for getting the closure of path parents. Would be nice to factor out.

src/libfetchers/filtering-input-accessor.hh Outdated Show resolved Hide resolved
@@ -111,7 +111,7 @@ struct SourceAccessor
std::optional<uint64_t> narOffset;
};

Stat lstat(const CanonPath & path);
virtual Stat lstat(const CanonPath & path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC if allowed paths is closed under taking parent dirs, then we don't need this, because this is just done for sake of resolving symlinks?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary to get the correct error message for inaccessible paths, i.e. forbidden in restricted mode rather than does not exist.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense,

I was thinking more the other thing, having lstatMaybe not allow /nix and /nix/store again. And the interaction with the other PR more broadly.

@Ericson2314
Copy link
Member

We talked about this a while today in the Nix meting. I unfortunately basically changed my mind: I am not comfortable with /foo/bar existing not implying /foo existing, especially while the SourceAccessor interface is so new and we are still figuring out what its "laws" are.

This means I am actually back to preferring the original version of the PR, which did not change the deep abstraction of SourceAccessor and just did a quick hack in the evaluator. In particular, I would like to just have that quick hack for "restricted eval", and leave pure eval as is, with builtins.pathExists "/nix/store" == true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fetching Networking with the outside (non-Nix) world with-tests Issues related to testing. PRs with tests have some priority
Projects
None yet
Development

Successfully merging this pull request may close these issues.

possible regression: "stack overflow (possible infinite recursion)"
3 participants