It appears msdosfs is using a vnode after having released its reference on
it, which could lead to a bad things under high load. I've patched the
OpenBSD errata to apply cleanly to FreeBSD.

--- msdosfs_vnops.c.orig        Mon Jun 26 06:10:40 2000
+++ msdosfs_vnops.c     Mon Jun 26 07:10:17 2000
@@ -1095,9 +1095,9 @@
                newparent = 1;
        vrele(fdvp);
        if (doingdirectory && newparent) {
                if (error)      /* write access check above */
-                       goto bad;
+                       goto bad1;
                if (xp != NULL)
                        vput(tvp);
                /*
                 * doscheckpath() vput()'s dp,
@@ -1123,22 +1123,22 @@
                 */
                if (xp->de_Attributes & ATTR_DIRECTORY) {
                        if (!dosdirempty(xp)) {
                                error = ENOTEMPTY;
-                               goto bad;
+                               goto bad1;
                        }
                        if (!doingdirectory) {
                                error = ENOTDIR;
-                               goto bad;
+                               goto bad1;
                        }
                        cache_purge(tdvp);
                } else if (doingdirectory) {
                        error = EISDIR;
-                       goto bad;
+                       goto bad1;
                }
                error = removede(dp, xp);
                if (error)
-                       goto bad;
+                       goto bad1;
                vput(tvp);
                xp = NULL;
        }
 
@@ -1148,9 +1148,9 @@
         * file/directory.
         */
        error = uniqdosname(VTODE(tdvp), tcnp, toname);
        if (error)
-               goto abortit;
+               goto bad1;
 
        /*
         * Since from wasn't locked at various places above,
         * have to do a relookup here.
@@ -1189,9 +1189,8 @@
        if (xp != ip) {
                if (doingdirectory)
                        panic("rename: lost dir entry");
                vrele(ap->a_fvp);
-               VOP_UNLOCK(fvp, 0, p);
                if (newparent)
                        VOP_UNLOCK(fdvp, 0, p);
                xp = NULL;
        } else {
@@ -1214,9 +1213,8 @@
                if (error) {
                        bcopy(oldname, ip->de_Name, 11);
                        if (newparent)
                                VOP_UNLOCK(fdvp, 0, p);
-                       VOP_UNLOCK(fvp, 0, p);
                        goto bad;
                }
                ip->de_refcnt++;
                zp->de_fndoffset = from_diroffset;
@@ -1224,9 +1222,8 @@
                if (error) {
                        /* XXX should really panic here, fs is corrupt */
                        if (newparent)
                                VOP_UNLOCK(fdvp, 0, p);
-                       VOP_UNLOCK(fvp, 0, p);
                        goto bad;
                }
                if (!doingdirectory) {
                        error = pcbmap(dp, de_cluster(pmp, to_diroffset), 0,
@@ -1234,9 +1231,8 @@
                        if (error) {
                                /* XXX should really panic here, fs is corrupt */
                                if (newparent)
                                        VOP_UNLOCK(fdvp, 0, p);
-                               VOP_UNLOCK(fvp, 0, p);
                                goto bad;
                        }
                        if (ip->de_dirclust == MSDOSFSROOT)
                                ip->de_diroffset = to_diroffset;
@@ -1263,9 +1259,8 @@
                              NOCRED, &bp);
                if (error) {
                        /* XXX should really panic here, fs is corrupt */
                        brelse(bp);
-                       VOP_UNLOCK(fvp, 0, p);
                        goto bad;
                }
                dotdotp = (struct direntry *)bp->b_data + 1;
                putushort(dotdotp->deStartCluster, dp->de_StartCluster);
@@ -1273,21 +1268,21 @@
                        putushort(dotdotp->deHighClust, dp->de_StartCluster >> 16);
                error = bwrite(bp);
                if (error) {
                        /* XXX should really panic here, fs is corrupt */
-                       VOP_UNLOCK(fvp, 0, p);
                        goto bad;
                }
        }
 
-       VOP_UNLOCK(fvp, 0, p);
 bad:
+       VOP_UNLOCK(fvp, 0, p);
+       vrele(fdvp);
+bad1:
        if (xp)
                vput(tvp);
        vput(tdvp);
 out:
        ip->de_flag &= ~DE_RENAME;
-       vrele(fdvp);
        vrele(fvp);
        return (error);
 
 }



To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to