Skip to content

feat(fast_io): fchmodat/fchownat/utimensat sandbox helpers (SEC-1.i)#4690

Merged
oferchen merged 6 commits into
masterfrom
feat/fast-io-fchmodat-fchownat-utimensat-sec1i
May 21, 2026
Merged

feat(fast_io): fchmodat/fchownat/utimensat sandbox helpers (SEC-1.i)#4690
oferchen merged 6 commits into
masterfrom
feat/fast-io-fchmodat-fchownat-utimensat-sec1i

Conversation

@oferchen
Copy link
Copy Markdown
Owner

Summary

Extends the SEC-1 dirfd-anchored carrier with the metadata-application siblings:

  • fchmodat(dirfd, name, mode, follow_symlinks)
  • fchownat(dirfd, name, uid, gid, follow_symlinks)
  • utimensat(dirfd, name, atime, mtime, follow_symlinks)
  • fchmodat_via_sandbox_or_fallback / fchownat_via_sandbox_or_fallback / utimensat_via_sandbox_or_fallback adaptors that route a single-component leaf under the receiver's DirSandbox root through the *at variant while preserving the existing path-based fallback for multi-component paths, missing sandbox, and non-Unix targets.

Pattern source: SEC-1.g (#4671) unlink_via_sandbox_or_fallback.

Module layout

The new helpers live in a sibling at_syscalls_metadata.rs module rather than extending at_syscalls.rs directly. Reason: SEC-1.h (#4683) and this branch were both extending the same file in flight; landing them as parallel files avoids a merge-conflict re-spin and keeps each PR's diff focused. Once both have merged, the two modules may be re-folded into a single at_syscalls namespace as housekeeping.

Coordination with SEC-1.h (#4683)

SEC-1.h merged at 2026-05-21T17:47:51Z, while this branch was in flight. Both touch crates/fast_io/src/dir_sandbox/mod.rs (re-exports), but in different lines, so no textual conflict is expected. If the merge ordering surfaces any re-export collision, the fix is to consolidate both module declarations under one pub mod at_syscalls block as a follow-up housekeeping PR.

Receiver wiring

Deferred. The metadata-application call sites (metadata::apply_metadata_from_file_entry, apply_file_metadata_with_options, ...) live in the metadata crate, which does not depend on fast_io today. Threading DirSandbox through apply_metadata_from_file_entry requires:

  1. Adding fast_io as a Unix-only dependency of metadata.
  2. Adding apply_*_with_sandbox variants of the public entry points in metadata::apply that accept Option<&DirSandbox> and dest_dir: &Path.
  3. Plumbing the sandbox through the transfer-side callers (crates/transfer/src/receiver/transfer/sync.rs, crates/transfer/src/receiver/directory/creation.rs, crates/transfer/src/receiver/quick_check.rs, crates/transfer/src/disk_commit/process.rs).

This is the same staging strategy used by SEC-1.b (which landed the carrier ahead of subsequent cutover PRs) and SEC-1.h (which deferred mknodat).

Cross-platform

  • Linux + macOS: fchmodat / fchownat / utimensat are POSIX-2008 syscalls, present on every supported Unix target. The fallback path uses std::fs::set_permissions, raw libc::chown / libc::lchown, and filetime::set_file_times / set_symlink_file_times.
  • Windows: the entire dir_sandbox module is #[cfg(unix)] (per the SEC-1.l audit, NTFS uses handle-based APIs that sidestep path TOCTOU). The new helpers inherit that gate; Windows builds compile this file out entirely.

Test plan

  • CI fmt + clippy
  • CI nextest (stable + Linux musl + macOS + Windows)
  • Helper-level unit tests cover: raw *at success, ENOENT on missing leaf, AT_SYMLINK_NOFOLLOW preserves target inode under swap, sandbox fast path takes the *at route for single-component, fallback for multi-component, fallback when sandbox is absent
  • Follow-up SEC-1.i.2 PR will wire receiver-side metadata application through the new helpers

Extends the SEC-1 dirfd-anchored carrier with the metadata-application
siblings:

- fchmodat(dirfd, name, mode, follow_symlinks)
- fchownat(dirfd, name, uid, gid, follow_symlinks)
- utimensat(dirfd, name, atime, mtime, follow_symlinks)
- fchmodat_via_sandbox_or_fallback / fchownat_via_sandbox_or_fallback /
  utimensat_via_sandbox_or_fallback adaptors that route single-component
  leaves under the receiver's DirSandbox root through the *at variant
  while preserving path-based fallbacks for multi-component paths,
  missing sandbox, and non-Unix targets.

Pattern source: SEC-1.g unlink_via_sandbox_or_fallback.

The new helpers live in a sibling at_syscalls_metadata.rs module so the
SEC-1.h create-class additions (#4683) and SEC-1.i metadata-class
additions can land independently without conflicting on the same file.
Once both PRs merge the two modules may be re-folded into a single
at_syscalls namespace as housekeeping.

Receiver-side wiring of the metadata application path through these
helpers is deferred follow-up: the metadata crate does not depend on
fast_io today and threading DirSandbox through apply_metadata_from_file_entry
requires propagating it across the transfer pipeline. Same staging
strategy as SEC-1.b which landed the carrier ahead of subsequent cutover
PRs.
@oferchen oferchen force-pushed the feat/fast-io-fchmodat-fchownat-utimensat-sec1i branch from 48692e6 to c36dcc3 Compare May 21, 2026 17:56
oferchen added 2 commits May 21, 2026 21:01
The fchmodat/fchownat/utimensat_via_sandbox_or_fallback helpers in
at_syscalls_metadata.rs use filetime::FileTime and
filetime::set_symlink_file_times for the multi-component fallback
path. Move filetime out of cfg(not(unix)) so it compiles on all
platforms.
oferchen added 3 commits May 21, 2026 21:55
at_syscalls_metadata.rs is unix-only (libc *at calls + filetime). The
mod declaration was unconditional, causing Windows builds to try
compiling it and fail with 'unresolved crate filetime'. Gate both the
mod declaration and the re-exports with #[cfg(unix)].
The cfg(unix) move regressed Windows because syscall_batch.rs has a
cfg(not(unix)) block that uses filetime::FileTime. Move filetime out of
target-specific deps to general [dependencies] so both unix
(at_syscalls_metadata fallback) and non-unix (syscall_batch) paths see
it.
…t deprecated)

musl 1.2.0 deprecated libc::time_t in favor of a 64-bit alias. Cast
unix_seconds() and nanoseconds() to the timespec field type with 'as _'
so the cast picks up whichever signed integer the target's libc uses.
@oferchen oferchen merged commit 1c3f7ad into master May 21, 2026
56 checks passed
oferchen added a commit that referenced this pull request May 21, 2026
…ship (#4695)

Captures the hygiene follow-up to consolidate
`crates/fast_io/src/dir_sandbox/at_syscalls{,_metadata,_rename}.rs`
into a single `at_syscalls` namespace now that all three SEC-1 *at*
helper PRs (.h #4683, .i #4690, .j #4693) are on master. Both .i and .j
module headers explicitly scheduled the re-fold; this doc turns that
into a concrete plan with section dividers, re-export collapse steps,
and an LoC sanity check that confirms the consolidated file remains
within the post-2026-05-18 LoC policy.
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