net-misc/rsync: Sync with Gentoo

It's from Gentoo commit 6aa07ed70557568899771004237c0a3925f3a8ef.

Signed-off-by: Flatcar Buildbot <buildbot@flatcar-linux.org>
This commit is contained in:
Flatcar Buildbot 2026-05-11 08:18:12 +00:00
parent 16fa4cf319
commit 0fb56c1c9d
17 changed files with 298 additions and 940 deletions

View File

@ -1,4 +1,4 @@
DIST rsync-3.3.0.tar.gz 1153969 BLAKE2B 75a3cc50452086aebd16f42d7a309c173cbc1ea156227afb10d2106d0b9043e973676995b8199d22840775ae3df8db97d1c0de5f3aa58afa130c5b1348c3f825 SHA512 df5c53bc2f2b0e7e30f475903e5e4296dc2fbcf08e9ea6c3c61462d0e52b067c27e82deeb4be79102c86e9aa55a825182e126f22df44dabf5b7328acb2a01d10
DIST rsync-3.3.0.tar.gz.asc 195 BLAKE2B bd077217bd44d406ac49a55b0c0d38c2accd4867b9fbf78a13fe906f52e1773d5a69aa3116a0c245abdeb1af54705d6ffc75aaba8b276ba9229bbb3340d7c3e8 SHA512 611d26374e0ff98ffb11b6ad6555f08773b9f09e1fbf232abc73c5d472b0defd28fd559bd42707774204d055b93be289f19f4db94bbdfe0b0935918fd922cced
DIST rsync-3.4.1.tar.gz 1172739 BLAKE2B 79c1cad697547059ee241e20c26d7f97bed3ad062deb856d31a617fead333a2d9f62c7c47c1efaf70033dbc358fe547d034c35e8181abb51a1fc893557882bc7 SHA512 a3ecde4843ddb795308dca88581b868ac0221eb6f88a1477d7a9a2ecb4e4686042966bdddbab40866f90a4715d3104daa7b83222ddf0f3387b796a86bde8e5c2
DIST rsync-3.4.1.tar.gz.asc 862 BLAKE2B 5684bd57423e8e43b973c2c416c4897901a3a8b33c22690eaedc609109088e1d5d70f5cf5deaafefc69f547d198b5f8b17f3c484211d545095b19dac7e0bc7d3 SHA512 c83e187c88110b6119a023d239c76291f15124760fd245ead17e747424946e7864187aae96af6f5930cb84beff7308b99daa0566f306c9f2de51e2475704c320
DIST rsync-3.4.2.tar.gz 1190383 BLAKE2B bfc8aa3dc3b75de5e81519eab6d505ebd4d05ebc79c3336ebc925486fa6267cd13a37844d0817183cec68215788bc07e4a281f716bcd0bc7d93daa995df9122c SHA512 74f623e7f5234ffc12fc60d30f4439bc18796404c866365b7c3bfda87f42b33fc01ce6060187534b6b47d799f5b47fcdb84717faff88b6ce30eb230f1b93afe7
DIST rsync-3.4.2.tar.gz.asc 862 BLAKE2B b6cc8bbb94fae5111143c9b0fe7aeca07b29494011060b7b00d98d2e6058f1d0474cc87f8db8d2d2812f1b039a4eb6ec386e4d706ee99bc4396ba995da14acae SHA512 c89f24640438566387aeee553c133859667c3e225439c3f113346241e3802c0652ebf6ab6005cc0f412a0f6e4bc055d76dd422691c3f024f347813183f66076e

View File

