Skip to content

Commit 331fee3

Browse files
committed
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()
2 parents b3c3a9c + a77cfcb commit 331fee3

File tree

4 files changed

+21
-10
lines changed

4 files changed

+21
-10
lines changed

fs/cifs/readdir.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,17 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -994,16 +994,18 @@ int iterate_fd(struct files_struct *files, unsigned n,
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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
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 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
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 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
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,

0 commit comments

Comments
 (0)