PR kern/41147: race between nfsd and local rm

Note that the race also exists between 2 nfs client, one of them doing the rm.
In ufs_ihashget(), vget() can return a vnode that has been vclean'ed because
vget() can sleep. After vget returns, check that vp is still connected with
ip, and that ip still points to the inode we want. This fix the NULL
pointer dereference in ufs_fhtovp() I've been seeing on a NFS server.

XXX I have no idea why using vput() instead of
vlockmgr(vp->v_vnlock, LK_RELEASE); vrele(vp); does not work.
This commit is contained in:
bouyer 2009-09-20 14:00:24 +00:00
parent 5a6dad0a4b
commit 7de71fb523
1 changed files with 11 additions and 2 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_ihash.c,v 1.26 2008/05/05 17:11:17 ad Exp $ */
/* $NetBSD: ufs_ihash.c,v 1.27 2009/09/20 14:00:24 bouyer Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ufs_ihash.c,v 1.26 2008/05/05 17:11:17 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ufs_ihash.c,v 1.27 2009/09/20 14:00:24 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -152,6 +152,15 @@ ufs_ihashget(dev_t dev, ino_t inum, int flags)
mutex_exit(&ufs_ihash_lock);
if (vget(vp, flags | LK_INTERLOCK))
goto loop;
if (VTOI(vp) != ip ||
ip->i_number != inum || ip->i_dev != dev) {
/* lost race against vclean() */
if (vlockmgr(vp->v_vnlock, LK_RELEASE))
printf("can't release lock\n");
vrele(vp);
vp = NULL;
goto loop;
}
}
return (vp);
}