@ -1,132 +0,0 @@
https://bugs.gentoo.org/948106
Backport provided by Red Hat on the VINCE case.
diff --git a/io.c b/io.c
index a99ac0e..bb60eec 100644
--- a/io.c
+++ b/io.c
@@ -55,6 +55,7 @@ extern int read_batch;
extern int compat_flags;
extern int protect_args;
extern int checksum_seed;
+extern int xfer_sum_len;
extern int daemon_connection;
extern int protocol_version;
extern int remove_source_files;
@@ -1977,7 +1978,7 @@ void read_sum_head(int f, struct sum_struct *sum)
exit_cleanup(RERR_PROTOCOL);
}
sum->s2length = protocol_version < 27 ? csum_length : (int)read_int(f);
- if (sum->s2length < 0 || sum->s2length > MAX_DIGEST_LEN) {
+ if (sum->s2length < 0 || sum->s2length > xfer_sum_len) {
rprintf(FERROR, "Invalid checksum length %d [%s]\n",
sum->s2length, who_am_i());
exit_cleanup(RERR_PROTOCOL);
diff --git a/match.c b/match.c
index cdb30a1..36e78ed 100644
--- a/match.c
+++ b/match.c
@@ -232,7 +232,7 @@ static void hash_search(int f,struct sum_struct *s,
done_csum2 = 1;
}
- if (memcmp(sum2,s->sums[i].sum2,s->s2length) != 0) {
+ if (memcmp(sum2, sum2_at(s, i), s->s2length) != 0) {
false_alarms++;
continue;
}
@@ -252,7 +252,7 @@ static void hash_search(int f,struct sum_struct *s,
if (i != aligned_i) {
if (sum != s->sums[aligned_i].sum1
|| l != s->sums[aligned_i].len
- || memcmp(sum2, s->sums[aligned_i].sum2, s->s2length) != 0)
+ || memcmp(sum2, sum2_at(s, aligned_i), s->s2length) != 0)
goto check_want_i;
i = aligned_i;
}
@@ -271,7 +271,7 @@ static void hash_search(int f,struct sum_struct *s,
if (sum != s->sums[i].sum1)
goto check_want_i;
get_checksum2((char *)map, l, sum2);
- if (memcmp(sum2, s->sums[i].sum2, s->s2length) != 0)
+ if (memcmp(sum2, sum2_at(s, i), s->s2length) != 0)
goto check_want_i;
/* OK, we have a re-alignment match. Bump the offset
* forward to the new match point. */
@@ -290,7 +290,7 @@ static void hash_search(int f,struct sum_struct *s,
&& (!updating_basis_file || s->sums[want_i].offset >= offset
|| s->sums[want_i].flags & SUMFLG_SAME_OFFSET)
&& sum == s->sums[want_i].sum1
- && memcmp(sum2, s->sums[want_i].sum2, s->s2length) == 0) {
+ && memcmp(sum2, sum2_at(s, want_i), s->s2length) == 0) {
/* we've found an adjacent match - the RLL coder
* will be happy */
i = want_i;
diff --git a/rsync.c b/rsync.c
index cd288f5..b130aba 100644
--- a/rsync.c
+++ b/rsync.c
@@ -437,7 +437,10 @@ int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr, uchar *type_ptr, cha
*/
void free_sums(struct sum_struct *s)
{
- if (s->sums) free(s->sums);
+ if (s->sums) {
+ free(s->sums);
+ free(s->sum2_array);
+ }
free(s);
}
diff --git a/rsync.h b/rsync.h
index d3709fe..0f9e277 100644
--- a/rsync.h
+++ b/rsync.h
@@ -958,12 +958,12 @@ struct sum_buf {
uint32 sum1; /**< simple checksum */
int32 chain; /**< next hash-table collision */
short flags; /**< flag bits */
- char sum2[SUM_LENGTH]; /**< checksum */
};
struct sum_struct {
OFF_T flength; /**< total file length */
struct sum_buf *sums; /**< points to info for each chunk */
+ char *sum2_array; /**< checksums of length xfer_sum_len */
int32 count; /**< how many chunks */
int32 blength; /**< block_length */
int32 remainder; /**< flength % block_length */
@@ -982,6 +982,8 @@ struct map_struct {
int status; /* first errno from read errors */
};
+#define sum2_at(s, i) ((s)->sum2_array + ((size_t)(i) * xfer_sum_len))
+
#define NAME_IS_FILE (0) /* filter name as a file */
#define NAME_IS_DIR (1<<0) /* filter name as a dir */
#define NAME_IS_XATTR (1<<2) /* filter name as an xattr */
diff --git a/sender.c b/sender.c
index 3d4f052..2bbff2f 100644
--- a/sender.c
+++ b/sender.c
@@ -31,6 +31,7 @@ extern int log_before_transfer;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int want_xattr_optim;
+extern int xfer_sum_len;
extern int csum_length;
extern int append_mode;
extern int copy_links;
@@ -94,10 +95,11 @@ static struct sum_struct *receive_sums(int f)
return(s);
s->sums = new_array(struct sum_buf, s->count);
+ s->sum2_array = new_array(char, (size_t)s->count * xfer_sum_len);
for (i = 0; i < s->count; i++) {
s->sums[i].sum1 = read_int(f);
- read_buf(f, s->sums[i].sum2, s->s2length);
+ read_buf(f, sum2_at(s, i), s->s2length);
s->sums[i].offset = offset;
s->sums[i].flags = 0;

View File

@ -1,17 +0,0 @@
https://bugs.gentoo.org/948106
Backport provided by Red Hat on the VINCE case.
diff --git a/match.c b/match.c
index 36e78ed..dfd6af2 100644
--- a/match.c
+++ b/match.c
@@ -147,6 +147,9 @@ static void hash_search(int f,struct sum_struct *s,
int more;
schar *map;
+ // prevent possible memory leaks
+ memset(sum2, 0, sizeof sum2);
+
/* want_i is used to encourage adjacent matches, allowing the RLL
* coding of the output to work more efficiently. */
want_i = 0;

View File

@ -1,200 +0,0 @@
https://bugs.gentoo.org/948106
Backport provided by Red Hat on the VINCE case.
diff --git a/receiver.c b/receiver.c
index 6b4b369..8031b8f 100644
--- a/receiver.c
+++ b/receiver.c
@@ -66,6 +66,7 @@ extern char sender_file_sum[MAX_DIGEST_LEN];
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern filter_rule_list daemon_filter_list;
extern OFF_T preallocated_len;
+extern int fuzzy_basis;
extern struct name_num_item *xfer_sum_nni;
extern int xfer_sum_len;
@@ -551,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. */
@@ -716,28 +719,34 @@ int recv_files(int f_in, int f_out, char *local_name)
fnamecmp = get_backup_name(fname);
break;
case FNAMECMP_FUZZY:
+ if (fuzzy_basis == 0) {
+ rprintf(FERROR_XFER, "rsync: refusing malicious fuzzy operation for %s\n", xname);
+ 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
@@ -760,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) {
@@ -771,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));
diff --git a/syscall.c b/syscall.c
index d92074a..47c5ea5 100644
--- a/syscall.c
+++ b/syscall.c
@@ -33,6 +33,8 @@
#include <sys/syscall.h>
#endif
+#include "ifuncs.h"
+
extern int dry_run;
extern int am_root;
extern int am_sender;
@@ -712,3 +714,82 @@ int do_open_nofollow(const char *pathname, int flags)
return fd;
}
+
+/*
+ open a file relative to a base directory. The basedir can be NULL,
+ in which case the current working directory is used. The relpath
+ must be a relative path, and the relpath must not contain any
+ elements in the path which follow symlinks (ie. like O_NOFOLLOW, but
+ applies to all path components, not just the last component)
+
+ The relpath must also not contain any ../ elements in the path
+*/
+int secure_relative_open(const char *basedir, const char *relpath, int flags, mode_t mode)
+{
+ if (!relpath || relpath[0] == '/') {
+ // must be a relative path
+ errno = EINVAL;
+ return -1;
+ }
+ if (strncmp(relpath, "../", 3) == 0 || strstr(relpath, "/../")) {
+ // no ../ elements allowed in the relpath
+ errno = EINVAL;
+ return -1;
+ }
+
+#if !defined(O_NOFOLLOW) || !defined(O_DIRECTORY)
+ // really old system, all we can do is live with the risks
+ if (!basedir) {
+ return open(relpath, flags, mode);
+ }
+ char fullpath[MAXPATHLEN];
+ pathjoin(fullpath, sizeof fullpath, basedir, relpath);
+ return open(fullpath, flags, mode);
+#else
+ int dirfd = AT_FDCWD;
+ if (basedir != NULL) {
+ dirfd = openat(AT_FDCWD, basedir, O_RDONLY | O_DIRECTORY);
+ if (dirfd == -1) {
+ return -1;
+ }
+ }
+ int retfd = -1;
+
+ char *path_copy = my_strdup(relpath, __FILE__, __LINE__);
+ if (!path_copy) {
+ return -1;
+ }
+
+ for (const char *part = strtok(path_copy, "/");
+ part != NULL;
+ part = strtok(NULL, "/"))
+ {
+ int next_fd = openat(dirfd, part, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
+ if (next_fd == -1 && errno == ENOTDIR) {
+ if (strtok(NULL, "/") != NULL) {
+ // this is not the last component of the path
+ errno = ELOOP;
+ goto cleanup;
+ }
+ // this could be the last component of the path, try as a file
+ retfd = openat(dirfd, part, flags | O_NOFOLLOW, mode);
+ goto cleanup;
+ }
+ if (next_fd == -1) {
+ goto cleanup;
+ }
+ if (dirfd != AT_FDCWD) close(dirfd);
+ dirfd = next_fd;
+ }
+
+ // the path must be a directory
+ errno = EINVAL;
+
+cleanup:
+ free(path_copy);
+ if (dirfd != AT_FDCWD) {
+ close(dirfd);
+ }
+ return retfd;
+#endif // O_NOFOLLOW, O_DIRECTORY
+}

View File

@ -1,26 +0,0 @@
https://github.com/RsyncProject/rsync/pull/707
From 4e9b6476325eb08931025d719cfc3ff2c94d2b23 Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Wed, 15 Jan 2025 15:59:17 +0100
Subject: [PATCH] Fix build on ancient glibc without openat(AT_FDCWD
Fixes: https://github.com/RsyncProject/rsync/issues/701
---
syscall.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/syscall.c b/syscall.c
index 8cea2900..34a9bba0 100644
--- a/syscall.c
+++ b/syscall.c
@@ -734,7 +734,7 @@ int secure_relative_open(const char *basedir, const char *relpath, int flags, mo
return -1;
}
-#if !defined(O_NOFOLLOW) || !defined(O_DIRECTORY)
+#if !defined(O_NOFOLLOW) || !defined(O_DIRECTORY) || !defined(AT_FDCWD)
// really old system, all we can do is live with the risks
if (!basedir) {
return open(relpath, flags, mode);

View File

@ -1,39 +0,0 @@
https://bugs.gentoo.org/948106
Backport provided by Red Hat on the VINCE case.
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");
flist_expand(flist, FLIST_START_LARGE);
diff --git a/rsync.h b/rsync.h
index 0f9e277..b9a7101 100644
--- a/rsync.h
+++ b/rsync.h
@@ -84,6 +84,7 @@
#define FLAG_DUPLICATE (1<<4) /* sender */
#define FLAG_MISSING_DIR (1<<4) /* generator */
#define FLAG_HLINKED (1<<5) /* receiver/generator (checked on all types) */
+#define FLAG_GOT_DIR_FLIST (1<<5)/* sender/receiver/generator - dir_flist only */
#define FLAG_HLINK_FIRST (1<<6) /* receiver/generator (w/FLAG_HLINKED) */
#define FLAG_IMPLIED_DIR (1<<6) /* sender/receiver/generator (dirs only) */
#define FLAG_HLINK_LAST (1<<7) /* receiver/generator */

View File

@ -1,36 +0,0 @@
https://github.com/RsyncProject/rsync/pull/705
From efb85fd8db9e8f74eb3ab91ebf44f6ed35e3da5b Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Wed, 15 Jan 2025 15:10:24 +0100
Subject: [PATCH] Fix FLAG_GOT_DIR_FLIST collission with FLAG_HLINKED
fixes commit 688f5c379a43 (Refuse a duplicate dirlist.)
Fixes: https://github.com/RsyncProject/rsync/issues/702
Fixes: https://github.com/RsyncProject/rsync/issues/697
---
rsync.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rsync.h b/rsync.h
index 9be1297b..479ac484 100644
--- a/rsync.h
+++ b/rsync.h
@@ -84,7 +84,6 @@
#define FLAG_DUPLICATE (1<<4) /* sender */
#define FLAG_MISSING_DIR (1<<4) /* generator */
#define FLAG_HLINKED (1<<5) /* receiver/generator (checked on all types) */
-#define FLAG_GOT_DIR_FLIST (1<<5)/* sender/receiver/generator - dir_flist only */
#define FLAG_HLINK_FIRST (1<<6) /* receiver/generator (w/FLAG_HLINKED) */
#define FLAG_IMPLIED_DIR (1<<6) /* sender/receiver/generator (dirs only) */
#define FLAG_HLINK_LAST (1<<7) /* receiver/generator */
@@ -93,6 +92,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. */

View File

@ -1,60 +0,0 @@
https://bugs.gentoo.org/948106
Backport provided by Red Hat on the VINCE case.
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/util1.c b/util1.c
index da50ff1..f260d39 100644
--- a/util1.c
+++ b/util1.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. */

View File

@ -1,166 +0,0 @@
https://bugs.gentoo.org/948106
Backport provided by Red Hat on the VINCE case.
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)
int32 remainder;
int fd;
- fd = do_open(fname, O_RDONLY, 0);
+ fd = do_open_checklinks(fname);
if (fd == -1) {
memset(sum, 0, file_sum_len);
return;
diff --git a/flist.c b/flist.c
index 087f9da..1783253 100644
--- a/flist.c
+++ b/flist.c
@@ -1390,7 +1390,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
if (copy_devices && am_sender && IS_DEVICE(st.st_mode)) {
if (st.st_size == 0) {
- int fd = do_open(fname, O_RDONLY, 0);
+ int fd = do_open_checklinks(fname);
if (fd >= 0) {
st.st_size = get_device_size(fd, fname);
close(fd);
diff --git a/generator.c b/generator.c
index 110db28..3f13bb9 100644
--- a/generator.c
+++ b/generator.c
@@ -1798,7 +1798,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (write_devices && IS_DEVICE(sx.st.st_mode) && sx.st.st_size == 0) {
/* This early open into fd skips the regular open below. */
- if ((fd = do_open(fnamecmp, O_RDONLY, 0)) >= 0)
+ if ((fd = do_open_nofollow(fnamecmp, O_RDONLY)) >= 0)
real_sx.st.st_size = sx.st.st_size = get_device_size(fd, fnamecmp);
}
@@ -1867,7 +1867,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
/* open the file */
- if (fd < 0 && (fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) {
+ if (fd < 0 && (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 (fnamecmp != fname) {
fnamecmp = fname;
fnamecmp_type = 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 && protocol_version < 28 ? FERROR : FWARNING;
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 preserve_perms;
extern int preserve_executability;
extern int open_noatime;
+extern int copy_links;
+extern int copy_unsafe_links;
#ifndef S_BLKSIZE
# if defined hpux || defined __hpux__ || defined __hpux
@@ -793,3 +795,21 @@ cleanup:
return retfd;
#endif // O_NOFOLLOW, O_DIRECTORY
}
+
+/*
+ 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 am_sender = 1;
int read_only = 0;
int list_only = 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 link_times = 0;
int link_owner = 0;
int nsec_times = 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 am_sender = 1;
int read_only = 1;
int list_only = 0;
+int copy_links = 0;
+int copy_unsafe_links = 0;
int
main(int argc, char **argv)
diff --git a/util1.c b/util1.c
index f260d39..d84bc41 100644
--- a/util1.c
+++ b/util1.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;

View File

@ -1,34 +0,0 @@
https://github.com/RsyncProject/rsync/pull/706
From f923b19fd85039a2b0e908391074872334646d51 Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Wed, 15 Jan 2025 15:48:04 +0100
Subject: [PATCH] Fix use-after-free in generator
full_fname() will free the return value in the next call so we need to
duplicate it before passing it to rsyserr.
Fixes: https://github.com/RsyncProject/rsync/issues/704
---
generator.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/generator.c b/generator.c
index 3f13bb95..b56fa569 100644
--- a/generator.c
+++ b/generator.c
@@ -2041,8 +2041,12 @@ int atomic_create(struct file_struct *file, char *fname, const char *slnk, const
if (!skip_atomic) {
if (do_rename(tmpname, fname) < 0) {
+ char *full_tmpname = strdup(full_fname(tmpname));
+ if (full_tmpname == NULL)
+ out_of_memory("atomic_create");
rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\" failed",
- full_fname(tmpname), full_fname(fname));
+ full_tmpname, full_fname(fname));
+ free(full_tmpname);
do_unlink(tmpname);
return 0;
}

View File

@ -0,0 +1,202 @@
https://github.com/RsyncProject/rsync/commit/aa142f08ef31d3ffa8d6b3b8af16d00324a98c1b
From: Andrew Tridgell <andrew@tridgell.net>
Date: Sun, 1 Mar 2026 08:42:04 +1100
Subject: [PATCH] fix uninitialized mul_one in AVX2 checksum and add SIMD checksum test
The AVX2 get_checksum1_avx2_64() read mul_one before initializing it,
which is undefined behavior. Replace the cmpeq/abs trick with
_mm256_set1_epi8(1) to match the SSSE3 and SSE2 versions.
Add a TEST_SIMD_CHECKSUM1 test mode that verifies all SIMD paths
(SSE2, SSSE3, AVX2, and the full dispatch chain) produce identical
results to the C reference, across multiple buffer sizes with both
aligned and unaligned buffers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Makefile.in | 11 +++-
simd-checksum-x86_64.cpp | 115 ++++++++++++++++++++++++++++++++++-
testsuite/simd-checksum.test | 11 ++++
3 files changed, 134 insertions(+), 3 deletions(-)
create mode 100755 testsuite/simd-checksum.test
diff --git a/Makefile.in b/Makefile.in
index 6340403be..6f188ee8a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -57,7 +57,8 @@ TLS_OBJ = tls.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/perms
# Programs we must have to run the test cases
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
- testrun$(EXEEXT) trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
+ testrun$(EXEEXT) trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT) \
+ simdtest$(EXEEXT)
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test testsuite/xattrs-hlink.test
@@ -326,6 +327,14 @@ wildtest.o: wildtest.c t_stub.o lib/wildmatch.c rsync.h config.h
wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
+simdtest$(EXEEXT): simd-checksum-x86_64.cpp $(HEADERS)
+ @if test x"@ROLL_SIMD@" != x; then \
+ $(CXX) -I. $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -DTEST_SIMD_CHECKSUM1 \
+ -o $@ $(srcdir)/simd-checksum-x86_64.cpp @ROLL_ASM@ $(LIBS); \
+ else \
+ touch $@; \
+ fi
+
testsuite/chown-fake.test:
ln -s chown.test $(srcdir)/testsuite/chown-fake.test
diff --git a/simd-checksum-x86_64.cpp b/simd-checksum-x86_64.cpp
index d649091ea..99391cbe4 100644
--- a/simd-checksum-x86_64.cpp
+++ b/simd-checksum-x86_64.cpp
@@ -347,8 +347,7 @@ __attribute__ ((target("avx2"))) MVSTATIC int32 get_checksum1_avx2_64(schar* buf
__m128i tmp = _mm_load_si128((__m128i*) mul_t1_buf);
__m256i mul_t1 = _mm256_cvtepu8_epi16(tmp);
__m256i mul_const = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(4 | (3 << 8) | (2 << 16) | (1 << 24)));
- __m256i mul_one;
- mul_one = _mm256_abs_epi8(_mm256_cmpeq_epi16(mul_one,mul_one)); // set all vector elements to 1
+ __m256i mul_one = _mm256_set1_epi8(1);
for (; i < (len-64); i+=64) {
// Load ... 4*[int8*16]
@@ -548,6 +547,118 @@ int main() {
#pragma clang optimize on
#endif /* BENCHMARK_SIMD_CHECKSUM1 */
+#ifdef TEST_SIMD_CHECKSUM1
+
+static uint32 checksum_via_default(char *buf, int32 len)
+{
+ uint32 s1 = 0, s2 = 0;
+ get_checksum1_default_1((schar*)buf, len, 0, &s1, &s2);
+ return (s1 & 0xffff) + (s2 << 16);
+}
+
+static uint32 checksum_via_sse2(char *buf, int32 len)
+{
+ int32 i;
+ uint32 s1 = 0, s2 = 0;
+ i = get_checksum1_sse2_32((schar*)buf, len, 0, &s1, &s2);
+ get_checksum1_default_1((schar*)buf, len, i, &s1, &s2);
+ return (s1 & 0xffff) + (s2 << 16);
+}
+
+static uint32 checksum_via_ssse3(char *buf, int32 len)
+{
+ int32 i;
+ uint32 s1 = 0, s2 = 0;
+ i = get_checksum1_ssse3_32((schar*)buf, len, 0, &s1, &s2);
+ get_checksum1_default_1((schar*)buf, len, i, &s1, &s2);
+ return (s1 & 0xffff) + (s2 << 16);
+}
+
+static uint32 checksum_via_avx2(char *buf, int32 len)
+{
+ int32 i;
+ uint32 s1 = 0, s2 = 0;
+#ifdef USE_ROLL_ASM
+ i = get_checksum1_avx2_asm((schar*)buf, len, 0, &s1, &s2);
+#else
+ i = get_checksum1_avx2_64((schar*)buf, len, 0, &s1, &s2);
+#endif
+ get_checksum1_default_1((schar*)buf, len, i, &s1, &s2);
+ return (s1 & 0xffff) + (s2 << 16);
+}
+
+int main()
+{
+ static const int sizes[] = {1, 4, 31, 32, 33, 63, 64, 65, 128, 129, 256, 700, 1024, 4096, 65536};
+ int num_sizes = sizeof(sizes) / sizeof(sizes[0]);
+ int max_size = sizes[num_sizes - 1];
+ int failures = 0;
+
+ /* Allocate with extra bytes for unaligned test */
+ unsigned char *raw = (unsigned char *)malloc(max_size + 64 + 1);
+ if (!raw) {
+ fprintf(stderr, "malloc failed\n");
+ return 1;
+ }
+
+ /* Fill with deterministic data */
+ for (int i = 0; i < max_size + 64 + 1; i++)
+ raw[i] = (i + (i % 3) + (i % 11)) % 256;
+
+ /* Test with aligned buffer (64-byte aligned) */
+ unsigned char *aligned = raw + (64 - ((uintptr_t)raw % 64));
+
+ /* Test with unaligned buffer (+1 byte offset) */
+ unsigned char *unaligned = aligned + 1;
+
+ struct { const char *name; unsigned char *buf; } buffers[] = {
+ {"aligned", aligned},
+ {"unaligned", unaligned},
+ };
+
+ for (int b = 0; b < 2; b++) {
+ char *buf = (char *)buffers[b].buf;
+ const char *bname = buffers[b].name;
+
+ for (int s = 0; s < num_sizes; s++) {
+ int32 len = sizes[s];
+ uint32 ref = checksum_via_default(buf, len);
+ uint32 cs_sse2 = checksum_via_sse2(buf, len);
+ uint32 cs_ssse3 = checksum_via_ssse3(buf, len);
+ uint32 cs_avx2 = checksum_via_avx2(buf, len);
+ uint32 cs_auto = get_checksum1(buf, len);
+
+ if (cs_sse2 != ref) {
+ printf("FAIL %-9s size=%5d: SSE2=%08x ref=%08x\n", bname, len, cs_sse2, ref);
+ failures++;
+ }
+ if (cs_ssse3 != ref) {
+ printf("FAIL %-9s size=%5d: SSSE3=%08x ref=%08x\n", bname, len, cs_ssse3, ref);
+ failures++;
+ }
+ if (cs_avx2 != ref) {
+ printf("FAIL %-9s size=%5d: AVX2=%08x ref=%08x\n", bname, len, cs_avx2, ref);
+ failures++;
+ }
+ if (cs_auto != ref) {
+ printf("FAIL %-9s size=%5d: auto=%08x ref=%08x\n", bname, len, cs_auto, ref);
+ failures++;
+ }
+ }
+ }
+
+ free(raw);
+
+ if (failures) {
+ printf("%d checksum mismatches!\n", failures);
+ return 1;
+ }
+ printf("All SIMD checksum tests passed.\n");
+ return 0;
+}
+
+#endif /* TEST_SIMD_CHECKSUM1 */
+
#endif /* } USE_ROLL_SIMD */
#endif /* } __cplusplus */
#endif /* } __x86_64__ */
diff --git a/testsuite/simd-checksum.test b/testsuite/simd-checksum.test
new file mode 100755
index 000000000..cf7dba2ec
--- /dev/null
+++ b/testsuite/simd-checksum.test
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# Test SIMD checksum implementations against the C reference
+
+. "$suitedir/rsync.fns"
+
+if ! test -x "$TOOLDIR/simdtest"; then
+ test_skipped "simdtest not built (SIMD not available)"
+fi
+
+"$TOOLDIR/simdtest"

View File

@ -0,0 +1,77 @@
Manual backport of https://github.com/RsyncProject/rsync/pull/867
--- a/access.c
+++ b/access.c
@@ -99,7 +99,7 @@ static void make_mask(char *mask, int pl
return;
}
-static int match_address(const char *addr, const char *tok)
+static int match_address(const char *addr, char *tok)
{
char *p;
struct addrinfo hints, *resa, *rest;
--- a/checksum.c
+++ b/checksum.c
@@ -176,7 +176,7 @@ void parse_checksum_choice(int final_cal
if (valid_checksums.negotiated_nni)
xfer_sum_nni = file_sum_nni = valid_checksums.negotiated_nni;
else {
- char *cp = checksum_choice ? strchr(checksum_choice, ',') : NULL;
+ const char *cp = checksum_choice ? strchr(checksum_choice, ',') : NULL;
if (cp) {
xfer_sum_nni = parse_csum_name(checksum_choice, cp - checksum_choice);
file_sum_nni = parse_csum_name(cp+1, -1);
--- a/compat.c
+++ b/compat.c
@@ -131,7 +131,7 @@ static const char *client_info;
* of that protocol for it to be advertised as available. */
static void check_sub_protocol(void)
{
- char *dot;
+ const char *dot;
int their_protocol, their_sub;
int our_sub = get_subprotocol_version();
@@ -414,7 +414,7 @@ static const char *getenv_nstr(int ntype
env_str = ntype == NSTR_COMPRESS ? "zlib" : protocol_version >= 30 ? "md5" : "md4";
if (am_server && env_str) {
- char *cp = strchr(env_str, '&');
+ const char *cp = strchr(env_str, '&');
if (cp)
env_str = cp + 1;
}
--- a/exclude.c
+++ b/exclude.c
@@ -904,7 +904,7 @@ static int rule_matches(const char *fnam
{
int slash_handling, str_cnt = 0, anchored_match = 0;
int ret_match = ex->rflags & FILTRULE_NEGATE ? 0 : 1;
- char *p, *pattern = ex->pattern;
+ const char *p, *pattern = ex->pattern;
const char *strings[16]; /* more than enough */
const char *name = fname + (*fname == '/');
--- a/io.c
+++ b/io.c
@@ -1159,7 +1159,7 @@ void set_io_timeout(int secs)
static void check_for_d_option_error(const char *msg)
{
static char rsync263_opts[] = "BCDHIKLPRSTWabceghlnopqrtuvxz";
- char *colon;
+ const char *colon;
int saw_d = 0;
if (*msg != 'r'
--- a/loadparm.c
+++ b/loadparm.c
@@ -178,7 +178,7 @@ static char *expand_vars(const char *str
for (t = buf, f = str; bufsize && *f; ) {
if (*f == '%' && isUpper(f+1)) {
- char *percent = strchr(f+1, '%');
+ const char *percent = strchr(f+1, '%');
if (percent && percent - f < bufsize) {
char *val;
strlcpy(t, f+1, percent - f);

View File

@ -1,210 +0,0 @@
# Copyright 1999-2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
# Uncomment when introducing a patch which touches configure
RSYNC_NEEDS_AUTOCONF=1
PYTHON_COMPAT=( python3_{11..13} )
inherit flag-o-matic prefix python-single-r1 systemd
DESCRIPTION="File transfer program to keep remote files into sync"
HOMEPAGE="https://rsync.samba.org/"
if [[ ${PV} == *9999 ]] ; then
EGIT_REPO_URI="https://github.com/WayneD/rsync.git"
inherit autotools git-r3
REQUIRED_USE="${PYTHON_REQUIRED_USE}"
else
VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/waynedavison.asc
inherit verify-sig
if [[ -n ${RSYNC_NEEDS_AUTOCONF} ]] ; then
inherit autotools
fi
if [[ ${PV} == *_pre* ]] ; then
SRC_DIR="src-previews"
else
SRC_DIR="src"
KEYWORDS="~alpha amd64 arm arm64 ~hppa ~loong ~m68k ~mips ppc ppc64 ~riscv ~s390 ~sparc x86 ~arm64-macos ~x64-macos ~x64-solaris"
fi
SRC_URI="https://rsync.samba.org/ftp/rsync/${SRC_DIR}/${P/_/}.tar.gz
verify-sig? ( https://rsync.samba.org/ftp/rsync/${SRC_DIR}/${P/_/}.tar.gz.asc )"
S="${WORKDIR}"/${P/_/}
fi
LICENSE="GPL-3"
SLOT="0"
IUSE="acl examples iconv lz4 rrsync ssl stunnel system-zlib xattr xxhash zstd"
REQUIRED_USE+=" examples? ( ${PYTHON_REQUIRED_USE} )"
REQUIRED_USE+=" rrsync? ( ${PYTHON_REQUIRED_USE} )"
# attr is autodetected and then dropped by -Wl,--as-needed:
# https://github.com/RsyncProject/rsync/pull/753
RDEPEND="
>=dev-libs/popt-1.5
acl? ( virtual/acl )
examples? (
${PYTHON_DEPS}
dev-lang/perl
)
lz4? ( app-arch/lz4:= )
rrsync? (
${PYTHON_DEPS}
$(python_gen_cond_dep '
dev-python/bracex[${PYTHON_USEDEP}]
')
)
ssl? ( dev-libs/openssl:= )
system-zlib? ( virtual/zlib:= )
xxhash? ( >=dev-libs/xxhash-0.8 )
zstd? ( >=app-arch/zstd-1.4:= )
iconv? ( virtual/libiconv )"
DEPEND="${RDEPEND}"
BDEPEND="
examples? ( ${PYTHON_DEPS} )
rrsync? ( ${PYTHON_DEPS} )
"
if [[ ${PV} == *9999 ]] ; then
BDEPEND+=" ${PYTHON_DEPS}
$(python_gen_cond_dep '
dev-python/commonmark[${PYTHON_USEDEP}]
')"
else
BDEPEND+=" verify-sig? ( sec-keys/openpgp-keys-waynedavison )"
fi
PATCHES=(
# Temporary just for the bug #948106 CVE fixes
"${FILESDIR}"/3.3.0
)
pkg_setup() {
# - USE=examples needs Python itself at runtime, but nothing else
# - 9999 needs commonmark at build time
if [[ ${PV} == *9999 ]] || use examples || use rrsync; then
python-single-r1_pkg_setup
fi
}
src_prepare() {
default
sed -i -e 's/AC_HEADER_MAJOR_FIXED/AC_HEADER_MAJOR/' configure.ac
if [[ ${PV} == *9999 || -n ${RSYNC_NEEDS_AUTOCONF} ]] ; then
eaclocal -I m4
eautoconf -o configure.sh
eautoheader && touch config.h.in
fi
if use examples || use rrsync; then
python_fix_shebang support/
fi
if [[ -f rrsync.1 ]]; then
# If the pre-build rrsync.1 man page exists, then link to it
# from support/rrsync.1 to avoid rsync's build system attempting
# re-creating the man page (bug #883049).
ln -s ../rrsync.1 support/rrsync.1 || die
fi
}
src_configure() {
# Should be fixed upstream in next release (>3.3.0) (bug #943745)
append-cflags $(test-flags-CC -std=gnu17)
local myeconfargs=(
--with-rsyncd-conf="${EPREFIX}"/etc/rsyncd.conf
--without-included-popt
--enable-ipv6
$(use_enable acl acl-support)
$(use_enable iconv)
$(use_enable lz4)
$(use_with rrsync)
$(use_enable ssl openssl)
$(use_with !system-zlib included-zlib)
$(use_enable xattr xattr-support)
$(use_enable xxhash)
$(use_enable zstd)
)
# https://github.com/WayneD/rsync/pull/428
if is-flagq -fsanitize=undefined ; then
sed -E -i \
-e 's:#define CAREFUL_ALIGNMENT (0|1):#define CAREFUL_ALIGNMENT 1:' \
byteorder.h || die
append-flags -DCAREFUL_ALIGNMENT
fi
econf "${myeconfargs[@]}"
}
src_install() {
emake DESTDIR="${D}" install
newconfd "${FILESDIR}"/rsyncd.conf.d rsyncd
newinitd "${FILESDIR}"/rsyncd.init.d-r1 rsyncd
dodoc NEWS.md README.md TODO tech_report.tex
insinto /etc
newins "${FILESDIR}"/rsyncd.conf-3.2.7-r5 rsyncd.conf
insinto /etc/logrotate.d
newins "${FILESDIR}"/rsyncd.logrotate rsyncd
insinto /etc/xinetd.d
newins "${FILESDIR}"/rsyncd.xinetd-3.0.9-r1 rsyncd
# Install stunnel helpers
if use stunnel ; then
emake DESTDIR="${D}" install-ssl-daemon
fi
# Install the useful contrib scripts
if use examples ; then
# The 'rrsync' script is installed conditionally via the 'rrysnc'
# USE flag, and not via the 'examples' USE flag.
rm support/rrsync* || die
exeinto /usr/share/rsync
doexe support/*
rm -f "${ED}"/usr/share/rsync/{Makefile*,*.c}
fi
eprefixify "${ED}"/etc/{,xinetd.d}/rsyncd*
systemd_newunit packaging/systemd/rsync.service rsyncd.service
}
pkg_postinst() {
if grep -Eqis '^[[:space:]]use chroot[[:space:]]*=[[:space:]]*(no|0|false)' \
"${EROOT}"/etc/rsyncd.conf "${EROOT}"/etc/rsync/rsyncd.conf ; then
ewarn "You have disabled chroot support in your rsyncd.conf. This"
ewarn "is a security risk which you should fix. Please check your"
ewarn "/etc/rsyncd.conf file and fix the setting 'use chroot'."
fi
if use stunnel ; then
einfo "Please install \">=net-misc/stunnel-4\" in order to use stunnel feature."
einfo
einfo "You maybe have to update the certificates configured in"
einfo "${EROOT}/etc/stunnel/rsync.conf"
fi
if use system-zlib ; then
ewarn "Using system-zlib is incompatible with <rsync-3.1.1 when"
ewarn "using the --compress option."
ewarn
ewarn "When syncing with >=rsync-3.1.1 built with bundled zlib,"
ewarn "and the --compress option, add --new-compress (-zz)."
ewarn
ewarn "For syncing the portage tree, add:"
ewarn "PORTAGE_RSYNC_EXTRA_OPTS=\"--new-compress\" to make.conf"
fi
}

View File

@ -27,7 +27,7 @@ else
SRC_DIR="src-previews"
else
SRC_DIR="src"
KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~arm64-macos ~x64-macos ~x64-solaris"
KEYWORDS="~alpha amd64 arm arm64 ~hppa ~loong ~m68k ~mips ppc ppc64 ~riscv ~s390 ~sparc x86 ~arm64-macos ~x64-macos ~x64-solaris"
fi
SRC_URI="https://rsync.samba.org/ftp/rsync/${SRC_DIR}/${P/_/}.tar.gz

View File

@ -1,11 +1,11 @@
# Copyright 1999-2025 Gentoo Authors
# Copyright 1999-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
# Uncomment when introducing a patch which touches configure
RSYNC_NEEDS_AUTOCONF=1
PYTHON_COMPAT=( python3_{11..13} )
PYTHON_COMPAT=( python3_{11..14} )
inherit flag-o-matic prefix python-single-r1 systemd
DESCRIPTION="File transfer program to keep remote files into sync"
@ -27,7 +27,7 @@ else
SRC_DIR="src-previews"
else
SRC_DIR="src"
KEYWORDS="~alpha amd64 arm arm64 ~hppa ~loong ~m68k ~mips ppc ppc64 ~riscv ~s390 ~sparc x86 ~arm64-macos ~x64-macos ~x64-solaris"
KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~arm64-macos ~x64-macos ~x64-solaris"
fi
SRC_URI="https://rsync.samba.org/ftp/rsync/${SRC_DIR}/${P/_/}.tar.gz
@ -37,7 +37,7 @@ fi
LICENSE="GPL-3"
SLOT="0"
IUSE="acl examples iconv lz4 rrsync ssl stunnel system-zlib xattr xxhash zstd"
IUSE="acl examples iconv lz4 rrsync ssl stunnel system-zlib xattr +xxhash zstd"
REQUIRED_USE+=" examples? ( ${PYTHON_REQUIRED_USE} )"
REQUIRED_USE+=" rrsync? ( ${PYTHON_REQUIRED_USE} )"
@ -79,6 +79,9 @@ fi
PATCHES=(
"${FILESDIR}"/${PN}-3.4.1-c23.patch
"${FILESDIR}"/${PN}-3.4.1-CVE-2025-10158.patch
"${FILESDIR}"/${PN}-3.4.1-fix-uninitialized-mul_one.patch
"${FILESDIR}"/${PN}-3.4.1-glibc-2.43.patch
)
pkg_setup() {
@ -136,6 +139,10 @@ src_configure() {
append-flags -DCAREFUL_ALIGNMENT
fi
# workaround for autoconf-2.73 using C23:
# https://bugs.gentoo.org/972320
append-cflags -std=gnu17
econf "${myeconfargs[@]}"
}

View File

@ -1,11 +1,11 @@
# Copyright 1999-2025 Gentoo Authors
# Copyright 1999-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
# Uncomment when introducing a patch which touches configure
RSYNC_NEEDS_AUTOCONF=1
PYTHON_COMPAT=( python3_{11..13} )
PYTHON_COMPAT=( python3_{11..14} )
inherit flag-o-matic prefix python-single-r1 systemd
DESCRIPTION="File transfer program to keep remote files into sync"
@ -27,7 +27,7 @@ else
SRC_DIR="src-previews"
else
SRC_DIR="src"
KEYWORDS="~alpha amd64 arm arm64 ~hppa ~loong ~m68k ~mips ppc ppc64 ~riscv ~s390 ~sparc x86 ~arm64-macos ~x64-macos ~x64-solaris"
KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~arm64-macos ~x64-macos ~x64-solaris"
fi
SRC_URI="https://rsync.samba.org/ftp/rsync/${SRC_DIR}/${P/_/}.tar.gz
@ -41,8 +41,6 @@ IUSE="acl examples iconv lz4 rrsync ssl stunnel system-zlib xattr +xxhash zstd"
REQUIRED_USE+=" examples? ( ${PYTHON_REQUIRED_USE} )"
REQUIRED_USE+=" rrsync? ( ${PYTHON_REQUIRED_USE} )"
# attr is autodetected and then dropped by -Wl,--as-needed:
# https://github.com/RsyncProject/rsync/pull/753
RDEPEND="
>=dev-libs/popt-1.19
acl? ( virtual/acl )
@ -77,10 +75,6 @@ else
BDEPEND+=" verify-sig? ( sec-keys/openpgp-keys-andrewtridgell )"
fi
PATCHES=(
"${FILESDIR}"/${PN}-3.4.1-c23.patch
)
pkg_setup() {
# - USE=examples needs Python itself at runtime, but nothing else
# - 9999 needs commonmark at build time

View File

@ -1,11 +1,11 @@
# Copyright 1999-2025 Gentoo Authors
# Copyright 1999-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
# Uncomment when introducing a patch which touches configure
RSYNC_NEEDS_AUTOCONF=1
PYTHON_COMPAT=( python3_{11..13} )
PYTHON_COMPAT=( python3_{11..14} )
inherit flag-o-matic prefix python-single-r1 systemd
DESCRIPTION="File transfer program to keep remote files into sync"
@ -41,8 +41,6 @@ IUSE="acl examples iconv lz4 rrsync ssl stunnel system-zlib xattr +xxhash zstd"
REQUIRED_USE+=" examples? ( ${PYTHON_REQUIRED_USE} )"
REQUIRED_USE+=" rrsync? ( ${PYTHON_REQUIRED_USE} )"
# attr is autodetected and then dropped by -Wl,--as-needed:
# https://github.com/RsyncProject/rsync/pull/753
RDEPEND="
>=dev-libs/popt-1.19
acl? ( virtual/acl )