svn commit: r283273 - head/sys/fs/nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Thu May 21 23:14:19 UTC 2015
Author: rmacklem
Date: Thu May 21 23:14:18 2015
New Revision: 283273
URL: https://svnweb.freebsd.org/changeset/base/283273
Log:
The NFS client wasn't handling getdirentries(2) requests for sizes
that are not an exact multiple of DIRBLKSIZ correctly. Fortunately
readdir(3) always uses an exact multiple of DIRBLKSIZ, so few applications
were affected. This patch fixes this problem by reducing the size
of the directory read to an exact multiple of DIRBLKSIZ.
Tested by: trasz
Reported by: trasz
Reviewed by: trasz
MFC after: 2 weeks
Modified:
head/sys/fs/nfsclient/nfs_clvnops.c
Modified: head/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clvnops.c Thu May 21 22:50:39 2015 (r283272)
+++ head/sys/fs/nfsclient/nfs_clvnops.c Thu May 21 23:14:18 2015 (r283273)
@@ -2210,7 +2210,7 @@ nfs_readdir(struct vop_readdir_args *ap)
struct vnode *vp = ap->a_vp;
struct nfsnode *np = VTONFS(vp);
struct uio *uio = ap->a_uio;
- ssize_t tresid;
+ ssize_t tresid, left;
int error = 0;
struct vattr vattr;
@@ -2239,6 +2239,17 @@ nfs_readdir(struct vop_readdir_args *ap)
}
/*
+ * NFS always guarantees that directory entries don't straddle
+ * DIRBLKSIZ boundaries. As such, we need to limit the size
+ * to an exact multiple of DIRBLKSIZ, to avoid copying a partial
+ * directory entry.
+ */
+ left = uio->uio_resid % DIRBLKSIZ;
+ if (left == uio->uio_resid)
+ return (EINVAL);
+ uio->uio_resid -= left;
+
+ /*
* Call ncl_bioread() to do the real work.
*/
tresid = uio->uio_resid;
@@ -2249,6 +2260,9 @@ nfs_readdir(struct vop_readdir_args *ap)
if (ap->a_eofflag != NULL)
*ap->a_eofflag = 1;
}
+
+ /* Add the partial DIRBLKSIZ (left) back in. */
+ uio->uio_resid += left;
return (error);
}
More information about the svn-src-all
mailing list