Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 9 Aug 2015 22:07:52 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r286558 - stable/9/sys/fs/nfsclient
Message-ID:  <201508092207.t79M7q5L061751@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sun Aug  9 22:07:52 2015
New Revision: 286558
URL: https://svnweb.freebsd.org/changeset/base/286558

Log:
  MFC: r283273
  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.

Modified:
  stable/9/sys/fs/nfsclient/nfs_clvnops.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/fs/   (props changed)

Modified: stable/9/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- stable/9/sys/fs/nfsclient/nfs_clvnops.c	Sun Aug  9 21:32:05 2015	(r286557)
+++ stable/9/sys/fs/nfsclient/nfs_clvnops.c	Sun Aug  9 22:07:52 2015	(r286558)
@@ -2191,7 +2191,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;
 	
@@ -2220,6 +2220,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;
@@ -2230,6 +2241,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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508092207.t79M7q5L061751>