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

+21 -10
+4 -1
fs/cifs/readdir.c
··· 86 87 dentry = d_lookup(parent, name); 88 if (dentry) { 89 inode = dentry->d_inode; 90 /* update inode in place if i_ino didn't change */ 91 if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { 92 cifs_fattr_to_inode(inode, fattr); 93 return dentry; 94 } 95 - d_drop(dentry); 96 dput(dentry); 97 } 98 99 dentry = d_alloc(parent, name);
··· 86 87 dentry = d_lookup(parent, name); 88 if (dentry) { 89 + int err; 90 inode = dentry->d_inode; 91 /* update inode in place if i_ino didn't change */ 92 if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { 93 cifs_fattr_to_inode(inode, fattr); 94 return dentry; 95 } 96 + err = d_invalidate(dentry); 97 dput(dentry); 98 + if (err) 99 + return NULL; 100 } 101 102 dentry = d_alloc(parent, name);
+8 -6
fs/file.c
··· 994 const void *p) 995 { 996 struct fdtable *fdt; 997 - struct file *file; 998 int res = 0; 999 if (!files) 1000 return 0; 1001 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); 1007 } 1008 spin_unlock(&files->file_lock); 1009 return res;
··· 994 const void *p) 995 { 996 struct fdtable *fdt; 997 int res = 0; 998 if (!files) 999 return 0; 1000 spin_lock(&files->file_lock); 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; 1009 } 1010 spin_unlock(&files->file_lock); 1011 return res;
+5
fs/namei.c
··· 2131 if (!len) 2132 return ERR_PTR(-EACCES); 2133 2134 while (len--) { 2135 c = *(const unsigned char *)name++; 2136 if (c == '/' || c == '\0')
··· 2131 if (!len) 2132 return ERR_PTR(-EACCES); 2133 2134 + if (unlikely(name[0] == '.')) { 2135 + if (len < 2 || (len == 2 && name[1] == '.')) 2136 + return ERR_PTR(-EACCES); 2137 + } 2138 + 2139 while (len--) { 2140 c = *(const unsigned char *)name++; 2141 if (c == '/' || c == '\0')
+4 -3
fs/nfs/dir.c
··· 450 nfs_refresh_inode(dentry->d_inode, entry->fattr); 451 goto out; 452 } else { 453 - d_drop(dentry); 454 dput(dentry); 455 } 456 } ··· 1101 out_zap_parent: 1102 nfs_zap_caches(dir); 1103 out_bad: 1104 nfs_mark_for_revalidate(dir); 1105 if (inode && S_ISDIR(inode->i_mode)) { 1106 /* Purge readdir caches. */ ··· 1115 shrink_dcache_parent(dentry); 1116 } 1117 d_drop(dentry); 1118 - nfs_free_fattr(fattr); 1119 - nfs_free_fhandle(fhandle); 1120 dput(parent); 1121 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", 1122 __func__, dentry->d_parent->d_name.name,
··· 450 nfs_refresh_inode(dentry->d_inode, entry->fattr); 451 goto out; 452 } else { 453 + if (d_invalidate(dentry) != 0) 454 + goto out; 455 dput(dentry); 456 } 457 } ··· 1100 out_zap_parent: 1101 nfs_zap_caches(dir); 1102 out_bad: 1103 + nfs_free_fattr(fattr); 1104 + nfs_free_fhandle(fhandle); 1105 nfs_mark_for_revalidate(dir); 1106 if (inode && S_ISDIR(inode->i_mode)) { 1107 /* Purge readdir caches. */ ··· 1112 shrink_dcache_parent(dentry); 1113 } 1114 d_drop(dentry); 1115 dput(parent); 1116 dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", 1117 __func__, dentry->d_parent->d_name.name,