BUG: possible NULL pointer dereference in nfs server

Rick Macklem rmacklem at uoguelph.ca
Mon Feb 24 03:13:05 UTC 2014


Dimitry Andric wrote:
> On 23 Feb 2014, at 22:33, Dimitry Andric <dim at freebsd.org> wrote:
> > On 01 Feb 2014, at 00:52, Rick Macklem <rmacklem at uoguelph.ca>
> > wrote:
> >> John Baldwin wrote:
> > ...
> >>> OTOH, the new_lfpp thing just seems to be obfuscation.  Seems you
> >>> can
> >>> remove
> >>> one layer of pointer there.  It doesn't help you with the
> >>> compiler
> >>> not being
> >>> able to see the invariant that prevents the problem though.
> >>> 
> >>> Index: nfs_nfsdstate.c
> >>> ===================================================================
> >>> --- nfs_nfsdstate.c	(revision 261291)
> >>> +++ nfs_nfsdstate.c	(working copy)
> >>> @@ -79,7 +79,7 @@ static int nfsrv_getstate(struct nfsclient
> >>> *clp, n
> >>> static void nfsrv_getowner(struct nfsstatehead *hp, struct
> >>> nfsstate
> >>> *new_stp,
> >>>    struct nfsstate **stpp);
> >>> static int nfsrv_getlockfh(vnode_t vp, u_short flags,
> >>> -    struct nfslockfile **new_lfpp, fhandle_t *nfhp, NFSPROC_T
> >>> *p);
> >>> +    struct nfslockfile *new_lfp, fhandle_t *nfhp, NFSPROC_T *p);
> >>> static int nfsrv_getlockfile(u_short flags, struct nfslockfile
> >>> **new_lfpp,
> >>>    struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit);
> >>> static void nfsrv_insertlock(struct nfslock *new_lop,
> >>> @@ -1985,7 +1985,7 @@ tryagain:
> >>> 	MALLOC(new_lfp, struct nfslockfile *, sizeof (struct
> >>> 	nfslockfile),
> >>> 	    M_NFSDLOCKFILE, M_WAITOK);
> >>> 	if (vp)
> >>> -		getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, &new_lfp,
> >>> +		getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
> >>> 		    NULL, p);
> >>> 	NFSLOCKSTATE();
> >>> 	/*
> >>> @@ -2235,7 +2235,7 @@ tryagain:
> >>> 	    M_NFSDSTATE, M_WAITOK);
> >>> 	MALLOC(new_deleg, struct nfsstate *, sizeof (struct nfsstate),
> >>> 	    M_NFSDSTATE, M_WAITOK);
> >>> -	getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, &new_lfp,
> >>> +	getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
> >>> 	    NULL, p);
> >>> 	NFSLOCKSTATE();
> >>> 	/*
> >>> @@ -3143,10 +3143,9 @@ out:
> >>> */
> >>> static int
> >>> nfsrv_getlockfh(vnode_t vp, u_short flags,
> >>> -    struct nfslockfile **new_lfpp, fhandle_t *nfhp, NFSPROC_T
> >>> *p)
> >>> +    struct nfslockfile *new_lfp, fhandle_t *nfhp, NFSPROC_T *p)
> >>> {
> >>> 	fhandle_t *fhp = NULL;
> >>> -	struct nfslockfile *new_lfp;
> >>> 	int error;
> >>> 
> >>> 	/*
> >>> @@ -3154,7 +3153,6 @@ nfsrv_getlockfh(vnode_t vp, u_short flags,
> >>> 	 * a fhandle_t on the stack.
> >>> 	 */
> >>> 	if (flags & NFSLCK_OPEN) {
> >>> -		new_lfp = *new_lfpp;
> >>> 		fhp = &new_lfp->lf_fh;
> >>> 	} else if (nfhp) {
> >>> 		fhp = nfhp;
> >>> 
> >>> 
> >> Yep, this looks good to me, although I have no idea if it makes
> >> the
> >> compiler happy?
> > 
> > It seems to, though I think it could still crash if it ever got its
> > flags in an unexpected state, while new_lfp is NULL.  Let's just
> > hope
> > that never happens.
> > 
> > So can we commit jhb's patch now?  That would be very handy for my
> > clang-sparc64 project branch. :)
> 
> Alternatively, just this simple fix:
> 
> Index: sys/fs/nfsserver/nfs_nfsdstate.c
> ===================================================================
> --- sys/fs/nfsserver/nfs_nfsdstate.c    (revision 262397)
> +++ sys/fs/nfsserver/nfs_nfsdstate.c    (working copy)
> @@ -3154,6 +3154,9 @@ nfsrv_getlockfh(vnode_t vp, u_short flags,
>          * a fhandle_t on the stack.
>          */
>         if (flags & NFSLCK_OPEN) {
> +               if (new_lfpp == NULL) {
> +                       panic("nfsrv_getlockfh");
> +               }
>                 new_lfp = *new_lfpp;
>                 fhp = &new_lfp->lf_fh;
>         } else if (nfhp) {
> 
> If new_lfpp is really never going to be NULL the panic will never be
> hit.  If the "impossible" happens anyway, you will have a nice panic.
> 
> No undefined behavior anywhere anymore, and no need for abort()
> implementations. :-)
> 
> -Dimitry
> 
> 
I have no strong opinion on this, but I do think jhb@'s patch cleans up
the code (and I think I mentioned before that I didn't know if it made the
compiler happy).

Personally, I'd suggest jhb@'s patch plus whatever it takes to make clang
happy.

I can't do commits until mid-April, so I'd suggest you guys commit whatever
you think is appropriate.

rick


More information about the freebsd-fs mailing list