svn commit: r193028 - in head/sys: kern sys

Dag-Erling Smorgrav des at FreeBSD.org
Fri May 29 10:02:45 UTC 2009


Author: des
Date: Fri May 29 10:02:44 2009
New Revision: 193028
URL: http://svn.freebsd.org/changeset/base/193028

Log:
  Let vfs_lookup() return ENOTDIR if the path has a trailing slash and
  the last component is a symlink to something that isn't a directory.
  
  We introduce a new namei flag, TRAILINGSLASH, which is set by lookup()
  if the last component is followed by a slash.  The trailing slash is
  then stripped, as before.  If the final component is a symlink,
  lookup() will return to namei(), which will expand the symlink and
  call lookup() with the new path.  When all symlinks have been
  resolved, lookup() checks if the TRAILINGSLASH flag is set, and if it
  is, and the vnode it ended up with is not a directory, it returns
  ENOTDIR.
  
  PR:		kern/21768
  Submitted by:	Eygene Ryabinkin <rea-fbsd at codelabs.ru>
  MFC after:	3 weeks

Modified:
  head/sys/kern/vfs_lookup.c
  head/sys/sys/namei.h

Modified: head/sys/kern/vfs_lookup.c
==============================================================================
--- head/sys/kern/vfs_lookup.c	Fri May 29 09:52:13 2009	(r193027)
+++ head/sys/kern/vfs_lookup.c	Fri May 29 10:02:44 2009	(r193028)
@@ -147,6 +147,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.
@@ -533,6 +536,7 @@ dirloop:
 		if (*cp == '\0') {
 			trailing_slash = 1;
 			*ndp->ni_next = '\0';	/* XXX for direnter() ... */
+			cnp->cn_flags |= TRAILINGSLASH;
 		}
 	}
 	ndp->ni_next = cp;
@@ -807,14 +811,6 @@ 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,
@@ -838,6 +834,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 &&

Modified: head/sys/sys/namei.h
==============================================================================
--- head/sys/sys/namei.h	Fri May 29 09:52:13 2009	(r193027)
+++ head/sys/sys/namei.h	Fri May 29 10:02:44 2009	(r193028)
@@ -142,7 +142,8 @@ struct nameidata {
 #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	PARAMASK	0x0ffffe00 /* mask of parameter descriptors */
+#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-head mailing list