Skip to content

Comments

Store::getFSAccessor: Do not include the store dir #12531

Merged
edolstra merged 2 commits intoNixOS:masterfrom
obsidiansystems:store-accessor-root
Apr 10, 2025
Merged

Store::getFSAccessor: Do not include the store dir #12531
edolstra merged 2 commits intoNixOS:masterfrom
obsidiansystems:store-accessor-root

Conversation

@Ericson2314
Copy link
Member

@Ericson2314 Ericson2314 commented Feb 20, 2025

Motivation

Rather than "mounting" the store inside an empty virtual filesystem,
just return the store as a virtual filesystem. This is more modular.

Context

Depends on #12667

FWIW, it also supports two long term hopes of mind:

  1. More capability-based Nix language mode. I dream of a "super pure
    eval" where you can only use relative path literals (See no-absolute-path-literals experimental feature #8738), and
    any fetchTree-fetched stuff + the store are all disjoint (none is
    mounted in another) file systems.

  2. Windows, where the store dir may include drive letters, etc., and is
    thus unsuitable to be the prefix of any CanonPaths.


Add 👍 to pull requests you find important.

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

@github-actions github-actions bot added new-cli Relating to the "nix" command with-tests Issues related to testing. PRs with tests have some priority store Issues and pull requests concerning the Nix store fetching Networking with the outside (non-Nix) world, input locking labels Feb 20, 2025

# Test that symlinks outside of the store don't work.
expect 1 nix shell -f shell-hello.nix forbidden-symlink -c hello 2>&1 | grepQuiet "is not in the Nix store"
expect 1 nix shell -f shell-hello.nix forbidden-symlink -c hello 2>&1 | grepQuiet "points outside source accessor"
Copy link
Member Author

Choose a reason for hiding this comment

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

N.B. error message is quite arguably worse.

On the other hand, this error message should be something that can occur in other contexts for other reasons (e.g. symlinks escaping fetch-tree'd source), in which case having the same message to show the commonality is good.

The fullt expanded messages has all the relevant paths, so the user will still see /nix/store.

@Ericson2314 Ericson2314 force-pushed the store-accessor-root branch 2 times, most recently from e98041b to ca13970 Compare February 20, 2025 01:52
@edolstra edolstra self-assigned this Feb 26, 2025
@Ericson2314 Ericson2314 force-pushed the store-accessor-root branch from c811b33 to 46fbfea Compare March 17, 2025 04:18
Copy link
Member

@edolstra edolstra left a comment

Choose a reason for hiding this comment

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

I don't really understand what ownLocationForSymlinkResolution is for. Can you give a concrete example where it's needed?

have host-OS-agnostic designs), we cannot simply
use whether we are running on Unix or Windows for
this. */
if (!(hasPrefix(target, ownLocationForSymlinkResolution) && (target.size() == prefixLen || target[prefixLen] == '/'))) {
Copy link
Member

Choose a reason for hiding this comment

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

Should target be canonicalized before doing hasPrefix() on it? Otherwise a legal symlink target like /foo///bar won't match /foo/bar.

Also I think you can use isInDir() here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do we have code for a really weak canonicalization for this? We should not get rid of .. for example, we should just collapse adjacent /.

I guess I could write it, but it is tempting to factor out the CanonPath iterator that does this.

@Ericson2314 Ericson2314 force-pushed the store-accessor-root branch 2 times, most recently from 27727a8 to ba3f481 Compare March 17, 2025 22:22
*
* (I made these examples use Windows/DOS paths to remind the reader
* that neither the symlink target nor
* `ownLocationForSymlinkResolution` should be a `CanonPath`.)
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure how this would work since our source accessor abstraction has no concept of drive letters. Its concept of a path is the CanonPath.

Copy link
Member Author

Choose a reason for hiding this comment

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

@edolstra (Just writing down some things we discussed on the call)

Its concept of a path is the CanonPath.

And that doesn't change. This is just about how we interact with the "external" paths in symlink targets, which we need to convert back to our own "internal" paths.

* to implement correctly that I (@Ericson2314) am not doing this at
* this time, however.
*/
std::filesystem::path ownLocationForSymlinkResolution = "/";
Copy link
Member

Choose a reason for hiding this comment

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

I'm still not clear on why this is needed (given that we didn't need it prior to this PR). There may be an issue if you call resolveSymlinks on a projected store path accessor, but presumably we only call resolveSymlinks on storeFS (i.e. the MountedSourceAccessor that sees the entire store, and where we don't need to rewrite /nix/store).

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed on the call, without this there is a test failure because of /nix/store absolute paths in symlink targets. I split the history in two so that if one just tries the first commit it doesn't have this, and that test failure is reproduced.

@Ericson2314 Ericson2314 force-pushed the store-accessor-root branch 2 times, most recently from 729a4dc to d5548a3 Compare March 19, 2025 21:46
@dpulls
Copy link

dpulls bot commented Mar 19, 2025

🎉 All dependencies have been resolved !

@edolstra
Copy link
Member

@Ericson2314 I've made a different fix for the ownLocationForSymlinkResolution: f69bccf (this replaces the last commit of this PR). It makes nix shell use storeFS (which is the MountedSourceAccessor that wraps store->getFSAccessor()).

Having said that, I'm not sure whether it really makes sense to have Store::getFSAccessor() not include the store directory. Logically the store directory is essential, since absolute symlink resolution just doesn't work without it.

@Ericson2314
Copy link
Member Author

Ericson2314 commented Apr 7, 2025

@edolstra, I am very much a fan of having a storeFS --- I was going to do that next after this --- but I am skeptical that solvesthe problem.

Having said that, I'm not sure whether it really makes sense to have Store::getFSAccessor() not include the store directory. Logically the store directory is essential, since absolute symlink resolution just doesn't work without it.

Bu that is what my commit you are skeptical of is for! Making things that don't "locally" include / while not breaking absolute symlink resolution.

Perhaps we should talk about these things wednesday, once we're good for Nix 2.28 in Nixpkgs.

@Ericson2314 Ericson2314 force-pushed the store-accessor-root branch from d5548a3 to 2d77c87 Compare April 9, 2025 21:25
@Ericson2314
Copy link
Member Author

Ericson2314 commented Apr 9, 2025

OK we agreed to do it with @edolstra's second commit for now. I still want to do my second commit (and other changes too), but that can be a subsequent PR.

@edolstra will do one final review tomorrow.

Ericson2314 and others added 2 commits April 9, 2025 17:34
Rather than "mounting" the store inside an empty virtual filesystem,
just return the store as a virtual filesystem. This is more modular.

(FWIW, it also supports two long term hopes of mind:

1. More capability-based Nix language mode. I dream of a "super pure
   eval" where you can only use relative path literals (See NixOS#8738), and
   any `fetchTree`-fetched stuff + the store are all disjoint (none is
   mounted in another) file systems.

2. Windows, where the store dir may include drive letters, etc., and is
   thus unsuitable to be the prefix of any `CanonPath`s.

)

Co-authored-by: Eelco Dolstra <[email protected]>
`storeFS` is the `MountedSourceAccessor` that wraps `store->getFSAccessor()`.
@Ericson2314 Ericson2314 force-pushed the store-accessor-root branch from 2d77c87 to 9d35956 Compare April 9, 2025 21:35
@edolstra edolstra merged commit 26cb166 into NixOS:master Apr 10, 2025
12 checks passed
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, input locking new-cli Relating to the "nix" command store Issues and pull requests concerning the Nix store 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.

4 participants