Bug 7489 - rsyncd segfaults using daemon exclude filter
Summary: rsyncd segfaults using daemon exclude filter
Status: RESOLVED FIXED
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 3.0.6
Hardware: x86 Linux
: P3 normal (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-06-02 16:11 UTC by Michael Roberts
Modified: 2010-06-05 01:12 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Roberts 2010-06-02 16:11:09 UTC
Using target side filters in rsyncd.conf works well for files that are
only manipulated on the target.

However, if files from the source system match a filter on the target you can
generate a core and rsync will stop responding on that system.

in /var/log/messages you will see:

May 28 19:47:06 v-lab-30-244-127 rsyncd[9157]: receiving file list
May 28 19:47:06 v-lab-30-244-127 rsyncd[9157]: skipping daemon-excluded
directory ".snap1"
May 28 19:47:06 v-lab-30-244-127 rsyncd[9157]: *** Skipping any contents from
this failed directory ***
May 28 13:47:06 v-lab-30-244-127 kernel: rsyncd[9157]: segfault at
fffffffffffffff9 rip 0000003ba1a758bb rsp 00007fff5b1c7750 error 4

In this case '.snap1' directory was created, and a file created in that
directory.
The target has a filter:

.fs_*/***
.snap*/***

which matches, and the daemon dumps core.

The problem appears in versions 3.0.6, 3.0.7 & HEAD, it is in generator.c. There is an error path that takes a 'goto' that skips the initialization of sx struct, then the cleanup tries to free random memory with a call to free_acl(&sx). In acls.c the free is

void free_acl(stat_x *sxp)
{
        if (sxp->acc_acl) {
                rsync_acl_free(sxp->acc_acl);
                free(sxp->acc_acl);       <<<<<<< uninitialized



In version 3.0.6 the 'bad' goto is at line 1315:

                        rprintf(FERROR_XFER,
                                "skipping daemon-excluded %s \"%s\"\n",
                                is_dir ? "directory" : "file", fname);
                        if (is_dir)
                                goto skipping_dir_contents;  <<<<<<<<<<<<<<<<< bad goto


The fix is to move the initialization earlier in the code:

# diff -c generator.c.orig generator.c
*** generator.c.orig    2009-04-26 08:51:50.000000000 -0600
--- generator.c 2010-06-02 15:04:36.000000000 -0600
***************
*** 1300,1305 ****
--- 1300,1311 ----
                skip_dir = NULL;
        }

+ #ifdef SUPPORT_ACLS
+       sx.acc_acl = sx.def_acl = NULL;
+ #endif
+ #ifdef SUPPORT_XATTRS
+       sx.xattr = NULL;
+ #endif
        if (daemon_filter_list.head && (*fname != '.' || fname[1])) {
                if (check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {
                        if (is_dir < 0)
***************
*** 1317,1328 ****
                }
        }

- #ifdef SUPPORT_ACLS
-       sx.acc_acl = sx.def_acl = NULL;
- #endif
- #ifdef SUPPORT_XATTRS
-       sx.xattr = NULL;
- #endif
        if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
          parent_is_dry_missing:
                if (fuzzy_dirlist) {
--- 1323,1328 ----
Comment 1 Wayne Davison 2010-06-05 01:12:13 UTC
Thanks for the bug report and the fix!  This is now committed in the git repository (on both master and b3.0.x branches).