From owner-svn-src-stable@FreeBSD.ORG Sun Apr 18 22:51:16 2010 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3C5B2106566C; Sun, 18 Apr 2010 22:51:16 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2A75C8FC1B; Sun, 18 Apr 2010 22:51:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3IMpGVk018259; Sun, 18 Apr 2010 22:51:16 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3IMpGJb018257; Sun, 18 Apr 2010 22:51:16 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201004182251.o3IMpGJb018257@svn.freebsd.org> From: Rick Macklem Date: Sun, 18 Apr 2010 22:51:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r206821 - stable/8/sys/fs/nfsserver X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Apr 2010 22:51:16 -0000 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));