Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Mar 2011 16:15:43 +0000 (09:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Mar 2011 16:15:43 +0000 (09:15 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (33 commits)
  AppArmor: kill unused macros in lsm.c
  AppArmor: cleanup generated files correctly
  KEYS: Add an iovec version of KEYCTL_INSTANTIATE
  KEYS: Add a new keyctl op to reject a key with a specified error code
  KEYS: Add a key type op to permit the key description to be vetted
  KEYS: Add an RCU payload dereference macro
  AppArmor: Cleanup make file to remove cruft and make it easier to read
  SELinux: implement the new sb_remount LSM hook
  LSM: Pass -o remount options to the LSM
  SELinux: Compute SID for the newly created socket
  SELinux: Socket retains creator role and MLS attribute
  SELinux: Auto-generate security_is_socket_class
  TOMOYO: Fix memory leak upon file open.
  Revert "selinux: simplify ioctl checking"
  selinux: drop unused packet flow permissions
  selinux: Fix packet forwarding checks on postrouting
  selinux: Fix wrong checks for selinux_policycap_netpeer
  selinux: Fix check for xfrm selinux context algorithm
  ima: remove unnecessary call to ima_must_measure
  IMA: remove IMA imbalance checking
  ...

14 files changed:
1  2 
arch/x86/Kconfig
fs/btrfs/inode.c
fs/ext3/namei.c
fs/file_table.c
fs/jfs/namei.c
fs/namespace.c
fs/ocfs2/refcounttree.c
fs/open.c
fs/reiserfs/namei.c
include/linux/fs.h
include/linux/security.h
kernel/sysctl.c
mm/shmem.c
security/security.c

diff --combined arch/x86/Kconfig
@@@ -64,12 -64,8 +64,12 @@@ config X8
        select HAVE_TEXT_POKE_SMP
        select HAVE_GENERIC_HARDIRQS
        select HAVE_SPARSE_IRQ
 +      select GENERIC_FIND_FIRST_BIT
 +      select GENERIC_FIND_NEXT_BIT
        select GENERIC_IRQ_PROBE
        select GENERIC_PENDING_IRQ if SMP
 +      select GENERIC_IRQ_SHOW
 +      select IRQ_FORCED_THREADING
        select USE_GENERIC_SMP_HELPERS if SMP
  
  config INSTRUCTION_DECODER
@@@ -386,8 -382,6 +386,8 @@@ config X86_INTEL_C
        depends on X86_32
        depends on X86_EXTENDED_PLATFORM
        select X86_REBOOTFIXUPS
 +      select OF
 +      select OF_EARLY_FLATTREE
        ---help---
          Select for the Intel CE media processor (CE4100) SOC.
          This option compiles in support for the CE4100 SOC for settop
@@@ -817,7 -811,7 +817,7 @@@ config X86_LOCAL_API
  
  config X86_IO_APIC
        def_bool y
 -      depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
 +      depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
  
  config X86_VISWS_APIC
        def_bool y
@@@ -1711,7 -1705,7 +1711,7 @@@ config HAVE_ARCH_EARLY_PFN_TO_NI
        depends on NUMA
  
  config USE_PERCPU_NUMA_NODE_ID
 -      def_bool X86_64
 +      def_bool y
        depends on NUMA
  
  menu "Power management and ACPI options"
@@@ -2072,10 -2066,9 +2072,10 @@@ config SCx200HR_TIME
  
  config OLPC
        bool "One Laptop Per Child support"
 +      depends on !X86_PAE
        select GPIOLIB
 -      select OLPC_OPENFIRMWARE
 -      depends on !X86_64 && !X86_PAE
 +      select OF
 +      select OF_PROMTREE if PROC_DEVICETREE
        ---help---
          Add support for detecting the unique features of the OLPC
          XO hardware.
@@@ -2086,6 -2079,21 +2086,6 @@@ config OLPC_XO
        ---help---
          Add support for non-essential features of the OLPC XO-1 laptop.
  
 -config OLPC_OPENFIRMWARE
 -      bool "Support for OLPC's Open Firmware"
 -      depends on !X86_64 && !X86_PAE
 -      default n
 -      select OF
 -      help
 -        This option adds support for the implementation of Open Firmware
 -        that is used on the OLPC XO-1 Children's Machine.
 -        If unsure, say N here.
 -
 -config OLPC_OPENFIRMWARE_DT
 -      bool
 -      default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE
 -      select OF_PROMTREE
 -
  endif # X86_32
  
  config AMD_NB
@@@ -2130,6 -2138,11 +2130,11 @@@ config SYSVIPC_COMPA
        def_bool y
        depends on COMPAT && SYSVIPC
  
+ config KEYS_COMPAT
+       bool
+       depends on COMPAT && KEYS
+       default y
  endmenu
  
  
diff --combined fs/btrfs/inode.c
@@@ -90,13 -90,14 +90,14 @@@ static noinline int cow_file_range(stru
                                   unsigned long *nr_written, int unlock);
  
  static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
-                                    struct inode *inode,  struct inode *dir)
+                                    struct inode *inode,  struct inode *dir,
+                                    const struct qstr *qstr)
  {
        int err;
  
        err = btrfs_init_acl(trans, inode, dir);
        if (!err)
-               err = btrfs_xattr_security_init(trans, inode, dir);
+               err = btrfs_xattr_security_init(trans, inode, dir, qstr);
        return err;
  }
  
