svn commit: r194604 - in stable/7/sys: . contrib/pf kern sys
Dag-Erling Smorgrav
des at FreeBSD.org
Sun Jun 21 19:39:35 UTC 2009
Author: des
Date: Sun Jun 21 19:39:34 2009
New Revision: 194604
URL: http://svn.freebsd.org/changeset/base/194604
Log:
merge r193027, r193557, r192900, r193028: fix trailing-slash symlink bug
PR: kern/21768
Modified:
stable/7/sys/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/kern/vfs_lookup.c
stable/7/sys/sys/namei.h
Modified: stable/7/sys/kern/vfs_lookup.c
==============================================================================
--- stable/7/sys/kern/vfs_lookup.c Sun Jun 21 19:31:41 2009 (r194603)
+++ stable/7/sys/kern/vfs_lookup.c Sun Jun 21 19:39:34 2009 (r194604)
@@ -138,6 +138,9 @@ namei(struct nameidata *ndp)
cnp->cn_flags &= ~LOCKSHARED;
fdp = p->p_fd;
+ /* We will set this ourselves if we need it. */
+ cnp->cn_flags &= ~TRAILINGSLASH;
+
/*
* Get a buffer for the name to be translated, and copy the
* name into the buffer.
@@ -224,7 +227,7 @@ namei(struct nameidata *ndp)
vfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
ndp->ni_cnd.cn_flags &= ~GIANTHELD;
/*
- * Check for symbolic link
+ * If not a symbolic link, we're done.
*/
if ((cnp->cn_flags & ISSYMLINK) == 0) {
if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) {
@@ -367,7 +370,6 @@ lookup(struct nameidata *ndp)
int docache; /* == 0 do not cache last component */
int wantparent; /* 1 => wantparent or lockparent flag */
int rdonly; /* lookup read-only flag bit */
- int trailing_slash;
int error = 0;
int dpunlocked = 0; /* dp has already been unlocked */
struct componentname *cnp = &ndp->ni_cnd;
@@ -439,13 +441,12 @@ dirloop:
* trailing slashes to handle symlinks, existing non-directories
* and non-existing files that won't be directories specially later.
*/
- trailing_slash = 0;
while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
cp++;
ndp->ni_pathlen--;
if (*cp == '\0') {
- trailing_slash = 1;
- *ndp->ni_next = '\0'; /* XXX for direnter() ... */
+ *ndp->ni_next = '\0';
+ cnp->cn_flags |= TRAILINGSLASH;
}
}
ndp->ni_next = cp;
@@ -604,27 +605,24 @@ unionlookup:
if (error != EJUSTRETURN)
goto bad;
/*
- * If creating and at end of pathname, then can consider
- * allowing file to be created.
+ * At this point, we know we're at the end of the
+ * pathname. If creating / renaming, we can consider
+ * allowing the file or directory to be created / renamed,
+ * provided we're not on a read-only filesystem.
*/
if (rdonly) {
error = EROFS;
goto bad;
}
- if (*cp == '\0' && trailing_slash &&
- !(cnp->cn_flags & WILLBEDIR)) {
+ /* trailing slash only allowed for directories */
+ if ((cnp->cn_flags & TRAILINGSLASH) &&
+ !(cnp->cn_flags & WILLBEDIR)) {
error = ENOENT;
goto bad;
}
if ((cnp->cn_flags & LOCKPARENT) == 0)
VOP_UNLOCK(dp, 0, td);
/*
- * This is a temporary assert to make sure I know what the
- * behavior here was.
- */
- KASSERT((cnp->cn_flags & (WANTPARENT|LOCKPARENT)) != 0,
- ("lookup: Unhandled case."));
- /*
* We return with ni_vp NULL to indicate that the entry
* doesn't currently exist, leaving a pointer to the
* (possibly locked) directory vnode in ndp->ni_dvp.
@@ -687,7 +685,7 @@ unionlookup:
* Check for symbolic link
*/
if ((dp->v_type == VLNK) &&
- ((cnp->cn_flags & FOLLOW) || trailing_slash ||
+ ((cnp->cn_flags & FOLLOW) || (cnp->cn_flags & TRAILINGSLASH) ||
*ndp->ni_next == '/')) {
cnp->cn_flags |= ISSYMLINK;
if (dp->v_iflag & VI_DOOMED) {
@@ -710,18 +708,10 @@ unionlookup:
goto success;
}
- /*
- * Check for bogus trailing slashes.
- */
- if (trailing_slash && dp->v_type != VDIR) {
- error = ENOTDIR;
- goto bad2;
- }
-
nextname:
/*
- * Not a symbolic link. If more pathname,
- * continue at next component, else return.
+ * Not a symbolic link that we will follow. Continue with the
+ * next component if there is any; otherwise, we're done.
*/
KASSERT((cnp->cn_flags & ISLASTCN) || *ndp->ni_next == '/',
("lookup: invalid path state."));
@@ -741,6 +731,14 @@ nextname:
goto dirloop;
}
/*
+ * If we're processing a path with a trailing slash,
+ * check that the end result is a directory.
+ */
+ if ((cnp->cn_flags & TRAILINGSLASH) && dp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto bad2;
+ }
+ /*
* Disallow directory write attempts on read-only filesystems.
*/
if (rdonly &&
@@ -891,12 +889,6 @@ relookup(struct vnode *dvp, struct vnode
if ((cnp->cn_flags & LOCKPARENT) == 0)
VOP_UNLOCK(dp, 0, td);
/*
- * This is a temporary assert to make sure I know what the
- * behavior here was.
- */
- KASSERT((cnp->cn_flags & (WANTPARENT|LOCKPARENT)) != 0,
- ("relookup: Unhandled case."));
- /*
* We return with ni_vp NULL to indicate that the entry
* doesn't currently exist, leaving a pointer to the
* (possibly locked) directory vnode in ndp->ni_dvp.
Modified: stable/7/sys/sys/namei.h
==============================================================================
--- stable/7/sys/sys/namei.h Sun Jun 21 19:31:41 2009 (r194603)
+++ stable/7/sys/sys/namei.h Sun Jun 21 19:39:34 2009 (r194604)
@@ -127,26 +127,27 @@ struct nameidata {
* name being sought. The caller is responsible for releasing the
* buffer and for vrele'ing ni_startdir.
*/
-#define RDONLY 0x0000200 /* lookup with read-only semantics */
-#define HASBUF 0x0000400 /* has allocated pathname buffer */
-#define SAVENAME 0x0000800 /* save pathname buffer */
-#define SAVESTART 0x0001000 /* save starting directory */
-#define ISDOTDOT 0x0002000 /* current component name is .. */
-#define MAKEENTRY 0x0004000 /* entry is to be added to name cache */
-#define ISLASTCN 0x0008000 /* this is last component of pathname */
-#define ISSYMLINK 0x0010000 /* symlink needs interpretation */
-#define ISWHITEOUT 0x0020000 /* found whiteout */
-#define DOWHITEOUT 0x0040000 /* do whiteouts */
-#define WILLBEDIR 0x0080000 /* new files will be dirs; allow trailing / */
-#define ISUNICODE 0x0100000 /* current component name is unicode*/
-#define ISOPEN 0x0200000 /* caller is opening; return a real vnode. */
-#define NOCROSSMOUNT 0x0400000 /* do not cross mount points */
-#define NOMACCHECK 0x0800000 /* do not perform MAC checks */
-#define MPSAFE 0x1000000 /* namei() must acquire Giant if needed. */
-#define GIANTHELD 0x2000000 /* namei() is holding giant. */
-#define AUDITVNODE1 0x4000000 /* audit the looked up vnode information */
-#define AUDITVNODE2 0x8000000 /* audit the looked up vnode information */
-#define PARAMASK 0xffffe00 /* mask of parameter descriptors */
+#define RDONLY 0x00000200 /* lookup with read-only semantics */
+#define HASBUF 0x00000400 /* has allocated pathname buffer */
+#define SAVENAME 0x00000800 /* save pathname buffer */
+#define SAVESTART 0x00001000 /* save starting directory */
+#define ISDOTDOT 0x00002000 /* current component name is .. */
+#define MAKEENTRY 0x00004000 /* entry is to be added to name cache */
+#define ISLASTCN 0x00008000 /* this is last component of pathname */
+#define ISSYMLINK 0x00010000 /* symlink needs interpretation */
+#define ISWHITEOUT 0x00020000 /* found whiteout */
+#define DOWHITEOUT 0x00040000 /* do whiteouts */
+#define WILLBEDIR 0x00080000 /* new files will be dirs; allow trailing / */
+#define ISUNICODE 0x00100000 /* current component name is unicode*/
+#define ISOPEN 0x00200000 /* caller is opening; return a real vnode. */
+#define NOCROSSMOUNT 0x00400000 /* do not cross mount points */
+#define NOMACCHECK 0x00800000 /* do not perform MAC checks */
+#define MPSAFE 0x01000000 /* namei() must acquire Giant if needed. */
+#define GIANTHELD 0x02000000 /* namei() is holding giant. */
+#define AUDITVNODE1 0x04000000 /* audit the looked up vnode information */
+#define AUDITVNODE2 0x08000000 /* audit the looked up vnode information */
+#define TRAILINGSLASH 0x10000000 /* path ended in a slash */
+#define PARAMASK 0x1ffffe00 /* mask of parameter descriptors */
#define NDHASGIANT(NDP) (((NDP)->ni_cnd.cn_flags & GIANTHELD) != 0)
More information about the svn-src-stable-7
mailing list