Andrew TridgellandLeonid Bugaev 0894e0422e rrsync: pin a sender argument where rsync will actually resolve it
88cee089 rewrote every validated argument to /proc/self/fd/N so the
spawned rsync re-resolves it to the pinned inode.  That is right for a
receiver, which open()s its destination, but a sender never opens its
source argument: send_file_list() lstat()s it first, and lstat of a
procfs magic link is always S_IFLNK.  So the sender described the
argument as a symlink and sent no data -- silent data loss on
"rsync -a user@host:file dest/", the most ordinary command there is.
Of the argument shapes now covered, only a trailing-slash directory
survived.

Leonid Bugaev reported the regression, diagnosed the lstat-vs-magic-link
mechanism, and supplied the first regression test.

Which pin is usable depends on what rsync does with the argument:

  * a trailing "/" or "/." directory is opened, not lstat()ed, and rsync
    does follow a symlink there, so it keeps the leaf pin -- verified:
    without it a flipped leaf transfers the outside directory's content;
  * anything else pins one level up and passes the leaf by name.  rsync
    will not follow a symlink at that position (it sends the symlink
    itself), -L/-k/--copy-unsafe-links are already disabled for a
    restricted dir, and rsync's own leaf open is O_NOFOLLOW.

The directory pin resolves normally, including a symlink at its last
component, which is legitimate and which 3.4.4 accepts; the readlink
check afterwards is what proves the held inode is in-tree.  It uses
O_PATH because reaching a known name beneath a directory needs only
search permission, and a mode 0111 parent is an ordinary way to publish
a file without letting it be listed.

Under --relative the transmitted name is the whole argument rather than
its basename, so the pin moves up to where that name starts and the rest
is spelled after a /./ marker.  The client's own first marker wins if it
supplied one, including when nothing follows it; -R is parsed out of the
short-option cluster rather than sniffed for the letter, so the trailing
capability blob (-e.iLsfxC) cannot be mistaken for it.

Directory pins are keyed by (st_dev, st_ino), so a glob whose matches
share a parent inherits one descriptor rather than one per argument.

Every shape now delivers what a pristine 3.4.4 delivers, which is what
rrsync-pull-arg-shapes asserts -- it passes against 3.4.4 itself, so the
expectations are that behaviour and not this implementation's.  The
"-R --no-implied-dirs" case is gated on protocol >= 30: at protocol 29
the receiver rejects it with "invalid path from sender" and transfers
nothing, which 3.4.4 does identically.

Moving the sender's pin off the leaf invalidates rrsync-symlink's oracle,
so it is reworked here rather than left failing.  It patches rsync to a
stub that open()s its last argument, which is a faithful model for an
intermediate path component -- whatever rsync does with the final name,
it must not reach it through a flipped parent -- but not for the leaf: a
sender lstat()s its source and transmits a symlink there rather than
reading through it.  So it now flips an intermediate directory, and the
leaf is covered against the real binary by rrsync-sender-leaf-flip, which
races both a plain file argument and a trailing-slash directory and
asserts no outside CONTENT is delivered rather than requiring a symptom
from a race that may not be won on a given run.  Its trailing-slash half
is RED against a pristine 3.4.4 rrsync, which delivers outside/dir/loot.

rrsync-symlink is now sender-only.  Measured over a 5s race, the stub
reached the outside marker 28 times in 98 runs as a sender and 25 in 97
as a receiver against 3.4.4; with the pin it is 0 as a sender but still
7-9 as a receiver, on the branch base as well as here.  That residual is
the receiver's not-yet-existing-destination fallback, which predates this
work and is tracked in #139 rather than folded in.

Clearing FD_CLOEXEC goes through F_SETFD rather than os.set_inheritable(),
which prefers ioctl(FIONCLEX) and gets EBADF from an O_PATH descriptor on
older kernels -- every sender pull on Ubuntu 18.04 aborted with "Bad file
descriptor" the moment a directory pin was taken.

Co-authored-by: Leonid Bugaev <leonsbox@gmail.com>

