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__)

Reply via email to