Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
Linus Torvalds [Wed, 16 Dec 2009 20:04:02 +0000 (12:04 -0800)]
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (38 commits)
  direct I/O fallback sync simplification
  ocfs: stop using do_sync_mapping_range
  cleanup blockdev_direct_IO locking
  make generic_acl slightly more generic
  sanitize xattr handler prototypes
  libfs: move EXPORT_SYMBOL for d_alloc_name
  vfs: force reval of target when following LAST_BIND symlinks (try #7)
  ima: limit imbalance msg
  Untangling ima mess, part 3: kill dead code in ima
  Untangling ima mess, part 2: deal with counters
  Untangling ima mess, part 1: alloc_file()
  O_TRUNC open shouldn't fail after file truncation
  ima: call ima_inode_free ima_inode_free
  IMA: clean up the IMA counts updating code
  ima: only insert at inode creation time
  ima: valid return code from ima_inode_alloc
  fs: move get_empty_filp() deffinition to internal.h
  Sanitize exec_permission_lite()
  Kill cached_lookup() and real_lookup()
  Kill path_lookup_open()
  ...

Trivial conflicts in fs/direct-io.c

1  2 
fs/nfsd/vfs.c
ipc/shm.c

diff --combined fs/nfsd/vfs.c
@@@ -1,5 -1,7 +1,5 @@@
  #define MSNFS /* HACK HACK */
  /*
 - * linux/fs/nfsd/vfs.c
 - *
   * File operations used by nfsd. Some of these have been ripped from
   * other parts of the kernel because they weren't exported, others
   * are partial duplicates with added or changed functionality.
   * Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp>
   */
  
 -#include <linux/string.h>
 -#include <linux/time.h>
 -#include <linux/errno.h>
  #include <linux/fs.h>
  #include <linux/file.h>
 -#include <linux/mount.h>
 -#include <linux/major.h>
  #include <linux/splice.h>
 -#include <linux/proc_fs.h>
 -#include <linux/stat.h>
  #include <linux/fcntl.h>
 -#include <linux/net.h>
 -#include <linux/unistd.h>
 -#include <linux/slab.h>
 -#include <linux/pagemap.h>
 -#include <linux/in.h>
 -#include <linux/module.h>
  #include <linux/namei.h>
 -#include <linux/vfs.h>
  #include <linux/delay.h>
 -#include <linux/sunrpc/svc.h>
 -#include <linux/nfsd/nfsd.h>
 -#ifdef CONFIG_NFSD_V3
 -#include <linux/nfs3.h>
 -#include <linux/nfsd/xdr3.h>
 -#endif /* CONFIG_NFSD_V3 */
 -#include <linux/nfsd/nfsfh.h>
  #include <linux/quotaops.h>
  #include <linux/fsnotify.h>
 -#include <linux/posix_acl.h>
  #include <linux/posix_acl_xattr.h>
  #include <linux/xattr.h>
 +#include <linux/jhash.h>
 +#include <linux/ima.h>
 +#include <asm/uaccess.h>
 +
 +#ifdef CONFIG_NFSD_V3
 +#include "xdr3.h"
 +#endif /* CONFIG_NFSD_V3 */
 +
  #ifdef CONFIG_NFSD_V4
 -#include <linux/nfs4.h>
  #include <linux/nfs4_acl.h>
  #include <linux/nfsd_idmap.h>
 -#include <linux/security.h>
  #endif /* CONFIG_NFSD_V4 */
 -#include <linux/jhash.h>
 -#include <linux/ima.h>
  
 -#include <asm/uaccess.h>
 +#include "nfsd.h"
 +#include "vfs.h"
  
  #define NFSDDBG_FACILITY              NFSDDBG_FILEOP
  
@@@ -70,6 -89,12 +70,6 @@@ struct raparm_hbucket 
  #define RAPARM_HASH_MASK      (RAPARM_HASH_SIZE-1)
  static struct raparm_hbucket  raparm_hash[RAPARM_HASH_SIZE];
  
 -static inline int
 -nfsd_v4client(struct svc_rqst *rq)
 -{
 -    return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
 -}
 -
  /* 
   * Called from nfsd_lookup and encode_dirent. Check if we have crossed 
   * a mount point.
@@@ -91,16 -116,8 +91,16 @@@ nfsd_cross_mnt(struct svc_rqst *rqstp, 
  
        exp2 = rqst_exp_get_by_name(rqstp, &path);
        if (IS_ERR(exp2)) {
 -              if (PTR_ERR(exp2) != -ENOENT)
 -                      err = PTR_ERR(exp2);
 +              err = PTR_ERR(exp2);
 +              /*
 +               * We normally allow NFS clients to continue
 +               * "underneath" a mountpoint that is not exported.
 +               * The exception is V4ROOT, where no traversal is ever
 +               * allowed without an explicit export of the new
 +               * directory.
 +               */
 +              if (err == -ENOENT && !(exp->ex_flags & NFSEXP_V4ROOT))
 +                      err = 0;
                path_put(&path);
                goto out;
        }
