Source-Changes-HG archive

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

[src/trunk]: src/sys/fs/msdosfs Convert msdosfs_rename() to use genfs_sane_re...



details:   https://anonhg.NetBSD.org/src/rev/f36a18b5cc47
branches:  trunk
changeset: 1024426:f36a18b5cc47
user:      hannken <hannken%NetBSD.org@localhost>
date:      Sat Oct 23 07:45:03 2021 +0000

description:
Convert msdosfs_rename() to use genfs_sane_rename().

Based on work by Taylor R Campbell.

diffstat:

 sys/fs/msdosfs/denode.h         |     3 +-
 sys/fs/msdosfs/msdosfs_rename.c |  1163 +++++++++++++++++++++++++-------------
 2 files changed, 747 insertions(+), 419 deletions(-)

diffs (truncated from 1278 to 300 lines):

diff -r 3b3835f61884 -r f36a18b5cc47 sys/fs/msdosfs/denode.h
--- a/sys/fs/msdosfs/denode.h   Sat Oct 23 07:41:37 2021 +0000
+++ b/sys/fs/msdosfs/denode.h   Sat Oct 23 07:45:03 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: denode.h,v 1.27 2021/10/23 07:38:33 hannken Exp $      */
+/*     $NetBSD: denode.h,v 1.28 2021/10/23 07:45:03 hannken Exp $      */
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -318,7 +318,6 @@
 #endif
 int detrunc(struct denode *, u_long, int, struct kauth_cred *);
 int deupdat(struct denode *, int);
