BUG: possible NULL pointer dereference in nfs server
Rick Macklem
rmacklem at uoguelph.ca
Fri Jan 31 23:52:06 UTC 2014
John Baldwin wrote:
> On Tuesday, January 28, 2014 4:40:45 am Roman Divacky wrote:
> > > > Yea, so long as it includes a comment that states this is done
> > > > to
> > > > work around a stupid compiler bug.
> > >
> > > Ugh.
> > >
> > > The above has the following bugs:
> > > - gross style bugs (lines longer than 80 characters)
> > > - large code to do nothing
> > > - would be even larger with a comment
> > > - cannot actually work around any compiler bug involving abort(),
> > > since it
> > > has no effect on production kernels where KASSERT() is null.
> > >
> > > >> It is present even in your setup :) Just "objdump -d kernel |
> > > >> grep
> > > >> ud2" on kernel compiled
> > > >> by clang.
> > > >>
> > > > I actually use gcc, but I believe you. I'll admit I still don't
> > > > understand
> > > > why having a trap instruction that never gets executed is a bad
> > > > thing?
> > >
> > > It isn't but trying to link to the noexistent function abort() on
> > > arches that don't have any trap instruction is a bad thing.
> > > According
> > > the above, this occurs on sparc64. It must be a gcc bug, since
> > > sparc64
> > > doesn't have clang. However, I couldn't get gcc on sparc64 to
> > > generate
> > > an abort() for *NULL. Similarly on x86 (gcc is hard to test on
> > > x86,
> > > since it is broken (not installed) on FreeBSD cluster machines
> > > for
> >
> > I was testing clang compiled kernel on sparc64.
> >
> > The problem is that there's nothing making sure that the NULL
> > pointer
> > dereference doesnt happen. So if someone happens to call the
> > function with
> > wrong flags it will crash.
> >
> > Thats why I want to add the KASSERT, to catch possible future cases
> > when this happens.
> >
> > Unfortunately our KASSERT is not an assert so to remove the actual
> > abort/trap/ud2 I have to remove the flag.
>
> Why not make a simple abort() that calls panic()? It seems clumsy to
> have to
> add hacks in the source code.
>
> 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?
I think the new_lfpp argument was a vestige
created when nfsrv_getlockfh() became a separate function from nfsrv_getlockfile()
during development. (The latter needs the "**", since it sets it to NULL to
indicate the new structure is being used and shouldn't be free'd.)
rick
> --
> John Baldwin
> _______________________________________________
> freebsd-fs at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-fs
> To unsubscribe, send any mail to "freebsd-fs-unsubscribe at freebsd.org"
>
More information about the freebsd-fs
mailing list