mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-08-02 08:47:28 -04:00
testsuite: probe RESOLVE_BENEATH support functionally for the #715 test
Add resolve_beneath_supported() to rsyncfns: it functionally probes whether the rsync binary can follow an in-tree directory symlink under its secure resolver (an initial transfer plus a delta update through a dir-symlink, the operation issue #715 is about). This tracks the actual binary instead of a platform name. Use it in symlink-dirlink-basis_test.py in place of the SunOS/OpenBSD/NetBSD/ Cygwin name check: it skips on those platforms too, and additionally on Linux < 5.6, a seccomp-blocked openat2, and the new --disable-openat2 build, where the portable O_NOFOLLOW fallback rejects the in-tree symlink. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1126,6 +1126,48 @@ def assert_not_exists(path, label: str = '') -> 'None':
|
||||
test_fail(f"{_tag(label)}{path} exists but should not")
|
||||
|
||||
|
||||
_rb_cache = None
|
||||
|
||||
|
||||
def resolve_beneath_supported() -> bool:
|
||||
"""True if this rsync can FOLLOW an in-tree directory symlink under its
|
||||
secure resolver -- i.e. update a file through a dir-symlink on the receiver
|
||||
(--keep-dirlinks; issue #715).
|
||||
|
||||
False wherever the portable per-component O_NOFOLLOW fallback is the active
|
||||
resolver: a platform with no kernel "beneath" primitive, Linux < 5.6, a
|
||||
seccomp-blocked openat2, or a --disable-openat2 build. There the delta
|
||||
update through the symlinked directory fails verification. Probed
|
||||
functionally (an initial transfer plus a delta update through a dir-symlink)
|
||||
so it tracks the actual binary rather than a platform name, and cached."""
|
||||
global _rb_cache
|
||||
if _rb_cache is not None:
|
||||
return _rb_cache
|
||||
probe = SCRATCHDIR / '.rb_probe'
|
||||
rmtree(probe)
|
||||
(probe / 'home' / 'real').mkdir(parents=True)
|
||||
os.symlink('real', probe / 'home' / 'link')
|
||||
(probe / 'src' / 'link').mkdir(parents=True)
|
||||
f = probe / 'src' / 'link' / 'f'
|
||||
make_data_file(f, 40000)
|
||||
|
||||
def push():
|
||||
subprocess.run(
|
||||
rsync_argv('-KRl', '--no-whole-file', 'link/f',
|
||||
f"{probe / 'home'}/"),
|
||||
cwd=str(probe / 'src'),
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
push()
|
||||
with open(f, 'ab') as fh: # size change -> forces a delta update
|
||||
fh.write(b'appended tail for delta\n')
|
||||
push()
|
||||
dst = probe / 'home' / 'real' / 'f'
|
||||
_rb_cache = dst.is_file() and filecmp.cmp(str(f), str(dst), shallow=False)
|
||||
rmtree(probe)
|
||||
return _rb_cache
|
||||
|
||||
|
||||
def write_daemon_conf(modules, globals=None, *,
|
||||
name: str = 'test-rsyncd.conf') -> 'Path':
|
||||
"""Write a custom rsyncd.conf for daemon-parameter tests.
|
||||
|
||||
@@ -14,20 +14,27 @@
|
||||
|
||||
import filecmp
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from rsyncfns import (
|
||||
RSYNC, SCRATCHDIR, SRCDIR, TMPDIR,
|
||||
make_data_file, rsync_argv, test_fail, test_skipped,
|
||||
make_data_file, resolve_beneath_supported, rsync_argv, test_fail,
|
||||
test_skipped,
|
||||
)
|
||||
|
||||
|
||||
if platform.system() in ('SunOS', 'OpenBSD', 'NetBSD') or platform.system().startswith('CYGWIN'):
|
||||
# Following an in-tree directory symlink under the secure resolver needs a
|
||||
# kernel "beneath" primitive (RESOLVE_BENEATH/O_RESOLVE_BENEATH). Probe the
|
||||
# actual binary rather than guessing from the platform name: this also skips
|
||||
# correctly on Linux < 5.6, a seccomp-blocked openat2, and a --disable-openat2
|
||||
# build, where the portable O_NOFOLLOW fallback rejects the in-tree symlink
|
||||
# (issue #715).
|
||||
if not resolve_beneath_supported():
|
||||
test_skipped(
|
||||
f"secure_relative_open lacks RESOLVE_BENEATH equivalent on "
|
||||
f"{platform.system()}; issue #715 still affects this platform"
|
||||
"this rsync can't follow an in-tree directory symlink under its "
|
||||
"secure resolver (no RESOLVE_BENEATH equivalent / --disable-openat2); "
|
||||
"issue #715 still affects this configuration"
|
||||
)
|
||||
|
||||
os.environ['RSYNC_RSH'] = str(SRCDIR / 'support' / 'lsh.sh')
|
||||
|
||||
Reference in New Issue
Block a user