-int doscheckpath(struct denode *, struct denode *);
 int dosdirempty(struct denode *);
 int readde(struct denode *, struct buf **, struct direntry **);
 int readep(struct msdosfsmount *, u_long, u_long,
diff -r 3b3835f61884 -r f36a18b5cc47 sys/fs/msdosfs/msdosfs_rename.c
--- a/sys/fs/msdosfs/msdosfs_rename.c   Sat Oct 23 07:41:37 2021 +0000
+++ b/sys/fs/msdosfs/msdosfs_rename.c   Sat Oct 23 07:45:03 2021 +0000
@@ -1,10 +1,11 @@
-/*     $NetBSD: msdosfs_rename.c,v 1.1 2021/10/23 07:41:37 hannken Exp $       */
+/*     $NetBSD: msdosfs_rename.c,v 1.2 2021/10/23 07:45:03 hannken Exp $       */
 
 /*-
- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
- * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
- * Original code by Paul Popelka (paulp%uts.amdahl.com@localhost) (see below).
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R Campbell.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -14,60 +15,36 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by TooLs GmbH.
- * 4. The name of TooLs GmbH may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Written by Paul Popelka (paulp%uts.amdahl.com@localhost)
- *
- * You can do anything you want with this software, just don't say you wrote
- * it, and don't remove this notice.
- *
- * This software is provided "as is".
- *
- * The author supplies this software to be publicly redistributed on the
- * understanding that the author is not responsible for the correct
- * functioning of this software in any circumstances and is not liable for
- * any damages caused by this software.
- *
- * October 1992
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * MS-DOS FS Rename
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_rename.c,v 1.2 2021/10/23 07:45:03 hannken Exp $");
+
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/resourcevar.h>   /* defines plimit structure in proc struct */
-#include <sys/kernel.h>
-#include <sys/file.h>          /* define FWRITE ... */
-#include <sys/stat.h>
 #include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
+#include <sys/errno.h>
+#include <sys/kauth.h>
+#include <sys/namei.h>
 #include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/kauth.h>
+#include <sys/vnode_if.h>
 
 #include <miscfs/genfs/genfs.h>
-#include <miscfs/specfs/specdev.h> /* XXX */   /* defines v_rdev */
-
-#include <uvm/uvm_extern.h>
 
 #include <fs/msdosfs/bpb.h>
 #include <fs/msdosfs/direntry.h>
@@ -75,10 +52,50 @@
 #include <fs/msdosfs/msdosfsmount.h>
 #include <fs/msdosfs/fat.h>
 
+/*
+ * Forward declarations
+ */
+
+static int msdosfs_sane_rename(struct vnode *, struct componentname *,
+    struct vnode *, struct componentname *,
+    kauth_cred_t, bool);
+static bool msdosfs_rmdired_p(struct vnode *);
+static int msdosfs_read_dotdot(struct vnode *, kauth_cred_t, unsigned long *);
+static int msdosfs_rename_replace_dotdot(struct vnode *,
+    struct vnode *, struct vnode *, kauth_cred_t);
+static int msdosfs_gro_lock_directory(struct mount *, struct vnode *);
+
+static const struct genfs_rename_ops msdosfs_genfs_rename_ops;
+
+/*
+ * msdosfs_rename: The hairiest vop, with the insanest API.
+ *
+ * Arguments:
+ *
+ * . fdvp (from directory vnode),
+ * . fvp (from vnode),
+ * . fcnp (from component name),
+ * . tdvp (to directory vnode),
+ * . tvp (to vnode, or NULL), and
+ * . tcnp (to component name).
+ *
+ * Any pair of vnode parameters may have the same vnode.
+ *
+ * On entry,
+ *
+ * . fdvp, fvp, tdvp, and tvp are referenced,
+ * . fdvp and fvp are unlocked, and
+ * . tdvp and tvp (if nonnull) are locked.
+ *
+ * On exit,
+ *
+ * . fdvp, fvp, tdvp, and tvp (if nonnull) are unreferenced, and
+ * . tdvp and tvp are unlocked.
+ */
 int
 msdosfs_rename(void *v)
 {
-       struct vop_rename_args /* {
+       struct vop_rename_args  /* {
                struct vnode *a_fdvp;
                struct vnode *a_fvp;
                struct componentname *a_fcnp;
@@ -86,165 +103,345 @@
                struct vnode *a_tvp;
                struct componentname *a_tcnp;
        } */ *ap = v;
-       struct vnode *tvp = ap->a_tvp;
-       struct vnode *tdvp = ap->a_tdvp;
+       struct vnode *fdvp = ap->a_fdvp;
        struct vnode *fvp = ap->a_fvp;
-       struct vnode *fdvp = ap->a_fdvp;
-       struct componentname *tcnp = ap->a_tcnp;
        struct componentname *fcnp = ap->a_fcnp;
-       struct denode *ip, *xp, *dp, *zp;
-       u_char toname[12], oldname[12];
-       u_long from_diroffset, to_diroffset;
-       u_char to_count;
-       int doingdirectory = 0, newparent = 0;
+       struct vnode *tdvp = ap->a_tdvp;
+       struct vnode *tvp = ap->a_tvp;
+       struct componentname *tcnp = ap->a_tcnp;
+       kauth_cred_t cred;
        int error;
-       u_long cn;
-       daddr_t bn;
-       struct msdosfsmount *pmp;
-       struct direntry *dotdotp;
-       struct buf *bp;
-
-       pmp = VFSTOMSDOSFS(fdvp->v_mount);
 
-       /*
-        * Check for cross-device rename.
-        */
-       if ((fvp->v_mount != tdvp->v_mount) ||
-           (tvp && (fvp->v_mount != tvp->v_mount))) {
-               error = EXDEV;
-abortit:
-               VOP_ABORTOP(tdvp, tcnp);
-               if (tdvp == tvp)
-                       vrele(tdvp);
-               else
-                       vput(tdvp);
-               if (tvp)
-                       vput(tvp);
-               VOP_ABORTOP(fdvp, fcnp);
-               vrele(fdvp);
-               vrele(fvp);
-               return (error);
-       }
+       KASSERT(fdvp != NULL);
+       KASSERT(fvp != NULL);
+       KASSERT(fcnp != NULL);
+       KASSERT(fcnp->cn_nameptr != NULL);
+       KASSERT(tdvp != NULL);
+       KASSERT(tcnp != NULL);
+       KASSERT(fcnp->cn_nameptr != NULL);
+       /* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
+       /* KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */
+       KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
+       KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
+       KASSERT(fdvp->v_type == VDIR);
+       KASSERT(tdvp->v_type == VDIR);
 
-       /*
-        * If source and dest are the same, do nothing.
-        */
-       if (tvp == fvp) {
-               error = 0;
-               goto abortit;
-       }
-
-       /*
-        * XXX: This can deadlock since we hold tdvp/tvp locked.
-        * But I'm not going to fix it now.
-        */
-       if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
-               goto abortit;
-       dp = VTODE(fdvp);
-       ip = VTODE(fvp);
+       cred = fcnp->cn_cred;
+       KASSERT(tcnp->cn_cred == cred);
 
        /*
-        * Be sure we are not renaming ".", "..", or an alias of ".". This
-        * leads to a crippled directory tree.  It's pretty tough to do a
-        * "ls" or "pwd" with the "." directory entry missing, and "cd .."
-        * doesn't work if the ".." entry is missing.
+        * Sanitize our world from the VFS insanity.  Unlock the target
+        * directory and node, which are locked.  Release the children,
+        * which are referenced.  Check for rename("x", "y/."), which
+        * it is our responsibility to reject, not the caller's.  (But
+        * the caller does reject rename("x/.", "y").  Go figure.)
+        */
+
+       VOP_UNLOCK(tdvp);
+       if ((tvp != NULL) && (tvp != tdvp))
+               VOP_UNLOCK(tvp);
+
+       vrele(fvp);
+       if (tvp != NULL)
+               vrele(tvp);
+
+       if (tvp == tdvp) {
+               error = EINVAL;
+               goto out;
+       }
+
+       error = msdosfs_sane_rename(fdvp, fcnp, tdvp, tcnp, cred, false);
+
+out:   /*
+        * All done, whether with success or failure.  Release the
+        * directory nodes now, as the caller expects from the VFS
+        * protocol.
         */
-       if (ip->de_Attributes & ATTR_DIRECTORY) {
-               /*
-                * Avoid ".", "..", and aliases of "." for obvious reasons.
-                */
-               if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
-                   dp == ip ||
-                   (fcnp->cn_flags & ISDOTDOT) ||
-                   (tcnp->cn_flags & ISDOTDOT) ||
-                   (ip->de_flag & DE_RENAME)) {
-                       VOP_UNLOCK(fvp);
-                       error = EINVAL;
-                       goto abortit;
-               }
-               ip->de_flag |= DE_RENAME;
-               doingdirectory++;
-       }



Home | Main Index | Thread Index | Old Index