socsvn commit: r224305 - in soc2011/gk/ino64-head/sys: fs/nfsclient
nfsclient
gk at FreeBSD.org
gk at FreeBSD.org
Sat Jul 16 10:43:17 UTC 2011
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);
More information about the svn-soc-all
mailing list