rsync/rsync-CVE-2024-12086_03.patch
Angel Yankov 04926b0b74 - Security update,CVE-2024-12747, bsc#1235475 race condition in handling symbolic links
* Added rsync-CVE-2024-12747.patch

- Security update, fix multiple vulnerabilities:
  * CVE-2024-12084, bsc#1234100 - Heap Buffer Overflow in Checksum Parsing
  * CVE-2024-12085, bsc#1234101 - Info Leak via uninitialized Stack contents defeats ASLR
  * CVE-2024-12086, bsc#1234102 - Server leaks arbitrary client files
  * CVE-2024-12087, bsc#1234103 - Server can make client write files outside of destination directory using symbolic links
  * CVE-2024-12088, bsc#1234104 - --safe-links Bypass
  * Added rsync-CVE-2024-12084-overflow-01.patch
  * Added rsync-CVE-2024-12084-overflow-02.patch
  * Added rsync-CVE-2024-12085.patch
  * Added rsync-CVE-2024-12086_01.patch
  * Added rsync-CVE-2024-12086_02.patch
  * Added rsync-CVE-2024-12086_03.patch
  * Added rsync-CVE-2024-12086_04.patch
  * Added rsync-CVE-2024-12087_01.patch
  * Added rsync-CVE-2024-12087_02.patch
  * Added rsync-CVE-2024-12088.patch

OBS-URL: https://build.opensuse.org/package/show/network/rsync?expand=0&rev=129
2025-01-15 08:07:45 +00:00

105 lines
3.3 KiB
Diff

From e59ef9939d3f0ccc8f9bab51442989a81be0c914 Mon Sep 17 00:00:00 2001
From: Andrew Tridgell <andrew@tridgell.net>
Date: Sat, 23 Nov 2024 12:28:13 +1100
Subject: [PATCH 3/4] receiver: use secure_relative_open() for basis file
this prevents attacks where the basis file is manipulated by a
malicious sender to gain information about files outside the
destination tree
---
receiver.c | 42 ++++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/receiver.c b/receiver.c
index 2d7f6033..8031b8f4 100644
--- a/receiver.c
+++ b/receiver.c
@@ -552,6 +552,8 @@ int recv_files(int f_in, int f_out, char *local_name)
progress_init();
while (1) {
+ const char *basedir = NULL;
+
cleanup_disable();
/* This call also sets cur_flist. */
@@ -722,27 +724,29 @@ int recv_files(int f_in, int f_out, char *local_name)
exit_cleanup(RERR_PROTOCOL);
}
if (file->dirname) {
- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, file->dirname, xname);
- fnamecmp = fnamecmpbuf;
- } else
- fnamecmp = xname;
+ basedir = file->dirname;
+ }
+ fnamecmp = xname;
break;
default:
if (fnamecmp_type > FNAMECMP_FUZZY && fnamecmp_type-FNAMECMP_FUZZY <= basis_dir_cnt) {
fnamecmp_type -= FNAMECMP_FUZZY + 1;
if (file->dirname) {
- stringjoin(fnamecmpbuf, sizeof fnamecmpbuf,
- basis_dir[fnamecmp_type], "/", file->dirname, "/", xname, NULL);
- } else
- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], xname);
+ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], file->dirname);
+ basedir = fnamecmpbuf;
+ } else {
+ basedir = basis_dir[fnamecmp_type];
+ }
+ fnamecmp = xname;
} else if (fnamecmp_type >= basis_dir_cnt) {
rprintf(FERROR,
"invalid basis_dir index: %d.\n",
fnamecmp_type);
exit_cleanup(RERR_PROTOCOL);
- } else
- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], fname);
- fnamecmp = fnamecmpbuf;
+ } else {
+ basedir = basis_dir[fnamecmp_type];
+ fnamecmp = fname;
+ }
break;
}
if (!fnamecmp || (daemon_filter_list.head
@@ -765,7 +769,7 @@ int recv_files(int f_in, int f_out, char *local_name)
}
/* open the file */
- fd1 = do_open(fnamecmp, O_RDONLY, 0);
+ fd1 = secure_relative_open(basedir, fnamecmp, O_RDONLY, 0);
if (fd1 == -1 && protocol_version < 29) {
if (fnamecmp != fname) {
@@ -776,14 +780,20 @@ int recv_files(int f_in, int f_out, char *local_name)
if (fd1 == -1 && basis_dir[0]) {
/* pre-29 allowed only one alternate basis */
- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
- basis_dir[0], fname);
- fnamecmp = fnamecmpbuf;
+ basedir = basis_dir[0];
+ fnamecmp = fname;
fnamecmp_type = FNAMECMP_BASIS_DIR_LOW;
- fd1 = do_open(fnamecmp, O_RDONLY, 0);
+ fd1 = secure_relative_open(basedir, fnamecmp, O_RDONLY, 0);
}
}
+ if (basedir) {
+ // for the following code we need the full
+ // path name as a single string
+ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basedir, fnamecmp);
+ fnamecmp = fnamecmpbuf;
+ }
+
one_inplace = inplace_partial && fnamecmp_type == FNAMECMP_PARTIAL_DIR;
updating_basis_or_equiv = one_inplace
|| (inplace && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP));
--
2.34.1