(cherry picked from commit 6edb7dea2a)
2026-08-02 21:33:25 +10:00
2022-10-16 10:28:58 -07:00
2025-01-16 07:27:46 +11:00
2020-07-15 10:20:52 -07:00
2022-08-14 10:15:08 -07:00
2021-09-26 18:55:46 -07:00
2023-05-04 08:45:42 -07:00
2023-05-04 08:45:42 -07:00
2021-09-26 16:57:55 -07:00
2019-03-16 09:15:49 -07:00
2020-06-13 19:15:02 -07:00
2020-06-27 21:19:52 -07:00
2022-01-15 17:21:01 -08:00
2024-05-29 11:19:19 +10:00
2019-03-16 09:15:49 -07:00
2019-03-16 09:15:49 -07:00
2022-01-15 17:21:01 -08:00
2020-06-13 19:15:02 -07:00
2022-03-26 08:58:51 -07:00
2022-01-15 17:21:01 -08:00
2020-06-22 14:21:15 -07:00
2022-01-15 17:21:01 -08:00
2025-01-15 12:13:41 +11:00
2026-05-07 06:33:16 +10:00
2020-06-22 14:21:15 -07:00

WHAT IS RSYNC?

Rsync is a fast and extraordinarily versatile file copying tool for both remote and local files.

Rsync uses a delta-transfer algorithm which provides a very fast method for bringing remote files into sync. It does this by sending just the differences in the files across the link, without requiring that both sets of files are present at one of the ends of the link beforehand. At first glance this may seem impossible because the calculation of diffs between two files normally requires local access to both files.

A technical report describing the rsync algorithm is included with this package.

USAGE

Basically you use rsync just like scp, but rsync has many additional options. To get a complete list of supported options type:

rsync --help

See the manpage for more detailed information.

BUILDING AND INSTALLING

If you need to build rsync yourself, check out the INSTALL page for information on what libraries and packages you can use to get the maximum features in your build.

SETUP

Rsync normally uses ssh or rsh for communication with remote systems. It does not need to be setuid and requires no special privileges for installation. You must, however, have a working ssh or rsh system. Using ssh is recommended for its security features.

Alternatively, rsync can run in `daemon' mode, listening on a socket. This is generally used for public file distribution, although authentication and access control are available.

To install rsync, first run the "configure" script. This will create a Makefile and config.h appropriate for your system. Then type "make".

Note that on some systems you will have to force configure not to use gcc because gcc may not support some features (such as 64 bit file offsets) that your system may support. Set the environment variable CC to the name of your native compiler before running configure in this case.

Once built put a copy of rsync in your search path on the local and remote systems (or use "make install"). That's it!

RSYNC DAEMONS

Rsync can also talk to "rsync daemons" which can provide anonymous or authenticated rsync. See the rsyncd.conf(5) manpage for details on how to setup an rsync daemon. See the rsync(1) manpage for info on how to connect to an rsync daemon.

WEB SITE

For more information, visit the main rsync web site.

You'll find a FAQ list, downloads, resources, HTML versions of the manpages, etc.

MAILING LISTS

There is a mailing list for the discussion of rsync and its applications that is open to anyone to join. New releases are announced on this list, and there is also an announcement-only mailing list for those that want official announcements. See the mailing-list page for full details.

BUG REPORTS

The bug-tracking web page has full details on bug reporting.

That page contains links to the current bug list, and information on how to do a good job when reporting a bug. You might also like to try searching the Internet for the error message you've received, or looking in the mailing list archives.

To send a bug report, follow the instructions on the bug-tracking page of the web site.

Alternately, email your bug report to rsync@lists.samba.org.

For security issues please email details of the issue to rsync.project@gmail.com.

GIT REPOSITORY

If you want to get the very latest version of rsync direct from the source code repository, then you will need to use git. The git repo is hosted on GitHub and on Samba's site.

See the download page for full details on all the ways to grab the source.

Rsync was originally written by Andrew Tridgell and Paul Mackerras. Many people from around the world have helped to maintain and improve it.

Special thanks go to Wayne Davison, who maintained rsync from 2004 to 2024.

Rsync may be used, modified and redistributed only under the terms of the GNU General Public License, found in the file COPYING in this distribution, or at the Free Software Foundation.

S
Description
No description provided
Readme GPL-3.0
69 MiB
0 Stars 1 Watchers 0 Forks
Languages
C 48.4%
Python 41.8%
HTML 4.3%
M4 1.3%
Shell 0.8%
Other 3.3%