On Wed, Sep 10, 2008 at 03:50:46PM +0200, Paul Slootman wrote:
> Apparently in pre-3.0.0 versions '%P' would log the actual path as
> specified in the module entry in rsyncd.conf, but now it's apparently
> relative to the chroot...

Yeah, that appears to have happened in the security release that added
the ability to have an interior module path inside a chroot (so a
patched 2.6.9 would also be affected).  If the user is not using an
interior-chroot path, then a single-line tweak in log.c would be all
that is needed to avoid the issue.  However, with an interior path, we
need to take extra steps to avoid truncating the input value.

The attached patch should fix things.  It's relative to 3.0.4, but will
also apply with a little twiddling to the 3.1.0dev source (and it should
be easy to patch older versions too).

..wayne..
--- a/clientserver.c
+++ b/clientserver.c
@@ -398,7 +398,7 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
 static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
 {
 	int argc;
-	char **argv, **orig_argv, **orig_early_argv, *chroot_path = NULL;
+	char **argv, **orig_argv, **orig_early_argv, *module_chdir;
 	char line[BIGPATHBUFLEN];
 	uid_t uid = (uid_t)-2;  /* canonically "nobody" */
 	gid_t gid = (gid_t)-2;
@@ -501,26 +501,32 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
 	module_dir = lp_path(i);
 	if (use_chroot) {
 		if ((p = strstr(module_dir, "/./")) != NULL) {
-			*p = '\0';
-			p += 2;
-		} else if ((p = strdup("/")) == NULL) /* MEMORY LEAK */
-			out_of_memory("rsync_module");
-	}
+			int len = p - module_dir + 1;
+			if (!(module_chdir = new_array(char, len))) /* MEMORY LEAK */
+				out_of_memory("rsync_module");
+			strlcpy(module_chdir, module_dir, len);
+			if (!(p = strdup(p + 2)))
+				out_of_memory("rsync_module");
+			clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
+			module_dir = p;
+		} else {
+			module_chdir = module_dir;
+			if ((module_dir = strdup("/")) == NULL)
+				out_of_memory("rsync_module");
+		}
+	} else
+		module_chdir = module_dir;
 
 	/* We do a change_dir() that doesn't actually call chdir()
 	 * just to make a relative path absolute. */
 	strlcpy(line, curr_dir, sizeof line);
-	if (!change_dir(module_dir, CD_SKIP_CHDIR))
+	if (!change_dir(module_chdir, CD_SKIP_CHDIR))
 		goto chdir_failed;
-	if (strcmp(curr_dir, module_dir) != 0
-	 && (module_dir = strdup(curr_dir)) == NULL)
+	if (strcmp(curr_dir, module_chdir) != 0
+	 && (module_chdir = strdup(curr_dir)) == NULL) /* MEMORY LEAK */
 		out_of_memory("rsync_module");
 	change_dir(line, CD_SKIP_CHDIR); /* Restore curr_dir. */
 
-	if (use_chroot) {
-		chroot_path = module_dir;
-		module_dir = p; /* p is "/" or our inside-chroot path */
-	}
 	module_dirlen = clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
 
 	if (module_dirlen == 1) {
@@ -557,16 +563,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
 		char *modname, *modpath, *hostaddr, *hostname, *username;
 		int status;
 
-		if (!use_chroot)
-			p = module_dir;
-		else if (module_dirlen) {
-			pathjoin(line, sizeof line, chroot_path, module_dir+1);
-			p = line;
-		} else
-			p = chroot_path;
-
 		if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
-		 || asprintf(&modpath, "RSYNC_MODULE_PATH=%s", p) < 0
+		 || asprintf(&modpath, "RSYNC_MODULE_PATH=%s", lp_path(i)) < 0
 		 || asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
 		 || asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
 		 || asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
@@ -666,25 +664,23 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
 		 * a warning, unless a "require chroot" flag is set,
 		 * in which case we fail.
 		 */
-		if (chroot(chroot_path)) {
-			rsyserr(FLOG, errno, "chroot %s failed", chroot_path);
+		if (chroot(module_chdir)) {
+			rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
 			io_printf(f_out, "@ERROR: chroot failed\n");
 			return -1;
 		}
-		if (!change_dir(module_dir, CD_NORMAL))
-			goto chdir_failed;
-		if (module_dirlen)
-			sanitize_paths = 1;
-	} else {
-		if (!change_dir(module_dir, CD_NORMAL)) {
-		  chdir_failed:
-			rsyserr(FLOG, errno, "chdir %s failed\n", module_dir);
-			io_printf(f_out, "@ERROR: chdir failed\n");
-			return -1;
-		}
-		sanitize_paths = 1;
+		module_chdir = module_dir;
 	}
 
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+	  chdir_failed:
+		rsyserr(FLOG, errno, "chdir %s failed\n", module_chdir);
+		io_printf(f_out, "@ERROR: chdir failed\n");
+		return -1;
+	}
+	if (module_dirlen || !use_chroot)
+		sanitize_paths = 1;
+
 	if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
 		munge_symlinks = !use_chroot || module_dirlen;
 	if (munge_symlinks) {
--- a/log.c
+++ b/log.c
@@ -55,7 +55,6 @@ extern iconv_t ic_chck;
 extern iconv_t ic_send, ic_recv;
 #endif
 extern char curr_dir[];
-extern char *module_dir;
 extern unsigned int module_dirlen;
 
 static int log_initialised;
@@ -603,7 +602,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
 			n = timestring(time(NULL));
 			break;
 		case 'P':
-			n = module_dir;
+			n = lp_path(module_id);
 			break;
 		case 'u':
 			n = auth_user;
-- 
Please use reply-all for most replies to avoid omitting the mailing list.
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to