From 397a2b54335af9c2f495db4d97411a0388d8ac0a Mon Sep 17 00:00:00 2001 From: Zhao Hang Date: Tue, 11 Mar 2025 17:47:47 +0800 Subject: [PATCH 1/3] [CVE]update to rsync-3.1.3-21 to #IBSK1C update to rsync-3.1.3-21 for CVE-2024-12087 CVE-2024-12088 CVE-2024-12747 Project: TC2024080204 Signed-off-by: Zhao Hang --- 1000-rsync-lchmod.patch | 53 ------------ rsync-3.1.3-cve-2024-12087.patch | 36 ++++++++ rsync-3.1.3-cve-2024-12088.patch | 57 +++++++++++++ rsync-3.1.3-cve-2024-12747.patch | 141 +++++++++++++++++++++++++++++++ rsync.spec | 38 +++------ 5 files changed, 248 insertions(+), 77 deletions(-) delete mode 100644 1000-rsync-lchmod.patch create mode 100644 rsync-3.1.3-cve-2024-12087.patch create mode 100644 rsync-3.1.3-cve-2024-12088.patch create mode 100644 rsync-3.1.3-cve-2024-12747.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-2024-12087.patch b/rsync-3.1.3-cve-2024-12087.patch new file mode 100644 index 0000000..187f580 --- /dev/null +++ b/rsync-3.1.3-cve-2024-12087.patch @@ -0,0 +1,36 @@ +diff --git a/flist.c b/flist.c +index 464d556..087f9da 100644 +--- a/flist.c ++++ b/flist.c +@@ -2584,6 +2584,19 @@ struct file_list *recv_file_list(int f, int dir_ndx) + init_hard_links(); + #endif + ++ if (inc_recurse && dir_ndx >= 0) { ++ if (dir_ndx >= dir_flist->used) { ++ rprintf(FERROR_XFER, "rsync: refusing invalid dir_ndx %u >= %u\n", dir_ndx, dir_flist->used); ++ exit_cleanup(RERR_PROTOCOL); ++ } ++ struct file_struct *file = dir_flist->files[dir_ndx]; ++ if (file->flags & FLAG_GOT_DIR_FLIST) { ++ rprintf(FERROR_XFER, "rsync: refusing malicious duplicate flist for dir %d\n", dir_ndx); ++ exit_cleanup(RERR_PROTOCOL); ++ } ++ file->flags |= FLAG_GOT_DIR_FLIST; ++ } ++ + flist = flist_new(0, "recv_file_list"); + + if (inc_recurse) { +diff --git a/rsync.h b/rsync.h +index b357dad..bc9abac 100644 +--- a/rsync.h ++++ b/rsync.h +@@ -83,6 +83,7 @@ + #define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */ + #define FLAG_TIME_FAILED (1<<11)/* generator */ + #define FLAG_MOD_NSEC (1<<12) /* sender/receiver/generator */ ++#define FLAG_GOT_DIR_FLIST (1<<13)/* sender/receiver/generator - dir_flist only */ + + /* These flags are passed to functions but not stored. */ + diff --git a/rsync-3.1.3-cve-2024-12088.patch b/rsync-3.1.3-cve-2024-12088.patch new file mode 100644 index 0000000..412242e --- /dev/null +++ b/rsync-3.1.3-cve-2024-12088.patch @@ -0,0 +1,57 @@ +diff --git a/testsuite/unsafe-byname.test b/testsuite/unsafe-byname.test +index 75e7201..d2e318e 100644 +--- a/testsuite/unsafe-byname.test ++++ b/testsuite/unsafe-byname.test +@@ -40,7 +40,7 @@ test_unsafe ..//../dest from/dir unsafe + test_unsafe .. from/file safe + test_unsafe ../.. from/file unsafe + test_unsafe ..//.. from//file unsafe +-test_unsafe dir/.. from safe ++test_unsafe dir/.. from unsafe + test_unsafe dir/../.. from unsafe + test_unsafe dir/..//.. from unsafe + +diff --git a/util.c b/util.c +index da50ff1..f260d39 100644 +--- a/util.c ++++ b/util.c +@@ -1318,7 +1318,14 @@ int handle_partial_dir(const char *fname, int create) + * + * "src" is the top source directory currently applicable at the level + * of the referenced symlink. This is usually the symlink's full path +- * (including its name), as referenced from the root of the transfer. */ ++ * (including its name), as referenced from the root of the transfer. ++ * ++ * NOTE: this also rejects dest names with a .. component in other ++ * than the first component of the name ie. it rejects names such as ++ * a/b/../x/y. This needs to be done as the leading subpaths 'a' or ++ * 'b' could later be replaced with symlinks such as a link to '.' ++ * resulting in the link being transferred now becoming unsafe ++ */ + int unsafe_symlink(const char *dest, const char *src) + { + const char *name, *slash; +@@ -1328,6 +1335,23 @@ int unsafe_symlink(const char *dest, const char *src) + if (!dest || !*dest || *dest == '/') + return 1; + ++ // reject destinations with /../ in the name other than at the start of the name ++ const char *dest2 = dest; ++ while (strncmp(dest2, "../", 3) == 0) { ++ dest2 += 3; ++ while (*dest2 == '/') { ++ // allow for ..//..///../foo ++ dest2++; ++ } ++ } ++ if (strstr(dest2, "/../")) ++ return 1; ++ ++ // reject if the destination ends in /.. ++ const size_t dlen = strlen(dest); ++ if (dlen > 3 && strcmp(&dest[dlen-3], "/..") == 0) ++ return 1; ++ + /* find out what our safety margin is */ + for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) { + /* ".." segment starts the count over. "." segment is ignored. */ diff --git a/rsync-3.1.3-cve-2024-12747.patch b/rsync-3.1.3-cve-2024-12747.patch new file mode 100644 index 0000000..85bd696 --- /dev/null +++ b/rsync-3.1.3-cve-2024-12747.patch @@ -0,0 +1,141 @@ +diff --git a/checksum.c b/checksum.c +index cb21882..66e8089 100644 +--- a/checksum.c ++++ b/checksum.c +@@ -406,7 +406,7 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum) + + memset(sum, 0, MAX_DIGEST_LEN); + +- fd = do_open(fname, O_RDONLY, 0); ++ fd = do_open_checklinks(fname); + if (fd == -1) + return; + +diff --git a/generator.c b/generator.c +index 110db28..3f13bb9 100644 +--- a/generator.c ++++ b/generator.c +@@ -1867,7 +1867,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, + } + + /* open the file */ +- if ((fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) { ++ if ((fd = do_open_checklinks(fnamecmp)) < 0) { + rsyserr(FERROR, errno, "failed to open %s, continuing", + full_fname(fnamecmp)); + pretend_missing: +diff --git a/receiver.c b/receiver.c +index 8031b8f..edfbb21 100644 +--- a/receiver.c ++++ b/receiver.c +@@ -775,7 +775,7 @@ int recv_files(int f_in, int f_out, char *local_name) + if (fd1 == -1 && protocol_version < 29) { + if (fnamecmp != fname) { + fnamecmp = fname; +- fd1 = do_open(fnamecmp, O_RDONLY, 0); ++ fd1 = do_open_nofollow(fnamecmp, O_RDONLY); + } + + if (fd1 == -1 && basis_dir[0]) { +diff --git a/sender.c b/sender.c +index 2bbff2f..a4d46c3 100644 +--- a/sender.c ++++ b/sender.c +@@ -350,7 +350,7 @@ void send_files(int f_in, int f_out) + exit_cleanup(RERR_PROTOCOL); + } + +- fd = do_open(fname, O_RDONLY, 0); ++ fd = do_open_checklinks(fname); + if (fd == -1) { + if (errno == ENOENT) { + enum logcode c = am_daemon +diff --git a/syscall.c b/syscall.c +index 47c5ea5..c55ae5f 100644 +--- a/syscall.c ++++ b/syscall.c +@@ -45,6 +45,8 @@ extern int preallocate_files; + extern int preallocate_files; + extern int preserve_perms; + extern int preserve_executability; ++extern int copy_links; ++extern int copy_unsafe_links; + + #ifndef S_BLKSIZE + # if defined hpux || defined __hpux__ || defined __hpux +@@ -575,3 +575,21 @@ int do_open_nofollow(const char *pathname, int flags) + + return fd; + } ++ ++/* ++ varient of do_open/do_open_nofollow which does do_open() if the ++ copy_links or copy_unsafe_links options are set and does ++ do_open_nofollow() otherwise ++ ++ This is used to prevent a race condition where an attacker could be ++ switching a file between being a symlink and being a normal file ++ ++ The open is always done with O_RDONLY flags ++ */ ++int do_open_checklinks(const char *pathname) ++{ ++ if (copy_links || copy_unsafe_links) { ++ return do_open(pathname, O_RDONLY, 0); ++ } ++ return do_open_nofollow(pathname, O_RDONLY); ++} +diff --git a/t_unsafe.c b/t_unsafe.c +index 010cac5..e10619a 100644 +--- a/t_unsafe.c ++++ b/t_unsafe.c +@@ -28,6 +28,9 @@ int am_root = 0; + int human_readable = 0; + int preserve_perms = 0; + int preserve_executability = 0; ++int copy_links = 0; ++int copy_unsafe_links = 0; ++ + short info_levels[COUNT_INFO], debug_levels[COUNT_DEBUG]; + + int +diff --git a/tls.c b/tls.c +index e6b0708..858f8f1 100644 +--- a/tls.c ++++ b/tls.c +@@ -49,6 +49,9 @@ int list_only = 0; + int preserve_executability = 0; + int preallocate_files = 0; + int inplace = 0; ++int safe_symlinks = 0; ++int copy_links = 0; ++int copy_unsafe_links = 0; + + #ifdef SUPPORT_XATTRS + +diff --git a/trimslash.c b/trimslash.c +index 1ec928c..f2774cd 100644 +--- a/trimslash.c ++++ b/trimslash.c +@@ -26,6 +26,8 @@ int am_root = 0; + int preserve_executability = 0; + int preallocate_files = 0; + int inplace = 0; ++int copy_links = 0; ++int copy_unsafe_links = 0; + + int + main(int argc, char **argv) +diff --git a/util.c b/util.c +index f260d39..d84bc41 100644 +--- a/util.c ++++ b/util.c +@@ -365,7 +365,7 @@ int copy_file(const char *source, const char *dest, int tmpfilefd, mode_t mode) + int len; /* Number of bytes read into `buf'. */ + OFF_T prealloc_len = 0, offset = 0; + +- if ((ifd = do_open(source, O_RDONLY, 0)) < 0) { ++ if ((ifd = do_open_nofollow(source, O_RDONLY)) < 0) { + int save_errno = errno; + rsyserr(FERROR_XFER, errno, "open %s", full_fname(source)); + errno = save_errno; diff --git a/rsync.spec b/rsync.spec index f851894..d493056 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: 20%{anolis_release}%{?dist} +Release: 21%{?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 @@ -47,9 +43,9 @@ Patch12: rsync-3.1.3-cve-2022-37434.patch Patch13: rsync-3.1.3-filtering-rules.patch Patch14: rsync-3.1.3-missing-xattr-filter.patch Patch15: rsync-3.1.3-cve-2024-12085.patch -# https://github.com/WayneD/rsync/commit/9dd62525f3b98d692e031f22c02be8f775966503 -# https://github.com/WayneD/rsync/issues/109 -Patch1000: 1000-rsync-lchmod.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 %description Rsync uses a reliable algorithm to bring remote and host files into @@ -69,14 +65,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 @@ -111,7 +99,9 @@ patch -p1 -i patches/copy-devices.diff %patch13 -p1 -b .filtering-rules %patch14 -p1 -b .xattr-filter %patch15 -p1 -b .cve-2024-12085 -%patch1000 -p1 +%patch16 -p1 -b .cve-2024-12087 +%patch17 -p1 -b .cve-2024-12088 +%patch18 -p1 -b .cve-2024-12747 %build %configure @@ -136,6 +126,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* @@ -156,15 +147,14 @@ chmod -x support/* %postun daemon %systemd_postun_with_restart rsyncd.service -%files doc -%doc NEWS OLDNEWS README support/ tech_report.tex - %changelog -* Thu Jan 16 2025 Xiaoping Liu - 3.1.3-20.0.1 -- Add doc sub package -- fix rsync lchmod (xuchunmei@linux.alibaba.com) +* Tue Feb 04 2025 Michal Ruprich - 3.1.3-21 +- Resolves: RHEL-70207 - Path traversal vulnerability in rsync -* Fri Jan 03 2025 Michal Ruprich - 3.1.3-20 +* Mon Feb 03 2025 Michal Ruprich - 3.1.3-20 +- Resolves: RHEL-70207 - Path traversal vulnerability in rsync +- Resolves: RHEL-70209 - --safe-links option bypass leads to path traversal +- Resolves: RHEL-72502 - Race Condition in rsync Handling Symbolic Links - Resolves: RHEL-70157 - Info Leak via Uninitialized Stack Contents * Wed Nov 02 2022 Michal Ruprich - 3.1.3-19.1 -- Gitee From c9f4c2a2185a01fab354687f0d8dd357873279fc 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 d493056..06e15aa 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: 21%{?dist} +Release: 21%{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 @@ -65,6 +69,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 @@ -126,7 +138,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* @@ -147,7 +158,13 @@ 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 + * Tue Feb 04 2025 Michal Ruprich - 3.1.3-21 - Resolves: RHEL-70207 - Path traversal vulnerability in rsync -- Gitee From 4117d6744750c8287060e10b4cec14a23e1d906a 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 06e15aa..3431d89 100644 --- a/rsync.spec +++ b/rsync.spec @@ -50,6 +50,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 %description Rsync uses a reliable algorithm to bring remote and host files into @@ -114,6 +117,7 @@ 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 %build %configure @@ -164,6 +168,7 @@ chmod -x support/* %changelog * Tue Mar 11 2025 Xiaoping Liu - 3.1.3-21.0.1 - Add doc sub package +- fix rsync lchmod (xuchunmei@linux.alibaba.com) * Tue Feb 04 2025 Michal Ruprich - 3.1.3-21 - Resolves: RHEL-70207 - Path traversal vulnerability in rsync -- Gitee