From ea53d161be54a474088df51063df128ff5da5af4 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Fri, 10 Apr 2009 16:09:39 -0700 Subject: [PATCH] Fixed an ACL/xattr corruption issue where the --backup option could cause rsync to associate the wrong ACL/xattr information with received files. --- NEWS | 3 +++ acls.c | 38 +++++++++++++++++++++++++++++++++++++- backup.c | 32 ++++++++++++++++++++++++++++---- xattrs.c | 21 ++++++++++++++++++++- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 1e80e042..a077de62 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,9 @@ Changes since 3.0.5: - Fixed the dropping of an ACL mask when no named ACL values were present. + - Fixed an ACL/xattr corruption issue where the --backup option could cause + rsync to associate the wrong ACL/xattr information with received files. + - Fixed the use of --dry-run with --read-batch. - Fixed configure's erroneous use of target. diff --git a/acls.c b/acls.c index 434bc61d..e2bdc4c9 100644 --- a/acls.c +++ b/acls.c @@ -88,6 +88,9 @@ static const rsync_acl empty_rsync_acl = { static item_list access_acl_list = EMPTY_ITEM_LIST; static item_list default_acl_list = EMPTY_ITEM_LIST; +static size_t prior_access_count = (size_t)-1; +static size_t prior_default_count = (size_t)-1; + /* === Calculations on ACL types === */ static const char *str_acl_type(SMB_ACL_TYPE_T type) @@ -788,17 +791,50 @@ static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl /* Turn the ACL data in stat_x into cached ACL data, setting the index * values in the file struct. */ -void cache_acl(struct file_struct *file, stat_x *sxp) +void cache_tmp_acl(struct file_struct *file, stat_x *sxp) { + if (prior_access_count == (size_t)-1) + prior_access_count = access_acl_list.count; + F_ACL(file) = cache_rsync_acl(sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list); if (S_ISDIR(sxp->st.st_mode)) { + if (prior_default_count == (size_t)-1) + prior_default_count = default_acl_list.count; F_DIR_DEFACL(file) = cache_rsync_acl(sxp->def_acl, SMB_ACL_TYPE_DEFAULT, &default_acl_list); } } +static void uncache_duo_acls(item_list *duo_list, size_t start) +{ + acl_duo *duo_item = duo_list->items; + acl_duo *duo_start = duo_item + start; + + duo_item += duo_list->count; + duo_list->count = start; + + while (duo_item-- > duo_start) { + rsync_acl_free(&duo_item->racl); + if (duo_item->sacl) + sys_acl_free_acl(duo_item->sacl); + } +} + +void uncache_tmp_acls(void) +{ + if (prior_access_count != (size_t)-1) { + uncache_duo_acls(&access_acl_list, prior_access_count); + prior_access_count = (size_t)-1; + } + + if (prior_default_count != (size_t)-1) { + uncache_duo_acls(&default_acl_list, prior_default_count); + prior_default_count = (size_t)-1; + } +} + #ifndef HAVE_OSX_ACLS static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode, mode_t mode) { diff --git a/backup.c b/backup.c index ecc40d52..7512d921 100644 --- a/backup.c +++ b/backup.c @@ -148,19 +148,25 @@ int make_bak_dir(const char *fullpath) #ifdef SUPPORT_ACLS if (preserve_acls && !S_ISLNK(file->mode)) { get_acl(rel, &sx); - cache_acl(file, &sx); + cache_tmp_acl(file, &sx); free_acl(&sx); } #endif #ifdef SUPPORT_XATTRS if (preserve_xattrs) { get_xattr(rel, &sx); - cache_xattr(file, &sx); + cache_tmp_xattr(file, &sx); free_xattr(&sx); } #endif set_file_attrs(fbuf, file, NULL, NULL, 0); unmake_file(file); +#ifdef SUPPORT_ACLS + uncache_tmp_acls(); +#endif +#ifdef SUPPORT_XATTRS + uncache_tmp_xattrs(); +#endif } } *p = '/'; @@ -223,20 +229,26 @@ static int keep_backup(const char *fname) if (!(buf = get_backup_name(fname))) { unmake_file(file); +#ifdef SUPPORT_ACLS + uncache_tmp_acls(); +#endif +#ifdef SUPPORT_XATTRS + uncache_tmp_xattrs(); +#endif return 0; } #ifdef SUPPORT_ACLS if (preserve_acls && !S_ISLNK(file->mode)) { get_acl(fname, &sx); - cache_acl(file, &sx); + cache_tmp_acl(file, &sx); free_acl(&sx); } #endif #ifdef SUPPORT_XATTRS if (preserve_xattrs) { get_xattr(fname, &sx); - cache_xattr(file, &sx); + cache_tmp_xattr(file, &sx); free_xattr(&sx); } #endif @@ -326,6 +338,12 @@ static int keep_backup(const char *fname) rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname); unmake_file(file); +#ifdef SUPPORT_ACLS + uncache_tmp_acls(); +#endif +#ifdef SUPPORT_XATTRS + uncache_tmp_xattrs(); +#endif return 1; } @@ -344,6 +362,12 @@ static int keep_backup(const char *fname) set_file_attrs(buf, file, NULL, fname, 0); preserve_xattrs = save_preserve_xattrs; unmake_file(file); +#ifdef SUPPORT_ACLS + uncache_tmp_acls(); +#endif +#ifdef SUPPORT_XATTRS + uncache_tmp_xattrs(); +#endif if (verbose > 1) { rprintf(FINFO, "backed up %s to %s\n", diff --git a/xattrs.c b/xattrs.c index 0eb73237..674d3578 100644 --- a/xattrs.c +++ b/xattrs.c @@ -81,6 +81,8 @@ static char *namebuf = NULL; static item_list empty_xattr = EMPTY_ITEM_LIST; static item_list rsync_xal_l = EMPTY_ITEM_LIST; +static size_t prior_xattr_count = (size_t)-1; + /* ------------------------------------------------------------------------- */ static void rsync_xal_free(item_list *xalp) @@ -724,13 +726,15 @@ void receive_xattr(struct file_struct *file, int f) /* Turn the xattr data in stat_x into cached xattr data, setting the index * values in the file struct. */ -void cache_xattr(struct file_struct *file, stat_x *sxp) +void cache_tmp_xattr(struct file_struct *file, stat_x *sxp) { int ndx; if (!sxp->xattr) return; + if (prior_xattr_count == (size_t)-1) + prior_xattr_count = rsync_xal_l.count; ndx = find_matching_xattr(sxp->xattr); if (ndx < 0) rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */ @@ -738,6 +742,21 @@ void cache_xattr(struct file_struct *file, stat_x *sxp) F_XATTR(file) = ndx; } +void uncache_tmp_xattrs(void) +{ + if (prior_xattr_count != (size_t)-1) { + item_list *xattr_item = rsync_xal_l.items; + item_list *xattr_start = xattr_item + prior_xattr_count; + xattr_item += rsync_xal_l.count; + rsync_xal_l.count = prior_xattr_count; + while (xattr_item-- > xattr_start) { + rsync_xal_free(xattr_item); + free(xattr_item); + } + prior_xattr_count = (size_t)-1; + } +} + static int rsync_xal_set(const char *fname, item_list *xalp, const char *fnamecmp, stat_x *sxp) { -- 2.34.1