Skip to content

fix: rename transfers via a nofollow parent dirfd - #17

Merged
AlpinDale merged 1 commit into
masterfrom
fix/symlink-rename-race
Aug 13, 2026
Merged

AlpinDale merged 1 commit into
masterfrom
fix/symlink-rename-race

Conversation

@AlpinDale

Copy link
Copy Markdown
Owner

Closes M1: the final partial-to-destination rename used fs::rename, which follows a symlinked parent directory. Between the validate_destination_path lstat and the rename, a concurrent local process could swap a parent directory for a symlink, causing the file to be written outside the destination root.

safe_rename now opens the destination parent with openat(O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC) (refusing symlinks) and renames into the pinned dirfd via renameat, so the destination directory cannot be swapped between validation and rename.

Verified the mechanism (a rename through a symlinked parent escapes the root) and that O_NOFOLLOW refuses the symlink; the normal transfer path still works.

@AlpinDale
AlpinDale force-pushed the fix/symlink-rename-race branch from 4f2d6b3 to f293961 Compare August 13, 2026 02:32
@AlpinDale
AlpinDale force-pushed the fix/symlink-rename-race branch from f293961 to 3d36b9e Compare August 13, 2026 02:37
@AlpinDale
AlpinDale force-pushed the fix/symlink-rename-race branch from 3d36b9e to 0a56c97 Compare August 13, 2026 02:54
Base automatically changed from fix/symlink-replace-directory to master August 13, 2026 03:01
@AlpinDale
AlpinDale force-pushed the fix/symlink-rename-race branch from 0a56c97 to f64c204 Compare August 13, 2026 03:01
@AlpinDale
AlpinDale merged commit c2e5adc into master Aug 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant