From b7231c7d02cfb65d291af74ff66e7d8c507ee871 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sun, 31 Jul 2022 16:55:34 -0700 Subject: [PATCH] Some extra file-list safety checks. Conflict:don't apply add_implied_include(),adapt context in flist.c,delete rsync.1.md Reference:https://github.com/WayneD/rsync/commit/b7231c7d02cfb65d291af74ff66e7d8c507ee871 --- exclude.c | 4 +++- flist.c | 10 ++++++++++ main.c | 2 ++ receiver.c | 11 +++++++---- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/exclude.c b/exclude.c index e095744..ab91999 100644 --- a/exclude.c +++ b/exclude.c @@ -46,6 +46,7 @@ filter_rule_list cvs_filter_list = { .debug_type = " [global CVS]" }; filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" }; int saw_xattr_filter = 0; +int trust_sender_filter = 0; /* Need room enough for ":MODS " prefix plus some room to grow. */ #define MAX_RULE_PREFIX (16) @@ -714,7 +715,7 @@ static void report_filter_result(enum logcode code, char const *name, : name_flags & NAME_IS_DIR ? "directory" : "file"; rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n", - w, actions[*w!='s'][!(ent->rflags & FILTRULE_INCLUDE)], + w, actions[*w=='g'][!(ent->rflags & FILTRULE_INCLUDE)], t, name, ent->pattern, ent->rflags & FILTRULE_DIRECTORY ? "/" : "", type); } @@ -886,6 +887,7 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr, } switch (ch) { case ':': + trust_sender_filter = 1; rule->rflags |= FILTRULE_PERDIR_MERGE | FILTRULE_FINISH_SETUP; /* FALL THROUGH */ diff --git a/flist.c b/flist.c index 5a1e424..5d5c7a2 100644 --- a/flist.c +++ b/flist.c @@ -72,6 +72,7 @@ extern int need_unsorted_flist; extern int sender_symlink_iconv; extern int output_needs_newline; extern int sender_keeps_checksum; +extern int trust_sender_filter; extern int unsort_ndx; extern uid_t our_uid; extern struct stats stats; @@ -971,6 +972,15 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x exit_cleanup(RERR_UNSUPPORTED); } + if (*thisname != '.' || thisname[1] != '\0') { + int filt_flags = S_ISDIR(mode) ? NAME_IS_DIR : NAME_IS_FILE; + if (!trust_sender_filter /* a per-dir filter rule means we must trust the sender's filtering */ + && filter_list.head && check_filter(&filter_list, FINFO, thisname, filt_flags) < 0) { + rprintf(FERROR, "ERROR: rejecting excluded file-list name: %s\n", thisname); + exit_cleanup(RERR_PROTOCOL); + } + } + if (inc_recurse && S_ISDIR(mode)) { if (one_file_system) { /* Room to save the dir's device for -x */ diff --git a/main.c b/main.c index 46b97b5..c688e6d 100644 --- a/main.c +++ b/main.c @@ -87,6 +87,7 @@ extern BOOL shutting_down; extern int backup_dir_len; extern int basis_dir_cnt; extern int default_af_hint; +extern int trust_sender_filter; extern struct stats stats; extern char *stdout_format; extern char *logfile_format; @@ -642,6 +643,7 @@ 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/receiver.c b/receiver.c index 9df603f..3182e2d 100644 --- a/receiver.c +++ b/receiver.c @@ -584,10 +584,13 @@ int recv_files(int f_in, int f_out, char *local_name) if (DEBUG_GTE(RECV, 1)) rprintf(FINFO, "recv_files(%s)\n", fname); - if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0') - && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) { - rprintf(FERROR, "attempt to hack rsync failed.\n"); - exit_cleanup(RERR_PROTOCOL); + if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0')) { + int filt_flags = S_ISDIR(file->mode) ? NAME_IS_DIR : NAME_IS_FILE; + if (check_filter(&daemon_filter_list, FLOG, fname, filt_flags) < 0) { + rprintf(FERROR, "ERROR: rejecting file transfer request for daemon excluded file: %s\n", + fname); + exit_cleanup(RERR_PROTOCOL); + } } #ifdef SUPPORT_XATTRS -- 2.27.0