Funny issue with chroot + symlink outside chroot
Matt McCutchen
matt at mattmccutchen.net
Wed Jan 30 02:06:34 GMT 2008
On Sat, 2007-11-10 at 18:36 +0100, Olivier Thauvin wrote:
> How to reproduce:
> On server side I setup a tree and share using rsync + xinetd, of course, for
> security reason I use chroot option.
>
> Now I push this symlink:
> lrwxrwxrwx 1 root root 4 nov 10 16:28 horsroot -> /bin/
>
> Now I try to do:
> ./rsync -avPH --copy-unsafe-links draco::test/ /tmp/rsyncdest/
>
> (Of course the transfert will failed because /bin is outside the chroot.)
>
> The first problem is the error message is not push to stderr but stdout:
> ---------------------------
> [nanardon at draco rsync]$ rsync -avPH --copy-unsafe-links
> virgo::test/ /tmp/rsyncdest/ 2>/dev/null
> [...]
> file has vanished: "/horsroot" (in test)
> --------------------------
>
> Nothing is sent to stderr whereas error code is set:
> $ echo $?
> 24
>
> I had a look to flist.c/sender.c, it seems this is expected behavior:
> (flist.c:1037)
> enum logcode c = am_daemon && protocol_version < 28
> ? FERROR : FINFO;
> and indeed the message is produce by daemon, and I am using proto 29 or 30.
>
> Well, I also found the message is not the appropriate one, the file has not
> vanished (at least, we cannot know that, the file pointed is outside our
> tree).
>
> I tried this to fix, but this part is not trivial, and I am not sure this does
> not have side effect. (The patch is partial, the same should be applied to
> sender.c).
>
> diff -u -b -B -w -p -r1.468 flist.c
> --- flist.c 6 Nov 2007 15:25:02 -0000 1.468
> +++ flist.c 10 Nov 2007 17:21:51 -0000
> @@ -1026,8 +1026,8 @@ struct file_struct *make_file(const char
> if (save_errno == ENOENT) {
> #ifdef SUPPORT_LINKS
> /* Avoid "vanished" error if symlink points nowhere.
> */
> - if (copy_links && x_lstat(thisname, &st, NULL) == 0
> - && S_ISLNK(st.st_mode)) {
> + if ((copy_links && x_lstat(thisname, &st, NULL) == 0
> + && S_ISLNK(st.st_mode)) || x_stat(thisname, &st,
> NULL) != 0) {
> io_error |= IOERR_GENERAL;
> rprintf(FERROR, "symlink has no
> referent: %s\n",
> full_fname(thisname));
The trouble is that the "symlink has no referent" message needs to be
extended to apply to symlinks followed because of --copy-unsafe-links as
well as --copy-links. Your patch will trigger the message for *all*
vanishings regardless of whether a symlink is involved, which is wrong.
My proposed patch will follow.
Matt
More information about the rsync
mailing list