patch-2.1.126 linux/fs/namei.c

Next file: linux/fs/nfs/file.c
Previous file: linux/fs/minix/bitmap.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.125/linux/fs/namei.c linux/fs/namei.c
@@ -460,7 +460,6 @@
 			break;
 		if (flags & LOOKUP_SLASHOK)
 			goto return_base;
-		dentry = ERR_PTR(-ENOTDIR);
 		break;
 	}
 	dput(base);
@@ -536,6 +535,28 @@
 	return dir;
 }
 
+/* 
+ * Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security
+ * reasons.
+ *
+ * O_DIRECTORY translates into forcing a directory lookup.
+ */
+static inline int lookup_flags(unsigned int f)
+{
+	unsigned long retval = LOOKUP_FOLLOW;
+
+	if (f & O_NOFOLLOW)
+		retval &= ~LOOKUP_FOLLOW;
+	
+	if ((f & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+		retval &= ~LOOKUP_FOLLOW;
+	
+	if (f & O_DIRECTORY)
+		retval |= LOOKUP_DIRECTORY;
+	
+	return retval;
+}
+
 /*
  *	open_namei()
  *
@@ -558,13 +579,7 @@
 	mode &= S_IALLUGO & ~current->fs->umask;
 	mode |= S_IFREG;
 
-	/* 
-	 * Special case: O_CREAT|O_EXCL on a dangling symlink should
-	 * give EEXIST for security reasons.  While inconsistent, this
-	 * is the same scheme used by, for example, Solaris 2.5.1.  --KAB
-	 */
-	dentry = lookup_dentry(pathname, NULL,
-			       (flag & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL));
+	dentry = lookup_dentry(pathname, NULL, lookup_flags(flag));
 	if (IS_ERR(dentry))
 		return dentry;
 
@@ -611,6 +626,10 @@
 	if (!inode)
 		goto exit;
 
+	error = -EACCES;
+	if (S_ISLNK(inode->i_mode))
+		goto exit;
+	
 	error = -EISDIR;
 	if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
 		goto exit;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov