Skip to content

fixes for android/termux setup#909

Open
tridge wants to merge 6 commits into
RsyncProject:masterfrom
tridge:pr-termux-test
Open

fixes for android/termux setup#909
tridge wants to merge 6 commits into
RsyncProject:masterfrom
tridge:pr-termux-test

Conversation

@tridge
Copy link
Copy Markdown
Member

@tridge tridge commented May 22, 2026

No description provided.

@tridge tridge added the WIP label May 22, 2026
tridge and others added 5 commits May 23, 2026 08:55
secure_relative_open() invokes openat2(2) directly via syscall() (glibc
lacked a wrapper for years). In a seccomp-restricted environment a
disallowed syscall raises SIGSYS and kills the process rather than
failing with ENOSYS, so the existing "fall back on ENOSYS" path never
runs. The Android app sandbox blocks openat2 exactly this way: on Termux
every rsync transfer died the moment the receiver opened a basis file
(receiver.c calls secure_relative_open unconditionally), with the peer
seeing only "connection unexpectedly closed". The same hazard applies to
hardened containers and systemd's SystemCallFilter.

Probe openat2 once behind a temporary SIGSYS handler (sigsetjmp/
siglongjmp). If it is missing or blocked, secure_relative_open_linux()
returns ENOSYS so callers use the portable per-component O_NOFOLLOW walk,
which relies only on openat() and is never seccomp-blocked. Where openat2
is available (the normal case) behaviour is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Termux's Python is built without os.link, and Android app storage rejects
link(2) outright, so tests that build hard links crashed with
AttributeError instead of skipping. Add hardlinks_supported() (a cached
probe) and make_hardlink() (raises OSError, never AttributeError) to
rsyncfns.py. The dedicated hardlinks test now skips cleanly; hands and
relative guard their incidental hard links (the rest of each test still
runs); itemize skips (its expected itemized output assumes the link).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Python 3.13's Path.is_file() propagates PermissionError, which Android's
app sandbox raises for /proc/sys/fs/protected_regular, crashing the test
before its guarded read_text(). Wrap is_file()+read_text() in one
try/except OSError -> test_skipped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
kernel_resolve_beneath_supported() calls openat2 directly to detect
RESOLVE_BENEATH support. In a seccomp sandbox (Android/Termux) that call
is killed with SIGSYS rather than failing with ENOSYS, killing the
helper and failing chmod-symlink-race. Probe behind a temporary SIGSYS
handler (sigsetjmp/siglongjmp), reporting "unsupported" when blocked --
matching the secure_relative_open() fix in syscall.c.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The issue RsyncProject#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 RsyncProject#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>
Add packaging/build-termux-deb.sh, which cross-compiles a statically-linked
rsync with the Android NDK and packages it as a Termux .deb (installed under
the Termux prefix, /data/data/com.termux/files/usr/bin/rsync), and a
termux-deb.yml workflow that runs it for every Termux architecture
(aarch64, arm, x86_64, i686) and uploads the .deb files as artifacts.

The binary is self-contained: optional external libraries (zstd/lz4/xxhash/
openssl/acl/xattr/iconv) are omitted, leaving md5/md4 and bundled zlib, so
the .deb has no Termux dependencies and installs with `dpkg -i` (or
`apt install ./rsync_<ver>_<arch>.deb`) on any Termux version. The build
forces the cross-compile cache values configure can't probe (lchmod/lutimes
off; socketpair and mknod-FIFO/socket on; IPv6 enabled). The resulting
binary includes the openat2-seccomp fallback, so transfers work in the
Android app sandbox.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ketas
Copy link
Copy Markdown

ketas commented May 23, 2026

i confirm rsync working again

here's test i did, complete with failure before and ok after, with test procedure, done in fdroid termux v0.118.3 shell on samsung galaxy note 20 5g ultra with latest officially released android version 13, oneui 5.1

> uname -a
Linux localhost 4.19.87-27103109 #1 SMP PREEMPT Mon Aug 4 18:51:27 KST 2025 aarch64 Android
> pwd
/data/data/com.termux/files/home
> rsync -V | head -1
rsync  version 3.4.3  protocol version 32
> mkdir a b
> touch a/0
> rsync -av a/ b/
sending incremental file list
./
0
rsync: connection unexpectedly closed (72 bytes received so far) [generator]
rsync error: error in rsync protocol data stream (code 12) at io.c(232) [generator=3.4.3]
rsync: connection unexpectedly closed (26 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(232) [sender=3.4.3]
> pkg install ./rsync-termux-aarch64/rsync_3.5.0dev_aarch64.deb
Checking availability of current mirror:
[*] https://mirror.autkin.net/termux/termux-main: ok
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Note, selecting 'rsync' instead of './rsync-termux-aarch64/rsync_3.5.0dev_aarch64.deb'
The following packages were automatically installed and are no longer required:
  libpopt openssl-tool
Use 'apt autoremove' to remove them.
The following packages will be upgraded:
  rsync
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/488 kB of archives.
After this operation, 524 kB of additional disk space will be used.
Get:1 /data/data/com.termux/files/home/rsync-termux-aarch64/rsync_3.5.0dev_aarch64.deb rsync aarch64 3.5.0dev [488 kB]
(Reading database ... 25808 files and directories currently installed.)
Preparing to unpack .../rsync_3.5.0dev_aarch64.deb ...
Unpacking rsync (3.5.0dev) over (3.4.3) ...
Setting up rsync (3.5.0dev) ...
Processing triggers for mandoc (1.14.6-6) ...
> rsync -V | head -1
rsync  version 3.4.3-27-g471d4aee  protocol version 32
> rsync -av a/ b/
sending incremental file list
0

sent 118 bytes  received 35 bytes  306.00 bytes/sec
total size is 0  speedup is 0.00
>

@ketas
Copy link
Copy Markdown

ketas commented May 23, 2026

short test:

cd /data/data/com.termux/files/home && mkdir a b && touch a/0 && rsync -av a/ b/

ribbons added a commit to ribbons/android-rsync that referenced this pull request May 23, 2026
Apply 9de8f6ab1f proposed by tridge upstream as part of
RsyncProject/rsync#909 to fix a crash when attempting to open files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants