BUG: possible NULL pointer dereference in nfs server
Dimitry Andric
dim at FreeBSD.org
Sun Feb 23 21:49:04 UTC 2014
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 203 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.freebsd.org/pipermail/freebsd-fs/attachments/20140223/14c7afdd/attachment.sig>
More information about the freebsd-fs
mailing list