Use unshare with user namespace UID mapping to run the
protected-regular test without real root privileges. Falls back
to skipping if unshare or uidmap is not available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
secure_relative_open() has a kernel-enforced "stay below dirfd" path
on Linux 5.6+ (openat2 RESOLVE_BENEATH) and FreeBSD 13+ (openat
O_RESOLVE_BENEATH). On Solaris, OpenBSD, NetBSD, and Cygwin the code
falls back to the per-component O_NOFOLLOW walk, which by design
rejects every directory symlink in the path -- the very case this
test exercises. Mark the test skipped there rather than have it
fail with a known regression that's tracked separately.
macOS is intentionally not in the skip list: although it does not
have O_RESOLVE_BENEATH either, the test passes there in practice;
investigation of the underlying reason is left as follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The CVE fix in commit c35e283 made secure_relative_open() walk every
component of relpath with O_NOFOLLOW. That blocks every symlink in the
path, which is stricter than the threat model required: legitimate
directory symlinks within the destination tree (e.g. when using -K /
--copy-dirlinks) are also rejected, breaking delta transfers with
"failed verification -- update discarded". See issue #715.
On Linux 5.6+, openat2(RESOLVE_BENEATH | RESOLVE_NO_MAGICLINKS) gives
us exactly what we want: the kernel rejects any resolution that would
escape the starting directory (via "..", absolute paths, or symlinks
pointing outside dirfd) while still following symlinks that resolve
within it. /proc magic-links are blocked too.
Use openat2 first; fall back to the existing per-component O_NOFOLLOW
walk on ENOSYS (kernel < 5.6). The lexical "../" checks at the head
of the function are kept as defense in depth. The Linux gate is
plain #ifdef __linux__: the runtime ENOSYS fallback covers the only
case that actually matters (header present + old kernel), and any
Linux build environment without linux/openat2.h will fail with a
clear "no such file" error rather than silently disabling the
protection.
Verified manually that openat2(RESOLVE_BENEATH) blocks all four
escape patterns (absolute symlink, ../ symlink, lexical .., absolute
path) while allowing direct and within-tree symlinks. The new
testsuite/symlink-dirlink-basis.test (taken from PR #864 by Samuel
Henrique) exercises the issue #715 regression and passes; full
make check passes 47/47.
Test: testsuite/symlink-dirlink-basis.test (8 scenarios)
Fixes: https://github.com/RsyncProject/rsync/issues/715
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Solaris xls() function listed every entry in the file's xattr
directory, which on Solaris includes OS-managed SUNWattr_ro and
SUNWattr_rw pseudo-attributes. SUNWattr_rw embeds the file creation
time, so its bytes naturally differ between the source and destination
files, making the xattrs and xattrs-hlink tests fail with diffs that
have nothing to do with rsync.
Rsync's own listxattr wrapper already filters these out
(lib/sysxattrs.c), so the right fix is to filter them in the test
display too. Other platforms are unaffected because each has its own
xls() branch in the case statement.
With the test now actually passing on Solaris, drop the CI hack that
overwrote testsuite/xattrs.test with a skip stub.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add parallel test execution using concurrent.futures. With -j8 the
test suite completes in ~4s vs ~29s sequential (~7x speedup).
Also fix two issues that caused failures under parallel execution:
- rsync_ls_lR now prunes testtmp/ so parallel tests don't see each
other's temp files when scanning the source tree
- clean-fname-underflow.test now uses $scratchdir instead of /tmp
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite the test runner in Python with proper command-line options
including --valgrind which directs valgrind output to per-process
log files so it doesn't interfere with test output comparisons.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The AVX2 get_checksum1_avx2_64() read mul_one before initializing it,
which is undefined behavior. Replace the cmpeq/abs trick with
_mm256_set1_epi8(1) to match the SSSE3 and SSE2 versions.
Add a TEST_SIMD_CHECKSUM1 test mode that verifies all SIMD paths
(SSE2, SSSE3, AVX2, and the full dispatch chain) produce identical
results to the C reference, across multiple buffer sizes with both
aligned and unaligned buffers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This can happen when the tests are unable to `stat(2)` some files in
`/etc`, `/bin`, or `/`, due to Unix permissions or other sandboxing. We
still guard against serious errors, which use exit code 2.
The test was added in dc34990, it turns out that it's flaky. It failed
once on the Debian build infra, cf. [1].
The problem is that the command `rsync -aH '$fromdir/sym' '$todir'`
updates the mod time of `$todir`, so there might be a diff between the
output of `rsync_ls_lR $fromdir` and `rsync_ls_lR $todir`, if ever rsync
runs 1 second (or more) after the directories were created.
To clarify: it's easy to make the test fails 100% of the times with this
change:
```
makepath "$fromdir/sym" "$todir"
+sleep 5
checkit "$RSYNC -aH '$fromdir/sym' '$todir'" "$fromdir" "$todir"
```
With the fix proposed here, we don't use `checkit` anymore, instead we
just run the rsync command, then a simple `diff` to compare the two
directories. This is exactly what the other `-H` test just above does.
In case there's some doubts, `diff` fails if `sym` is missing:
```
$ mkdir -p foo/sym bar
$ diff foo bar || echo KO!
Only in foo: sym
KO!
```
I tested that, after this commit, the test still catches the `-H`
regression in rsync 3.4.0.
Fixes: https://github.com/RsyncProject/rsync/issues/735
[1]: https://buildd.debian.org/status/fetch.php?pkg=rsync&arch=ppc64el&ver=3.4.1%2Bds1-1&stamp=1741147156&raw=0
atime of source files could sometimes be overwritten
even though --open-noatime option was used.
To fix that, optional O_NOATIME flag was added
to do_open_nofollow which is also used to open regular
files since fix:
"fixed symlink race condition in sender"
Previously optional O_NOATIME flag was only in do_open.
The exclude.test file continues to run local copies (which are a special
kind of "push") while the exclude-lsh.test symlink runs a a "pull" using
the lsh.sh script as the "remote" shell.
* add tests to exercise copy_file
* Extract new function unlink_and_reopen from copy_file
The argument `ofd` to copy_file is always set to -1 unless
`open_tmpfile()` is called at generator.c:909
This change
* removes assignment to a function argument
* renames argument `ofd` to `tmpfilefd` in line with existing uses
* extracts a new function `unlink_and_reopen` which is static to util1.c
* rewrites header comments for copy_file
The Linux fs.protected_regular sysctl setting could cause rsync to fail to write a file in-place with the O_CREAT flag set, so the code now tries an open without O_CREAT when it might help to avoid an EACCES error. A testsuite script is included (and slightly improved by Wayne to ensure that it outputs a SKIP when fs.protected_regular is turned off).
- use `grep -E` and `grep -F` (`egrep` and `fgrep` are non-standard)
- use same hashbang style for all test scripts
- use explicit comparisons in test scripts
- remove redundant ; from test scripts
- make test script not executable, just like all the other scripts
- unify codestyle across all test scripts
- make openssl license exception clearer by having it at the top
- use modern links in COPYING. The text now matches:
https://www.gnu.org/licenses/gpl-3.0.txt
- fix typo
We now put the configure.sh, config.h.in, and aclocal.m4 files in the
alternate build dir along with the other generated files. This requires
that we create symlinks for configure.ac & m4 in the build dir, which is
handled on the first run of configure or prepare-source. I also changed
the patch-branch handling away from the .gen-stash dir to an automatic
build/$PATCH subdir idiom that will keep each branch's configuration
separated. These automatic build dirs are only used when there is a
.git dir, a build/master dir, and no top-dir Makefile. You'll also
want to have package/make early on your path for optimal ease of use.