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()
Unified · Split
| @@ -86,14 +86,17 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, · 85 unmodified lines | ||
| 86 | 86 | |
| 87 | 87 | dentry = d_lookup(parent, name); |
| 88 | 88 | if (dentry) { |
| 89 | + int err; | |
| 89 | 90 | inode = dentry->d_inode; |
| 90 | 91 | /* update inode in place if i_ino didn't change */ |
| 91 | 92 | if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { |
| 92 | 93 | cifs_fattr_to_inode(inode, fattr); |
| 93 | 94 | return dentry; |
| 94 | 95 | } |
| 95 | − d_drop(dentry); | |
| 96 | + err = d_invalidate(dentry); | |
| 96 | 97 | dput(dentry); |
| 98 | + if (err) | |
| 99 | + return NULL; | |
| 97 | 100 | } |
| 98 | 101 | |
| 99 | 102 | dentry = d_alloc(parent, name); |
| @@ -994,16 +994,18 @@ int iterate_fd(struct files_struct *files, unsigned n, · 993 unmodified lines | ||
| 994 | 994 | const void *p) |
| 995 | 995 | { |
| 996 | 996 | struct fdtable *fdt; |
| 997 | − struct file *file; | |
| 998 | 997 | int res = 0; |
| 999 | 998 | if (!files) |
| 1000 | 999 | return 0; |
| 1001 | 1000 | 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; | |
| 1007 | 1009 | } |
| 1008 | 1010 | spin_unlock(&files->file_lock); |
| 1009 | 1011 | return res; |
| @@ -2131,6 +2131,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) · 2130 unmodified lines | ||
| 2131 | 2131 | if (!len) |
| 2132 | 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 | 2139 | while (len--) { |
| 2135 | 2140 | c = *(const unsigned char *)name++; |
| 2136 | 2141 | if (c == '/' || c == '\0') |
| @@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) · 449 unmodified lines | ||
| 450 | 450 | nfs_refresh_inode(dentry->d_inode, entry->fattr); |
| 451 | 451 | goto out; |
| 452 | 452 | } else { |
| 453 | − d_drop(dentry); | |
| 453 | + if (d_invalidate(dentry) != 0) | |
| 454 | + goto out; | |
| 454 | 455 | dput(dentry); |
| 455 | 456 | } |
| 456 | 457 | } |
| @@ -1100,6 +1101,8 @@ out_set_verifier: · 643 unmodified lines | ||
| 1100 | 1101 | out_zap_parent: |
| 1101 | 1102 | nfs_zap_caches(dir); |
| 1102 | 1103 | out_bad: |
| 1104 | + nfs_free_fattr(fattr); | |
| 1105 | + nfs_free_fhandle(fhandle); | |
| 1103 | 1106 | nfs_mark_for_revalidate(dir); |
| 1104 | 1107 | if (inode && S_ISDIR(inode->i_mode)) { |
| 1105 | 1108 | /* Purge readdir caches. */ |
| @@ -1112,8 +1115,6 @@ out_zap_parent: · 6 unmodified lines | ||
| 1112 | 1115 | shrink_dcache_parent(dentry); |
| 1113 | 1116 | } |
| 1114 | 1117 | d_drop(dentry); |
| 1115 | − nfs_free_fattr(fattr); | |
| 1116 | − nfs_free_fhandle(fhandle); | |
| 1117 | 1118 | dput(parent); |
| 1118 | 1119 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n", |
| 1119 | 1120 | __func__, dentry->d_parent->d_name.name, |