History

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()

Linus Torvalds committed 13 years ago

Commit 331fee32 parents b3c3a9c a77cfcb4 files · +21 −10Browse files

Unified · Split

4 files
  1. fs/cifs/readdir.c +4 −1
  2. fs/file.c +8 −6
  3. fs/namei.c +5 −0
  4. fs/nfs/dir.c +4 −3
fs/cifs/readdir.c+4−1
@@ -86,14 +86,17 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, · 85 unmodified lines
8686
8787 dentry = d_lookup(parent, name);
8888 if (dentry) {
89+ int err;
8990 inode = dentry->d_inode;
9091 /* update inode in place if i_ino didn't change */
9192 if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
9293 cifs_fattr_to_inode(inode, fattr);
9394 return dentry;
9495 }
95− d_drop(dentry);
96+ err = d_invalidate(dentry);
9697 dput(dentry);
98+ if (err)
99+ return NULL;
97100 }
98101
99102 dentry = d_alloc(parent, name);
fs/file.c+8−6
@@ -994,16 +994,18 @@ int iterate_fd(struct files_struct *files, unsigned n, · 993 unmodified lines
994994 const void *p)
995995 {
996996 struct fdtable *fdt;
997− struct file *file;
998997 int res = 0;
999998 if (!files)
1000999 return 0;
10011000 spin_lock(&files->file_lock);
1002− fdt = files_fdtable(files);
1003− while (!res && n < fdt->max_fds) {
1004− file = rcu_dereference_check_fdtable(files, fdt->fd[n++]);
1005− if (file)
1006− res = f(p, file, n);
1001+ for (fdt = files_fdtable(files); n < fdt->max_fds; n++) {
1002+ struct file *file;
1003+ file = rcu_dereference_check_fdtable(files, fdt->fd[n]);
1004+ if (!file)
1005+ continue;
1006+ res = f(p, file, n);
1007+ if (res)
1008+ break;
10071009 }
10081010 spin_unlock(&files->file_lock);
10091011 return res;
fs/namei.c+5−0
@@ -2131,6 +2131,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) · 2130 unmodified lines
21312131 if (!len)
21322132 return ERR_PTR(-EACCES);
21332133
2134+ if (unlikely(name[0] == '.')) {
2135+ if (len < 2 || (len == 2 && name[1] == '.'))
2136+ return ERR_PTR(-EACCES);
2137+ }
2138+
21342139 while (len--) {
21352140 c = *(const unsigned char *)name++;
21362141 if (c == '/' || c == '\0')
fs/nfs/dir.c+4−3
@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) · 449 unmodified lines
450450 nfs_refresh_inode(dentry->d_inode, entry->fattr);
451451 goto out;
452452 } else {
453− d_drop(dentry);
453+ if (d_invalidate(dentry) != 0)
454+ goto out;
454455 dput(dentry);
455456 }
456457 }
@@ -1100,6 +1101,8 @@ out_set_verifier: · 643 unmodified lines
11001101 out_zap_parent:
11011102 nfs_zap_caches(dir);
11021103 out_bad:
1104+ nfs_free_fattr(fattr);
1105+ nfs_free_fhandle(fhandle);
11031106 nfs_mark_for_revalidate(dir);
11041107 if (inode && S_ISDIR(inode->i_mode)) {
11051108 /* Purge readdir caches. */
@@ -1112,8 +1115,6 @@ out_zap_parent: · 6 unmodified lines
11121115 shrink_dcache_parent(dentry);
11131116 }
11141117 d_drop(dentry);
1115− nfs_free_fattr(fattr);
1116− nfs_free_fhandle(fhandle);
11171118 dput(parent);
11181119 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
11191120 __func__, dentry->d_parent->d_name.name,