Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Using vfinddev() leads to vnode races as it returns an unref...



details:   https://anonhg.NetBSD.org/src/rev/243b990cb025
branches:  trunk
changeset: 756524:243b990cb025
user:      hannken <hannken%NetBSD.org@localhost>
date:      Wed Jul 21 09:06:37 2010 +0000

description:
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.

diffstat:

 share/man/man9/vnode.9                        |   6 ++--
 sys/external/bsd/drm/dist/bsd-core/drm_bufs.c |   3 ++
 sys/kern/vfs_subr.c                           |  30 ++++++++++++++++----------
 sys/miscfs/kernfs/kernfs_subr.c               |   8 ++++--
 sys/miscfs/kernfs/kernfs_vnops.c              |   6 +++-
 sys/sys/param.h                               |   4 +-
 6 files changed, 35 insertions(+), 22 deletions(-)

diffs (191 lines):

diff -r f3a0fc85bcd0 -r 243b990cb025 share/man/man9/vnode.9
--- a/share/man/man9/vnode.9    Wed Jul 21 09:01:35 2010 +0000
+++ b/share/man/man9/vnode.9    Wed Jul 21 09:06:37 2010 +0000
@@ -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
diff -r f3a0fc85bcd0 -r 243b990cb025 sys/external/bsd/drm/dist/bsd-core/drm_bufs.c
--- a/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c     Wed Jul 21 09:01:35 2010 +0000
+++ b/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c     Wed Jul 21 09:06:37 2010 +0000
@@ -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);
 
diff -r f3a0fc85bcd0 -r 243b990cb025 sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c       Wed Jul 21 09:01:35 2010 +0000
+++ b/sys/kern/vfs_subr.c       Wed Jul 21 09:06:37 2010 +0000
@@ -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);
+                               }
                        }
                }
 
diff -r f3a0fc85bcd0 -r 243b990cb025 sys/miscfs/kernfs/kernfs_subr.c
--- a/sys/miscfs/kernfs/kernfs_subr.c   Wed Jul 21 09:01:35 2010 +0000
+++ b/sys/miscfs/kernfs/kernfs_subr.c   Wed Jul 21 09:06:37 2010 +0000
@@ -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);
diff -r f3a0fc85bcd0 -r 243b990cb025 sys/miscfs/kernfs/kernfs_vnops.c
--- a/sys/miscfs/kernfs/kernfs_vnops.c  Wed Jul 21 09:01:35 2010 +0000
+++ b/sys/miscfs/kernfs/kernfs_vnops.c  Wed Jul 21 09:06:37 2010 +0000
@@ -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,
diff -r f3a0fc85bcd0 -r 243b990cb025 sys/sys/param.h
--- a/sys/sys/param.h   Wed Jul 21 09:01:35 2010 +0000
+++ b/sys/sys/param.h   Wed Jul 21 09:06:37 2010 +0000
@@ -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__)



Home | Main Index | Thread Index | Old Index