Commit 57edc480 authored by Matt McCutchen's avatar Matt McCutchen Committed by Wayne Davison

Avoid changing file_extra_cnt during deletion.

The I/O code can receive incremental file-list chunks during deletion,
and their OPT_EXTRA fields would get corrupted when file_extra_cnt is
incremented.

Instead of temporarily enabling uid_ndx to find out whether the user
owns a file, have make_file() set a flag for that purpose.

Applied with a few minor tweaks by Wayne.  Fixes bug 7936.
parent 69be312b
......@@ -28,7 +28,6 @@ extern int max_delete;
extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
extern uid_t our_uid;
extern struct stats stats;
int ignore_perishable = 0;
......@@ -98,7 +97,7 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
}
strlcpy(p, fp->basename, remainder);
if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
do_chmod(fname, fp->mode | S_IWUSR);
/* Save stack by recursing to ourself directly. */
if (S_ISDIR(fp->mode)) {
......@@ -143,19 +142,12 @@ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
do_chmod(fbuf, mode | S_IWUSR);
if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
int save_uid_ndx = uid_ndx;
/* This only happens on the first call to delete_item() since
* delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
if (!uid_ndx)
uid_ndx = ++file_extra_cnt;
ignore_perishable = 1;
/* If DEL_RECURSE is not set, this just reports emptiness. */
ret = delete_dir_contents(fbuf, flags);
ignore_perishable = 0;
if (!save_uid_ndx) {
--file_extra_cnt;
uid_ndx = 0;
}
if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)
goto check_ret;
/* OK: try to delete the directory. */
......
......@@ -69,6 +69,7 @@ extern int sender_symlink_iconv;
extern int output_needs_newline;
extern int sender_keeps_checksum;
extern int unsort_ndx;
extern uid_t our_uid;
extern struct stats stats;
extern char *filesfrom_host;
extern char *usermap, *groupmap;
......@@ -1371,10 +1372,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
}
#endif
file->mode = st.st_mode;
if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
if (preserve_uid)
F_OWNER(file) = st.st_uid;
if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
if (preserve_gid)
F_GROUP(file) = st.st_gid;
if (am_generator && st.st_uid == our_uid)
file->flags |= FLAG_OWNED_BY_US;
if (basename != thisname)
file->dirname = lastdir;
......
......@@ -276,7 +276,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
struct file_list *dirlist;
char delbuf[MAXPATHLEN];
int dlen, i;
int save_uid_ndx = uid_ndx;
if (!fbuf) {
change_local_filter_dir(NULL, 0, 0);
......@@ -308,9 +307,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
return;
}
if (!uid_ndx)
uid_ndx = ++file_extra_cnt;
dirlist = get_dirlist(fbuf, dlen, 0);
/* If an item in dirlist is not found in flist, delete it
......@@ -330,7 +326,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
* a delete_item call with a DEL_MAKE_ROOM flag. */
if (flist_find_ignore_dirness(cur_flist, fp) < 0) {
int flags = DEL_RECURSE;
if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
flags |= DEL_NO_UID_WRITE;
f_name(fp, delbuf);
if (delete_during == 2) {
......@@ -342,11 +338,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
}
flist_free(dirlist);
if (!save_uid_ndx) {
--file_extra_cnt;
uid_ndx = 0;
}
}
/* This deletes any files on the receiving side that are not present on the
......
......@@ -66,6 +66,7 @@
/* These flags are used in the live flist data. */
#define FLAG_TOP_DIR (1<<0) /* sender/receiver/generator */
#define FLAG_OWNED_BY_US (1<<0) /* generator: set by make_file() for aux flists only */
#define FLAG_FILE_SENT (1<<1) /* sender/receiver/generator */
#define FLAG_DIR_CREATED (1<<1) /* generator */
#define FLAG_CONTENT_DIR (1<<2) /* sender/receiver/generator */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment