[SCM] The rsync repository. - branch master updated

Rsync CVS commit messages rsync-cvs at lists.samba.org
Tue Sep 20 07:11:01 UTC 2022


The branch, master has been updated
       via  97e02bf2 Some "use chroot" improvements.
       via  77d762ce Stop importing "re".
      from  5b27d2e6 Pre-compute FILE_SUM_EXTRA_CNT.

https://git.samba.org/?p=rsync.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 97e02bf21a119971e258550bdcd3e56096bdd7b2
Author: Wayne Davison <wayne at opencoder.net>
Date:   Mon Sep 19 22:37:29 2022 -0700

    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.

commit 77d762ced8bae1dac1de48b0a3814a49a1371c99
Author: Wayne Davison <wayne at opencoder.net>
Date:   Mon Sep 19 22:36:49 2022 -0700

    Stop importing "re".

-----------------------------------------------------------------------

Summary of changes:
 NEWS.md                    | 13 +++++++++
 clientserver.c             | 40 +++++++++++++++-----------
 daemon-parm.txt            |  2 +-
 rsyncd.conf.5.md           | 70 +++++++++++++++++++++++++++++++---------------
 support/json-rsync-version |  2 +-
 5 files changed, 85 insertions(+), 42 deletions(-)


Changeset truncated at 500 lines:

diff --git a/NEWS.md b/NEWS.md
index d40b7fa2..63191360 100644
--- a/NEWS.md
+++ b/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)
diff --git a/clientserver.c b/clientserver.c
index 9ad7eaf7..67983f77 100644
--- a/clientserver.c
+++ b/clientserver.c
@@ -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;
 		}
 	}
diff --git a/daemon-parm.txt b/daemon-parm.txt
index 3b438b02..69034173 100644
--- a/daemon-parm.txt
+++ b/daemon-parm.txt
@@ -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
diff --git a/rsyncd.conf.5.md b/rsyncd.conf.5.md
index 400ad107..abb6c578 100644
--- a/rsyncd.conf.5.md
+++ b/rsyncd.conf.5.md
@@ -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 "/".
-
-    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).
-
-    When this parameter is enabled *and* the "[name converter](#)" parameter is
+    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.
+
+    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.
+
+    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)
diff --git a/support/json-rsync-version b/support/json-rsync-version
index a51c3a88..bf5684b7 100755
--- a/support/json-rsync-version
+++ b/support/json-rsync-version
@@ -1,6 +1,6 @@
 #!/usr/bin/python3
 
-import sys, re, argparse, subprocess, json
+import sys, argparse, subprocess, json
 
 def main():
     if not args.rsync or args.rsync == '-':


-- 
The rsync repository.



More information about the rsync-cvs mailing list