When an inode collision occurs a partially initialized vnode will be
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 30 Jul 2007 14:44:56 +0000 (14:44 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 30 Jul 2007 14:44:56 +0000 (14:44 +0000)
destroyed.  Fix several NULL pointer dereferences in msdosfs that could
occur in this case.  Loosely taken from the UFS code.

Inode collision checks were added to DragonFly to close race conditions
in both the creation and termination of a vnode that were found in UFS.
Subsequently other filesystems were found to have the same race conditions.
Because the VM cache is based on filesystem objects and not on physical
disk blocks, such collisions could result in multiple buffers associated
with different vnodes referencing the same physical disk block and I/O
reordering would then cause stale data to be written to disk.

Submitted-by: "Nicolas Thery" <nthery@gmail.com>
sys/vfs/msdosfs/msdosfs_denode.c

index 8f90993..b77adc5 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: src/sys/msdosfs/msdosfs_denode.c,v 1.47.2.3 2002/08/22 16:20:15 trhodes Exp $ */
-/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_denode.c,v 1.29 2007/06/14 02:55:27 dillon Exp $ */
+/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_denode.c,v 1.30 2007/07/30 14:44:56 dillon Exp $ */
 /*     $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg Exp $  */
 
 /*-
@@ -689,7 +689,8 @@ msdosfs_inactive(struct vop_inactive_args *ap)
        int error = 0;
 
 #ifdef MSDOSFS_DEBUG
-       kprintf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
+       kprintf("msdosfs_inactive(): dep %p, de_Name[0] %x\n",
+               dep, (dep ? dep->de_Name[0] : 0));
 #endif
 
        if (prtactive && vp->v_sysref.refcnt > 1)
@@ -698,7 +699,7 @@ msdosfs_inactive(struct vop_inactive_args *ap)
        /*
         * Ignore denodes related to stale file handles.
         */
-       if (dep->de_Name[0] == SLOT_DELETED)
+       if (dep == NULL || dep->de_Name[0] == SLOT_DELETED)
                goto out;
 
        /*
@@ -724,9 +725,9 @@ out:
         */
 #ifdef MSDOSFS_DEBUG
        kprintf("msdosfs_inactive(): v_sysrefs %d, de_Name[0] %x\n",
-               vp->v_sysref.refcnt, dep->de_Name[0]);
+               vp->v_sysref.refcnt, )dep ? dep->de_Name[0] : 0));
 #endif
-       if (dep->de_Name[0] == SLOT_DELETED)
+       if (dep == NULL || dep->de_Name[0] == SLOT_DELETED)
                vrecycle(vp);
        return (error);
 }