You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
install -D could not create leading directories inside a directory that is writable and searchable but not readable, where GNU can:
$ mkdir wx && chmod 300 wx && echo hi > f
$ install -D f wx/sub/f
install: cannot create directory 'wx/sub': Permission denied
create_dir_all_safe opens the deepest existing ancestor with O_RDONLY | O_DIRECTORY to anchor the walk, which demands read permission. mkdirat only needs write and execute.
DirFd::open_anchor falls back to a search-only descriptor - O_PATH on Linux, O_SEARCH elsewhere - when the readable open returns EACCES. Everything install does through that descriptor works with it: mkdirat, openat of a child directory, openat with O_CREAT, fstatat, fchmodat, fchownat, renameat, linkat, unlinkat, utimensat. It cannot list directory entries, which the creation walk never does. Platforms with neither flag keep today's EACCES.
Only symlink-following opens get the fallback; the NoFollow opens in the descent are untouched, so the TOCTOU hardening from #10140 is unchanged.
install -d and installing into an existing write-only directory were already fine; this is only about creating leading directories.
About the red Tests (unix) job: that runner is OpenBSD 7.9, which has neither O_PATH nor O_SEARCH, so there's no way to anchor *at calls on a directory we can't read and this approach can't work there. safe_traversal now exports SEARCH_ONLY_SUPPORTED and the new test skips when it's false.
To be explicit about the gap: install -D into a write-only directory still fails on OpenBSD, exactly as it did before this PR. The fix applies on Linux, macOS, FreeBSD, NetBSD and the Solaris family. I could add a path-based fallback for the rest, but that trades the fd-anchored traversal for plain path resolution and I'd rather not do that silently — tell me if you want it.
The Linux explanation here is inaccurate: O_PATH does not ignore O_NOFOLLOW; with O_PATH|O_NOFOLLOW it refers to the symlink itself (and combining O_DIRECTORY can reject it), rather than resolving it. The fallback intentionally omits O_NOFOLLOW to preserve Follow semantics, so document that choice directly instead of attributing it to an ignored flag.
This issue also appears on line 230 of the same file.
The reason will be displayed to describe this comment to others. Learn more.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
Fixes #14778.
install -Dcould not create leading directories inside a directory that is writable and searchable but not readable, where GNU can:create_dir_all_safeopens the deepest existing ancestor withO_RDONLY | O_DIRECTORYto anchor the walk, which demands read permission.mkdiratonly needs write and execute.DirFd::open_anchorfalls back to a search-only descriptor -O_PATHon Linux,O_SEARCHelsewhere - when the readable open returns EACCES. Everythinginstalldoes through that descriptor works with it:mkdirat,openatof a child directory,openatwithO_CREAT,fstatat,fchmodat,fchownat,renameat,linkat,unlinkat,utimensat. It cannot list directory entries, which the creation walk never does. Platforms with neither flag keep today's EACCES.Only symlink-following opens get the fallback; the
NoFollowopens in the descent are untouched, so the TOCTOU hardening from #10140 is unchanged.install -dand installing into an existing write-only directory were already fine; this is only about creating leading directories.