Commit Graph
5 Commits
Author SHA1 Message Date
Zen Dodd 013f76dc8d syscall: preserve Cygwin UNC roots in ownership walks (#1113)
* syscall: preserve Cygwin UNC roots in ownership walks
* syscall: remove duplicate anchor state update
2026-10-03 10:05:25 +10:00
Zen Dodd 7c7e1bee86 syscall: follow trusted sender ancestor links (#1088)
* syscall: follow trusted sender ancestor links
* testsuite: accept BSD symlink errors
* syscall: anchor sender paths at explicit source roots
* flist: pin explicit file source parents
* flist: preserve search-only source traversal
* sender: follow trusted files-from ancestors
* sender: enforce files-from symlink ownership
* sender: harden files-from path resolution
2026-09-20 23:36:00 +10:00
Andrew Tridgell c5bc4e3677 syscall: defer a literal ".." to the walk before the leaf fast paths
secure_walk_at() has two fast paths for the final component that call
openat(ds_cur(&ds), part, ...) directly instead of going through
ds_descend().  A final component of ".." therefore never met the anchor
floor, and what happened depended entirely on the caller's flags:

    ".." with O_DIRECTORY              -> ELOOP          (refused)
    ".." with O_DIRECTORY|O_NOFOLLOW   -> fd for the directory ABOVE
                                          the anchor
    ".." without O_DIRECTORY           -> parent opened, then closed,
                                          EISDIR returned

That was harmless while every literal ".." was rejected at the front
door, but secure_relative_open_at_beneath() now admits them and
documents the held-fd stack as refusing every climb above the anchor.
The sender's own call passes O_RDONLY|O_DIRECTORY and so was never
affected -- but the guarantee the new API advertises has to hold for
whatever flags the next caller picks.

Route a literal "." or ".." through ds_descend() before the leaf fast
paths.  All three flag combinations now refuse a bare ".." with ELOOP,
and t_secure_relpath covers the matrix.
2026-07-25 17:28:54 +10:00
Filipe Casal 4d8cbbecac sender: allow confined parent-relative copy-links targets 2026-07-25 17:28:54 +10:00
Andrew TridgellandClaude Opus 4.7 30656c5e35 syscall: add symlink-race-safe do_*_at() wrappers and harden secure_relative_open
Add the rest of the path-based syscall wrappers and migrate every
receiver-side caller:
  - do_lchown_at, do_rename_at, do_mkdir_at, do_symlink_at,
    do_mknod_at, do_link_at, do_unlink_at, do_rmdir_at,
    do_utimensat_at, do_stat_at, do_lstat_at

Same shape as do_chmod_at: open each parent under
secure_relative_open(), call the *at() variant against the dirfd,
fall through to the bare path-based syscall in non-daemon /
chrooted / absolute-path / no-parent cases. macOS's
setattrlist-based set_times tier is also routed through the
utimensat_at path on daemon-no-chroot.

Hardenings to secure_relative_open() itself:
  - confine basedir resolution under the same kernel mechanism
    used for relpath (basedirs from --copy-dest / --link-dest are
    sender-controllable in daemon mode)
  - reject any '..' component (bare '..', 'foo/..', 'subdir/..')
    so the per-component O_NOFOLLOW fallback can't escape
  - return the dirfd we built up from the per-component fallback
    when the caller passed O_DIRECTORY (otherwise every do_*_at
    failed with EINVAL on platforms without RESOLVE_BENEATH)

Adds testsuite/alt-dest-symlink-race.test and
testsuite/secure-relpath-validation.test (with t_secure_relpath
helper) as regression coverage for the new hardenings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:01:22 +10:00