Files
rsync/testsuite/operator-path-temp-dir_test.py
T
Andrew TridgellandOmar Elsayed 4705b6fb92 testsuite: symlink-race and operator/peer path-resolution coverage
The TOCTOU / symlink-race suite for the secure resolver and operator-supplied
paths: chdir/chmod/rename/mknod/source/dest symlink races, relative make_path and
symlinked-parent cases, the operator-path matrix (--temp/partial/backup-dir,
alt-dest basis, files-from, log-file, insecure-links), and the admin-file opens
(--password-file / daemon secrets / config / log-file / early-input symlinks),
plus the daemon module-confinement and chroot inner-module cases.

Co-authored-by: Omar Elsayed <omarelsayed161@gmail.com>
2026-07-20 14:05:31 +10:00

37 lines
1.5 KiB
Python

#!/usr/bin/env python3
# --temp-dir symlink policy matrix. A followed --temp-dir symlink makes the
# receiver create its scratch temp file in an out-of-tree directory (the data is
# written there, then renamed to dest). The temp is renamed away, so we detect
# the escape by the target directory's mtime advancing (a file was created in
# it). The ownership walk must follow only uid0/euid-owned symlinks; a relative
# --temp-dir anchors at the cwd. --insecure-links is the local opt-out.
import subprocess
import time
from rsyncfns import rsync_argv, run_symlink_matrix, plant_operator_symlink
def case(ctx):
src = ctx.base / 'src'
dest = ctx.base / 'dest'
src.mkdir()
dest.mkdir()
(src / 'f0').write_text("PAYLOAD-DATA\n")
# A relative --temp-dir is resolved by the receiver, whose cwd is the
# destination directory -- so a relative plant anchors at dest, not the cwd.
opt, escape = plant_operator_symlink(ctx, dest)
escape.mkdir(parents=True, exist_ok=True) # --temp-dir must exist
before = escape.stat().st_mtime_ns
time.sleep(0.01)
extra = ['--insecure-links'] if ctx.insecure else []
subprocess.run(
rsync_argv('-a', f'--temp-dir={opt}', *extra, 'src/', 'dest/'),
cwd=str(ctx.base), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Followed == the receiver created its temp in the out-of-tree dir.
return escape.stat().st_mtime_ns != before
run_symlink_matrix('--temp-dir', case)
print("--temp-dir symlink policy matrix: enforced")