From 5940497a19d7d028cb6e39a594c0d5106cf15c88 Mon Sep 17 00:00:00 2001 From: Jacob Wang Date: Tue, 3 Jun 2025 14:48:01 +0800 Subject: [PATCH 1/3] [CVE]update to rsync-3.1.3-23 to #ICC5YK update to rsync-3.1.3-23 for CVE-2016-9840 Project: TC2024080204 Signed-off-by: Jacob Wang --- 1000-rsync-lchmod.patch | 53 -------- rsync-3.1.3-cve-2025-4638.patch | 54 ++++++++ rsync-3.1.3-trust-sender.patch | 218 ++++++++++++++++++++++++++++++++ rsync.spec | 35 ++--- 4 files changed, 284 insertions(+), 76 deletions(-) delete mode 100644 1000-rsync-lchmod.patch create mode 100644 rsync-3.1.3-cve-2025-4638.patch create mode 100644 rsync-3.1.3-trust-sender.patch diff --git a/1000-rsync-lchmod.patch b/1000-rsync-lchmod.patch deleted file mode 100644 index 813c6b5..0000000 --- a/1000-rsync-lchmod.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/syscall.c b/syscall.c -index b9c3b4ef..11d10e4a 100644 ---- a/syscall.c -+++ b/syscall.c -@@ -227,27 +227,35 @@ int do_open(const char *pathname, int flags, mode_t mode) - #ifdef HAVE_CHMOD - int do_chmod(const char *path, mode_t mode) - { -+ static int switch_step = 0; - int code; - if (dry_run) return 0; - RETURN_ERROR_IF_RO_OR_LO; -+ switch (switch_step) { - #ifdef HAVE_LCHMOD -- code = lchmod(path, mode & CHMOD_BITS); --#else -- if (S_ISLNK(mode)) { -+#include "case_N.h" -+ if ((code = lchmod(path, mode & CHMOD_BITS)) == 0 || errno != ENOTSUP) -+ break; -+ switch_step++; -+#endif -+ -+#include "case_N.h" -+ if (S_ISLNK(mode)) { - # if defined HAVE_SETATTRLIST -- struct attrlist attrList; -- uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */ -+ struct attrlist attrList; -+ uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */ - -- memset(&attrList, 0, sizeof attrList); -- attrList.bitmapcount = ATTR_BIT_MAP_COUNT; -- attrList.commonattr = ATTR_CMN_ACCESSMASK; -- code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW); -+ memset(&attrList, 0, sizeof attrList); -+ attrList.bitmapcount = ATTR_BIT_MAP_COUNT; -+ attrList.commonattr = ATTR_CMN_ACCESSMASK; -+ code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW); - # else -- code = 1; -+ code = 1; - # endif -- } else -- code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ --#endif /* !HAVE_LCHMOD */ -+ } else -+ code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ -+ break; -+ } - if (code != 0 && (preserve_perms || preserve_executability)) - return code; - return 0; diff --git a/rsync-3.1.3-cve-2025-4638.patch b/rsync-3.1.3-cve-2025-4638.patch new file mode 100644 index 0000000..3c4220f --- /dev/null +++ b/rsync-3.1.3-cve-2025-4638.patch @@ -0,0 +1,54 @@ +diff --git a/zlib/inftrees.c b/zlib/inftrees.c +index 44d89cf2..571e8100 100644 +--- a/zlib/inftrees.c ++++ b/zlib/inftrees.c +@@ -54,7 +54,7 @@ unsigned short FAR *work; + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ +- int end; /* use base and extra for symbol > end */ ++ unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ +@@ -181,19 +181,17 @@ unsigned short FAR *work; + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ +- end = 19; ++ match = 20; + break; + case LENS: + base = lbase; +- base -= 257; + extra = lext; +- extra -= 257; +- end = 256; ++ match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; +- end = -1; ++ match = 0; + } + + /* initialize state for loop */ +@@ -216,13 +214,13 @@ unsigned short FAR *work; + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); +- if ((int)(work[sym]) < end) { ++ if (work[sym] + 1u < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } +- else if ((int)(work[sym]) > end) { +- here.op = (unsigned char)(extra[work[sym]]); +- here.val = base[work[sym]]; ++ else if (work[sym] >= match) { ++ here.op = (unsigned char)(extra[work[sym] - match]); ++ here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ diff --git a/rsync-3.1.3-trust-sender.patch b/rsync-3.1.3-trust-sender.patch new file mode 100644 index 0000000..0616272 --- /dev/null +++ b/rsync-3.1.3-trust-sender.patch @@ -0,0 +1,218 @@ +diff --git a/exclude.c b/exclude.c +index d36a105e..da25661b 100644 +--- a/exclude.c ++++ b/exclude.c +@@ -33,18 +33,15 @@ 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 read_batch; +-extern int list_only; ++extern int trust_sender_args; + extern int module_id; + +-extern char *filesfrom_host; + extern char curr_dir[MAXPATHLEN]; + extern unsigned int curr_dir_len; + extern unsigned int module_dirlen; +@@ -55,6 +52,7 @@ 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_args = 0; + int trust_sender_filter = 0; + + /* Need room enough for ":MODS " prefix plus some room to grow. */ +@@ -377,7 +375,7 @@ void add_implied_include(const char *arg, int skip_daemon_module) + int slash_cnt = 0; + const char *cp; + char *p; +- if (am_server || old_style_args || list_only || read_batch || filesfrom_host != NULL) ++ if (trust_sender_args) + return; + if (partial_string_len) { + arg_len = strlen(arg); +diff --git a/main.c b/main.c +index 6721ceb7..9ebfbea7 100644 +--- a/main.c ++++ b/main.c +@@ -89,7 +89,6 @@ extern int backup_dir_len; + extern BOOL shutting_down; + extern int backup_dir_len; + extern int basis_dir_cnt; +-extern int trust_sender_filter; + extern struct stats stats; + extern char *stdout_format; + extern char *logfile_format; +@@ -636,7 +635,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in + #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. */ +diff --git a/options.c b/options.c +index e7a9fcae..4feeb7e0 100644 +--- a/options.c ++++ b/options.c +@@ -27,6 +27,8 @@ + extern int local_server; + extern int sanitize_paths; + extern int daemon_over_rsh; ++extern int trust_sender_args; ++extern int trust_sender_filter; + extern unsigned int module_dirlen; + extern filter_rule_list filter_list; + extern filter_rule_list daemon_filter_list; +@@ -64,6 +66,7 @@ int preserve_atimes = 0; + static int daemon_opt; /* sets am_daemon after option error-reporting */ + static int omit_dir_times = 0; + static int omit_link_times = 0; ++int trust_sender = 0; + static int F_option_cnt = 0; + static int modify_window_set; + static int itemize_changes = 0; +@@ -788,6 +791,7 @@ static struct poptOption long_options[] = { + {"protect-args", 's', POPT_ARG_VAL, &protect_args, 1, 0, 0}, + {"no-protect-args", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0}, + {"no-s", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0}, ++ {"trust-sender", 0, POPT_ARG_VAL, &trust_sender, 1, 0, 0}, + {"numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 1, 0, 0 }, + {"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 }, + {"usermap", 0, POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 }, +@@ -2465,6 +2469,11 @@ int parse_arguments(int *argc_p, const char ***argv_p) + } + } + ++ if (trust_sender || am_server || read_batch) ++ trust_sender_args = trust_sender_filter = 1; ++ else if (old_style_args || filesfrom_host != NULL) ++ trust_sender_args = 1; ++ + am_starting_up = 0; + + return 1; +@@ -2438,9 +2438,7 @@ char *safe_arg(const char *opt, const char *arg) + char *ret; + if (!protect_args && old_style_args < 2 && (!old_style_args || (!is_filename_arg && opt != SPLIT_ARG_WHEN_OLD))) { + const char *f; +- if (!old_style_args && *arg == '~' +- && ((relative_paths && !strstr(arg, "/./")) +- || !strchr(arg, '/'))) { ++ if (!trust_sender_args && *arg == '~' && (relative_paths || !strchr(arg, '/'))) { + extras++; + escape_leading_tilde = 1; + } +diff --git a/rsync.1.old b/rsync.1 +index 839f5ad..6882cf5 100644 +--- a/rsync.1.old ++++ b/rsync.1 +@@ -182,9 +182,39 @@ particular rsync daemon by leaving off the module name: + \f(CWrsync somehost.mydomain.com::\fP + .RE + +-.PP +-See the following section for more details. +-.PP ++.SH "MULTI-HOST SECURITY" ++ ++.PP ++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. ++.PP ++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, 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. ++.PP ++For those that don't yet have a 3.2.5 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: ++.PP ++.RS ++\f(CWrsync \-aiv host:dir1 ~\fP ++.RE ++.PP ++A safer command would be: ++.RS ++\f(CWrsync \-aiv host:dir1 ~/host-files\fP ++.RE ++.PP ++See the \fB\-\-trust\-sender\fP option for additional details. ++ + .SH "ADVANCED USAGE" + + .PP +@@ -519,6 +549,7 @@ to the detailed description below for a complete description. + \-0, \-\-from0 all *from/filter files are delimited by 0s + \-\-old\-args disable the modern arg-protection idiom + \-s, \-\-protect\-args no space\-splitting; wildcard chars only ++ \-\-trust\-sender trust the remote sender's file list + \-\-address=ADDRESS bind address for outgoing socket to daemon + \-\-port=PORT specify double\-colon alternate port number + \-\-sockopts=OPTIONS specify custom TCP options +@@ -2119,6 +2150,49 @@ This option conflicts with the \fB\-\-old\-args\fP option. + Note that this option is incompatible with the use of the restricted rsync + script (`rrsync`) since it hides options from the script's inspection. + .IP ++.IP "\fB\-\-trust\-sender\fP" ++This option disables two extra validation checks that a local client ++performs on the file list generated by a remote sender. This option should ++only be used if you trust the sender to not put something malicious in the ++file list (something that could possibly be done via a modified rsync, a ++modified shell, or some other similar manipulation). ++.IP ++Normally, the rsync client (as of version 3.2.5) runs two extra validation ++checks when pulling files from a remote rsync: ++.RS ++.IP o ++It verifies that additional arg items didn't get added at the top of the ++transfer. ++.IP o ++It verifies that none of the items in the file list are names that should ++have been excluded (if filter rules were specified). ++.RE ++.IP ++Note that various options can turn off one or both of these checks if the ++option interferes with the validation. For instance: ++.RS ++.IP o ++Using a per-directory filter file reads filter rules that only the server ++knows about, so the filter checking is disabled. ++.IP o ++Using the \fB\-\-old\-args\fP option allows the sender to manipulate the ++requested args, so the arg checking is disabled. ++.IP o ++Reading the files-from list from the server side means that the client ++doesn't know the arg list, so the arg checking is disabled. ++.IP o ++Using \fB\-\-read\-batch\fP disables both checks since the batch file's ++contents will have been verified when it was created. ++.RE ++.IP ++This option may help an under-powered client server if the extra pattern ++matching is slowing things down on a huge transfer. It can also be used ++work around a currently-unknown bug in the verification logic for a transfer ++from a trusted sender. ++.IP ++When using this option it is a good idea to specify a dedicated destination ++directory, as discussed in the \(dq\&MULTI-HOST SECURITY\(dq\& section. ++.IP + .IP "\fB\-T, \-\-temp\-dir=DIR\fP" + This option instructs rsync to use DIR as a + scratch directory when creating temporary copies of the files transferred diff --git a/rsync.spec b/rsync.spec index 3431d89..ea9b51c 100644 --- a/rsync.spec +++ b/rsync.spec @@ -1,4 +1,3 @@ -%define anolis_release .0.1 %global _hardened_build 1 %define isprerelease 0 @@ -10,7 +9,7 @@ Summary: A program for synchronizing files over a network Name: rsync Version: 3.1.3 -Release: 21%{anolis_release}%{?dist} +Release: 23%{?dist} Group: Applications/Internet URL: http://rsync.samba.org/ @@ -28,9 +27,6 @@ BuildRequires: libacl-devel, libattr-devel, autoconf, popt-devel, systemd Provides: bundled(zlib) = 1.2.8 License: GPLv3+ -Provides: /usr/bin/rsync -Requires: glibc - Patch0: rsync-man.patch Patch1: rsync-3.0.6-iconv-logging.patch Patch2: rsync-3.1.3-covscan.patch @@ -50,9 +46,9 @@ Patch15: rsync-3.1.3-cve-2024-12085.patch Patch16: rsync-3.1.3-cve-2024-12087.patch Patch17: rsync-3.1.3-cve-2024-12088.patch Patch18: rsync-3.1.3-cve-2024-12747.patch -# https://github.com/WayneD/rsync/commit/9dd62525f3b98d692e031f22c02be8f775966503 -# https://github.com/WayneD/rsync/issues/109 -Patch1000: 1000-rsync-lchmod.patch +# a fix for CVE-2016-9840 in zlib but marked as CVE-2025-4638 for a different component +Patch19: rsync-3.1.3-cve-2025-4638.patch +Patch20: rsync-3.1.3-trust-sender.patch %description Rsync uses a reliable algorithm to bring remote and host files into @@ -72,14 +68,6 @@ Requires: %{name} = %{version}-%{release} Rsync can be used to offer read only access to anonymous clients. This package provides the anonymous rsync service. -%package doc -Summary: Documents for %{name} -BuildArch: noarch -Requires: %{name} = %{version}-%{release} - -%description doc -Doc pages for %{name}. - %prep # TAG: for pre versions use @@ -117,7 +105,8 @@ patch -p1 -i patches/copy-devices.diff %patch16 -p1 -b .cve-2024-12087 %patch17 -p1 -b .cve-2024-12088 %patch18 -p1 -b .cve-2024-12747 -%patch1000 -p1 +%patch19 -p1 -b .cve-2025-4638 +%patch20 -p1 -b .trust-sender %build %configure @@ -142,6 +131,7 @@ chmod -x support/* %files %{!?_licensedir:%global license %%doc} %license COPYING +%doc NEWS OLDNEWS README support/ tech_report.tex %{_bindir}/%{name} %{_mandir}/man1/%{name}.1* @@ -162,13 +152,12 @@ chmod -x support/* %postun daemon %systemd_postun_with_restart rsyncd.service -%files doc -%doc NEWS OLDNEWS README support/ tech_report.tex - %changelog -* Tue Mar 11 2025 Xiaoping Liu - 3.1.3-21.0.1 -- Add doc sub package -- fix rsync lchmod (xuchunmei@linux.alibaba.com) +* Wed May 28 2025 Michal Ruprich - 3.1.3-23 +- Resolves: RHEL-52004 - Slowness in rsync due to extra validation steps + +* Mon May 26 2025 Michal Ruprich - 3.1.3-22 +- Resolves: RHEL-91519 - Improper Pointer Arithmetic in pcl * Tue Feb 04 2025 Michal Ruprich - 3.1.3-21 - Resolves: RHEL-70207 - Path traversal vulnerability in rsync -- Gitee From 2ab75cc61dd388a5626a1d2d51ff623c33c5f950 Mon Sep 17 00:00:00 2001 From: liuxiaoping Date: Sat, 16 Jul 2022 17:10:34 +0800 Subject: [PATCH 2/3] Add doc sub package --- rsync.spec | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/rsync.spec b/rsync.spec index ea9b51c..cac5acf 100644 --- a/rsync.spec +++ b/rsync.spec @@ -1,3 +1,4 @@ +%define anolis_release .0.1 %global _hardened_build 1 %define isprerelease 0 @@ -9,7 +10,7 @@ Summary: A program for synchronizing files over a network Name: rsync Version: 3.1.3 -Release: 23%{?dist} +Release: 23%{anolis_release}%{?dist} Group: Applications/Internet URL: http://rsync.samba.org/ @@ -27,6 +28,9 @@ BuildRequires: libacl-devel, libattr-devel, autoconf, popt-devel, systemd Provides: bundled(zlib) = 1.2.8 License: GPLv3+ +Provides: /usr/bin/rsync +Requires: glibc + Patch0: rsync-man.patch Patch1: rsync-3.0.6-iconv-logging.patch Patch2: rsync-3.1.3-covscan.patch @@ -68,6 +72,14 @@ Requires: %{name} = %{version}-%{release} Rsync can be used to offer read only access to anonymous clients. This package provides the anonymous rsync service. +%package doc +Summary: Documents for %{name} +BuildArch: noarch +Requires: %{name} = %{version}-%{release} + +%description doc +Doc pages for %{name}. + %prep # TAG: for pre versions use @@ -131,7 +143,6 @@ chmod -x support/* %files %{!?_licensedir:%global license %%doc} %license COPYING -%doc NEWS OLDNEWS README support/ tech_report.tex %{_bindir}/%{name} %{_mandir}/man1/%{name}.1* @@ -152,7 +163,13 @@ chmod -x support/* %postun daemon %systemd_postun_with_restart rsyncd.service +%files doc +%doc NEWS OLDNEWS README support/ tech_report.tex + %changelog +* Tue Jun 03 2025 Xiaoping Liu - 3.1.3-23.0.1 +- Add doc sub package + * Wed May 28 2025 Michal Ruprich - 3.1.3-23 - Resolves: RHEL-52004 - Slowness in rsync due to extra validation steps -- Gitee From 66261d99f9b3ae7d1e5214f4cc64ab3e44feece4 Mon Sep 17 00:00:00 2001 From: Chunmei Xu Date: Tue, 2 Apr 2024 17:37:53 +0800 Subject: [PATCH 3/3] fix rsync lchmod Signed-off-by: Chunmei Xu --- 1000-rsync-lchmod.patch | 53 +++++++++++++++++++++++++++++++++++++++++ rsync.spec | 5 ++++ 2 files changed, 58 insertions(+) create mode 100644 1000-rsync-lchmod.patch diff --git a/1000-rsync-lchmod.patch b/1000-rsync-lchmod.patch new file mode 100644 index 0000000..813c6b5 --- /dev/null +++ b/1000-rsync-lchmod.patch @@ -0,0 +1,53 @@ +diff --git a/syscall.c b/syscall.c +index b9c3b4ef..11d10e4a 100644 +--- a/syscall.c ++++ b/syscall.c +@@ -227,27 +227,35 @@ int do_open(const char *pathname, int flags, mode_t mode) + #ifdef HAVE_CHMOD + int do_chmod(const char *path, mode_t mode) + { ++ static int switch_step = 0; + int code; + if (dry_run) return 0; + RETURN_ERROR_IF_RO_OR_LO; ++ switch (switch_step) { + #ifdef HAVE_LCHMOD +- code = lchmod(path, mode & CHMOD_BITS); +-#else +- if (S_ISLNK(mode)) { ++#include "case_N.h" ++ if ((code = lchmod(path, mode & CHMOD_BITS)) == 0 || errno != ENOTSUP) ++ break; ++ switch_step++; ++#endif ++ ++#include "case_N.h" ++ if (S_ISLNK(mode)) { + # if defined HAVE_SETATTRLIST +- struct attrlist attrList; +- uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */ ++ struct attrlist attrList; ++ uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */ + +- memset(&attrList, 0, sizeof attrList); +- attrList.bitmapcount = ATTR_BIT_MAP_COUNT; +- attrList.commonattr = ATTR_CMN_ACCESSMASK; +- code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW); ++ memset(&attrList, 0, sizeof attrList); ++ attrList.bitmapcount = ATTR_BIT_MAP_COUNT; ++ attrList.commonattr = ATTR_CMN_ACCESSMASK; ++ code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW); + # else +- code = 1; ++ code = 1; + # endif +- } else +- code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ +-#endif /* !HAVE_LCHMOD */ ++ } else ++ code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ ++ break; ++ } + if (code != 0 && (preserve_perms || preserve_executability)) + return code; + return 0; diff --git a/rsync.spec b/rsync.spec index cac5acf..c3d5fe8 100644 --- a/rsync.spec +++ b/rsync.spec @@ -53,6 +53,9 @@ Patch18: rsync-3.1.3-cve-2024-12747.patch # a fix for CVE-2016-9840 in zlib but marked as CVE-2025-4638 for a different component Patch19: rsync-3.1.3-cve-2025-4638.patch Patch20: rsync-3.1.3-trust-sender.patch +# https://github.com/WayneD/rsync/commit/9dd62525f3b98d692e031f22c02be8f775966503 +# https://github.com/WayneD/rsync/issues/109 +Patch1000: 1000-rsync-lchmod.patch %description Rsync uses a reliable algorithm to bring remote and host files into @@ -119,6 +122,7 @@ patch -p1 -i patches/copy-devices.diff %patch18 -p1 -b .cve-2024-12747 %patch19 -p1 -b .cve-2025-4638 %patch20 -p1 -b .trust-sender +%patch1000 -p1 %build %configure @@ -169,6 +173,7 @@ chmod -x support/* %changelog * Tue Jun 03 2025 Xiaoping Liu - 3.1.3-23.0.1 - Add doc sub package +- fix rsync lchmod (xuchunmei@linux.alibaba.com) * Wed May 28 2025 Michal Ruprich - 3.1.3-23 - Resolves: RHEL-52004 - Slowness in rsync due to extra validation steps -- Gitee