aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-01 16:29:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-01 16:29:55 -0500
commit331fee3cd31c3ec3641062ca01a71b79dbf58b40 (patch)
tree90fa1a59b0256c82f95853f60b5e551431a1eb43
parentb3c3a9cf2a28ee4a8d0b62e2e58c61e9ca9bb47b (diff)
parenta77cfcb429ed98845a4e4df72473b8f37acd890b (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "A bunch of fixes; the last one is this cycle regression, the rest are -stable fodder." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fix off-by-one in argument passed by iterate_fd() to callbacks lookup_one_len: don't accept . and .. cifs: get rid of blind d_drop() in readdir nfs_lookup_revalidate(): fix a leak don't do blind d_drop() in nfs_prime_dcache()
-rw-r--r--fs/cifs/readdir.c5
-rw-r--r--fs/file.c14
-rw-r--r--fs/namei.c5
-rw-r--r--fs/nfs/dir.c7
4 files changed, 21 insertions, 10 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index f9b5d3d6cf33..1c576e871366 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -86,14 +86,17 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
86 86
87 dentry = d_lookup(parent, name); 87 dentry = d_lookup(parent, name);
88 if (dentry) { 88 if (dentry) {
89 int err;
89 inode = dentry->d_inode; 90 inode = dentry->d_inode;
90 /* update inode in place if i_ino didn't change */ 91 /* update inode in place if i_ino didn't change */
91 if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { 92 if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
92 cifs_fattr_to_inode(inode, fattr); 93 cifs_fattr_to_inode(inode, fattr);
93 return dentry; 94 return dentry;
94 } 95 }
95 d_drop(dentry); 96 err = d_invalidate(dentry);
96 dput(dentry); 97 dput(dentry);
98 if (err)
99 return NULL;
97 } 100 }
98 101
99 dentry = d_alloc(parent, name); 102 dentry = d_alloc(parent, name);
diff --git a/fs/file.c b/fs/file.c
index 7cb71b992603..eff23162485f 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -994,16 +994,18 @@ int iterate_fd(struct files_struct *files, unsigned n,
994 const void *p) 994 const void *p)
995{ 995{
996 struct fdtable *fdt; 996 struct fdtable *fdt;
997 struct file *file;
998 int res = 0; 997 int res = 0;
999 if (!files) 998 if (!files)
1000 return 0; 999 return 0;
1001 spin_lock(&files->file_lock); 1000 spin_lock(&files->file_lock);
1002 fdt = files_fdtable(files); 1001 for (fdt = files_fdtable(files); n < fdt->max_fds; n++) {
1003 while (!res && n < fdt->max_fds) { 1002 struct file *file;
1004 file = rcu_dereference_check_fdtable(files, fdt->fd[n++]); 1003 file = rcu_dereference_check_fdtable(files, fdt->fd[n]);
1005 if (file) 1004 if (!file)
1006 res = f(p, file, n); 1005 continue;
1006 res = f(p, file, n);
1007 if (res)
1008 break;
1007 } 1009 }
1008 spin_unlock(&files->file_lock); 1010 spin_unlock(&files->file_lock);
1009 return res; 1011 return res;
diff --git a/fs/namei.c b/fs/namei.c
index 937f9d50c84b..5f4cdf3ad913 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2131,6 +2131,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
2131 if (!len) 2131 if (!len)
2132 return ERR_PTR(-EACCES); 2132 return ERR_PTR(-EACCES);
2133 2133
2134 if (unlikely(name[0] == '.')) {
2135 if (len < 2 || (len == 2 && name[1] == '.'))
2136 return ERR_PTR(-EACCES);
2137 }
2138
2134 while (len--) { 2139 while (len--) {
2135 c = *(const unsigned char *)name++; 2140 c = *(const unsigned char *)name++;
2136 if (c == '/' || c == '\0') 2141 if (c == '/' || c == '\0')
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ce8cb926526b..b9e66b7e0c14 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
450 nfs_refresh_inode(dentry->d_inode, entry->fattr); 450 nfs_refresh_inode(dentry->d_inode, entry->fattr);
451 goto out; 451 goto out;
452 } else { 452 } else {
453 d_drop(dentry); 453 if (d_invalidate(dentry) != 0)
454 goto out;
454 dput(dentry); 455 dput(dentry);
455 } 456 }
456 } 457 }
@@ -1100,6 +1101,8 @@ out_set_verifier:
1100out_zap_parent: 1101out_zap_parent:
1101 nfs_zap_caches(dir); 1102 nfs_zap_caches(dir);
1102 out_bad: 1103 out_bad:
1104 nfs_free_fattr(fattr);
1105 nfs_free_fhandle(fhandle);
1103 nfs_mark_for_revalidate(dir); 1106 nfs_mark_for_revalidate(dir);
1104 if (inode && S_ISDIR(inode->i_mode)) { 1107 if (inode && S_ISDIR(inode->i_mode)) {
1105 /* Purge readdir caches. */ 1108 /* Purge readdir caches. */
@@ -1112,8 +1115,6 @@ out_zap_parent:
1112 shrink_dcache_parent(dentry); 1115 shrink_dcache_parent(dentry);
1113 } 1116 }
1114 d_drop(dentry); 1117 d_drop(dentry);
1115 nfs_free_fattr(fattr);
1116 nfs_free_fhandle(fhandle);
1117 dput(parent); 1118 dput(parent);
1118 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", 1119 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
1119 __func__, dentry->d_parent->d_name.name, 1120 __func__, dentry->d_parent->d_name.name,