Subject: Re: NFSv3 bug
To: Love <lha@stacken.kth.se>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-kern
Date: 09/26/2002 23:24:55
--dDRMvlgZJXvWKvBx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Thu, Sep 26, 2002 at 11:07:20PM +0200, Love wrote:
> Manuel Bouyer <bouyer@antioche.lip6.fr> writes:
> 
> > On Thu, Sep 26, 2002 at 08:06:36PM +0200, Manuel Bouyer wrote:
> > > Hum, we have the size of the file in struct vnode, so if it's up to date
> > > at this point, we could use that (off, vp->v_size - off). But I didn't
> > > try this one. I'll do tomorow, unless someone can tell me it won't
> > > work just by reading the code :)
> > 
> > Well, it doens't work (couldn't wait till tomorow :).
> > If should be (off, vp->v_size), not (off, vp->v_size - off).
> > This one does work.
> 
> What stops the client from sending a off + cnt that is larger then quad_t
> that also will trigger the assert ?

Well, this would be a bug in the client, then :)
We should probably sanity-check what we get from network, but then the whole
NFS code needs to be audited. That's more than what I can do at this time.
I can fix this one however. Would anyone object to the attached patch ?

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
--

--dDRMvlgZJXvWKvBx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.nfs3"

Index: nfs_serv.c
===================================================================
RCS file: /cvsroot/syssrc/sys/nfs/nfs_serv.c,v
retrieving revision 1.64
diff -u -r1.64 nfs_serv.c
--- nfs_serv.c	2002/09/26 20:41:25	1.64
+++ nfs_serv.c	2002/09/26 21:24:31
@@ -2989,7 +2989,7 @@
 	int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
 	char *cp2;
 	struct mbuf *mb, *mb2, *mreq;
-	u_quad_t frev, off;
+	u_quad_t frev, off, end;
 
 #ifndef nolint
 	cache = 0;
@@ -3009,10 +3009,10 @@
 		return (0);
 	}
 	for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
-	if (cnt > 0)
-		error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, off + cnt, procp);
-	else
-		error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, vp->v_size, procp);
+	end = (cnt > 0) ? off + cnt : vp->v_size;
+	if (end < off)
+		end = vp->v_size;
+	error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, end, procp);
 	aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
 	vput(vp);
 	nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);

--dDRMvlgZJXvWKvBx--