Skip to content

Commit acb4562

Browse files
tridgeclaude
andcommitted
testsuite: skip dir-symlink-basis when openat2/RESOLVE_BENEATH is absent
The issue #715 fix relies on openat2(RESOLVE_BENEATH); without it secure_relative_open() uses the per-component fallback, which can't follow a dir-symlink basedir, so #715 still applies. The test already skips on the non-Linux fallback platforms by name, but Android/Termux is a Linux kernel with openat2 blocked by seccomp, so it must skip too. Probe openat2(RESOLVE_BENEATH) at runtime in a subprocess (so a seccomp SIGSYS kills the child, not the test) and skip when it's unavailable. Also handle Termux's platform.system() == 'Android'. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 863da26 commit acb4562

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

testsuite/symlink-dirlink-basis_test.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import os
1717
import platform
1818
import subprocess
19+
import sys
1920
import time
2021

2122
from rsyncfns import (
@@ -30,6 +31,37 @@
3031
f"{platform.system()}; issue #715 still affects this platform"
3132
)
3233

34+
35+
def _resolve_beneath_works() -> bool:
36+
"""The issue #715 fix relies on openat2(RESOLVE_BENEATH). Where that is
37+
unavailable (kernel < 5.6) or blocked by a seccomp filter (the Android
38+
app sandbox, hardened containers), secure_relative_open() uses the
39+
per-component fallback, which can't follow a dir-symlink basedir -- so
40+
#715 still applies and this test must skip, exactly as it does on the
41+
non-Linux fallback platforms above. Probe in a subprocess so a seccomp
42+
SIGSYS kills the child rather than this test."""
43+
code = (
44+
"import ctypes, sys\n"
45+
"class H(ctypes.Structure):\n"
46+
" _fields_ = [('f', ctypes.c_uint64), ('m', ctypes.c_uint64),\n"
47+
" ('r', ctypes.c_uint64)]\n"
48+
"libc = ctypes.CDLL(None, use_errno=True)\n"
49+
"h = H(0, 0, 0x08) # resolve = RESOLVE_BENEATH\n"
50+
"fd = libc.syscall(437, -100, b'.', ctypes.byref(h), ctypes.sizeof(h))\n"
51+
"sys.exit(0 if fd >= 0 else 1)\n"
52+
)
53+
return subprocess.run([sys.executable, '-c', code]).returncode == 0
54+
55+
56+
# Termux's Python reports 'Android', not 'Linux'; both run the Linux
57+
# kernel where syscall 437 is openat2, so probe on either. (Darwin and
58+
# FreeBSD use O_RESOLVE_BENEATH and must not run the Linux-specific probe.)
59+
if platform.system() in ('Linux', 'Android') and not _resolve_beneath_works():
60+
test_skipped(
61+
"openat2(RESOLVE_BENEATH) is unavailable here (old kernel or a "
62+
"seccomp filter); issue #715's dir-symlink-basis fix relies on it"
63+
)
64+
3365
os.environ['RSYNC_RSH'] = str(SRCDIR / 'support' / 'lsh.sh')
3466
# HOME -> SCRATCHDIR is set up by rsyncfns import.
3567

0 commit comments

Comments
 (0)