svn commit: r206821 - stable/8/sys/fs/nfsserver

Rick Macklem rmacklem at FreeBSD.org
Sun Apr 18 22:51:16 UTC 2010


Author: rmacklem
Date: Sun Apr 18 22:51:15 2010
New Revision: 206821
URL: http://svn.freebsd.org/changeset/base/206821

Log:
  MFC: r206170
  Harden the experimental NFS server a little, by adding extra checks
  in the readdir functions for non-positive byte count arguments.
  For the negative case, set it to the maximum allowable, since it
  was actually a large positive value (unsigned) on the wire.
  Also, fix up the readdir function comment a bit.

Modified:
  stable/8/sys/fs/nfsserver/nfs_nfsdport.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/dev/uath/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- stable/8/sys/fs/nfsserver/nfs_nfsdport.c	Sun Apr 18 22:34:29 2010	(r206820)
+++ stable/8/sys/fs/nfsserver/nfs_nfsdport.c	Sun Apr 18 22:51:15 2010	(r206821)
@@ -1397,24 +1397,16 @@ nfsvno_fillattr(struct nfsrv_descript *n
  * nfs readdir service
  * - mallocs what it thinks is enough to read
  *	count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR
- * - calls nfsvno_readdir()
+ * - calls VOP_READDIR()
  * - loops around building the reply
  *	if the output generated exceeds count break out of loop
  *	The NFSM_CLGET macro is used here so that the reply will be packed
  *	tightly in mbuf clusters.
- * - it only knows that it has encountered eof when the nfsvno_readdir()
- *	reads nothing
- * - as such one readdir rpc will return eof false although you are there
- *	and then the next will return eof
  * - it trims out records with d_fileno == 0
  *	this doesn't matter for Unix clients, but they might confuse clients
  *	for other os'.
  * - it trims out records with d_type == DT_WHT
  *	these cannot be seen through NFS (unless we extend the protocol)
- * NB: It is tempting to set eof to true if the nfsvno_readdir() reads less
- *	than requested, but this may not apply to all filesystems. For
- *	example, client NFS does not { although it is never remote mounted
- *	anyhow }
  *     The alternate call nfsrvd_readdirplus() does lookups as well.
  * PS: The NFS protocol spec. does not clarify what the "count" byte
  *	argument is a count of.. just name strings and file id's or the
@@ -1456,7 +1448,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd
 	}
 	toff = off;
 	cnt = fxdr_unsigned(int, *tl);
-	if (cnt > NFS_SRVMAXDATA(nd))
+	if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0)
 		cnt = NFS_SRVMAXDATA(nd);
 	siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 	fullsiz = siz;
@@ -1474,6 +1466,13 @@ nfsrvd_readdir(struct nfsrv_descript *nd
 			nd->nd_repstat = NFSERR_BAD_COOKIE;
 #endif
 	}
+	if (nd->nd_repstat == 0 && cnt == 0) {
+		if (nd->nd_flag & ND_NFSV2)
+			/* NFSv2 does not have NFSERR_TOOSMALL */
+			nd->nd_repstat = EPERM;
+		else
+			nd->nd_repstat = NFSERR_TOOSMALL;
+	}
 	if (!nd->nd_repstat)
 		nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
 		    nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
@@ -1696,7 +1695,7 @@ nfsrvd_readdirplus(struct nfsrv_descript
 	 * Use the server's maximum data transfer size as the upper bound
 	 * on reply datalen.
 	 */
-	if (cnt > NFS_SRVMAXDATA(nd))
+	if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0)
 		cnt = NFS_SRVMAXDATA(nd);
 
 	/*
@@ -1705,7 +1704,7 @@ nfsrvd_readdirplus(struct nfsrv_descript
 	 * so I set it to cnt for that case. I also round it up to the
 	 * next multiple of DIRBLKSIZ.
 	 */
-	if (siz == 0)
+	if (siz <= 0)
 		siz = cnt;
 	siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 


More information about the svn-src-stable mailing list