should vn_fullpath1() ever return a path with "." in it?
Konstantin Belousov
kostikbel at gmail.com
Thu Feb 28 07:05:23 UTC 2013
On Wed, Feb 27, 2013 at 09:59:22PM -0500, Rick Macklem wrote:
> Hi,
>
> Sergey Kandaurov reported a problem where getcwd() returns a
> path with "/./" imbedded in it for an NFSv4 mount. This is
> caused by a mount point crossing on the server when at the
> server's root because vn_fullpath1() uses VV_ROOT to spot
> mount point crossings.
>
> The current workaround is to use the sysctls:
> debug.disablegetcwd=1
> debug.disablefullpath=1
>
> However, it would be nice to fix this when vn_fullpath1()
> is being used.
>
> A simple fix is to have vn_fullpath1() fail when it finds
> "." as a directory match in the path. When vn_fullpath1()
> fails, the syscalls fail and that allows the libc algorithm
> to be used (which works for this case because it doesn't
> depend on VV_ROOT being set, etc).
>
> So, I am wondering if a patch (I have attached one) that
> makes vn_fullpath1() fail when it matches "." will break
> anything else? (I don't think so, since the code checks
> for VV_ROOT in the loop above the check for a match of
> ".", but I am not sure?)
>
> Thanks for any input w.r.t. this, rick
> --- kern/vfs_cache.c.sav 2013-02-27 20:44:42.000000000 -0500
> +++ kern/vfs_cache.c 2013-02-27 21:10:39.000000000 -0500
> @@ -1333,6 +1333,20 @@ vn_fullpath1(struct thread *td, struct v
> startvp, NULL, 0, 0);
> break;
> }
> + if (buf[buflen] == '.' && (buf[buflen + 1] == '\0' ||
> + buf[buflen + 1] == '/')) {
> + /*
> + * Fail if it matched ".". This should only happen
> + * for NFSv4 mounts that cross server mount points.
> + */
> + CACHE_RUNLOCK();
> + vrele(vp);
> + numfullpathfail1++;
> + error = ENOENT;
> + SDT_PROBE(vfs, namecache, fullpath, return,
> + error, vp, NULL, 0, 0);
> + break;
> + }
> buf[--buflen] = '/';
> slash_prefixed = 1;
> }
I do not quite understand this. Did the dvp (parent) vnode returned by
VOP_VPTOCNP() equal to vp (child) vnode in the case of the "." name ?
It must be, for the correct operation, but also it should cause the almost
infinite loop in the vn_fullpath1(). The loop is not really infinite due
to a limited size of the buffer where the infinite amount of "./" is placed.
Anyway, I think we should do better than this patch, even if it is
legitimate. I think that the better place to check the condition is the
default implementation of VOP_VPTOCNP(). Am I right that this is where
it broke for you ?
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index 00d064e..1dd0185 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -856,8 +856,12 @@ vop_stdvptocnp(struct vop_vptocnp_args *ap)
error = ENOMEM;
goto out;
}
- bcopy(dp->d_name, buf + i, dp->d_namlen);
- error = 0;
+ if (dp->d_namlen == 1 && dp->d_name[0] == '.') {
+ error = ENOENT;
+ } else {
+ bcopy(dp->d_name, buf + i, dp->d_namlen);
+ error = 0;
+ }
goto out;
}
} while (len > 0 || !eofflag);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 834 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-fs/attachments/20130228/4a75349e/attachment.sig>
More information about the freebsd-fs
mailing list