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