@@@ -124,53 -141,6 +124,53 @@@ out
        return err;
  }
  
 +static void follow_to_parent(struct path *path)
 +{
 +      struct dentry *dp;
 +
 +      while (path->dentry == path->mnt->mnt_root && follow_up(path))
 +              ;
 +      dp = dget_parent(path->dentry);
 +      dput(path->dentry);
 +      path->dentry = dp;
 +}
 +
 +static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, struct svc_export **exp, struct dentry **dentryp)
 +{
 +      struct svc_export *exp2;
 +      struct path path = {.mnt = mntget((*exp)->ex_path.mnt),
 +                          .dentry = dget(dparent)};
 +
 +      follow_to_parent(&path);
 +
 +      exp2 = rqst_exp_parent(rqstp, &path);
 +      if (PTR_ERR(exp2) == -ENOENT) {
 +              *dentryp = dget(dparent);
 +      } else if (IS_ERR(exp2)) {
 +              path_put(&path);
 +              return PTR_ERR(exp2);
 +      } else {
 +              *dentryp = dget(path.dentry);
 +              exp_put(*exp);
 +              *exp = exp2;
 +      }
 +      path_put(&path);
 +      return 0;
 +}
 +
 +/*
 + * For nfsd purposes, we treat V4ROOT exports as though there was an
 + * export at *every* directory.
 + */
 +int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
 +{
 +      if (d_mountpoint(dentry))
 +              return 1;
 +      if (!(exp->ex_flags & NFSEXP_V4ROOT))
 +              return 0;
 +      return dentry->d_inode != NULL;
 +}
 +
  __be32
  nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
                   const char *name, unsigned int len,
                        dentry = dget(dparent);
                else if (dparent != exp->ex_path.dentry)
                        dentry = dget_parent(dparent);
 -              else if (!EX_NOHIDE(exp))
 +              else if (!EX_NOHIDE(exp) && !nfsd_v4client(rqstp))
                        dentry = dget(dparent); /* .. == . just like at / */
                else {
                        /* checking mountpoint crossing is very different when stepping up */
 -                      struct svc_export *exp2 = NULL;
 -                      struct dentry *dp;
 -                      struct path path = {.mnt = mntget(exp->ex_path.mnt),
 -                                          .dentry = dget(dparent)};
 -
 -                      while (path.dentry == path.mnt->mnt_root &&
 -                             follow_up(&path))
 -                              ;
 -                      dp = dget_parent(path.dentry);
 -                      dput(path.dentry);
 -                      path.dentry = dp;
 -
 -                      exp2 = rqst_exp_parent(rqstp, &path);
 -                      if (PTR_ERR(exp2) == -ENOENT) {
 -                              dentry = dget(dparent);
 -                      } else if (IS_ERR(exp2)) {
 -                              host_err = PTR_ERR(exp2);
 -                              path_put(&path);
 +                      host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry);
 +                      if (host_err)
                                goto out_nfserr;
 -                      } else {
 -                              dentry = dget(path.dentry);
 -                              exp_put(exp);
 -                              exp = exp2;
 -                      }
 -                      path_put(&path);
                }
        } else {
                fh_lock(fhp);
                /*
                 * check if we have crossed a mount point ...
                 */
 -              if (d_mountpoint(dentry)) {
 +              if (nfsd_mountpoint(dentry, exp)) {
                        if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
                                dput(dentry);
                                goto out_nfserr;
@@@ -752,8 -744,6 +752,6 @@@ nfsd_open(struct svc_rqst *rqstp, struc
                            flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
-       else
-               ima_counts_get(*filp);
  out_nfserr:
        err = nfserrno(host_err);
  out:
@@@ -2132,8 -2122,7 +2130,7 @@@ nfsd_permission(struct svc_rqst *rqstp
         */
        path.mnt = exp->ex_path.mnt;
        path.dentry = dentry;
-       err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC),
-                            IMA_COUNT_LEAVE);
+       err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
  nfsd_out:
        return err? nfserrno(err) : 0;
  }
diff --combined ipc/shm.c
+++ b/ipc/shm.c
@@@ -39,7 -39,6 +39,6 @@@
  #include <linux/nsproxy.h>
  #include <linux/mount.h>
  #include <linux/ipc_namespace.h>
- #include <linux/ima.h>
  
  #include <asm/uaccess.h>
  
@@@ -101,7 -100,6 +100,7 @@@ static void do_shm_rmid(struct ipc_name
  void shm_exit_ns(struct ipc_namespace *ns)
  {
        free_ipcs(ns, &shm_ids(ns), do_shm_rmid);
 +      idr_destroy(&ns->ids[IPC_SHM_IDS].ipcs_idr);
  }
  #endif
  
@@@ -879,8 -877,8 +878,8 @@@ long do_shmat(int shmid, char __user *s
        if (err)
                goto out_unlock;
  
-       path.dentry = dget(shp->shm_file->f_path.dentry);
-       path.mnt    = shp->shm_file->f_path.mnt;
+       path = shp->shm_file->f_path;
+       path_get(&path);
        shp->shm_nattch++;
        size = i_size_read(path.dentry->d_inode);
        shm_unlock(shp);
        if (!sfd)
                goto out_put_dentry;
  
-       file = alloc_file(path.mnt, path.dentry, f_mode,
-                       is_file_hugepages(shp->shm_file) ?
+       file = alloc_file(&path, f_mode,
+                         is_file_hugepages(shp->shm_file) ?
                                &shm_file_operations_huge :
                                &shm_file_operations);
        if (!file)
                goto out_free;
-       ima_counts_get(file);
  
        file->private_data = sfd;
        file->f_mapping = shp->shm_file->f_mapping;
@@@ -951,7 -948,7 +949,7 @@@ out_unlock
  out_free:
        kfree(sfd);
  out_put_dentry:
-       dput(path.dentry);
+       path_put(&path);
        goto out_nattch;
  }