new file mode 100644
@@ -0,0 +1,42 @@
+From 8ad4b5d912fad1df29717dddaa775724da77d299 Mon Sep 17 00:00:00 2001
+From: Andrew Tridgell <andrew@tridgell.net>
+Date: Sat, 23 Nov 2024 11:08:03 +1100
+Subject: [PATCH] refuse fuzzy options when fuzzy not selected
+
+this prevents a malicious server providing a file to compare to when
+the user has not given the fuzzy option
+
+CVE: CVE-2024-12086
+
+Upstream-Status: Backport [https://git.samba.org/?p=rsync.git;a=commit;h=8ad4b5d912fad1df29717dddaa775724da77d299]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ receiver.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/receiver.c b/receiver.c
+index 6b4b369e..2d7f6033 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;
+@@ -716,6 +717,10 @@ 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;
+--
+2.40.0
new file mode 100644
@@ -0,0 +1,108 @@
+From b4a27ca25d0abb6fcf14f41b7e11f3a6e1d8a4ff Mon Sep 17 00:00:00 2001
+From: Andrew Tridgell <andrew@tridgell.net>
+Date: Sat, 23 Nov 2024 12:26:10 +1100
+Subject: [PATCH] added secure_relative_open()
+
+this is an open that enforces no symlink following for all path
+components in a relative path
+
+CVE: CVE-2024-12086
+
+Upstream-Status: Backport [https://git.samba.org/?p=rsync.git;a=commit;h=b4a27ca25d0abb6fcf14f41b7e11f3a6e1d8a4ff]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ syscall.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 74 insertions(+)
+
+diff --git a/syscall.c b/syscall.c
+index b4b0f1f1..cffc814b 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;
+@@ -707,3 +709,75 @@ 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)
++*/
++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 !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
++}
+--
+2.40.0
new file mode 100644
@@ -0,0 +1,108 @@
+From c35e28331f10ba6eba370611abd78bde32d54da7 Mon Sep 17 00:00:00 2001
+From: Andrew Tridgell <andrew@tridgell.net>
+Date: Sat, 23 Nov 2024 12:28:13 +1100
+Subject: [PATCH] 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
+
+CVE: CVE-2024-12086
+
+Upstream-Status: Backport [https://git.samba.org/?p=rsync.git;a=commit;h=c35e28331f10ba6eba370611abd78bde32d54da7]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ 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.40.0
new file mode 100644
@@ -0,0 +1,41 @@
+From 9f86ddc9652247233f32b241a79d5aa4fb9d4afa Mon Sep 17 00:00:00 2001
+From: Andrew Tridgell <andrew@tridgell.net>
+Date: Tue, 26 Nov 2024 09:16:31 +1100
+Subject: [PATCH] disallow ../ elements in relpath for secure_relative_open
+
+CVE: CVE-2024-12086
+
+Upstream-Status: Backport [https://git.samba.org/?p=rsync.git;a=commit;h=9f86ddc9652247233f32b241a79d5aa4fb9d4afa]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ syscall.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/syscall.c b/syscall.c
+index cffc814b..081357bb 100644
+--- a/syscall.c
++++ b/syscall.c
+@@ -716,6 +716,8 @@ int do_open_nofollow(const char *pathname, int flags)
+ 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)
+ {
+@@ -724,6 +726,11 @@ int secure_relative_open(const char *basedir, const char *relpath, int flags, mo
+ 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
+--
+2.40.0
@@ -18,6 +18,10 @@ SRC_URI = "https://download.samba.org/pub/${BPN}/src/${BP}.tar.gz \
file://CVE-2024-12084-0001.patch \
file://CVE-2024-12084-0002.patch \
file://CVE-2024-12085.patch \
+ file://CVE-2024-12086-0001.patch \
+ file://CVE-2024-12086-0002.patch \
+ file://CVE-2024-12086-0003.patch \
+ file://CVE-2024-12086-0004.patch \
"
SRC_URI[sha256sum] = "4e7d9d3f6ed10878c58c5fb724a67dacf4b6aac7340b13e488fb2dc41346f2bb"