From b3097cbcf7b19ebac037c3eb4584ac4e1ea03635bc7cf4e521d3f64697170476 Mon Sep 17 00:00:00 2001 From: Pedro Monreal Gonzalez Date: Wed, 17 Aug 2022 11:32:58 +0000 Subject: [PATCH] Accepting request 997517 from home:david.anes:branches:network - Add upstream patch rsync-3.2.5-slp.patch, as the one included in the released tarball doesn't fully apply. - Drop patch rsync-CVE-2022-29154.patch, already included upstream. - Update to 3.2.5 * SECURITY FIXES: - Added some file-list safety checking that helps to ensure that a rogue sending rsync can't add unrequested top-level names and/or include recursive names that should have been excluded by the sender. These extra safety checks only require the receiver rsync to be updated. When dealing with an untrusted sending host, it is safest to copy into a dedicated destination directory for the remote content (i.e. don't copy into a destination directory that contains files that aren't from the remote host unless you trust the remote host). Fixes CVE-2022-29154. - A fix for CVE-2022-37434 in the bundled zlib (buffer overflow issue). * BUG FIXES: - Fixed the handling of filenames specified with backslash-quoted wildcards when the default remote-arg-escaping is enabled. - Fixed the configure check for signed char that was causing a host that defaults to unsigned characters to generate bogus rolling checksums. This made rsync send mostly literal data for a copy instead of finding matching data in the receiver's basis file (for a file that contains high-bit characters). - Lots of manpage improvements, including an attempt to better describe how include/exclude filters work. - If rsync is compiled with an xxhash 0.8 library and then moved to a system with a dynamically linked xxhash 0.7 library, we now detect this and disable the XX3 hashes (since these routines didn't stabilize until 0.8). * ENHANCEMENTS: - The [`--trust-sender`](rsync.1#opt) option was added as a way to bypass the extra file-list safety checking (should that be required). OBS-URL: https://build.opensuse.org/request/show/997517 OBS-URL: https://build.opensuse.org/package/show/network/rsync?expand=0&rev=93 --- rsync-3.2.4.tar.gz | 3 - rsync-3.2.4.tar.gz.asc | 6 - rsync-3.2.5-slp.patch | 532 +++++++++++++++++++++++++++++++++ rsync-3.2.5.tar.gz | 3 + rsync-3.2.5.tar.gz.asc | 6 + rsync-CVE-2022-29154.patch | 399 ------------------------- rsync-patches-3.2.4.tar.gz | 3 - rsync-patches-3.2.4.tar.gz.asc | 6 - rsync-patches-3.2.5.tar.gz | 3 + rsync-patches-3.2.5.tar.gz.asc | 6 + rsync.changes | 49 ++- rsync.spec | 13 +- 12 files changed, 608 insertions(+), 421 deletions(-) delete mode 100644 rsync-3.2.4.tar.gz delete mode 100644 rsync-3.2.4.tar.gz.asc create mode 100644 rsync-3.2.5-slp.patch create mode 100644 rsync-3.2.5.tar.gz create mode 100644 rsync-3.2.5.tar.gz.asc delete mode 100644 rsync-CVE-2022-29154.patch delete mode 100644 rsync-patches-3.2.4.tar.gz delete mode 100644 rsync-patches-3.2.4.tar.gz.asc create mode 100644 rsync-patches-3.2.5.tar.gz create mode 100644 rsync-patches-3.2.5.tar.gz.asc diff --git a/rsync-3.2.4.tar.gz b/rsync-3.2.4.tar.gz deleted file mode 100644 index 1ff574b..0000000 --- a/rsync-3.2.4.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f761838d08052b0b6579cf7f6737d93e47f01f4da04c5d24d3447b7f2a5fad1 -size 1114853 diff --git a/rsync-3.2.4.tar.gz.asc b/rsync-3.2.4.tar.gz.asc deleted file mode 100644 index aafcba1..0000000 --- a/rsync-3.2.4.tar.gz.asc +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iF0EABECAB0WIQQASMiwJtTJbw5YnC9shZ+xS5aoxQUCYlnXXQAKCRBshZ+xS5ao -xc+IAKD048bZqvc6HNIKwE1YeUe+x/46lgCfYwuhXBwgdOqeJ+5YCjfXqsAJcXw= -=QsHS ------END PGP SIGNATURE----- diff --git a/rsync-3.2.5-slp.patch b/rsync-3.2.5-slp.patch new file mode 100644 index 0000000..6bc8bce --- /dev/null +++ b/rsync-3.2.5-slp.patch @@ -0,0 +1,532 @@ +This adds Service Location Protocol support. + +To use this patch, run these commands for a successful build: + + patch -p1 rsync somehost.mydomain.com:: + +-See the following section for more details. ++And, if Service Location Protocol is available, the following will list the ++available rsync servers: ++ ++> rsync rsync:// ++ ++See the following section for even more usage details. ++ ++One more thing, if Service Location Protocol is available, the following will ++list the available rsync servers: ++ ++> rsync rsync:// ++ ++See the following section for even more usage details. + + ## SORTED TRANSFER ORDER + +diff --git a/rsync.h b/rsync.h +--- a/rsync.h ++++ b/rsync.h +@@ -234,6 +234,10 @@ + #define SIGNIFICANT_ITEM_FLAGS (~(\ + ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE)) + ++/* this is the minimum we'll use, irrespective of config setting */ ++/* definitely don't set to less than about 30 seconds */ ++#define SLP_MIN_TIMEOUT 120 ++ + #define CFN_KEEP_DOT_DIRS (1<<0) + #define CFN_KEEP_TRAILING_SLASH (1<<1) + #define CFN_DROP_TRAILING_DOT_DIR (1<<2) +diff --git a/rsyncd.conf b/rsyncd.conf +new file mode 100644 +--- /dev/null ++++ b/rsyncd.conf +@@ -0,0 +1 @@ ++slp refresh = 300 +diff --git a/rsyncd.conf.5.md b/rsyncd.conf.5.md +--- a/rsyncd.conf.5.md ++++ b/rsyncd.conf.5.md +@@ -138,6 +138,21 @@ a literal % into a value is to use %%. + You can override the default backlog value when the daemon listens for + connections. It defaults to 5. + ++0. `use slp` ++ ++ You can enable Service Location Protocol support by enabling this global ++ parameter. The default is "false". ++ ++0. `slp refresh` ++ ++ This parameter is used to determine how long service advertisements are ++ valid (measured in seconds), and is only applicable if you have Service ++ Location Protocol support compiled in. If this is not set or is set to ++ zero, then service advertisements never time out. If this is set to less ++ than 120 seconds, then 120 seconds is used. If it is set to more than ++ 65535, then 65535 is used (which is a limitation of SLP). Using 3600 ++ (one hour) is a good number if you tend to change your configuration. ++ + ## MODULE PARAMETERS + + After the global parameters you should define a number of modules, each module +@@ -1176,6 +1191,7 @@ A more sophisticated example would be: + > max connections = 4 + > syslog facility = local5 + > pid file = /var/run/rsyncd.pid ++> slp refresh = 3600 + > + > [ftp] + > path = /var/ftp/./pub +diff --git a/socket.c b/socket.c +--- a/socket.c ++++ b/socket.c +@@ -534,6 +534,16 @@ void start_accept_loop(int port, int (*fn)(int, int)) + { + fd_set deffds; + int *sp, maxfd, i; ++#ifdef HAVE_LIBSLP ++ time_t next_slp_refresh; ++ short slp_timeout = lp_use_slp() ? lp_slp_refresh() : 0; ++ if (slp_timeout) { ++ if (slp_timeout < SLP_MIN_TIMEOUT) ++ slp_timeout = SLP_MIN_TIMEOUT; ++ /* re-register before slp times out */ ++ slp_timeout -= 15; ++ } ++#endif + + #ifdef HAVE_SIGACTION + sigact.sa_flags = SA_NOCLDSTOP; +@@ -561,14 +571,25 @@ void start_accept_loop(int port, int (*fn)(int, int)) + maxfd = sp[i]; + } + ++#ifdef HAVE_LIBSLP ++ next_slp_refresh = time(NULL) + slp_timeout; ++#endif ++ + /* now accept incoming connections - forking a new process + * for each incoming connection */ + while (1) { + fd_set fds; + pid_t pid; + int fd; ++ int sel_ret; + struct sockaddr_storage addr; + socklen_t addrlen = sizeof addr; ++#ifdef HAVE_LIBSLP ++ struct timeval slp_tv; ++ ++ slp_tv.tv_sec = 10; ++ slp_tv.tv_usec = 0; ++#endif + + /* close log file before the potentially very long select so + * file can be trimmed by another process instead of growing +@@ -581,7 +602,18 @@ void start_accept_loop(int port, int (*fn)(int, int)) + fds = deffds; + #endif + +- if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1) ++#ifdef HAVE_LIBSLP ++ sel_ret = select(maxfd + 1, &fds, NULL, NULL, ++ slp_timeout ? &slp_tv : NULL); ++ if (sel_ret == 0 && slp_timeout && time(NULL) > next_slp_refresh) { ++ rprintf(FINFO, "Service registration expired, refreshing it\n"); ++ register_services(); ++ next_slp_refresh = time(NULL) + slp_timeout; ++ } ++#else ++ sel_ret = select(maxfd + 1, &fds, NULL, NULL, NULL); ++#endif ++ if (sel_ret < 1) + continue; + + for (i = 0, fd = -1; sp[i] >= 0; i++) { +diff --git a/srvloc.c b/srvloc.c +new file mode 100644 +--- /dev/null ++++ b/srvloc.c +@@ -0,0 +1,103 @@ ++/* -*- c-file-style: "linux"; -*- ++ ++ Copyright (C) 2002 by Brad Hards ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++/* This file implements the service location functionality */ ++/* Basically, it uses normal Service Location Protocol API */ ++ ++/* It is really a cheap hack - just to show how it might work ++ in a real application. ++*/ ++ ++#include "rsync.h" ++ ++#include ++#include ++#include ++ ++/* This one just prints out the attributes */ ++static SLPBoolean getAttrCallback(UNUSED(SLPHandle hslp), const char *attrlist, ++ SLPError errcode, UNUSED(void *cookie)) ++{ ++ char *cleanstr; ++ ++ if (errcode == SLP_OK) { ++ if (!strcmp(attrlist, "(comment=)")) ++ rprintf(FINFO, "\t(No description)\n"); ++ else { ++ cleanstr = strrchr(attrlist, ')') ; ++ *cleanstr = ' '; /* remove last ')' */ ++ rprintf(FINFO, "\t%s\n", strchr(attrlist, '=') + 1); ++ } ++ } ++ return SLP_FALSE; ++} ++ ++static SLPBoolean getSLPSrvURLCallback(UNUSED(SLPHandle hslp), ++ const char *srvurl, UNUSED(unsigned short lifetime), ++ SLPError errcode, void *cookie) ++{ ++ SLPError result; ++ SLPHandle attrhslp; ++ ++ if (errcode == SLP_OK) { ++ /* chop service: off the front */ ++ rprintf(FINFO, " %s ", (strchr(srvurl, ':') + 1)); ++ /* check for any attributes */ ++ if (SLPOpen("en", SLP_FALSE,&attrhslp) == SLP_OK) { ++ result = SLPFindAttrs(attrhslp, srvurl, ++ "", /* return all attributes */ ++ "", /* use configured scopes */ ++ getAttrCallback, NULL); ++ if (result != SLP_OK) { ++ rprintf(FERROR, "errorcode: %i\n",result); ++ } ++ SLPClose(attrhslp); ++ } ++ *(SLPError*)cookie = SLP_OK; ++ } else ++ *(SLPError*)cookie = errcode; ++ ++ /* Return SLP_TRUE because we want to be called again ++ * if more services were found. */ ++ ++ return SLP_TRUE; ++} ++ ++int print_service_list(void) ++{ ++ SLPError err; ++ SLPError callbackerr; ++ SLPHandle hslp; ++ ++ err = SLPOpen("en",SLP_FALSE,&hslp); ++ if (err != SLP_OK) { ++ rprintf(FERROR, "Error opening slp handle %i\n", err); ++ return err; ++ } ++ ++ SLPFindSrvs(hslp, "rsync", ++ 0, /* use configured scopes */ ++ 0, /* no attr filter */ ++ getSLPSrvURLCallback, &callbackerr); ++ ++ /* Now that we're done using slp, close the slp handle */ ++ SLPClose(hslp); ++ ++ return 0; ++} +diff --git a/srvreg.c b/srvreg.c +new file mode 100644 +--- /dev/null ++++ b/srvreg.c +@@ -0,0 +1,128 @@ ++/* -*- c-file-style: "linux"; -*- ++ ++ Copyright (C) 2002 by Brad Hards ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++/* This file implements the service registration functionality */ ++ ++/* Basically, it uses normal Service Location Protocol API */ ++ ++#include "rsync.h" ++#include "slp.h" ++#include "netdb.h" ++ ++extern int rsync_port; ++ ++static void slp_callback(UNUSED(SLPHandle hslp), SLPError errcode, void *cookie) ++{ ++ /* return the error code in the cookie */ ++ *(SLPError*)cookie = errcode; ++ ++ /* You could do something else here like print out ++ * the errcode, etc. Remember, as a general rule, ++ * do not try to do too much in a callback because ++ * it is being executed by the same thread that is ++ * reading slp packets from the wire. */ ++} ++ ++int register_services(void) ++{ ++ SLPError err, callbackerr; ++ SLPHandle hslp; ++ int n; ++ int i; ++ char srv[120]; ++ char attr[120]; ++ char localhost[256]; ++ extern char *config_file; ++ short timeout; ++ struct addrinfo aih, *ai = 0; ++ ++ if (!lp_load(config_file, 0)) { ++ exit_cleanup(RERR_SYNTAX); ++ } ++ ++ n = lp_num_modules(); ++ ++ if (0 == lp_slp_refresh()) ++ timeout = SLP_LIFETIME_MAXIMUM; /* don't expire, ever */ ++ else if (SLP_MIN_TIMEOUT > lp_slp_refresh()) ++ timeout = SLP_MIN_TIMEOUT; /* use a reasonable minimum */ ++ else if (SLP_LIFETIME_MAXIMUM <= lp_slp_refresh()) ++ timeout = (SLP_LIFETIME_MAXIMUM - 1); /* as long as possible */ ++ else ++ timeout = lp_slp_refresh(); ++ ++ rprintf(FINFO, "rsyncd registering %d service%s with slpd for %d seconds:\n", n, ((n==1)? "":"s"), timeout); ++ err = SLPOpen("en",SLP_FALSE,&hslp); ++ if (err != SLP_OK) { ++ rprintf(FINFO, "Error opening slp handle %i\n",err); ++ return err; ++ } ++ if (gethostname(localhost, sizeof localhost)) { ++ rprintf(FINFO, "Could not get hostname: %s\n", strerror(errno)); ++ return err; ++ } ++ memset(&aih, 0, sizeof aih); ++ aih.ai_family = PF_UNSPEC; ++ aih.ai_flags = AI_CANONNAME; ++ if (0 != (err = getaddrinfo(localhost, 0, &aih, &ai)) || !ai) { ++ rprintf(FINFO, "Could not resolve hostname: %s\n", gai_strerror(err)); ++ return err; ++ } ++ /* Register each service with SLP */ ++ for (i = 0; i < n; i++) { ++ if (!lp_list(i)) ++ continue; ++ ++ snprintf(srv, sizeof srv, "service:rsync://%s:%d/%s", ++ ai->ai_canonname, ++ rsync_port, ++ lp_name(i)); ++ rprintf(FINFO, " %s\n", srv); ++ if (lp_comment(i)) { ++ snprintf(attr, sizeof attr, "(comment=%s)", ++ lp_comment(i)); ++ } ++ err = SLPReg(hslp, ++ srv, /* service to register */ ++ timeout, ++ 0, /* this is ignored */ ++ attr, /* attributes */ ++ SLP_TRUE, /* new registration - don't change this */ ++ slp_callback, /* callback */ ++ &callbackerr); ++ ++ /* err may contain an error code that occurred as the slp library ++ * _prepared_ to make the call. */ ++ if (err != SLP_OK || callbackerr != SLP_OK) ++ rprintf(FINFO, "Error registering service with slp %i\n", err); ++ ++ /* callbackerr may contain an error code (that was assigned through ++ * the callback cookie) that occurred as slp packets were sent on ++ * the wire. */ ++ if (callbackerr != SLP_OK) ++ rprintf(FINFO, "Error registering service with slp %i\n",callbackerr); ++ } ++ ++ /* Now that we're done using slp, close the slp handle */ ++ freeaddrinfo(ai); ++ SLPClose(hslp); ++ ++ /* refresh is done in main select loop */ ++ return 0; ++} +diff --git a/usage.c b/usage.c +--- a/usage.c ++++ b/usage.c +@@ -137,6 +137,11 @@ static void print_info_flags(enum logcode f) + #endif + "crtimes", + ++#ifndef HAVE_LIBSLP ++ "no " ++#endif ++ "SLP", ++ + "*Optimizations", + + #ifndef USE_ROLL_SIMD diff --git a/rsync-3.2.5.tar.gz b/rsync-3.2.5.tar.gz new file mode 100644 index 0000000..e8d7eb5 --- /dev/null +++ b/rsync-3.2.5.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ac4d21635cdf791867bc377c35ca6dda7f50d919a58be45057fd51600c69aba +size 1129957 diff --git a/rsync-3.2.5.tar.gz.asc b/rsync-3.2.5.tar.gz.asc new file mode 100644 index 0000000..e015380 --- /dev/null +++ b/rsync-3.2.5.tar.gz.asc @@ -0,0 +1,6 @@ +-----BEGIN PGP SIGNATURE----- + +iF0EABECAB0WIQQASMiwJtTJbw5YnC9shZ+xS5aoxQUCYvlODgAKCRBshZ+xS5ao +xT3cAKC07We0q6kVJHbFJ53XkC7a+vE41gCguSxuuVS2LJPmwpZRxAEp6bH84vY= +=IsqH +-----END PGP SIGNATURE----- diff --git a/rsync-CVE-2022-29154.patch b/rsync-CVE-2022-29154.patch deleted file mode 100644 index 07fdbda..0000000 --- a/rsync-CVE-2022-29154.patch +++ /dev/null @@ -1,399 +0,0 @@ -From b7231c7d02cfb65d291af74ff66e7d8c507ee871 Mon Sep 17 00:00:00 2001 -From: Wayne Davison -Date: Sun, 31 Jul 2022 16:55:34 -0700 -Subject: [PATCH] Some extra file-list safety checks. - ---- - exclude.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++- - flist.c | 17 ++++++- - io.c | 4 ++ - main.c | 7 ++- - receiver.c | 11 +++-- - rsync.1.md | 44 ++++++++++++++++-- - 6 files changed, 202 insertions(+), 11 deletions(-) - -Index: rsync-3.2.4/exclude.c -=================================================================== ---- rsync-3.2.4.orig/exclude.c -+++ rsync-3.2.4/exclude.c -@@ -27,16 +27,22 @@ extern int am_server; - extern int am_sender; - extern int eol_nulls; - extern int io_error; -+extern int xfer_dirs; -+extern int recurse; - extern int local_server; - extern int prune_empty_dirs; - extern int ignore_perishable; -+extern int old_style_args; -+extern int relative_paths; - extern int delete_mode; - extern int delete_excluded; - extern int cvs_exclude; - extern int sanitize_paths; - extern int protocol_version; -+extern int list_only; - extern int module_id; - -+extern char *filesfrom_host; - extern char curr_dir[MAXPATHLEN]; - extern unsigned int curr_dir_len; - extern unsigned int module_dirlen; -@@ -44,8 +50,10 @@ extern unsigned int module_dirlen; - filter_rule_list filter_list = { .debug_type = "" }; - filter_rule_list cvs_filter_list = { .debug_type = " [global CVS]" }; - filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" }; -+filter_rule_list implied_filter_list = { .debug_type = " [implied]" }; - - int saw_xattr_filter = 0; -+int trust_sender_filter = 0; - - /* Need room enough for ":MODS " prefix plus some room to grow. */ - #define MAX_RULE_PREFIX (16) -@@ -292,6 +300,125 @@ static void add_rule(filter_rule_list *l - } - } - -+/* Each arg the client sends to the remote sender turns into an implied include -+ * that the receiver uses to validate the file list from the sender. */ -+void add_implied_include(const char *arg) -+{ -+ filter_rule *rule; -+ int arg_len, saw_wild = 0, backslash_cnt = 0; -+ int slash_cnt = 1; /* We know we're adding a leading slash. */ -+ const char *cp; -+ char *p; -+ if (old_style_args || list_only || filesfrom_host != NULL) -+ return; -+ if (relative_paths) { -+ cp = strstr(arg, "/./"); -+ if (cp) -+ arg = cp+3; -+ } else { -+ if ((cp = strrchr(arg, '/')) != NULL) -+ arg = cp + 1; -+ } -+ arg_len = strlen(arg); -+ if (arg_len) { -+ if (strpbrk(arg, "*[?")) { -+ /* We need to add room to escape backslashes if wildcard chars are present. */ -+ cp = arg; -+ while ((cp = strchr(cp, '\\')) != NULL) { -+ arg_len++; -+ cp++; -+ } -+ saw_wild = 1; -+ } -+ arg_len++; /* Leave room for the prefixed slash */ -+ rule = new0(filter_rule); -+ if (!implied_filter_list.head) -+ implied_filter_list.head = implied_filter_list.tail = rule; -+ else { -+ rule->next = implied_filter_list.head; -+ implied_filter_list.head = rule; -+ } -+ rule->rflags = FILTRULE_INCLUDE + (saw_wild ? FILTRULE_WILD : 0); -+ p = rule->pattern = new_array(char, arg_len + 1); -+ *p++ = '/'; -+ cp = arg; -+ while (*cp) { -+ switch (*cp) { -+ case '\\': -+ backslash_cnt++; -+ if (saw_wild) -+ *p++ = '\\'; -+ *p++ = *cp++; -+ break; -+ case '/': -+ if (p[-1] == '/') /* This is safe because of the initial slash. */ -+ break; -+ if (relative_paths) { -+ filter_rule const *ent; -+ int found = 0; -+ *p = '\0'; -+ for (ent = implied_filter_list.head; ent; ent = ent->next) { -+ if (ent != rule && strcmp(ent->pattern, rule->pattern) == 0) -+ found = 1; -+ } -+ if (!found) { -+ filter_rule *R_rule = new0(filter_rule); -+ R_rule->rflags = FILTRULE_INCLUDE + (saw_wild ? FILTRULE_WILD : 0); -+ R_rule->pattern = strdup(rule->pattern); -+ R_rule->u.slash_cnt = slash_cnt; -+ R_rule->next = implied_filter_list.head; -+ implied_filter_list.head = R_rule; -+ } -+ } -+ slash_cnt++; -+ *p++ = *cp++; -+ break; -+ default: -+ *p++ = *cp++; -+ break; -+ } -+ } -+ *p = '\0'; -+ rule->u.slash_cnt = slash_cnt; -+ arg = (const char *)rule->pattern; -+ } -+ -+ if (recurse || xfer_dirs) { -+ /* Now create a rule with an added "/" & "**" or "*" at the end */ -+ rule = new0(filter_rule); -+ if (recurse) -+ rule->rflags = FILTRULE_INCLUDE | FILTRULE_WILD | FILTRULE_WILD2; -+ else -+ rule->rflags = FILTRULE_INCLUDE | FILTRULE_WILD; -+ /* A +4 in the len leaves enough room for / * * \0 or / * \0 \0 */ -+ if (!saw_wild && backslash_cnt) { -+ /* We are appending a wildcard, so now the backslashes need to be escaped. */ -+ p = rule->pattern = new_array(char, arg_len + backslash_cnt + 3 + 1); -+ cp = arg; -+ while (*cp) { -+ if (*cp == '\\') -+ *p++ = '\\'; -+ *p++ = *cp++; -+ } -+ } else { -+ p = rule->pattern = new_array(char, arg_len + 3 + 1); -+ if (arg_len) { -+ memcpy(p, arg, arg_len); -+ p += arg_len; -+ } -+ } -+ if (p[-1] != '/') -+ *p++ = '/'; -+ *p++ = '*'; -+ if (recurse) -+ *p++ = '*'; -+ *p = '\0'; -+ rule->u.slash_cnt = slash_cnt + 1; -+ rule->next = implied_filter_list.head; -+ implied_filter_list.head = rule; -+ } -+} -+ - /* This frees any non-inherited items, leaving just inherited items on the list. */ - static void pop_filter_list(filter_rule_list *listp) - { -@@ -718,7 +845,7 @@ static void report_filter_result(enum lo - : name_flags & NAME_IS_DIR ? "directory" - : "file"; - rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n", -- w, actions[*w!='s'][!(ent->rflags & FILTRULE_INCLUDE)], -+ w, actions[*w=='g'][!(ent->rflags & FILTRULE_INCLUDE)], - t, name, ent->pattern, - ent->rflags & FILTRULE_DIRECTORY ? "/" : "", type); - } -@@ -890,6 +1017,7 @@ static filter_rule *parse_rule_tok(const - } - switch (ch) { - case ':': -+ trust_sender_filter = 1; - rule->rflags |= FILTRULE_PERDIR_MERGE - | FILTRULE_FINISH_SETUP; - /* FALL THROUGH */ -Index: rsync-3.2.4/flist.c -=================================================================== ---- rsync-3.2.4.orig/flist.c -+++ rsync-3.2.4/flist.c -@@ -73,6 +73,7 @@ extern int need_unsorted_flist; - extern int sender_symlink_iconv; - extern int output_needs_newline; - extern int sender_keeps_checksum; -+extern int trust_sender_filter; - extern int unsort_ndx; - extern uid_t our_uid; - extern struct stats stats; -@@ -83,8 +84,7 @@ extern char curr_dir[MAXPATHLEN]; - - extern struct chmod_mode_struct *chmod_modes; - --extern filter_rule_list filter_list; --extern filter_rule_list daemon_filter_list; -+extern filter_rule_list filter_list, implied_filter_list, daemon_filter_list; - - #ifdef ICONV_OPTION - extern int filesfrom_convert; -@@ -986,6 +986,19 @@ static struct file_struct *recv_file_ent - exit_cleanup(RERR_UNSUPPORTED); - } - -+ if (*thisname != '.' || thisname[1] != '\0') { -+ int filt_flags = S_ISDIR(mode) ? NAME_IS_DIR : NAME_IS_FILE; -+ if (!trust_sender_filter /* a per-dir filter rule means we must trust the sender's filtering */ -+ && filter_list.head && check_filter(&filter_list, FINFO, thisname, filt_flags) < 0) { -+ rprintf(FERROR, "ERROR: rejecting excluded file-list name: %s\n", thisname); -+ exit_cleanup(RERR_PROTOCOL); -+ } -+ if (implied_filter_list.head && check_filter(&implied_filter_list, FINFO, thisname, filt_flags) <= 0) { -+ rprintf(FERROR, "ERROR: rejecting unrequested file-list name: %s\n", thisname); -+ exit_cleanup(RERR_PROTOCOL); -+ } -+ } -+ - if (inc_recurse && S_ISDIR(mode)) { - if (one_file_system) { - /* Room to save the dir's device for -x */ -Index: rsync-3.2.4/io.c -=================================================================== ---- rsync-3.2.4.orig/io.c -+++ rsync-3.2.4/io.c -@@ -419,6 +419,7 @@ static void forward_filesfrom_data(void) - while (s != eob) { - if (*s++ == '\0') { - ff_xb.len = s - sob - 1; -+ add_implied_include(sob); - if (iconvbufs(ic_send, &ff_xb, &iobuf.out, flags) < 0) - exit_cleanup(RERR_PROTOCOL); /* impossible? */ - write_buf(iobuf.out_fd, s-1, 1); /* Send the '\0'. */ -@@ -450,9 +451,12 @@ static void forward_filesfrom_data(void) - char *f = ff_xb.buf + ff_xb.pos; - char *t = ff_xb.buf; - char *eob = f + len; -+ char *cur = t; - /* Eliminate any multi-'\0' runs. */ - while (f != eob) { - if (!(*t++ = *f++)) { -+ add_implied_include(cur); -+ cur = t; - while (f != eob && *f == '\0') - f++; - } -Index: rsync-3.2.4/main.c -=================================================================== ---- rsync-3.2.4.orig/main.c -+++ rsync-3.2.4/main.c -@@ -89,6 +89,7 @@ extern int backup_dir_len; - extern int basis_dir_cnt; - extern int default_af_hint; - extern int stdout_format_has_i; -+extern int trust_sender_filter; - extern struct stats stats; - extern char *stdout_format; - extern char *logfile_format; -@@ -104,7 +105,7 @@ extern char curr_dir[MAXPATHLEN]; - extern char backup_dir_buf[MAXPATHLEN]; - extern char *basis_dir[MAX_BASIS_DIRS+1]; - extern struct file_list *first_flist; --extern filter_rule_list daemon_filter_list; -+extern filter_rule_list daemon_filter_list, implied_filter_list; - - uid_t our_uid; - gid_t our_gid; -@@ -635,6 +636,7 @@ static pid_t do_cmd(char *cmd, char *mac - #ifdef ICONV_CONST - setup_iconv(); - #endif -+ trust_sender_filter = 1; - } else if (local_server) { - /* If the user didn't request --[no-]whole-file, force - * it on, but only if we're not batch processing. */ -@@ -1516,6 +1518,8 @@ static int start_client(int argc, char * - char *dummy_host; - int dummy_port = rsync_port; - int i; -+ if (filesfrom_fd < 0) -+ add_implied_include(remote_argv[0]); - /* For remote source, any extra source args must have either - * the same hostname or an empty hostname. */ - for (i = 1; i < remote_argc; i++) { -@@ -1539,6 +1543,7 @@ static int start_client(int argc, char * - if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */ - arg = "."; - remote_argv[i] = arg; -+ add_implied_include(arg); - } - } - -Index: rsync-3.2.4/receiver.c -=================================================================== ---- rsync-3.2.4.orig/receiver.c -+++ rsync-3.2.4/receiver.c -@@ -593,10 +593,13 @@ int recv_files(int f_in, int f_out, char - if (DEBUG_GTE(RECV, 1)) - rprintf(FINFO, "recv_files(%s)\n", fname); - -- if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0') -- && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) { -- rprintf(FERROR, "attempt to hack rsync failed.\n"); -- exit_cleanup(RERR_PROTOCOL); -+ if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0')) { -+ int filt_flags = S_ISDIR(file->mode) ? NAME_IS_DIR : NAME_IS_FILE; -+ if (check_filter(&daemon_filter_list, FLOG, fname, filt_flags) < 0) { -+ rprintf(FERROR, "ERROR: rejecting file transfer request for daemon excluded file: %s\n", -+ fname); -+ exit_cleanup(RERR_PROTOCOL); -+ } - } - - #ifdef SUPPORT_XATTRS -Index: rsync-3.2.4/rsync.1.md -=================================================================== ---- rsync-3.2.4.orig/rsync.1.md -+++ rsync-3.2.4/rsync.1.md -@@ -308,6 +308,35 @@ separate the files into different rsync - [`--delay-updates`](#opt) (which doesn't affect the sorted transfer order, but - does make the final file-updating phase happen much more rapidly). - -+## MULTI-HOST SECURITY -+ -+Rsync takes steps to ensure that the file requests that are shared in a -+transfer are protected against various security issues. Most of the potential -+problems arise on the receiving side where rsync takes steps to ensure that the -+list of files being transferred remains within the bounds of what was -+requested. -+ -+Toward this end, rsync 3.1.2 and later have aborted when a file list contains -+an absolute or relative path that tries to escape out of the top of the -+transfer. Also, beginning with version 3.2.5 (or a version patched against -+CVE-2022-29154), rsync does two more safety checks of the file list to (1) -+ensure that no extra source arguments were added into the transfer other than -+those that the client requested and (2) ensure that the file list obeys the -+exclude rules that we sent to the sender. -+ -+For those that don't yet have a 3.2.5 (or a version patched against -+CVE-2022-29154) client rsync, it is safest to do a copy into a dedicated -+destination directory for the remote files rather than requesting the remote -+content get mixed in with other local content. For example, doing an rsync copy -+into your home directory is potentially unsafe on an older rsync if the remote -+rsync is being controlled by a bad actor: -+ -+> rsync -aiv host1:dir1 ~ -+ -+A safer command would be: -+ -+> rsync -aiv host1:dir1 ~/host1-files -+ - ## EXAMPLES - - Here are some examples of how I use rsync. -@@ -2335,6 +2364,12 @@ your home directory (remove the '=' for - behavior. The environment is always overridden by manually specified - positive or negative options (the negative is `--no-old-args`). - -+ Note that this option also disables the extra safety check added in 3.2.5 -+ (or a version patched against CVE-2022-29154) that ensures that a remote -+ sender isn't including extra top-level items in the file-list that you -+ didn't request. This side-effect is necessary because we can't know for -+ sure what names to expect when the remote shell is interpreting the args. -+ - This option conflicts with the [`--protect-args`](#opt) option. - - 0. `--protect-args`, `-s` -@@ -3766,8 +3801,13 @@ available rule prefixes: - - 0. `exclude, '-'` specifies an exclude pattern. - 0. `include, '+'` specifies an include pattern. --0. `merge, '.'` specifies a merge-file to read for more rules. --0. `dir-merge, ':'` specifies a per-directory merge-file. -+0. `merge, '.'` specifies a merge-file on the client side to read for more -+ rules. -+0. `dir-merge, ':'` specifies a per-directory merge-file. Using this kind of -+ filter rule requires that you trust the sending side's filter checking, and -+ thus it disables the receiver's verification of the file-list names against -+ the filter rules (since only the sender can know for sure if it obeyed all -+ the filter rules when some are per-dir merged from the sender's files). - 0. `hide, 'H'` specifies a pattern for hiding files from the transfer. - 0. `show, 'S'` files that match the pattern are not hidden. - 0. `protect, 'P'` specifies a pattern for protecting files from deletion. diff --git a/rsync-patches-3.2.4.tar.gz b/rsync-patches-3.2.4.tar.gz deleted file mode 100644 index 9ad441d..0000000 --- a/rsync-patches-3.2.4.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:70a597590af6c61cf3d05d663429ff9f60ffe24e44f9c73a4cdc69ebdc1322a4 -size 133580 diff --git a/rsync-patches-3.2.4.tar.gz.asc b/rsync-patches-3.2.4.tar.gz.asc deleted file mode 100644 index 528112d..0000000 --- a/rsync-patches-3.2.4.tar.gz.asc +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iF0EABECAB0WIQQASMiwJtTJbw5YnC9shZ+xS5aoxQUCYlnXXQAKCRBshZ+xS5ao -xa40AJ9nhXAe+WGpq+hCo6D9TGPNDmKsWwCfR5dNecRPJBCsiffMAJXQUr7Mfg0= -=jE+s ------END PGP SIGNATURE----- diff --git a/rsync-patches-3.2.5.tar.gz b/rsync-patches-3.2.5.tar.gz new file mode 100644 index 0000000..fbfff84 --- /dev/null +++ b/rsync-patches-3.2.5.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7b1fdf1fc0fca68fd254246c2dc04f6ac90241e665dcf9dfc21dccd8270b6bb +size 141521 diff --git a/rsync-patches-3.2.5.tar.gz.asc b/rsync-patches-3.2.5.tar.gz.asc new file mode 100644 index 0000000..ca54873 --- /dev/null +++ b/rsync-patches-3.2.5.tar.gz.asc @@ -0,0 +1,6 @@ +-----BEGIN PGP SIGNATURE----- + +iF0EABECAB0WIQQASMiwJtTJbw5YnC9shZ+xS5aoxQUCYvkwjgAKCRBshZ+xS5ao +xWAMAKC8sGretqzHSgTCOW8eCO/pFwh5DQCeJTD+07rzAvXt3HnJKvor9D3/jF4= +=UjDZ +-----END PGP SIGNATURE----- diff --git a/rsync.changes b/rsync.changes index cef069f..6bf7837 100644 --- a/rsync.changes +++ b/rsync.changes @@ -1,9 +1,56 @@ +------------------------------------------------------------------- +Tue Aug 16 08:19:20 UTC 2022 - David Anes + +- Add upstream patch rsync-3.2.5-slp.patch, as the one included in + the released tarball doesn't fully apply. + +- Drop patch rsync-CVE-2022-29154.patch, already included upstream. + +- Update to 3.2.5 + * SECURITY FIXES: + - Added some file-list safety checking that helps to ensure that a rogue + sending rsync can't add unrequested top-level names and/or include recursive + names that should have been excluded by the sender. These extra safety + checks only require the receiver rsync to be updated. When dealing with an + untrusted sending host, it is safest to copy into a dedicated destination + directory for the remote content (i.e. don't copy into a destination + directory that contains files that aren't from the remote host unless you + trust the remote host). Fixes CVE-2022-29154. + - A fix for CVE-2022-37434 in the bundled zlib (buffer overflow issue). + * BUG FIXES: + - Fixed the handling of filenames specified with backslash-quoted wildcards + when the default remote-arg-escaping is enabled. + - Fixed the configure check for signed char that was causing a host that + defaults to unsigned characters to generate bogus rolling checksums. This + made rsync send mostly literal data for a copy instead of finding matching + data in the receiver's basis file (for a file that contains high-bit + characters). + - Lots of manpage improvements, including an attempt to better describe how + include/exclude filters work. + - If rsync is compiled with an xxhash 0.8 library and then moved to a system + with a dynamically linked xxhash 0.7 library, we now detect this and disable + the XX3 hashes (since these routines didn't stabilize until 0.8). + * ENHANCEMENTS: + - The [`--trust-sender`](rsync.1#opt) option was added as a way to bypass the + extra file-list safety checking (should that be required). + * PACKAGING RELATED: + - A note to those wanting to patch older rsync versions: the changes in this + release requires the quoted argument change from 3.2.4. Then, you'll want + every single code change from 3.2.5 since there is no fluff in this release. + - The build date that goes into the manpages is now based on the developer's + release date, not on the build's local-timezone interpretation of the date. + * DEVELOPER RELATED: + - Configure now defaults GETGROUPS_T to gid_t when cross compiling. + - Configure now looks for the bsd/string.h include file in order to fix the + build on a host that has strlcpy() in the main libc but not defined in the + main string.h file. + ------------------------------------------------------------------- Mon Aug 1 12:27:43 UTC 2022 - David Anes - Security fix: [bsc#1201840, CVE-2022-29154] * arbitrary file write vulnerability via do_server_recv function - * Added patch rsync-rsync-CVE-2022-29154.patch + * Added patch rsync-CVE-2022-29154.patch ------------------------------------------------------------------- Tue Jun 21 10:34:12 UTC 2022 - Stefan Schubert diff --git a/rsync.spec b/rsync.spec index 9067d1c..4a679d5 100644 --- a/rsync.spec +++ b/rsync.spec @@ -23,7 +23,7 @@ %endif Name: rsync -Version: 3.2.4 +Version: 3.2.5 Release: 0 Summary: Versatile tool for fast incremental file transfer License: GPL-3.0-or-later @@ -41,8 +41,11 @@ Source9: rsyncd@.service Source10: http://rsync.samba.org/ftp/rsync/src/rsync-%{version}.tar.gz.asc Source11: http://rsync.samba.org/ftp/rsync/src/rsync-patches-%{version}.tar.gz.asc Source12: %{name}.keyring +# PATCH-FIX-UPSTREAM: slp.diff included in distribution tar file does not apply +# cleanly, therefore we use the upstream patch directly (for 3.2.5) +Source13: https://raw.githubusercontent.com/WayneD/rsync-patches/d899304ea5daa125417f296bdd6f8bff0ed342ca/slp.diff#:/rsync-3.2.5-slp.patch Patch0: rsync-no-libattr.patch -Patch1: rsync-CVE-2022-29154.patch +Patch1: rsync-3.2.5-slp.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: c++_compiler @@ -76,7 +79,11 @@ for backups and mirroring and as an improved copy command for everyday use. %setup -q -b 1 rm -f zlib/*.h -patch -p1 < patches/slp.diff +# TODO: (See Source13/Patch1) we have to re-enable the patching of SLP using +# the patch included in the distributed tar file for next version, for now +# we apply latest upstream patch (for 3.2.5) from Github, the one included +# in tar fiel desn't apply cleanly +# patch -p1 < patches/slp.diff %autopatch -p1