must do a complete path check when moving directories to new parent
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Sun, 29 May 1983 10:10:06 +0000 (02:10 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Sun, 29 May 1983 10:10:06 +0000 (02:10 -0800)
SCCS-vsn: sys/kern/vfs_syscalls.c 4.58
SCCS-vsn: sys/ufs/ffs/ffs_vnops.c 4.58
SCCS-vsn: sys/ufs/ffs/ufs_vnops.c 4.58
SCCS-vsn: sys/ufs/lfs/lfs_vnops.c 4.58
SCCS-vsn: sys/ufs/ufs/ufs_vnops.c 4.58

usr/src/sys/kern/vfs_syscalls.c
usr/src/sys/ufs/ffs/ffs_vnops.c
usr/src/sys/ufs/ffs/ufs_vnops.c
usr/src/sys/ufs/lfs/lfs_vnops.c
usr/src/sys/ufs/ufs/ufs_vnops.c

index fecc165..95de59c 100644 (file)
@@ -1,4 +1,4 @@
-/*     vfs_syscalls.c  4.57    83/05/27        */
+/*     vfs_syscalls.c  4.58    83/05/28        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -873,11 +873,33 @@ rename()
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
-        * parent) then the user must have write permission.
+        * parent) then the source directory must not be in the
+        * directory heirarchy above the target, as this would
+        * orphan everything below the source directory. Also
+        * the user must have write permission in the source so
+        * as to be able to change "..". We must repeat the call 
+        * to namei, as the parent directory is unlocked by the
+        * call to checkpath().
         */
        parentdifferent = oldparent != dp->i_number;
         */
        parentdifferent = oldparent != dp->i_number;
-       if (doingdirectory && parentdifferent && access(ip, IWRITE))
-               goto bad;
+       if (doingdirectory && parentdifferent) {
+               if (access(ip, IWRITE))
+                       goto bad;
+               do {
+                       dp = u.u_pdir;
+                       if (xp != NULL)
+                               iput(xp);
+                       u.u_error = checkpath(ip, dp);
+                       if (u.u_error)
+                               goto out;
+                       u.u_dirp = (caddr_t)uap->to;
+                       xp = namei(uchar, CREATE | LOCKPARENT, 0);
+                       if (u.u_error) {
+                               error = u.u_error;
+                               goto out;
+                       }
+               } while (dp != u.u_pdir);
+       }
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
@@ -890,13 +912,6 @@ rename()
                        error = EXDEV;
                        goto bad;
                }
                        error = EXDEV;
                        goto bad;
                }
-               /*
-                * Disallow rename(foo, foo/bar).
-                */
-               if (dp->i_number == ip->i_number) {
-                       error = EEXIST;
-                       goto bad;
-               }
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
index 55ddf67..65c579a 100644 (file)
@@ -1,4 +1,4 @@
-/*     ffs_vnops.c     4.57    83/05/27        */
+/*     ffs_vnops.c     4.58    83/05/28        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -873,11 +873,33 @@ rename()
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
-        * parent) then the user must have write permission.
+        * parent) then the source directory must not be in the
+        * directory heirarchy above the target, as this would
+        * orphan everything below the source directory. Also
+        * the user must have write permission in the source so
+        * as to be able to change "..". We must repeat the call 
+        * to namei, as the parent directory is unlocked by the
+        * call to checkpath().
         */
        parentdifferent = oldparent != dp->i_number;
         */
        parentdifferent = oldparent != dp->i_number;
-       if (doingdirectory && parentdifferent && access(ip, IWRITE))
-               goto bad;
+       if (doingdirectory && parentdifferent) {
+               if (access(ip, IWRITE))
+                       goto bad;
+               do {
+                       dp = u.u_pdir;
+                       if (xp != NULL)
+                               iput(xp);
+                       u.u_error = checkpath(ip, dp);
+                       if (u.u_error)
+                               goto out;
+                       u.u_dirp = (caddr_t)uap->to;
+                       xp = namei(uchar, CREATE | LOCKPARENT, 0);
+                       if (u.u_error) {
+                               error = u.u_error;
+                               goto out;
+                       }
+               } while (dp != u.u_pdir);
+       }
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
@@ -890,13 +912,6 @@ rename()
                        error = EXDEV;
                        goto bad;
                }
                        error = EXDEV;
                        goto bad;
                }
-               /*
-                * Disallow rename(foo, foo/bar).
-                */
-               if (dp->i_number == ip->i_number) {
-                       error = EEXIST;
-                       goto bad;
-               }
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
index a3fdf59..9e6c27f 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_vnops.c     4.57    83/05/27        */
+/*     ufs_vnops.c     4.58    83/05/28        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -873,11 +873,33 @@ rename()
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
-        * parent) then the user must have write permission.
+        * parent) then the source directory must not be in the
+        * directory heirarchy above the target, as this would
+        * orphan everything below the source directory. Also
+        * the user must have write permission in the source so
+        * as to be able to change "..". We must repeat the call 
+        * to namei, as the parent directory is unlocked by the
+        * call to checkpath().
         */
        parentdifferent = oldparent != dp->i_number;
         */
        parentdifferent = oldparent != dp->i_number;
