libutil: Implement unix::fchmodatTryNoFollow, use in deletePath #14935
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
Using fchmodat after a fstatat in deletePath has a slight TOCTOU
window. We can plug it by using fchmodat (the libc wrapper with
AT_SYMLINK_NOFOLLOW), but it triesfchmodat2and falls back to theO_PATHtrick while failing when procfs isn't mounted. We can do a bitbetter than that and also cache whether syscalls are unsupported to
avoid the repeated context switching that glibc would impose.
Also tests the fallback path. It's only for kernels older than 6.6 and
when procfs isn't accessible that we fall back to the racy
fchmodatwithout
AT_SYMLINK_NOFOLLOW.What previously used to be:
Is now a TOCTOU-free sequence of syscalls:
Or if the
fchmodat2is not supported:This prevents a potentially arbitrary chmod that follows symlinks,
though the race window is very small. Also in the case that
fchmodat2isn't supported we could instead open the
/proc/self/fd/Npath insteadof using openat, but that's pretty much equivalent. We only care
about ensuring that the thing we chmodded wasn't a symlink since
fchmodatfollows symlinks and the support forAT_SYMLINK_NOFOLLOWin libc for that is pretty spotty on Linux. E.g. glibc fails if the
AT_SYMLINK_NOFOLLOWis specified and procfs isn't available even onregular files. The patch also includes a test that uses a user namespace
on Linux to test this exact scenario (though it's rather exotic).
Context
Add 👍 to pull requests you find important.
The Nix maintainer team uses a GitHub project board to schedule and track reviews.