@@@ -4704,7 -4705,7 +4705,7 @@@ static int btrfs_mknod(struct inode *di
        if (IS_ERR(inode))
                goto out_unlock;
  
-       err = btrfs_init_inode_security(trans, inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@@ -4765,7 -4766,7 +4766,7 @@@ static int btrfs_create(struct inode *d
        if (IS_ERR(inode))
                goto out_unlock;
  
-       err = btrfs_init_inode_security(trans, inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@@ -4806,6 -4807,9 +4807,6 @@@ static int btrfs_link(struct dentry *ol
        int err;
        int drop_inode = 0;
  
 -      if (inode->i_nlink == 0)
 -              return -ENOENT;
 -
        /* do not allow sys_link's with other subvols of the same device */
        if (root->objectid != BTRFS_I(inode)->root->objectid)
                return -EPERM;
@@@ -4891,7 -4895,7 +4892,7 @@@ static int btrfs_mkdir(struct inode *di
  
        drop_on_err = 1;
  
-       err = btrfs_init_inode_security(trans, inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err)
                goto out_fail;
  
@@@ -7103,7 -7107,7 +7104,7 @@@ static int btrfs_symlink(struct inode *
        if (IS_ERR(inode))
                goto out_unlock;
  
-       err = btrfs_init_inode_security(trans, inode, dir);
+       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
diff --combined fs/ext3/namei.c
@@@ -1710,7 -1710,7 +1710,7 @@@ retry
        if (IS_DIRSYNC(dir))
                handle->h_sync = 1;
  
-       inode = ext3_new_inode (handle, dir, mode);
+       inode = ext3_new_inode (handle, dir, &dentry->d_name, mode);
        err = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
                inode->i_op = &ext3_file_inode_operations;
@@@ -1746,7 -1746,7 +1746,7 @@@ retry
        if (IS_DIRSYNC(dir))
                handle->h_sync = 1;
  
-       inode = ext3_new_inode (handle, dir, mode);
+       inode = ext3_new_inode (handle, dir, &dentry->d_name, mode);
        err = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
                init_special_inode(inode, inode->i_mode, rdev);
@@@ -1784,7 -1784,7 +1784,7 @@@ retry
        if (IS_DIRSYNC(dir))
                handle->h_sync = 1;
  
-       inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
+       inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFDIR | mode);
        err = PTR_ERR(inode);
        if (IS_ERR(inode))
                goto out_stop;
@@@ -2206,7 -2206,7 +2206,7 @@@ retry
        if (IS_DIRSYNC(dir))
                handle->h_sync = 1;
  
-       inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
+       inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFLNK|S_IRWXUGO);
        err = PTR_ERR(inode);
        if (IS_ERR(inode))
                goto out_stop;
@@@ -2253,6 -2253,13 +2253,6 @@@ static int ext3_link (struct dentry * o
  
        dquot_initialize(dir);
  
 -      /*
 -       * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
 -       * otherwise has the potential to corrupt the orphan inode list.
 -       */
 -      if (inode->i_nlink == 0)
 -              return -ENOENT;
 -
  retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS);
diff --combined fs/file_table.c
@@@ -190,7 -190,8 +190,8 @@@ struct file *alloc_file(struct path *pa
                file_take_write(file);
                WARN_ON(mnt_clone_write(path->mnt));
        }
-       ima_counts_get(file);
+       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+               i_readcount_inc(path->dentry->d_inode);
        return file;
  }
  EXPORT_SYMBOL(alloc_file);
@@@ -251,6 -252,8 +252,8 @@@ static void __fput(struct file *file
        fops_put(file->f_op);
        put_pid(file->f_owner.pid);
        file_sb_list_del(file);
+       if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+               i_readcount_dec(inode);
        if (file->f_mode & FMODE_WRITE)
                drop_file_write_access(file);
        file->f_path.dentry = NULL;
@@@ -276,10 -279,11 +279,10 @@@ struct file *fget(unsigned int fd
        rcu_read_lock();
        file = fcheck_files(files, fd);
        if (file) {
 -              if (!atomic_long_inc_not_zero(&file->f_count)) {
 -                      /* File object ref couldn't be taken */
 -                      rcu_read_unlock();
 -                      return NULL;
 -              }
 +              /* File object ref couldn't be taken */
 +              if (file->f_mode & FMODE_PATH ||
 +                  !atomic_long_inc_not_zero(&file->f_count))
 +                      file = NULL;
        }
        rcu_read_unlock();
  
  
  EXPORT_SYMBOL(fget);
  
 +struct file *fget_raw(unsigned int fd)
 +{
 +      struct file *file;
 +      struct files_struct *files = current->files;
 +
 +      rcu_read_lock();
 +      file = fcheck_files(files, fd);
 +      if (file) {
 +              /* File object ref couldn't be taken */
 +              if (!atomic_long_inc_not_zero(&file->f_count))
 +                      file = NULL;
 +      }
 +      rcu_read_unlock();
 +
 +      return file;
 +}
 +
 +EXPORT_SYMBOL(fget_raw);
 +
  /*
   * Lightweight file lookup - no refcnt increment if fd table isn't shared.
   *
@@@ -331,33 -316,6 +334,33 @@@ struct file *fget_light(unsigned int fd
        *fput_needed = 0;
        if (atomic_read(&files->count) == 1) {
                file = fcheck_files(files, fd);
 +              if (file && (file->f_mode & FMODE_PATH))
 +                      file = NULL;
 +      } else {
 +              rcu_read_lock();
 +              file = fcheck_files(files, fd);
 +              if (file) {
 +                      if (!(file->f_mode & FMODE_PATH) &&
 +                          atomic_long_inc_not_zero(&file->f_count))
 +                              *fput_needed = 1;
 +                      else
 +                              /* Didn't get the reference, someone's freed */
 +                              file = NULL;
 +              }
 +              rcu_read_unlock();
 +      }
 +
 +      return file;
 +}
 +
 +struct file *fget_raw_light(unsigned int fd, int *fput_needed)
 +{
 +      struct file *file;
 +      struct files_struct *files = current->files;
 +
 +      *fput_needed = 0;
 +      if (atomic_read(&files->count) == 1) {
 +              file = fcheck_files(files, fd);
        } else {
                rcu_read_lock();
                file = fcheck_files(files, fd);
diff --combined fs/jfs/namei.c
@@@ -115,7 -115,7 +115,7 @@@ static int jfs_create(struct inode *dip
        if (rc)
                goto out3;
  
-       rc = jfs_init_security(tid, ip, dip);
+       rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
        if (rc) {
                txAbort(tid, 0);
                goto out3;
@@@ -253,7 -253,7 +253,7 @@@ static int jfs_mkdir(struct inode *dip
        if (rc)
                goto out3;
  
-       rc = jfs_init_security(tid, ip, dip);
+       rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
        if (rc) {
                txAbort(tid, 0);
                goto out3;
@@@ -809,6 -809,9 +809,6 @@@ static int jfs_link(struct dentry *old_
        if (ip->i_nlink == JFS_LINK_MAX)
                return -EMLINK;
  
 -      if (ip->i_nlink == 0)
 -              return -ENOENT;
 -
        dquot_initialize(dir);
  
        tid = txBegin(ip->i_sb, 0);
@@@ -929,7 -932,7 +929,7 @@@ static int jfs_symlink(struct inode *di
        mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
  
-       rc = jfs_init_security(tid, ip, dip);
+       rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
        if (rc)
                goto out3;
  
@@@ -1392,7 -1395,7 +1392,7 @@@ static int jfs_mknod(struct inode *dir
        if (rc)
                goto out3;
  
-       rc = jfs_init_security(tid, ip, dir);
+       rc = jfs_init_security(tid, ip, dir, &dentry->d_name);
        if (rc) {
                txAbort(tid, 0);
                goto out3;
diff --combined fs/namespace.c
@@@ -1002,18 -1002,6 +1002,18 @@@ const struct seq_operations mounts_op 
        .show   = show_vfsmnt
  };
  
 +static int uuid_is_nil(u8 *uuid)
 +{
 +      int i;
 +      u8  *cp = (u8 *)uuid;
 +
 +      for (i = 0; i < 16; i++) {
 +              if (*cp++)
 +                      return 0;
 +      }
 +      return 1;
 +}
 +
  static int show_mountinfo(struct seq_file *m, void *v)
  {
        struct proc_mounts *p = m->private;
        if (IS_MNT_UNBINDABLE(mnt))
                seq_puts(m, " unbindable");
  
 +      if (!uuid_is_nil(mnt->mnt_sb->s_uuid))
 +              /* print the uuid */
 +              seq_printf(m, " uuid:%pU", mnt->mnt_sb->s_uuid);
 +
        /* Filesystem specific data */
        seq_puts(m, " - ");
        show_type(m, sb);
@@@ -1783,6 -1767,10 +1783,10 @@@ static int do_remount(struct path *path
        if (path->dentry != path->mnt->mnt_root)
                return -EINVAL;
  
+       err = security_sb_remount(sb, data);
+       if (err)
+               return err;
        down_write(&sb->s_umount);
        if (flags & MS_BIND)
                err = change_mount_flags(path->mnt, flags);
diff --combined fs/ocfs2/refcounttree.c
@@@ -4328,7 -4328,8 +4328,8 @@@ static int ocfs2_reflink(struct dentry 
  
        /* If the security isn't preserved, we need to re-initialize them. */
        if (!preserve) {
-               error = ocfs2_init_security_and_acl(dir, new_orphan_inode);
+               error = ocfs2_init_security_and_acl(dir, new_orphan_inode,
+                                                   &new_dentry->d_name);
                if (error)
                        mlog_errno(error);
        }
@@@ -4379,7 -4380,7 +4380,7 @@@ static int ocfs2_user_path_parent(cons
        if (IS_ERR(s))
                return PTR_ERR(s);
  
 -      error = path_lookup(s, LOOKUP_PARENT, nd);
 +      error = kern_path_parent(s, nd);
        if (error)
                putname(s);
        else
diff --combined fs/open.c
+++ b/fs/open.c
@@@ -573,15 -573,13 +573,15 @@@ SYSCALL_DEFINE5(fchownat, int, dfd, con
  {
        struct path path;
        int error = -EINVAL;
 -      int follow;
 +      int lookup_flags;
  
 -      if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
 +      if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
                goto out;
  
 -      follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
 -      error = user_path_at(dfd, filename, follow, &path);
 +      lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
 +      if (flag & AT_EMPTY_PATH)
 +              lookup_flags |= LOOKUP_EMPTY;
 +      error = user_path_at(dfd, filename, lookup_flags, &path);
        if (error)
                goto out;
        error = mnt_want_write(path.mnt);
@@@ -671,16 -669,11 +671,16 @@@ static struct file *__dentry_open(struc
                                        int (*open)(struct inode *, struct file *),
                                        const struct cred *cred)
  {
 +      static const struct file_operations empty_fops = {};
        struct inode *inode;
        int error;
  
        f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
                                FMODE_PREAD | FMODE_PWRITE;
 +
 +      if (unlikely(f->f_flags & O_PATH))
 +              f->f_mode = FMODE_PATH;
 +
        inode = dentry->d_inode;
        if (f->f_mode & FMODE_WRITE) {
                error = __get_file_write_access(inode, mnt);
        f->f_path.dentry = dentry;
        f->f_path.mnt = mnt;
        f->f_pos = 0;
 -      f->f_op = fops_get(inode->i_fop);
        file_sb_list_add(f, inode->i_sb);
  
 +      if (unlikely(f->f_mode & FMODE_PATH)) {
 +              f->f_op = &empty_fops;
 +              return f;
 +      }
 +
 +      f->f_op = fops_get(inode->i_fop);
 +
        error = security_dentry_open(f, cred);
        if (error)
                goto cleanup_all;
                if (error)
                        goto cleanup_all;
        }
-       ima_counts_get(f);
+       if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+               i_readcount_inc(inode);
  
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
  
@@@ -903,110 -891,15 +904,110 @@@ void fd_install(unsigned int fd, struc
  
  EXPORT_SYMBOL(fd_install);
  
 +static inline int build_open_flags(int flags, int mode, struct open_flags *op)
 +{
 +      int lookup_flags = 0;
 +      int acc_mode;
 +
 +      if (!(flags & O_CREAT))
 +              mode = 0;
 +      op->mode = mode;
 +
 +      /* Must never be set by userspace */
 +      flags &= ~FMODE_NONOTIFY;
 +
 +      /*
 +       * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
 +       * check for O_DSYNC if the need any syncing at all we enforce it's
 +       * always set instead of having to deal with possibly weird behaviour
 +       * for malicious applications setting only __O_SYNC.
 +       */
 +      if (flags & __O_SYNC)
 +              flags |= O_DSYNC;
 +
 +      /*
 +       * If we have O_PATH in the open flag. Then we
 +       * cannot have anything other than the below set of flags
 +       */
 +      if (flags & O_PATH) {
 +              flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
 +              acc_mode = 0;
 +      } else {
 +              acc_mode = MAY_OPEN | ACC_MODE(flags);
 +      }
 +
 +      op->open_flag = flags;
 +
 +      /* O_TRUNC implies we need access checks for write permissions */
 +      if (flags & O_TRUNC)
 +              acc_mode |= MAY_WRITE;
 +
 +      /* Allow the LSM permission hook to distinguish append
 +         access from general write access. */
 +      if (flags & O_APPEND)
 +              acc_mode |= MAY_APPEND;
 +
 +      op->acc_mode = acc_mode;
 +
 +      op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN;
 +
 +      if (flags & O_CREAT) {
 +              op->intent |= LOOKUP_CREATE;
 +              if (flags & O_EXCL)
 +                      op->intent |= LOOKUP_EXCL;
 +      }
 +
 +      if (flags & O_DIRECTORY)
 +              lookup_flags |= LOOKUP_DIRECTORY;
 +      if (!(flags & O_NOFOLLOW))
 +              lookup_flags |= LOOKUP_FOLLOW;
 +      return lookup_flags;
 +}
 +
 +/**
 + * filp_open - open file and return file pointer
 + *
 + * @filename: path to open
 + * @flags:    open flags as per the open(2) second argument
 + * @mode:     mode for the new file if O_CREAT is set, else ignored
 + *
 + * This is the helper to open a file from kernelspace if you really
 + * have to.  But in generally you should not do this, so please move
 + * along, nothing to see here..
 + */
 +struct file *filp_open(const char *filename, int flags, int mode)
 +{
 +      struct open_flags op;
 +      int lookup = build_open_flags(flags, mode, &op);
 +      return do_filp_open(AT_FDCWD, filename, &op, lookup);
 +}
 +EXPORT_SYMBOL(filp_open);
 +
 +struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 +                          const char *filename, int flags)
 +{
 +      struct open_flags op;
 +      int lookup = build_open_flags(flags, 0, &op);
 +      if (flags & O_CREAT)
 +              return ERR_PTR(-EINVAL);
 +      if (!filename && (flags & O_DIRECTORY))
 +              if (!dentry->d_inode->i_op->lookup)
 +                      return ERR_PTR(-ENOTDIR);
 +      return do_file_open_root(dentry, mnt, filename, &op, lookup);
 +}
 +EXPORT_SYMBOL(file_open_root);
 +
  long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
  {
 +      struct open_flags op;
 +      int lookup = build_open_flags(flags, mode, &op);
        char *tmp = getname(filename);
        int fd = PTR_ERR(tmp);
  
        if (!IS_ERR(tmp)) {
                fd = get_unused_fd_flags(flags);
                if (fd >= 0) {
 -                      struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
 +                      struct file *f = do_filp_open(dfd, tmp, &op, lookup);
                        if (IS_ERR(f)) {
                                put_unused_fd(fd);
                                fd = PTR_ERR(f);
@@@ -1076,10 -969,8 +1077,10 @@@ int filp_close(struct file *filp, fl_ow
        if (filp->f_op && filp->f_op->flush)
                retval = filp->f_op->flush(filp, id);
  
 -      dnotify_flush(filp, id);
 -      locks_remove_posix(filp, id);
 +      if (likely(!(filp->f_mode & FMODE_PATH))) {
 +              dnotify_flush(filp, id);
 +              locks_remove_posix(filp, id);
 +      }
        fput(filp);
        return retval;
  }
diff --combined fs/reiserfs/namei.c
@@@ -593,7 -593,7 +593,7 @@@ static int reiserfs_create(struct inod
        new_inode_init(inode, dir, mode);
  
        jbegin_count += reiserfs_cache_default_acl(dir);
-       retval = reiserfs_security_init(dir, inode, &security);
+       retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
@@@ -667,7 -667,7 +667,7 @@@ static int reiserfs_mknod(struct inode 
        new_inode_init(inode, dir, mode);
  
        jbegin_count += reiserfs_cache_default_acl(dir);
-       retval = reiserfs_security_init(dir, inode, &security);
+       retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
@@@ -747,7 -747,7 +747,7 @@@ static int reiserfs_mkdir(struct inode 
        new_inode_init(inode, dir, mode);
  
        jbegin_count += reiserfs_cache_default_acl(dir);
-       retval = reiserfs_security_init(dir, inode, &security);
+       retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
@@@ -1032,7 -1032,8 +1032,8 @@@ static int reiserfs_symlink(struct inod
        }
        new_inode_init(inode, parent_dir, mode);
  
-       retval = reiserfs_security_init(parent_dir, inode, &security);
+       retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name,
+                                       &security);
        if (retval < 0) {
                drop_new_inode(inode);
                return retval;
@@@ -1122,6 -1123,10 +1123,6 @@@ static int reiserfs_link(struct dentry 
                reiserfs_write_unlock(dir->i_sb);
                return -EMLINK;
        }
 -      if (inode->i_nlink == 0) {
 -              reiserfs_write_unlock(dir->i_sb);
 -              return -ENOENT;
 -      }
  
        /* inc before scheduling so reiserfs_unlink knows we are here */
        inc_nlink(inode);
diff --combined include/linux/fs.h
@@@ -102,9 -102,6 +102,9 @@@ struct inodes_stat_t 
  /* File is huge (eg. /dev/kmem): treat loff_t as unsigned */
  #define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000)
  
 +/* File is opened with O_PATH; almost nothing can be done with it */
 +#define FMODE_PATH            ((__force fmode_t)0x4000)
 +
  /* File was opened by fanotify and shouldn't generate fanotify events */
  #define FMODE_NONOTIFY                ((__force fmode_t)0x1000000)
  
@@@ -801,8 -798,7 +801,7 @@@ struct inode 
  #endif
  
  #ifdef CONFIG_IMA
-       /* protected by i_lock */
-       unsigned int            i_readcount; /* struct files open RO */
+       atomic_t                i_readcount; /* struct files open RO */
  #endif
        atomic_t                i_writecount;
  #ifdef CONFIG_SECURITY
@@@ -981,13 -977,6 +980,13 @@@ struct file 
  #endif
  };
  
 +struct file_handle {
 +      __u32 handle_bytes;
 +      int handle_type;
 +      /* file identifier */
 +      unsigned char f_handle[0];
 +};
 +
  #define get_file(x)   atomic_long_inc(&(x)->f_count)
  #define fput_atomic(x)        atomic_long_add_unless(&(x)->f_count, -1, 1)
  #define file_count(x) atomic_long_read(&(x)->f_count)
@@@ -1411,7 -1400,6 +1410,7 @@@ struct super_block 
        wait_queue_head_t       s_wait_unfrozen;
  
        char s_id[32];                          /* Informational name */
 +      u8 s_uuid[16];                          /* UUID */
  
        void                    *s_fs_info;     /* Filesystem private info */
        fmode_t                 s_mode;
@@@ -1885,8 -1873,6 +1884,8 @@@ extern void drop_collected_mounts(struc
  extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
                          struct vfsmount *);
  extern int vfs_statfs(struct path *, struct kstatfs *);
 +extern int user_statfs(const char __user *, struct kstatfs *);
 +extern int fd_statfs(int, struct kstatfs *);
  extern int statfs_by_dentry(struct dentry *, struct kstatfs *);
  extern int freeze_super(struct super_block *super);
  extern int thaw_super(struct super_block *super);
@@@ -2003,8 -1989,6 +2002,8 @@@ extern int do_fallocate(struct file *fi
  extern long do_sys_open(int dfd, const char __user *filename, int flags,
                        int mode);
  extern struct file *filp_open(const char *, int, int);
 +extern struct file *file_open_root(struct dentry *, struct vfsmount *,
 +                                 const char *, int);
  extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
                                 const struct cred *);
  extern int filp_close(struct file *, fl_owner_t id);
@@@ -2215,11 -2199,35 +2214,31 @@@ static inline void allow_write_access(s
        if (file)
                atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
  }
+ #ifdef CONFIG_IMA
+ static inline void i_readcount_dec(struct inode *inode)
+ {
+       BUG_ON(!atomic_read(&inode->i_readcount));
+       atomic_dec(&inode->i_readcount);
+ }
+ static inline void i_readcount_inc(struct inode *inode)
+ {
+       atomic_inc(&inode->i_readcount);
+ }
+ #else
+ static inline void i_readcount_dec(struct inode *inode)
+ {
+       return;
+ }
+ static inline void i_readcount_inc(struct inode *inode)
+ {
+       return;
+ }
+ #endif
  extern int do_pipe_flags(int *, int);
  extern struct file *create_read_pipe(struct file *f, int flags);
  extern struct file *create_write_pipe(int flags);
  extern void free_write_pipe(struct file *);
  
 -extern struct file *do_filp_open(int dfd, const char *pathname,
 -              int open_flag, int mode, int acc_mode);
 -extern int may_open(struct path *, int, int);
 -
  extern int kernel_read(struct file *, loff_t, char *, unsigned long);
  extern struct file * open_exec(const char *);
   
diff --combined include/linux/security.h
@@@ -25,6 -25,7 +25,7 @@@
  #include <linux/fs.h>
  #include <linux/fsnotify.h>
  #include <linux/binfmts.h>
+ #include <linux/dcache.h>
  #include <linux/signal.h>
  #include <linux/resource.h>
  #include <linux/sem.h>
@@@ -53,7 -54,7 +54,7 @@@ struct audit_krule
   */
  extern int cap_capable(struct task_struct *tsk, const struct cred *cred,
                       int cap, int audit);
 -extern int cap_settime(struct timespec *ts, struct timezone *tz);
 +extern int cap_settime(const struct timespec *ts, const struct timezone *tz);
  extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
  extern int cap_ptrace_traceme(struct task_struct *parent);
  extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@@ -267,6 -268,12 +268,12 @@@ static inline void security_free_mnt_op
   *    @orig the original mount data copied from userspace.
   *    @copy copied data which will be passed to the security module.
   *    Returns 0 if the copy was successful.
+  * @sb_remount:
+  *    Extracts security system specifc mount options and verifys no changes
+  *    are being made to those options.
+  *    @sb superblock being remounted
+  *    @data contains the filesystem-specific data.
+  *    Return 0 if permission is granted.
   * @sb_umount:
   *    Check permission before the @mnt file system is unmounted.
   *    @mnt contains the mounted file system.
   *    then it should return -EOPNOTSUPP to skip this processing.
   *    @inode contains the inode structure of the newly created inode.
   *    @dir contains the inode structure of the parent directory.
+  *    @qstr contains the last path component of the new object
   *    @name will be set to the allocated name suffix (e.g. selinux).
   *    @value will be set to the allocated attribute value.
   *    @len will be set to the length of the value.
   *    @cap contains the capability <include/linux/capability.h>.
   *    @audit: Whether to write an audit message or not
   *    Return 0 if the capability is granted for @tsk.
-  * @sysctl:
-  *    Check permission before accessing the @table sysctl variable in the
-  *    manner specified by @op.
-  *    @table contains the ctl_table structure for the sysctl variable.
-  *    @op contains the operation (001 = search, 002 = write, 004 = read).
-  *    Return 0 if permission is granted.
   * @syslog:
   *    Check permission before accessing the kernel message ring or changing
   *    logging to the console.
@@@ -1383,11 -1385,10 +1385,10 @@@ struct security_operations 
                       const kernel_cap_t *permitted);
        int (*capable) (struct task_struct *tsk, const struct cred *cred,
                        int cap, int audit);
-       int (*sysctl) (struct ctl_table *table, int op);
        int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
        int (*quota_on) (struct dentry *dentry);
        int (*syslog) (int type);
 -      int (*settime) (struct timespec *ts, struct timezone *tz);
 +      int (*settime) (const struct timespec *ts, const struct timezone *tz);
        int (*vm_enough_memory) (struct mm_struct *mm, long pages);
  
        int (*bprm_set_creds) (struct linux_binprm *bprm);
        int (*sb_alloc_security) (struct super_block *sb);
        void (*sb_free_security) (struct super_block *sb);
        int (*sb_copy_data) (char *orig, char *copy);
+       int (*sb_remount) (struct super_block *sb, void *data);
        int (*sb_kern_mount) (struct super_block *sb, int flags, void *data);
        int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
        int (*sb_statfs) (struct dentry *dentry);
        int (*inode_alloc_security) (struct inode *inode);
        void (*inode_free_security) (struct inode *inode);
        int (*inode_init_security) (struct inode *inode, struct inode *dir,
-                                   char **name, void **value, size_t *len);
+                                   const struct qstr *qstr, char **name,
+                                   void **value, size_t *len);
        int (*inode_create) (struct inode *dir,
                             struct dentry *dentry, int mode);
        int (*inode_link) (struct dentry *old_dentry,
@@@ -1665,11 -1668,10 +1668,10 @@@ int security_capset(struct cred *new, c
  int security_capable(const struct cred *cred, int cap);
  int security_real_capable(struct task_struct *tsk, int cap);
  int security_real_capable_noaudit(struct task_struct *tsk, int cap);
- int security_sysctl(struct ctl_table *table, int op);
  int security_quotactl(int cmds, int type, int id, struct super_block *sb);
  int security_quota_on(struct dentry *dentry);
  int security_syslog(int type);
 -int security_settime(struct timespec *ts, struct timezone *tz);
 +int security_settime(const struct timespec *ts, const struct timezone *tz);
  int security_vm_enough_memory(long pages);
  int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
  int security_vm_enough_memory_kern(long pages);
@@@ -1681,6 -1683,7 +1683,7 @@@ int security_bprm_secureexec(struct lin
  int security_sb_alloc(struct super_block *sb);
  void security_sb_free(struct super_block *sb);
  int security_sb_copy_data(char *orig, char *copy);
+ int security_sb_remount(struct super_block *sb, void *data);
  int security_sb_kern_mount(struct super_block *sb, int flags, void *data);
  int security_sb_show_options(struct seq_file *m, struct super_block *sb);
  int security_sb_statfs(struct dentry *dentry);
@@@ -1696,7 -1699,8 +1699,8 @@@ int security_sb_parse_opts_str(char *op
  int security_inode_alloc(struct inode *inode);
  void security_inode_free(struct inode *inode);
  int security_inode_init_security(struct inode *inode, struct inode *dir,
-                                 char **name, void **value, size_t *len);
+                                const struct qstr *qstr, char **name,
+                                void **value, size_t *len);
  int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
  int security_inode_link(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *new_dentry);
@@@ -1883,11 -1887,6 +1887,6 @@@ int security_real_capable_noaudit(struc
        return ret;
  }
  
- static inline int security_sysctl(struct ctl_table *table, int op)
- {
-       return 0;
- }
  static inline int security_quotactl(int cmds, int type, int id,
                                     struct super_block *sb)
  {
@@@ -1904,8 -1903,7 +1903,8 @@@ static inline int security_syslog(int t
        return 0;
  }
  
 -static inline int security_settime(struct timespec *ts, struct timezone *tz)
 +static inline int security_settime(const struct timespec *ts,
 +                                 const struct timezone *tz)
  {
        return cap_settime(ts, tz);
  }
@@@ -1965,6 -1963,11 +1964,11 @@@ static inline int security_sb_copy_data
        return 0;
  }
  
+ static inline int security_sb_remount(struct super_block *sb, void *data)
+ {
+       return 0;
+ }
  static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
  {
        return 0;
@@@ -2024,6 -2027,7 +2028,7 @@@ static inline void security_inode_free(
  
  static inline int security_inode_init_security(struct inode *inode,
                                                struct inode *dir,
+                                               const struct qstr *qstr,
                                                char **name,
                                                void **value,
                                                size_t *len)
diff --combined kernel/sysctl.c
@@@ -361,13 -361,20 +361,13 @@@ static struct ctl_table kern_table[] = 
                .mode           = 0644,
                .proc_handler   = sched_rt_handler,
        },
 -      {
 -              .procname       = "sched_compat_yield",
 -              .data           = &sysctl_sched_compat_yield,
 -              .maxlen         = sizeof(unsigned int),
 -              .mode           = 0644,
 -              .proc_handler   = proc_dointvec,
 -      },
  #ifdef CONFIG_SCHED_AUTOGROUP
        {
                .procname       = "sched_autogroup_enabled",
                .data           = &sysctl_sched_autogroup_enabled,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
 -              .proc_handler   = proc_dointvec,
 +              .proc_handler   = proc_dointvec_minmax,
                .extra1         = &zero,
                .extra2         = &one,
        },
                .data           = &sysctl_perf_event_sample_rate,
                .maxlen         = sizeof(sysctl_perf_event_sample_rate),
                .mode           = 0644,
 -              .proc_handler   = proc_dointvec,
 +              .proc_handler   = perf_proc_update_handler,
        },
  #endif
  #ifdef CONFIG_KMEMCHECK
@@@ -1683,13 -1690,8 +1683,8 @@@ static int test_perm(int mode, int op
  
  int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
  {
-       int error;
        int mode;
  
-       error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
-       if (error)
-               return error;
        if (root->permissions)
                mode = root->permissions(root, current->nsproxy, table);
        else
diff --combined mm/shmem.c
@@@ -1843,8 -1843,9 +1843,9 @@@ shmem_mknod(struct inode *dir, struct d
  
        inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
        if (inode) {
-               error = security_inode_init_security(inode, dir, NULL, NULL,
-                                                    NULL);
+               error = security_inode_init_security(inode, dir,
+                                                    &dentry->d_name, NULL,
+                                                    NULL, NULL);
                if (error) {
                        if (error != -EOPNOTSUPP) {
                                iput(inode);
@@@ -1983,8 -1984,8 +1984,8 @@@ static int shmem_symlink(struct inode *
        if (!inode)
                return -ENOSPC;
  
-       error = security_inode_init_security(inode, dir, NULL, NULL,
-                                            NULL);
+       error = security_inode_init_security(inode, dir, &dentry->d_name, NULL,
+                                            NULL, NULL);
        if (error) {
                if (error != -EOPNOTSUPP) {
                        iput(inode);
@@@ -2144,10 -2145,8 +2145,10 @@@ static int shmem_encode_fh(struct dentr
  {
        struct inode *inode = dentry->d_inode;
  
 -      if (*len < 3)
 +      if (*len < 3) {
 +              *len = 3;
                return 255;
 +      }
  
        if (inode_unhashed(inode)) {
                /* Unfortunately insert_inode_hash is not idempotent,
diff --combined security/security.c
@@@ -181,11 -181,6 +181,6 @@@ int security_real_capable_noaudit(struc
        return ret;
  }
  
- int security_sysctl(struct ctl_table *table, int op)
- {
-       return security_ops->sysctl(table, op);
- }
  int security_quotactl(int cmds, int type, int id, struct super_block *sb)
  {
        return security_ops->quotactl(cmds, type, id, sb);
@@@ -201,7 -196,7 +196,7 @@@ int security_syslog(int type
        return security_ops->syslog(type);
  }
  
 -int security_settime(struct timespec *ts, struct timezone *tz)
 +int security_settime(const struct timespec *ts, const struct timezone *tz)
  {
        return security_ops->settime(ts, tz);
  }
@@@ -271,6 -266,11 +266,11 @@@ int security_sb_copy_data(char *orig, c
  }
  EXPORT_SYMBOL(security_sb_copy_data);
  
+ int security_sb_remount(struct super_block *sb, void *data)
+ {
+       return security_ops->sb_remount(sb, data);
+ }
  int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
  {
        return security_ops->sb_kern_mount(sb, flags, data);
@@@ -335,11 -335,13 +335,13 @@@ void security_inode_free(struct inode *
  }
  
  int security_inode_init_security(struct inode *inode, struct inode *dir,
-                                 char **name, void **value, size_t *len)
+                                const struct qstr *qstr, char **name,
+                                void **value, size_t *len)
  {
        if (unlikely(IS_PRIVATE(inode)))
                return -EOPNOTSUPP;
-       return security_ops->inode_init_security(inode, dir, name, value, len);
+       return security_ops->inode_init_security(inode, dir, qstr, name, value,
+                                                len);
  }
  EXPORT_SYMBOL(security_inode_init_security);
  
@@@ -359,6 -361,7 +361,7 @@@ int security_path_mkdir(struct path *di
                return 0;
        return security_ops->path_mkdir(dir, dentry, mode);
  }
+ EXPORT_SYMBOL(security_path_mkdir);
  
  int security_path_rmdir(struct path *dir, struct dentry *dentry)
  {
@@@ -373,6 -376,7 +376,7 @@@ int security_path_unlink(struct path *d
                return 0;
        return security_ops->path_unlink(dir, dentry);
  }
+ EXPORT_SYMBOL(security_path_unlink);
  
  int security_path_symlink(struct path *dir, struct dentry *dentry,
                          const char *old_name)
@@@ -399,6 -403,7 +403,7 @@@ int security_path_rename(struct path *o
        return security_ops->path_rename(old_dir, old_dentry, new_dir,
                                         new_dentry);
  }
+ EXPORT_SYMBOL(security_path_rename);
  
  int security_path_truncate(struct path *path)
  {