Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Jun 2009 19:39:34 +0000 (UTC)
From:      Dag-Erling Smorgrav <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r194604 - in stable/7/sys: . contrib/pf kern sys
Message-ID:  <200906211939.n5LJdYfq016530@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906211939.n5LJdYfq016530>