mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-12 00:46:09 -04:00
Some "use chroot" improvements.
- The sanitize_paths variable was set too often. It only needs to be set when the "inner" path is not "/". This change avoids sanitizing & munging things for a path=/ module just because chroot is off. - The default for "use chroot" is now "unset" instead of "true". When unset it checks if chrooting works, and if not, it proceeds with a sanitized copy instead of totally failing to work. This makes it easier to setup a non-root rsync daemon, for instance. It will have no effect on a typical Linux root-run daemon where the default will continue to use chroot (because chrooting works). A config file can explicitly set "use chroot = true | false" to force the choice. - Try to improve the "use chroot" manpage.
This commit is contained in:
13
NEWS.md
13
NEWS.md
@@ -8,6 +8,9 @@
|
||||
|
||||
- When rsync gets an unpack error on an ACL, mention the filename.
|
||||
|
||||
- Avoid oversetting sanitize_paths when a daemon is serving "/" (even if
|
||||
"use chroot" is false).
|
||||
|
||||
### ENHANCEMENTS:
|
||||
|
||||
- Added negotiated daemon-auth support that allows a stronger checksum digest
|
||||
@@ -32,6 +35,11 @@
|
||||
converted. Newer rsync versions will provide more complete info than older
|
||||
versions.
|
||||
|
||||
- The [`use chroot`](#rsyncd.conf) daemon parameter now defaults to "unset" so
|
||||
that rsync can test if chrooting works and decide to proceed with a sanitized
|
||||
copy if chroot is not supported (e.g., for a non-root daemon). Explicitly
|
||||
setting it to true or false (on or off) behaves the same way as before.
|
||||
|
||||
### PACKAGING RELATED:
|
||||
|
||||
- The checksum code now uses openssl's EVP methods, which gets rid of various
|
||||
@@ -49,6 +57,11 @@
|
||||
configured path in the OPENSSL_CONF environment variable (when the variable
|
||||
is not already set). This will enable openssl's MD4 code for rsync to use.
|
||||
|
||||
- The packager may wish to include an explicit "use chroot = true" in the top
|
||||
section of the /etc/rsyncd.conf file if the daemon is being installed to run
|
||||
as the root user (though rsync should behave the same even with the value
|
||||
unset, a little extra paranoia doesn't hurt).
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
# NEWS for rsync 3.2.6 (9 Sep 2022)
|
||||
|
||||
@@ -701,7 +701,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
int set_uid;
|
||||
char *p, *err_msg = NULL;
|
||||
char *name = lp_name(i);
|
||||
int use_chroot = lp_use_chroot(i);
|
||||
int use_chroot = lp_use_chroot(i); /* might be 1 (yes), 0 (no), or -1 (unset) */
|
||||
int ret, pre_exec_arg_fd = -1, pre_exec_error_fd = -1;
|
||||
int save_munge_symlinks;
|
||||
pid_t pre_exec_pid = 0;
|
||||
@@ -826,6 +826,20 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
io_printf(f_out, "@ERROR: no path setting.\n");
|
||||
return -1;
|
||||
}
|
||||
if (use_chroot < 0) {
|
||||
if (strstr(module_dir, "/./") != NULL)
|
||||
use_chroot = 1; /* The module is expecting a chroot inner & outer path. */
|
||||
else if (chroot("/") < 0) {
|
||||
rprintf(FLOG, "chroot test failed: %s. "
|
||||
"Switching 'use chroot' from unset to no.\n",
|
||||
strerror(errno));
|
||||
use_chroot = 0;
|
||||
} else {
|
||||
if (chdir("/") < 0)
|
||||
rsyserr(FLOG, errno, "chdir(\"/\") failed");
|
||||
use_chroot = 1;
|
||||
}
|
||||
}
|
||||
if (use_chroot) {
|
||||
if ((p = strstr(module_dir, "/./")) != NULL) {
|
||||
*p = '\0'; /* Temporary... */
|
||||
@@ -962,20 +976,8 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
}
|
||||
|
||||
if (use_chroot) {
|
||||
/*
|
||||
* XXX: The 'use chroot' flag is a fairly reliable
|
||||
* source of confusion, because it fails under two
|
||||
* important circumstances: running as non-root,
|
||||
* running on Win32 (or possibly others). On the
|
||||
* other hand, if you are running as root, then it
|
||||
* might be better to always use chroot.
|
||||
*
|
||||
* So, perhaps if we can't chroot we should just issue
|
||||
* a warning, unless a "require chroot" flag is set,
|
||||
* in which case we fail.
|
||||
*/
|
||||
if (chroot(module_chdir)) {
|
||||
rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
|
||||
rsyserr(FLOG, errno, "chroot(\"%s\") failed", module_chdir);
|
||||
io_printf(f_out, "@ERROR: chroot failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -984,7 +986,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
|
||||
|
||||
if (!change_dir(module_chdir, CD_NORMAL))
|
||||
return path_failure(f_out, module_chdir, True);
|
||||
if (module_dirlen || (!use_chroot && !*lp_daemon_chroot()))
|
||||
if (module_dirlen)
|
||||
sanitize_paths = 1;
|
||||
|
||||
if ((munge_symlinks = lp_munge_symlinks(module_id)) < 0)
|
||||
@@ -1299,8 +1301,12 @@ int start_daemon(int f_in, int f_out)
|
||||
p = lp_daemon_chroot();
|
||||
if (*p) {
|
||||
log_init(0); /* Make use we've initialized syslog before chrooting. */
|
||||
if (chroot(p) < 0 || chdir("/") < 0) {
|
||||
rsyserr(FLOG, errno, "daemon chroot %s failed", p);
|
||||
if (chroot(p) < 0) {
|
||||
rsyserr(FLOG, errno, "daemon chroot(\"%s\") failed", p);
|
||||
return -1;
|
||||
}
|
||||
if (chdir("/") < 0) {
|
||||
rsyserr(FLOG, errno, "daemon chdir(\"/\") failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ BOOL read_only True
|
||||
BOOL reverse_lookup True
|
||||
BOOL strict_modes True
|
||||
BOOL transfer_logging False
|
||||
BOOL use_chroot True
|
||||
BOOL write_only False
|
||||
|
||||
BOOL3 munge_symlinks Unset
|
||||
BOOL3 numeric_ids Unset
|
||||
BOOL3 open_noatime Unset
|
||||
BOOL3 use_chroot Unset
|
||||
|
||||
@@ -164,6 +164,16 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
available in this module. You must specify this parameter for each module
|
||||
in `rsyncd.conf`.
|
||||
|
||||
If the value contains a "/./" element then the path will be divided at that
|
||||
point into a chroot dir and an inner-chroot subdir. If [`use chroot`](#)
|
||||
is set to false, though, the extraneous dot dir is just cleaned out of the
|
||||
path. An example of this idiom is:
|
||||
|
||||
> path = /var/rsync/./module1
|
||||
|
||||
This will (when chrooting) chroot to "/var/rsync" and set the inside-chroot
|
||||
path to "/module1".
|
||||
|
||||
You may base the path's value off of an environment variable by surrounding
|
||||
the variable name with percent signs. You can even reference a variable
|
||||
that is set by rsync when the user connects. For example, this would use
|
||||
@@ -187,29 +197,43 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
|
||||
path, and of complicating the preservation of users and groups by name (see
|
||||
below).
|
||||
|
||||
As an additional safety feature, you can specify a dot-dir in the module's
|
||||
"[path](#)" to indicate the point where the chroot should occur. This allows
|
||||
rsync to run in a chroot with a non-"/" path for the top of the transfer
|
||||
hierarchy. Doing this guards against unintended library loading (since
|
||||
those absolute paths will not be inside the transfer hierarchy unless you
|
||||
have used an unwise pathname), and lets you setup libraries for the chroot
|
||||
that are outside of the transfer. For example, specifying
|
||||
"/var/rsync/./module1" will chroot to the "/var/rsync" directory and set
|
||||
the inside-chroot path to "/module1". If you had omitted the dot-dir, the
|
||||
chroot would have used the whole path, and the inside-chroot path would
|
||||
have been "/".
|
||||
If `use chroot` is not set, it defaults to trying to enable a chroot but
|
||||
allows the daemon to continue (after logging a warning) if it fails. The
|
||||
one exception to this is when a module's [`path`](#) has a "/./" chroot
|
||||
divider in it -- this causes an unset value to be treated as true for that
|
||||
module.
|
||||
|
||||
When both "use chroot" and "[daemon chroot](#)" are false, OR the inside-chroot
|
||||
path of "use chroot" is not "/", rsync will: (1) munge symlinks by default
|
||||
for security reasons (see "[munge symlinks](#)" for a way to turn this off, but
|
||||
only if you trust your users), (2) substitute leading slashes in absolute
|
||||
paths with the module's path (so that options such as `--backup-dir`,
|
||||
`--compare-dest`, etc. interpret an absolute path as rooted in the module's
|
||||
"[path](#)" dir), and (3) trim ".." path elements from args if rsync believes
|
||||
they would escape the module hierarchy. The default for "use chroot" is
|
||||
true, and is the safer choice (especially if the module is not read-only).
|
||||
Prior to rsync 3.2.7, the default value was "true". The new default makes
|
||||
it easier to setup an rsync daemon as a non-root user or to run a daemon on
|
||||
a system where chroot fails. Explicitly setting the value to true in the
|
||||
rsyncd.conf file will always require the chroot to succeed.
|
||||
|
||||
When this parameter is enabled *and* the "[name converter](#)" parameter is
|
||||
It is also possible to specify a dot-dir in the module's "[path](#)" to
|
||||
indicate that you want to chdir to the earlier part of the path and then
|
||||
serve files from inside the latter part of the path (with default
|
||||
sanitizing and symlink munging). This can be useful if you need some
|
||||
library dirs inside the chroot (typically for uid & gid lookups) but don't
|
||||
want to put the lib dir into the top of the served path (even though they
|
||||
can be hidden with an [`exclude`](#) directive). However, a better choice
|
||||
for a modern rsync setup is to use a [`name converter`](#)" and try to
|
||||
avoid inner lib dirs altogether. See also the [`daemon chroot`](#)
|
||||
parameter, which causes rsync to chroot into its own chroot area before
|
||||
doing any path-related chrooting.
|
||||
|
||||
If the daemon is serving the "/" dir (either directly or due to being
|
||||
chrooted to the module's path), rsync does not do any extra path sanitizing
|
||||
or (default) munging. When it has to limit access to a particular subdir
|
||||
(either due to chroot being disabled or having an inside-chroot path set),
|
||||
rsync will munge symlinks (by default) and sanitize paths. Those that
|
||||
dislike munged symlinks (and really, really trust their users to not break
|
||||
out of the subdir) can disable the symlink munging via the "[munge
|
||||
symlinks](#)" parameter. Sanitizing paths trims ".." path elements from
|
||||
args that rsync believes would escape the module hierarchy, and also
|
||||
substitutes leading slashes in absolute paths with the module's path (so
|
||||
that options such as `--backup-dir` & `--compare-dest` interpret an
|
||||
absolute path as rooted in the module's "[path](#)" dir).
|
||||
|
||||
When a chroot is in effect *and* the "[name converter](#)" parameter is
|
||||
*not* set, the "[numeric ids](#)" parameter will default to being enabled
|
||||
(disabling name lookups). This means that if you manually setup
|
||||
name-lookup libraries in your chroot (instead of using a name converter)
|
||||
|
||||
Reference in New Issue
Block a user