Module Name: src Committed By: hannken Date: Wed Jul 21 09:06:39 UTC 2010
Modified Files: src/share/man/man9: vnode.9 src/sys/external/bsd/drm/dist/bsd-core: drm_bufs.c src/sys/kern: vfs_subr.c src/sys/miscfs/kernfs: kernfs_subr.c kernfs_vnops.c src/sys/sys: param.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.49 -r1.50 src/share/man/man9/vnode.9 cvs rdiff -u -r1.7 -r1.8 src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c cvs rdiff -u -r1.408 -r1.409 src/sys/kern/vfs_subr.c cvs rdiff -u -r1.21 -r1.22 src/sys/miscfs/kernfs/kernfs_subr.c cvs rdiff -u -r1.142 -r1.143 src/sys/miscfs/kernfs/kernfs_vnops.c cvs rdiff -u -r1.371 -r1.372 src/sys/sys/param.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man9/vnode.9 diff -u src/share/man/man9/vnode.9:1.49 src/share/man/man9/vnode.9:1.50 --- src/share/man/man9/vnode.9:1.49 Sun Jun 6 08:01:31 2010 +++ src/share/man/man9/vnode.9 Wed Jul 21 09:06:37 2010 @@ -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 @@ 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 Index: src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c diff -u src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c:1.7 src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c:1.8 --- src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c:1.7 Tue Jan 26 08:01:26 2010 +++ src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c Wed Jul 21 09:06:38 2010 @@ -1146,6 +1146,9 @@ done: request->count = dma->buf_count; +#if defined(__NetBSD__) + vrele(vn); +#endif DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode); Index: src/sys/kern/vfs_subr.c diff -u src/sys/kern/vfs_subr.c:1.408 src/sys/kern/vfs_subr.c:1.409 --- src/sys/kern/vfs_subr.c:1.408 Thu Jul 1 13:00:56 2010 +++ src/sys/kern/vfs_subr.c Wed Jul 21 09:06:38 2010 @@ -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 @@ } /* - * 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 @@ 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); + } } } Index: src/sys/miscfs/kernfs/kernfs_subr.c diff -u src/sys/miscfs/kernfs/kernfs_subr.c:1.21 src/sys/miscfs/kernfs/kernfs_subr.c:1.22 --- src/sys/miscfs/kernfs/kernfs_subr.c:1.21 Thu Jul 1 13:00:56 2010 +++ src/sys/miscfs/kernfs/kernfs_subr.c Wed Jul 21 09:06:38 2010 @@ -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 @@ 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); Index: src/sys/miscfs/kernfs/kernfs_vnops.c diff -u src/sys/miscfs/kernfs/kernfs_vnops.c:1.142 src/sys/miscfs/kernfs/kernfs_vnops.c:1.143 --- src/sys/miscfs/kernfs/kernfs_vnops.c:1.142 Thu Jun 24 13:03:16 2010 +++ src/sys/miscfs/kernfs/kernfs_vnops.c Wed Jul 21 09:06:38 2010 @@ -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 @@ if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) continue; + vrele(fvp); } if (kt->kt_tag == KFSmsgbuf) { if (!msgbufenabled @@ -1250,6 +1251,7 @@ 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, Index: src/sys/sys/param.h diff -u src/sys/sys/param.h:1.371 src/sys/sys/param.h:1.372 --- src/sys/sys/param.h:1.371 Thu Jul 8 12:23:31 2010 +++ src/sys/sys/param.h Wed Jul 21 09:06:37 2010 @@ -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__)