diff options
author | Jan Kara <jack@suse.cz> | 2010-05-13 06:52:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-13 11:46:04 -0400 |
commit | 002baeecf53677d2034113e34197ec221f42e037 (patch) | |
tree | 081c54c4a9a266a894a00165e97dabfb212a2470 /fs/namei.c | |
parent | fc8e38f142dd59f81306ff6a81c1351e9eb0e014 (diff) |
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: Marius Tolzmann <tolzmann@molgen.mpg.de>
Acked-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c index a7dce91a7e42..16df7277a92e 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1641,7 +1641,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
1641 | if (nd->last.name[nd->last.len]) { | 1641 | if (nd->last.name[nd->last.len]) { |
1642 | if (open_flag & O_CREAT) | 1642 | if (open_flag & O_CREAT) |
1643 | goto exit; | 1643 | goto exit; |
1644 | nd->flags |= LOOKUP_DIRECTORY; | 1644 | nd->flags |= LOOKUP_DIRECTORY | LOOKUP_FOLLOW; |
1645 | } | 1645 | } |
1646 | 1646 | ||
1647 | /* just plain open? */ | 1647 | /* just plain open? */ |
@@ -1830,6 +1830,8 @@ reval: | |||
1830 | } | 1830 | } |
1831 | if (open_flag & O_DIRECTORY) | 1831 | if (open_flag & O_DIRECTORY) |
1832 | nd.flags |= LOOKUP_DIRECTORY; | 1832 | nd.flags |= LOOKUP_DIRECTORY; |
1833 | if (!(open_flag & O_NOFOLLOW)) | ||
1834 | nd.flags |= LOOKUP_FOLLOW; | ||
1833 | filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); | 1835 | filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); |
1834 | while (unlikely(!filp)) { /* trailing symlink */ | 1836 | while (unlikely(!filp)) { /* trailing symlink */ |
1835 | struct path holder; | 1837 | struct path holder; |
@@ -1837,7 +1839,7 @@ reval: | |||
1837 | void *cookie; | 1839 | void *cookie; |
1838 | error = -ELOOP; | 1840 | error = -ELOOP; |
1839 | /* S_ISDIR part is a temporary automount kludge */ | 1841 | /* S_ISDIR part is a temporary automount kludge */ |
1840 | if ((open_flag & O_NOFOLLOW) && !S_ISDIR(inode->i_mode)) | 1842 | if (!(nd.flags & LOOKUP_FOLLOW) && !S_ISDIR(inode->i_mode)) |
1841 | goto exit_dput; | 1843 | goto exit_dput; |
1842 | if (count++ == 32) | 1844 | if (count++ == 32) |
1843 | goto exit_dput; | 1845 | goto exit_dput; |