Debian Patches

Status for rsync/3.5.0+ds1-3

Patch Description Author Forwarded Bugs Origin Last update
disable_reconfigure_req.diff Remove need to run reconfigure target

===================================================================
Samuel Henrique <samueloph@debian.org> not-needed 2024-04-12
env_shebang.patch =?utf-8?q?Removes_usage_of_env_on_shebangs_as_per_Debian_Policy_?= =?utf-8?q?=C2=A7_10=2E4?= Samuel Henrique <samueloph@debian.org> not-needed 2024-04-12
fix_rrsync_man_generation.patch Fix manpage installation for rrsync
Otherwise we would get "ERROR: support/rrsync.1 cannot be created."
I'm not confident this is the best approach on solving this issue,
but I know this works with no regressions.
This patch needs to be reviewed before being submitted to upstream.
===================================================================
Samuel Henrique <samueloph@debian.org> no 2024-04-12
Honor_STRIP_in_install-strip_for_cross-compilation.patch Honor $(STRIP) in install-strip for cross-compilation (#1024)
* Honor $(STRIP) in install-strip for cross-compilation

The install-strip target hard-coded `install -s`, which strips via the
install program using the build host's strip and ignores the STRIP
variable. When cross-compiling this runs the host strip against a
target binary and fails.

Pass --strip-program=$(or $(STRIP),strip) so the target strip is used
when STRIP is set (as cross toolchains and build systems provide),
falling back to plain `strip` for native builds. A plain `make install`
is unaffected.

* Make install-strip portable (address review)

- Detect the target strip via AC_CHECK_TOOL([STRIP],[strip],[strip]) in
configure.ac (picks up the cross-prefixed strip when cross-compiling,
defaults to plain strip otherwise) and substitute @STRIP@ in Makefile.in.
- Rewrite install-strip to run a normal install then $(STRIP) on the
installed rsync binary, dropping the GNU Make $(or ...) and the GNU
install --strip-program extension that broke with install-sh/BSD install.
Alessandro Di Nepi <alessandro.dinepi@gmail.com> no 2026-08-16
rrsync_support_fd_pins_in_user_namespaces.patch rrsync: support fd pins in user namespaces (#1048)
* rrsync: support fd pins in user namespaces
* rrsync: support /dev/fd pins in user namespaces
Zen Dodd <mail@steadytao.com> no 2026-08-16
testsuite_bound_the_unshare_probe.patch testsuite: bound the unshare probe (#1049) Zen Dodd <mail@steadytao.com> no 2026-08-16
testsuite_make_basis_xname_oracle_deterministic.patch testsuite: make basis xname oracle deterministic (#1051) Zen Dodd <mail@steadytao.com> no 2026-08-15
testsuite_interpose_lfs_open_symbols.patch testsuite: interpose the large-file spellings of open/openat/fstatat
Which symbol names this test's LD_PRELOAD hook exports is decided by the
compiler that builds it, and which names rsync imports is decided by
configure -- and the two do not have to agree.

Where off_t is not already 64 bits, configure's AC_SYS_LARGEFILE adds
-D_FILE_OFFSET_BITS=64 (i386 and alpha in Debian), so glibc redirects every
open()/openat()/fstatat() call in rsync to open64(), openat64() and
fstatat64(). The hook is compiled by a bare "cc", so on those architectures
it defines only the unsuffixed names: the receiver's opens never reach it, no
EACCES is injected, the marker the positive control looks for is never
written, and the test fails with

positive control failed: receiver did not open the existing partial file
with O_CREAT (rc=0, output='')

It happens to work on Debian's 64-bit time_t ports (armhf, hppa, powerpc,
...) only by luck: their gcc predefines -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64,
so glibc's __REDIRECT renames the hook's own DEFINITIONS as well and it ends
up exporting exactly the *64 names rsync imports.

Define both spellings explicitly so the hook interposes whichever set the
rsync under test was linked against, and #undef the two macros at the top of
the hook so that renaming cannot happen -- otherwise, on precisely those ports
where the compiler predefines them, open() would be emitted as open64() and
collide with the explicit wrapper ("symbol `open64' is already defined"),
which would leave the hook unbuildable and the test skipped.

The new pointers are resolved through hook_resolve(), so the existing
nested-dlsym recursion guard covers them as well.
Samuel Henrique <samueloph@debian.org> yes 2026-08-17
testsuite_punch_granularity_guard.patch testsuite: probe the punch granularity each hole assertion relies on
The last section of preallocate_test.py writes 256 blocks of
[4 KiB data][24 KiB zeros][4 KiB data] and requires --inplace --sparse to
deallocate at least half of the file. A punch only frees whole allocation
units, and the 24 KiB interior run sits 4 KiB into each 32 KiB block: with a
4 KiB unit it covers six whole units (24 KiB freed per block), but with a
16 KiB unit it covers none at all, so st_blocks does not move.

That is what happens on loong64, whose kernel uses 16 KiB pages
(arch/loongarch/Kconfig defaults to 16KB_3LEVEL on 64-bit and Debian's
config does not override it), and the build fails with

--inplace --sparse left matching interior zero runs allocated: 8388608 of
8388608 bytes remain allocated after a 8388608-byte matched-block update

i.e. exactly "nothing was freed", which is the arithmetic of a punch
granularity >= 16 KiB rather than an rsync regression. fs_can_punch_holes()
does not catch it because it punches a whole 64 KiB file, which frees blocks
at any granularity.

Generalise that helper into punch_frees(offset, length, size) so each
assertion can probe the shape it actually depends on, and gate the interior
one on the exact [4 KiB data][24 KiB zeros][4 KiB data] layout. Where the
filesystem can free that run the assertion runs exactly as before; where it
cannot, the test says so rather than reporting a regression.

While here, call fallocate64() instead of fallocate(). ctypes declares the
offset and length as c_longlong, but where off_t is 32 bits glibc's
fallocate() takes 32-bit offsets -- so the callee reads the high half of
`offset` as its `length`, the probe fails with EINVAL, and can_punch comes
back False. That is why none of this file's hole-punching assertions have
ever run on a 32-bit port; on i386:

fs_can_punch_holes() as written : before=128 ret=-1 errno=22 -> False
the same probe via fallocate64 : before=128 ret=0 -> True

fallocate64() takes off64_t on every architecture and is a plain alias of
fallocate() where off_t is already 64 bits. The probe now writes urandom
rather than a repeated byte as well, so a filesystem that compresses does not
answer "nothing was freed" merely because nothing was allocated.
Samuel Henrique <samueloph@debian.org> yes 2026-08-17
Fix_ENOENT_when_resolving_kernel_pseudo_paths_in_ona_open_patch Fix ENOENT when resolving kernel pseudo-paths in ona_open (#1054)

* Fix ona_open to safely resolve bash process substitution pseudo-paths
Bash process substitution (e.g., `<(...)` or `>(...)`) exposes file
descriptors as symlinks under `/proc/self/fd/X` pointing to kernel
pseudo-paths such as `pipe:[12345]`. Previously, `ona_open()` would read
this target and attempt to resolve it as a literal file path on disk,
causing the operation to fail with `ENOENT` and breaking legitimate local
process substitution.

This patch safely intercepts and resolves these pseudo-paths while
maintaining strict confinement boundaries and averting TOCTOU risks:

- Detects kernel pseudo-paths (`pipe:[`, `socket:[`, `anon_inode:`)
only when `fd_pin_tail` confirms the path resolves precisely to a
direct child of a valid FD directory.
- Categorically rejects pseudo-path resolution if `confine_root` is
active (yielding `ENOENT`).
- Strips `O_NOFOLLOW` for legitimate leaf pseudo-paths, allowing
`openat()` to correctly delegate resolution.
- Reverts `fd_pin_tail` to its upstream signature, as manual PID
validation is no longer required due to the secure `openat()` design.

* testsuite: expect pseudo-path skip on Alma
* syscall: reject trailing pseudo-path components
Omar Elsayed <omarelsayed161@gmail.com> no 2026-09-03
batch_c_Allow_FIFO_pipes_in_batch_file_processing.patch batch.c: Allow FIFO pipes in batch file processing. Regression fix (#1060) Omar Elsayed <omarelsayed161@gmail.com> no 2026-09-03
options_accept_max_alloc_0_again_resolved_to_the_parsers_own_ceiling.patch options: accept --max-alloc=0 again, resolved to the parser's own ceiling (#1069)

* options: accept --max-alloc=0 again, resolved to the parser's own ceiling

3.5.0 rejected --max-alloc=0 (CVE-2026-53794). The stated rationale was that a
zero cap "disabled the per-allocation size cap (the defense behind
CVE-2024-12084)". That was true up to 3.2.7, where the check short-circuited:

if (max_alloc && num >= max_alloc/size)

but 2f9b963a ("Make `--max-alloc=0` safer", 3.3.0) removed the short-circuit and
mapped 0 to SIZE_MAX at parse time, leaving the guard unconditional. Since the
guard admits an allocation only when num < max_alloc/size, num*size stays below
max_alloc at every setting, so the num*size overflow check was armed for 0 just
as for any other value. From 3.3.0 onward, 0 raised the magnitude ceiling and
nothing else -- and an explicit 8191P raises it exactly as far, is accepted, and
is forwarded to the peer, so rejecting 0 removed no capability.

What it did remove is the only portable spelling. The parser's ceiling is
SIZE_MAX/2, so it tracks the build's word size: on ILP32 the suffix multiplier
alone exceeds the bound, making every P and T value an error whatever the digits
and capping the option at 2047M. Because max_alloc_arg goes on the wire
un-normalized, a 0 was re-resolved by each side against its own SIZE_MAX; any
literal is resolved once on the client and shipped verbatim, so nothing above
2047M survives a 64-bit client talking to a 32-bit daemon. There is no number a
user can compute that does what 0 did, which is what #1056 ran into.

So accept 0 again, but resolve it to SIZE_ARG_MAX (SIZE_MAX/2) rather than
SIZE_MAX, so it lands exactly on the largest value that could also be typed and
is no longer a limit only the 0 spelling can reach. Keep forwarding it
the substantive half of the 3.5.0 hardening -- bounding parse_size_arg() against
the unbounded `size *= atof(size_arg)` -- untouched.

The residual concern, a 0 forwarded to a <= 3.2.7 daemon that honours it, is not
something a client-side check can address: the client is the attacker's own
code, as daemon-max-alloc-zero_test.py noted in its own docstring. Operators
who want peers kept off their cap have `refuse options = max-alloc`.

Also drops the now-unreachable rejection message, which left the min-value error
recommending a value the parser refused ("min: 1.00M or 0 for unlimited").

daemon-max-alloc-zero, whose assertions are the behaviour being reverted. It
checks that 0 is accepted, that it reaches the peer as the literal "0" rather
than a resolved number (verified against a negative control that normalizes it),
and that the parser's upper bound still rejects an out-of-range value.

Fixes #1056


* testsuite: refresh Cygwin expectations
* docs: note max-alloc safety
Samuel Henrique <samueloph@gmail.com> no 2026-09-02
syscall_explain_untrusted_symlink_refusal.patch syscall: explain untrusted symlink refusal (#1074)
* syscall: explain untrusted symlink refusal
* syscall: emphasise insecure-links warning
Zen Dodd <mail@steadytao.com> no 2026-09-03
Fix_handling_of_dev_std_in_out_err_pseudo-paths_and_namespace_overflow_UID_checks.patch Fix handling of /dev/std{in,out,err} pseudo-paths and namespace overflow UID checks

Using --log-file or --files-from with /dev/stdin, /dev/stdout, or /dev/stderr
attached to a pipe previously failed in two ways:

1. On standard hosts, it failed with ENOENT because the symlink target
(pipe:[N]) was treated as a relative file path rather than a secure
kernel pseudo-path.
2. Inside user namespaces (e.g., rootless podman, unshare), it aborted
with ELOOP ("refusing to follow a symlink owned by an untrusted user").
The symlink ownership reported the kernel overflow UID (65534), which
completely blocked the walker from following the pseudo-paths.

This patch resolves the issues by refining the symlink path walker and
trust mechanisms:

* Updated fd_pin_tail() to natively recognize /dev/stdin, /dev/stdout,
and /dev/stderr, parsing them directly to their corresponding /0, /1,
and /2 descriptor tails.
* Introduced the is_anchored variable to strictly enforce absolute paths,
ensuring malformed paths cannot bypass the check using relative forms
like dev/fd/ or proc/self/.
* Removed pin_transit from the namespace_pin check and replaced it by
adding the is_anchored variable to the check. Checking for root confinement
or daemon status is unnecessary when we are already validating and restricting
traversal to known safe paths (Daemon also refuses any symlinks pointing to /).
* Added new cases to the test suite to validate standard stream pseudo-path
handling and ensure namespace overflow UID bypasses work correctly
without regression.
seks99x <omarelsayed161@gmail.com> no 2026-09-08

All known versions for source package 'rsync'

Links