The mode validation added as part of recent security hardening in recv_file_entry() (flist.c lines 864–876) breaks the --delete-missing-args feature when used with --files-from.
Steps to reproduce
echo "path/to/deleted/file.txt" | rsync --delete --delete-missing-args \
--files-from=- ./ user@remote:dest/
Where path/to/deleted/file.txt does not exist locally but exists on the remote.
Expected behaviour
The file is deleted on the remote, as documented for --delete-missing-args.
Actual behaviour
invalid file mode 00 for path/to/deleted/file.php [receiver]
rsync error: protocol incompatibility (code 2) at flist.c(874) [receiver=3.4.3]
Root cause
The sender deliberately sends mode=0 for missing-args entries — this is intentional by design, as documented in the sender code in flist.c:
} else /* (missing_args == 2) */ {
/* Send the arg as a "missing" entry with
* mode 0, which tells the generator to delete it. */
memset(&st, 0, sizeof st);
}
The generator in generator.c correctly handles this case:
if (missing_args == 2 && file->mode == 0) {
if (filter_list.head && check_filter(&filter_list, FINFO, fname, is_dir) < 0)
return;
if (statret == 0)
delete_item(fname, sx.st.st_mode, del_opts);
return;
}
However, the security validation added to recv_file_entry() rejects mode=0 before the entry ever reaches the generator:
if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode)
&& !S_ISCHR(mode) && !S_ISBLK(mode)
&& !S_ISFIFO(mode) && !S_ISSOCK(mode)) {
rprintf(FERROR, "invalid file mode 0%o for %s [%s]\n",
(unsigned)mode, lastname, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
Proposed fix
Add a missing_args == 2 exception to the mode validation:
if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode)
&& !S_ISCHR(mode) && !S_ISBLK(mode)
&& !S_ISFIFO(mode) && !S_ISSOCK(mode)
&& !(missing_args == 2 && mode == 0)) {
rprintf(FERROR, "invalid file mode 0%o for %s [%s]\n",
(unsigned)mode, lastname, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
Versions affected
3.4.3, plus security backports in 3.2.7. I haven't checked other versions.
The mode validation added as part of recent security hardening in
recv_file_entry()(flist.c lines 864–876) breaks the--delete-missing-argsfeature when used with--files-from.Steps to reproduce
Where
path/to/deleted/file.txtdoes not exist locally but exists on the remote.Expected behaviour
The file is deleted on the remote, as documented for
--delete-missing-args.Actual behaviour
Root cause
The sender deliberately sends
mode=0for missing-args entries — this is intentional by design, as documented in the sender code inflist.c:The generator in
generator.ccorrectly handles this case:However, the security validation added to
recv_file_entry()rejectsmode=0before the entry ever reaches the generator:Proposed fix
Add a
missing_args == 2exception to the mode validation:Versions affected
3.4.3, plus security backports in 3.2.7. I haven't checked other versions.