-       if (doingdirectory && parentdifferent && access(ip, IWRITE))
-               goto bad;
+       if (doingdirectory && parentdifferent) {
+               if (access(ip, IWRITE))
+                       goto bad;
+               do {
+                       dp = u.u_pdir;
+                       if (xp != NULL)
+                               iput(xp);
+                       u.u_error = checkpath(ip, dp);
+                       if (u.u_error)
+                               goto out;
+                       u.u_dirp = (caddr_t)uap->to;
+                       xp = namei(uchar, CREATE | LOCKPARENT, 0);
+                       if (u.u_error) {
+                               error = u.u_error;
+                               goto out;
+                       }
+               } while (dp != u.u_pdir);
+       }
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
@@ -890,13 +912,6 @@ rename()
                        error = EXDEV;
                        goto bad;
                }
                        error = EXDEV;
                        goto bad;
                }
-               /*
-                * Disallow rename(foo, foo/bar).
-                */
-               if (dp->i_number == ip->i_number) {
-                       error = EEXIST;
-                       goto bad;
-               }
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
index b5e8dce..e910771 100644 (file)
@@ -1,4 +1,4 @@
-/*     lfs_vnops.c     4.57    83/05/27        */
+/*     lfs_vnops.c     4.58    83/05/28        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -873,11 +873,33 @@ rename()
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
-        * parent) then the user must have write permission.
+        * parent) then the source directory must not be in the
+        * directory heirarchy above the target, as this would
+        * orphan everything below the source directory. Also
+        * the user must have write permission in the source so
+        * as to be able to change "..". We must repeat the call 
+        * to namei, as the parent directory is unlocked by the
+        * call to checkpath().
         */
        parentdifferent = oldparent != dp->i_number;
         */
        parentdifferent = oldparent != dp->i_number;
-       if (doingdirectory && parentdifferent && access(ip, IWRITE))
-               goto bad;
+       if (doingdirectory && parentdifferent) {
+               if (access(ip, IWRITE))
+                       goto bad;
+               do {
+                       dp = u.u_pdir;
+                       if (xp != NULL)
+                               iput(xp);
+                       u.u_error = checkpath(ip, dp);
+                       if (u.u_error)
+                               goto out;
+                       u.u_dirp = (caddr_t)uap->to;
+                       xp = namei(uchar, CREATE | LOCKPARENT, 0);
+                       if (u.u_error) {
+                               error = u.u_error;
+                               goto out;
+                       }
+               } while (dp != u.u_pdir);
+       }
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
@@ -890,13 +912,6 @@ rename()
                        error = EXDEV;
                        goto bad;
                }
                        error = EXDEV;
                        goto bad;
                }
-               /*
-                * Disallow rename(foo, foo/bar).
-                */
-               if (dp->i_number == ip->i_number) {
-                       error = EEXIST;
-                       goto bad;
-               }
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
index a3fdf59..9e6c27f 100644 (file)
@@ -1,4 +1,4 @@
-/*     ufs_vnops.c     4.57    83/05/27        */
+/*     ufs_vnops.c     4.58    83/05/28        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -873,11 +873,33 @@ rename()
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
        dp = u.u_pdir;
        /*
         * If ".." must be changed (ie the directory gets a new
-        * parent) then the user must have write permission.
+        * parent) then the source directory must not be in the
+        * directory heirarchy above the target, as this would
+        * orphan everything below the source directory. Also
+        * the user must have write permission in the source so
+        * as to be able to change "..". We must repeat the call 
+        * to namei, as the parent directory is unlocked by the
+        * call to checkpath().
         */
        parentdifferent = oldparent != dp->i_number;
         */
        parentdifferent = oldparent != dp->i_number;
-       if (doingdirectory && parentdifferent && access(ip, IWRITE))
-               goto bad;
+       if (doingdirectory && parentdifferent) {
+               if (access(ip, IWRITE))
+                       goto bad;
+               do {
+                       dp = u.u_pdir;
+                       if (xp != NULL)
+                               iput(xp);
+                       u.u_error = checkpath(ip, dp);
+                       if (u.u_error)
+                               goto out;
+                       u.u_dirp = (caddr_t)uap->to;
+                       xp = namei(uchar, CREATE | LOCKPARENT, 0);
+                       if (u.u_error) {
+                               error = u.u_error;
+                               goto out;
+                       }
+               } while (dp != u.u_pdir);
+       }
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
        /*
         * 2) If target doesn't exist, link the target
         *    to the source and unlink the source. 
@@ -890,13 +912,6 @@ rename()
                        error = EXDEV;
                        goto bad;
                }
                        error = EXDEV;
                        goto bad;
                }
-               /*
-                * Disallow rename(foo, foo/bar).
-                */
-               if (dp->i_number == ip->i_number) {
-                       error = EEXIST;
-                       goto bad;
-               }
                /*
                 * Account for ".." in directory.
                 * When source and destination have the
                /*
                 * Account for ".." in directory.
                 * When source and destination have the