Date: Fri, 3 Dec 1999 23:26:29 +0000 (GMT) From: iedowse@maths.tcd.ie To: FreeBSD-gnats-submit@freebsd.org Subject: kern/15249: nfs_serv.c can vput() junk + more Message-ID: <199912032326.aa35944@bell.maths.tcd.ie>
next in thread | raw e-mail | index | archive | help
>Number: 15249 >Category: kern >Synopsis: nfs_serv.c can vput() junk + more >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Dec 3 15:30:01 PST 1999 >Closed-Date: >Last-Modified: >Originator: Ian Dowse >Release: FreeBSD 3.3-STABLE i386 >Organization: School of Mathematics Trinity College Dublin >Environment: All versions of FreeBSD >Description: There are a number of places in nfs_serv.c where certain badly-formed NFS requests can result in vput() being called on an uninitialised vnode pointer. In nfsrv_getattr(), nfsrv_lookup(), nfsrv_read(), and nfsrv_writegather(), the exit code performs a vput(vp) if vp is non-NULL. However since vp is not initialised before the macro nfsm_srvmtofh() is invoked, it is possible for this exit code to get called with a junk vp if nfsm_srvmtofh() does a 'goto nfsmout'. Another problem that affects even more functions is that on certain (mainly kerboros related) errors nfsrv_fhtovp() does not leave NULL in its *vpp argument. Finally there is a problem in nqnfsrv_getlease() where it is possible to get it to vput(NULL). >How-To-Repeat: To repeat the first problem, send a truncated request to an NFS server where the request ends in the middle of the filehandle. I haven't cwtried to trigger the others, but it should be fairly easy. >Fix: Apply the following patches in src/sys/nfs --- nfs_serv.c.orig Fri Dec 3 22:03:37 1999 +++ nfs_serv.c Fri Dec 3 22:22:35 1999 @@ -249,7 +249,7 @@ register struct nfs_fattr *fp; struct vattr va; register struct vattr *vap = &va; - struct vnode *vp; + struct vnode *vp = NULL; nfsfh_t nfh; fhandle_t *fhp; register u_int32_t *tl; @@ -453,7 +453,7 @@ struct ucred *cred = &nfsd->nd_cr; register struct nfs_fattr *fp; struct nameidata nd, ind, *ndp = &nd; - struct vnode *vp, *dirp; + struct vnode *vp, *dirp = NULL; nfsfh_t nfh; fhandle_t *fhp; register caddr_t cp; @@ -775,7 +775,7 @@ char *cp2; struct mbuf *mb, *mb2, *mreq; struct mbuf *m2; - struct vnode *vp; + struct vnode *vp = NULL; nfsfh_t nfh; fhandle_t *fhp; struct uio io, *uiop = &io; @@ -1168,7 +1168,7 @@ int ioflags, aftat_ret = 1, s, adjust, v3, zeroing; char *cp2; struct mbuf *mb, *mb2, *mreq, *mrep, *md; - struct vnode *vp; + struct vnode *vp = NULL; struct uio io, *uiop = &io; u_quad_t frev, cur_usec; --- nfs_subs.c.orig Fri Dec 3 22:25:21 1999 +++ nfs_subs.c Fri Dec 3 22:26:57 1999 @@ -1943,6 +1943,7 @@ register int i; struct ucred *credanon; int error, exflags; + struct vnode *vp; #ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */ struct sockaddr_int *saddr; #endif @@ -1961,7 +1962,7 @@ error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); if (error) return (error); - error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); + error = VFS_FHTOVP(mp, &fhp->fh_fid, &vp); if (error) return (error); #ifdef MNT_EXNORESPORT @@ -1969,7 +1970,7 @@ saddr = (struct sockaddr_in *)nam; if (saddr->sin_family == AF_INET && ntohs(saddr->sin_port) >= IPPORT_RESERVED) { - vput(*vpp); + vput(vp); return (NFSERR_AUTHERR | AUTH_TOOWEAK); } } @@ -1979,11 +1980,11 @@ */ if (exflags & MNT_EXKERB) { if (!kerbflag) { - vput(*vpp); + vput(vp); return (NFSERR_AUTHERR | AUTH_TOOWEAK); } } else if (kerbflag) { - vput(*vpp); + vput(vp); return (NFSERR_AUTHERR | AUTH_TOOWEAK); } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { cred->cr_uid = credanon->cr_uid; @@ -1996,10 +1997,11 @@ else *rdonlyp = 0; - nfsrv_object_create(*vpp); + nfsrv_object_create(vp); if (!lockflag) - VOP_UNLOCK(*vpp, 0, p); + VOP_UNLOCK(vp, 0, p); + *vpp = vp; return (0); } --- nfs_nqlease.c.orig Fri Dec 3 22:57:42 1999 +++ nfs_nqlease.c Fri Dec 3 23:03:56 1999 @@ -769,8 +769,10 @@ nfsd->nd_duration = fxdr_unsigned(int, *tl); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); - if (error) + if (error) { nfsm_reply(0); + goto nfsmout; + } if (rdonly && flags == ND_WRITE) { error = EROFS; vput(vp); >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199912032326.aa35944>