Commit 002baeec authored by Jan Kara's avatar Jan Kara Committed by Linus Torvalds

vfs: Fix O_NOFOLLOW behavior for paths with trailing slashes

According to specification

	mkdir d; ln -s d a; open("a/", O_NOFOLLOW | O_RDONLY)

should return success but currently it returns ELOOP.  This is a
regression caused by path lookup cleanup patch series.

Fix the code to ignore O_NOFOLLOW in case the provided path has trailing
slashes.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Reported-by: default avatarMarius Tolzmann <tolzmann@molgen.mpg.de>
Acked-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent fc8e38f1
...@@ -1641,7 +1641,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, ...@@ -1641,7 +1641,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (nd->last.name[nd->last.len]) { if (nd->last.name[nd->last.len]) {
if (open_flag & O_CREAT) if (open_flag & O_CREAT)
goto exit; goto exit;
nd->flags |= LOOKUP_DIRECTORY; nd->flags |= LOOKUP_DIRECTORY | LOOKUP_FOLLOW;
} }
/* just plain open? */ /* just plain open? */
...@@ -1830,6 +1830,8 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1830,6 +1830,8 @@ struct file *do_filp_open(int dfd, const char *pathname,
} }
if (open_flag & O_DIRECTORY) if (open_flag & O_DIRECTORY)
nd.flags |= LOOKUP_DIRECTORY; nd.flags |= LOOKUP_DIRECTORY;
if (!(open_flag & O_NOFOLLOW))
nd.flags |= LOOKUP_FOLLOW;
filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
while (unlikely(!filp)) { /* trailing symlink */ while (unlikely(!filp)) { /* trailing symlink */
struct path holder; struct path holder;
...@@ -1837,7 +1839,7 @@ struct file *do_filp_open(int dfd, const char *pathname, ...@@ -1837,7 +1839,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
void *cookie; void *cookie;
error = -ELOOP; error = -ELOOP;
/* S_ISDIR part is a temporary automount kludge */ /* S_ISDIR part is a temporary automount kludge */
if ((open_flag & O_NOFOLLOW) && !S_ISDIR(inode->i_mode)) if (!(nd.flags & LOOKUP_FOLLOW) && !S_ISDIR(inode->i_mode))
goto exit_dput; goto exit_dput;
if (count++ == 32) if (count++ == 32)
goto exit_dput; goto exit_dput;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment