Skip to content

SourceAccessor: Allow the lstat cache to be invalidated#14957

Merged
edolstra merged 1 commit intomasterfrom
invalidate-lstat-cache
Feb 4, 2026
Merged

SourceAccessor: Allow the lstat cache to be invalidated#14957
edolstra merged 1 commit intomasterfrom
invalidate-lstat-cache

Conversation

@edolstra
Copy link
Member

@edolstra edolstra commented Jan 9, 2026

Motivation

After lockFlake() creates a flake.lock in a PosixSourceAccessor, it needs to be able to invalidate the lstat cache, otherwise a subsequent attempt to read flake.lock will fail with an erroneous "path does not exist" error.

This isn't an issue yet on master, but it arises when we make the path fetcher lazy (DeterminateSystems#312).

Context


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 the fetching Networking with the outside (non-Nix) world, input locking label Jan 9, 2026
@xokdvium
Copy link
Contributor

xokdvium commented Jan 9, 2026

Not sure we should make such a deficiency a part of the object model of the SourceAccessor. The stat cache is sadly very TOCTOU prone. If anything, we should cache parent directory file descriptors — that wouldn't be such a footgun and wouldn't need explicit invalidation.

@edolstra
Copy link
Member Author

edolstra commented Jan 9, 2026

How would that work? It's not the directory that's being invalidated here.

@xokdvium
Copy link
Contributor

xokdvium commented Jan 9, 2026

Just never do stat caching.

It's only hot at the moment because of the symlink check and that can be easily remedied by either using openat2 with RESOLVE_NO_SYMLINKS to ban symlink traversal or by doing one-path-component at a time traversal with O_NOFOLLOW. That would solve the primary issue (of not allowing symlink traversal) in a pretty cheap and race-free manner.

I have a PoC on the unix-source-accessor branch, but I still need to implement parent directory file descriptor caching to work better when openat2 is not available.

@xokdvium
Copy link
Contributor

xokdvium commented Jan 9, 2026

What I'm really worried about at the moment is that the stat cache makes the TOCTOU window arbitrarily large. Suppose it happens that daemon (for whatever reason) does a dumpPath on a tree that an adversary has a writable file descriptor to (think the FOD file descriptor smuggling). I don't think the daemon now uses the source accessor for such directory trees, but I'm not 100% sure.

Then the daemon does:

readDirectory("a")
readFile("a/b") # large file
# directory a gets swapped with a symlink to /some/sensitive/path
readFile("a/verysecretfile") # Doesn't barf because stat cache

@edolstra
Copy link
Member Author

edolstra commented Jan 9, 2026

Just never do stat caching.

Sure, that would be much nicer, but we can always remove this invalidation code when we get rid of the cache.

@xokdvium
Copy link
Contributor

xokdvium commented Jan 9, 2026

Also true. Just pointing out that it's not the best approach in the long run. @Ericson2314 would love to hear your opinion on this too.

After lockFlake() creates flake.lock in a PosixSourceAccessor, it
needs to be able to invalidate the lstat cache.
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.

I am OK doing this on a temporary basis, but once we have @xokdvium's DescriptorSourceAccessor we should revert it and delete the lstat cache. And we should do that soon!

@edolstra edolstra force-pushed the invalidate-lstat-cache branch from 0ef98fe to 139d05a Compare February 4, 2026 20:57
@edolstra edolstra enabled auto-merge February 4, 2026 20:58
@edolstra edolstra added this pull request to the merge queue Feb 4, 2026
Merged via the queue into master with commit 27d5cc3 Feb 4, 2026
18 checks passed
@edolstra edolstra deleted the invalidate-lstat-cache branch February 4, 2026 22:31
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants