Using vfinddev() leads to vnode races as it returns an unreferenced
vnode that may disappear before the caller has a chance to reference it. Reference the vnode while the specfs cache is locked. Welcome to 5.99.37. No objections on tech-kern.
This commit is contained in:
parent
e698a5d246
commit
1664eae7f3
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: vnode.9,v 1.49 2010/06/06 08:01:31 hannken Exp $
|
||||
.\" $NetBSD: vnode.9,v 1.50 2010/07/21 09:06:37 hannken Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001, 2005, 2006 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
|
@ -27,7 +27,7 @@
|
|||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd June 6, 2010
|
||||
.Dd July 21, 2010
|
||||
.Dt VNODE 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -654,7 +654,7 @@ Create a vnode for a character device.
|
|||
is used for the console and kernfs special devices.
|
||||
.It Fn vfinddev "dev" "vtype" "vpp"
|
||||
Lookup a vnode by device number.
|
||||
The vnode is returned in the address specified by
|
||||
The vnode is referenced and returned in the address specified by
|
||||
.Fa vpp .
|
||||
.It Fn vdevgone "int maj" "int min" "int minh" "enum vtype type"
|
||||
Reclaim all vnodes that correspond to the specified minor number range
|
||||
|
|
|
@ -1146,6 +1146,9 @@ int drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
|
||||
done:
|
||||
request->count = dma->buf_count;
|
||||
#if defined(__NetBSD__)
|
||||
vrele(vn);
|
||||
#endif
|
||||
|
||||
DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vfs_subr.c,v 1.408 2010/07/01 13:00:56 hannken Exp $ */
|
||||
/* $NetBSD: vfs_subr.c,v 1.409 2010/07/21 09:06:38 hannken Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -91,7 +91,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.408 2010/07/01 13:00:56 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.409 2010/07/21 09:06:38 hannken Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
|
@ -1993,24 +1993,28 @@ vgone(vnode_t *vp)
|
|||
}
|
||||
|
||||
/*
|
||||
* Lookup a vnode by device number.
|
||||
* Lookup a vnode by device number and return it referenced.
|
||||
*/
|
||||
int
|
||||
vfinddev(dev_t dev, enum vtype type, vnode_t **vpp)
|
||||
{
|
||||
vnode_t *vp;
|
||||
int rc = 0;
|
||||
|
||||
mutex_enter(&device_lock);
|
||||
for (vp = specfs_hash[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
|
||||
if (dev != vp->v_rdev || type != vp->v_type)
|
||||
continue;
|
||||
*vpp = vp;
|
||||
rc = 1;
|
||||
break;
|
||||
if (dev == vp->v_rdev && type == vp->v_type)
|
||||
break;
|
||||
}
|
||||
if (vp == NULL) {
|
||||
mutex_exit(&device_lock);
|
||||
return 0;
|
||||
}
|
||||
mutex_enter(&vp->v_interlock);
|
||||
mutex_exit(&device_lock);
|
||||
return (rc);
|
||||
if (vget(vp, LK_INTERLOCK) != 0)
|
||||
return 0;
|
||||
*vpp = vp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3366,9 +3370,11 @@ rawdev_mounted(struct vnode *vp, struct vnode **bvpp)
|
|||
|
||||
blkdev = devsw_chr2blk(dev);
|
||||
if (blkdev != NODEV) {
|
||||
vfinddev(blkdev, VBLK, &bvp);
|
||||
if (bvp != NULL)
|
||||
if (vfinddev(blkdev, VBLK, &bvp) != 0) {
|
||||
d_type = (cdev->d_flag & D_TYPEMASK);
|
||||
/* XXX: what if bvp disappears? */
|
||||
vrele(bvp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kernfs_subr.c,v 1.21 2010/07/01 13:00:56 hannken Exp $ */
|
||||
/* $NetBSD: kernfs_subr.c,v 1.22 2010/07/21 09:06:38 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1993
|
||||
|
@ -73,7 +73,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kernfs_subr.c,v 1.21 2010/07/01 13:00:56 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kernfs_subr.c,v 1.22 2010/07/21 09:06:38 hannken Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -176,8 +176,10 @@ kernfs_allocvp(struct mount *mp, struct vnode **vpp, kfstype kfs_type, const str
|
|||
return (ENOENT);
|
||||
}
|
||||
vp = fvp;
|
||||
if (vget(fvp, LK_EXCLUSIVE))
|
||||
if (vn_lock(fvp, LK_EXCLUSIVE)) {
|
||||
vrele(fvp);
|
||||
goto loop;
|
||||
}
|
||||
*vpp = vp;
|
||||
mutex_exit(&kfs_hashlock);
|
||||
return (0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kernfs_vnops.c,v 1.142 2010/06/24 13:03:16 hannken Exp $ */
|
||||
/* $NetBSD: kernfs_vnops.c,v 1.143 2010/07/21 09:06:38 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -39,7 +39,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.142 2010/06/24 13:03:16 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.143 2010/07/21 09:06:38 hannken Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -1168,6 +1168,7 @@ kernfs_readdir(void *v)
|
|||
if (*dp == NODEV ||
|
||||
!vfinddev(*dp, kt->kt_vtype, &fvp))
|
||||
continue;
|
||||
vrele(fvp);
|
||||
}
|
||||
if (kt->kt_tag == KFSmsgbuf) {
|
||||
if (!msgbufenabled
|
||||
|
@ -1250,6 +1251,7 @@ kernfs_readdir(void *v)
|
|||
if (*dp == NODEV ||
|
||||
!vfinddev(*dp, kt->kt_vtype, &fvp))
|
||||
continue;
|
||||
vrele(fvp);
|
||||
}
|
||||
d.d_namlen = kt->kt_namlen;
|
||||
if ((error = kernfs_setdirentfileno(&d, i, kfs,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: param.h,v 1.371 2010/07/08 12:23:31 rmind Exp $ */
|
||||
/* $NetBSD: param.h,v 1.372 2010/07/21 09:06:37 hannken Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
|
@ -63,7 +63,7 @@
|
|||
* 2.99.9 (299000900)
|
||||
*/
|
||||
|
||||
#define __NetBSD_Version__ 599003600 /* NetBSD 5.99.36 */
|
||||
#define __NetBSD_Version__ 599003700 /* NetBSD 5.99.37 */
|
||||
|
||||
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
|
||||
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)
|
||||
|
|
Loading…
Reference in New Issue