From owner-svn-soc-all@FreeBSD.ORG Sat Jul 16 10:43:17 2011 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id 3834F106566B for ; Sat, 16 Jul 2011 10:43:15 +0000 (UTC) (envelope-from gk@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Sat, 16 Jul 2011 10:43:15 +0000 Date: Sat, 16 Jul 2011 10:43:15 +0000 From: gk@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20110716104315.3834F106566B@hub.freebsd.org> Cc: Subject: socsvn commit: r224305 - in soc2011/gk/ino64-head/sys: fs/nfsclient nfsclient X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 16 Jul 2011 10:43:17 -0000 Author: gk Date: Sat Jul 16 10:43:14 2011 New Revision: 224305 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=224305 Log: Fix NFS readdir offset and buffer size alignment Align read result by DIRBLKSIZ (512 bytes) Fail if buffer is less than DIRBLKSIZ Bug fixed: getdirentries() call with not DIRBLKSIZ aligned offset and/or buffer size results in file offset that doesn't start on dirent boundary. Next getdirentries() call will return garbled output. Todo: Application is still allowed to use arbitrary offsets. Unlike other filesystems NFS readdir will not "correct" offset and will fill buffer with data that doesn't start on dirent boundary. Modified: soc2011/gk/ino64-head/sys/fs/nfsclient/nfs_clbio.c soc2011/gk/ino64-head/sys/nfsclient/nfs_bio.c Modified: soc2011/gk/ino64-head/sys/fs/nfsclient/nfs_clbio.c ============================================================================== --- soc2011/gk/ino64-head/sys/fs/nfsclient/nfs_clbio.c Sat Jul 16 10:43:03 2011 (r224304) +++ soc2011/gk/ino64-head/sys/fs/nfsclient/nfs_clbio.c Sat Jul 16 10:43:14 2011 (r224305) @@ -459,6 +459,8 @@ return (0); if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */ return (EINVAL); + if (vp->v_type == VDIR && uio->uio_resid < DIRBLKSIZ) + return (EINVAL); td = uio->uio_td; mtx_lock(&nmp->nm_mtx); @@ -601,6 +603,8 @@ && uio->uio_offset >= np->n_direofoffset) { return (0); } + if (uio->uio_resid < DIRBLKSIZ) + return (0); lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ; on = uio->uio_offset & (NFS_DIRBLKSIZ - 1); bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td); @@ -709,6 +713,9 @@ n = lmin(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on); if (np->n_direofoffset && n > np->n_direofoffset - uio->uio_offset) n = np->n_direofoffset - uio->uio_offset; + else + /* Align offset. Abort if n <= 0 or resid < DIRBLKSIZ */ + n -= (uio->uio_offset + n) & (DIRBLKSIZ - 1); break; default: ncl_printf(" ncl_bioread: type %x unexpected\n", vp->v_type); Modified: soc2011/gk/ino64-head/sys/nfsclient/nfs_bio.c ============================================================================== --- soc2011/gk/ino64-head/sys/nfsclient/nfs_bio.c Sat Jul 16 10:43:03 2011 (r224304) +++ soc2011/gk/ino64-head/sys/nfsclient/nfs_bio.c Sat Jul 16 10:43:14 2011 (r224305) @@ -458,6 +458,8 @@ return (0); if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */ return (EINVAL); + if (vp->v_type == VDIR && uio->uio_resid < DIRBLKSIZ) + return (EINVAL); td = uio->uio_td; mtx_lock(&nmp->nm_mtx); @@ -594,6 +596,8 @@ && uio->uio_offset >= np->n_direofoffset) { return (0); } + if (uio->uio_resid < DIRBLKSIZ) + return (0); lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ; on = uio->uio_offset & (NFS_DIRBLKSIZ - 1); bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td); @@ -702,6 +706,10 @@ n = lmin(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on); if (np->n_direofoffset && n > np->n_direofoffset - uio->uio_offset) n = np->n_direofoffset - uio->uio_offset; + else { + /* Align offset. Abort if n <= 0 or resid < DIRBLKSIZ */ + n -= (uio->uio_offset + n) & (DIRBLKSIZ - 1); + } break; default: nfs_printf(" nfs_bioread: type %x unexpected\n", vp->v_type);