From: Kirk McKusick Date: Sun, 29 May 1983 10:10:06 +0000 (-0800) Subject: must do a complete path check when moving directories to new parent X-Git-Tag: BSD-4_2-Snapshot-Development~1701 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/81552f0f5904ea22ac22667d377d623a641b663c must do a complete path check when moving directories to new parent 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 --- diff --git a/usr/src/sys/kern/vfs_syscalls.c b/usr/src/sys/kern/vfs_syscalls.c index fecc16593d..95de59c280 100644 --- a/usr/src/sys/kern/vfs_syscalls.c +++ b/usr/src/sys/kern/vfs_syscalls.c @@ -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" @@ -873,11 +873,33 @@ rename() 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; - 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. @@ -890,13 +912,6 @@ rename() 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 diff --git a/usr/src/sys/ufs/ffs/ffs_vnops.c b/usr/src/sys/ufs/ffs/ffs_vnops.c index 55ddf6717e..65c579a94d 100644 --- a/usr/src/sys/ufs/ffs/ffs_vnops.c +++ b/usr/src/sys/ufs/ffs/ffs_vnops.c @@ -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" @@ -873,11 +873,33 @@ rename() 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; - 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. @@ -890,13 +912,6 @@ rename() 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 diff --git a/usr/src/sys/ufs/ffs/ufs_vnops.c b/usr/src/sys/ufs/ffs/ufs_vnops.c index a3fdf59fe9..9e6c27ff1b 100644 --- a/usr/src/sys/ufs/ffs/ufs_vnops.c +++ b/usr/src/sys/ufs/ffs/ufs_vnops.c @@ -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" @@ -873,11 +873,33 @@ rename() 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; - 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. @@ -890,13 +912,6 @@ rename() 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 diff --git a/usr/src/sys/ufs/lfs/lfs_vnops.c b/usr/src/sys/ufs/lfs/lfs_vnops.c index b5e8dce5e9..e91077154a 100644 --- a/usr/src/sys/ufs/lfs/lfs_vnops.c +++ b/usr/src/sys/ufs/lfs/lfs_vnops.c @@ -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" @@ -873,11 +873,33 @@ rename() 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; - 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. @@ -890,13 +912,6 @@ rename() 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 diff --git a/usr/src/sys/ufs/ufs/ufs_vnops.c b/usr/src/sys/ufs/ufs/ufs_vnops.c index a3fdf59fe9..9e6c27ff1b 100644 --- a/usr/src/sys/ufs/ufs/ufs_vnops.c +++ b/usr/src/sys/ufs/ufs/ufs_vnops.c @@ -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" @@ -873,11 +873,33 @@ rename() 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; - 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. @@ -890,13 +912,6 @@ rename() 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