]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Dec 2012 21:29:55 +0000 (13:29 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 1 Dec 2012 21:29:55 +0000 (13:29 -0800)
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()

fs/cifs/readdir.c
fs/file.c
fs/namei.c
fs/nfs/dir.c

index f9b5d3d6cf33461081f4945d61a5d604fe2ef468..1c576e8713669534be76853aa6c45e97482def96 100644 (file)
@@ -86,14 +86,17 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
 
        dentry = d_lookup(parent, name);
        if (dentry) {
+               int err;
                inode = dentry->d_inode;
                /* update inode in place if i_ino didn't change */
                if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
                        cifs_fattr_to_inode(inode, fattr);
                        return dentry;
                }
-               d_drop(dentry);
+               err = d_invalidate(dentry);
                dput(dentry);
+               if (err)
+                       return NULL;
        }
 
        dentry = d_alloc(parent, name);
index 7cb71b99260340fe7302d2a8c5dc4f84f8029aff..eff23162485f93176255199b3ed74176534ae489 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -994,16 +994,18 @@ int iterate_fd(struct files_struct *files, unsigned n,
                const void *p)
 {
        struct fdtable *fdt;
-       struct file *file;
        int res = 0;
        if (!files)
                return 0;
        spin_lock(&files->file_lock);
-       fdt = files_fdtable(files);
-       while (!res && n < fdt->max_fds) {
-               file = rcu_dereference_check_fdtable(files, fdt->fd[n++]);
-               if (file)
-                       res = f(p, file, n);
+       for (fdt = files_fdtable(files); n < fdt->max_fds; n++) {
+               struct file *file;
+               file = rcu_dereference_check_fdtable(files, fdt->fd[n]);
+               if (!file)
+                       continue;
+               res = f(p, file, n);
+               if (res)
+                       break;
        }
        spin_unlock(&files->file_lock);
        return res;
index 937f9d50c84bdead7516057fead3d5a702ead4b9..5f4cdf3ad913fec928835d87fbe499efdf7d67e5 100644 (file)
@@ -2131,6 +2131,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
        if (!len)
                return ERR_PTR(-EACCES);
 
+       if (unlikely(name[0] == '.')) {
+               if (len < 2 || (len == 2 && name[1] == '.'))
+                       return ERR_PTR(-EACCES);
+       }
+
        while (len--) {
                c = *(const unsigned char *)name++;
                if (c == '/' || c == '\0')
index ce8cb926526bfad79aabe5b8448f80212e1670f9..b9e66b7e0c1495ba05c1fb6a4b2f1557ca6a9b24 100644 (file)
@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
                        nfs_refresh_inode(dentry->d_inode, entry->fattr);
                        goto out;
                } else {
-                       d_drop(dentry);
+                       if (d_invalidate(dentry) != 0)
+                               goto out;
                        dput(dentry);
                }
        }
@@ -1100,6 +1101,8 @@ out_set_verifier:
 out_zap_parent:
        nfs_zap_caches(dir);
  out_bad:
+       nfs_free_fattr(fattr);
+       nfs_free_fhandle(fhandle);
        nfs_mark_for_revalidate(dir);
        if (inode && S_ISDIR(inode->i_mode)) {
                /* Purge readdir caches. */
@@ -1112,8 +1115,6 @@ out_zap_parent:
                shrink_dcache_parent(dentry);
        }
        d_drop(dentry);
-       nfs_free_fattr(fattr);
-       nfs_free_fhandle(fhandle);
        dput(parent);
        dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
                        __func__, dentry->d_parent->d_name.name,