Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Sep 2009 15:55:49 +0000 (08:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Sep 2009 15:55:49 +0000 (08:55 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (57 commits)
  binfmt_elf: fix PT_INTERP bss handling
  TPM: Fixup boot probe timeout for tpm_tis driver
  sysfs: Add labeling support for sysfs
  LSM/SELinux: inode_{get,set,notify}secctx hooks to access LSM security context information.
  VFS: Factor out part of vfs_setxattr so it can be called from the SELinux hook for inode_setsecctx.
  KEYS: Add missing linux/tracehook.h #inclusions
  KEYS: Fix default security_session_to_parent()
  Security/SELinux: includecheck fix kernel/sysctl.c
  KEYS: security_cred_alloc_blank() should return int under all circumstances
  IMA: open new file for read
  KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]
  KEYS: Extend TIF_NOTIFY_RESUME to (almost) all architectures [try #6]
  KEYS: Do some whitespace cleanups [try #6]
  KEYS: Make /proc/keys use keyid not numread as file position [try #6]
  KEYS: Add garbage collection for dead, revoked and expired keys. [try #6]
  KEYS: Flag dead keys to induce EKEYREVOKED [try #6]
  KEYS: Allow keyctl_revoke() on keys that have SETATTR but not WRITE perm [try #6]
  KEYS: Deal with dead-type keys appropriately [try #6]
  CRED: Add some configurable debugging [try #6]
  selinux: Support for the new TUN LSM hooks
  ...

1  2 
fs/namei.c

diff --combined fs/namei.c
@@@ -169,10 -169,19 +169,10 @@@ void putname(const char *name
  EXPORT_SYMBOL(putname);
  #endif
  
 -
 -/**
 - * generic_permission  -  check for access rights on a Posix-like filesystem
 - * @inode:    inode to check access rights for
 - * @mask:     right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
 - * @check_acl:        optional callback to check for Posix ACLs
 - *
 - * Used to check for read/write/execute permissions on a file.
 - * We use "fsuid" for this, letting us set arbitrary permissions
 - * for filesystem access without changing the "normal" uids which
 - * are used for other things..
 +/*
 + * This does basic POSIX ACL permission checking
   */
 -int generic_permission(struct inode *inode, int mask,
 +static int acl_permission_check(struct inode *inode, int mask,
                int (*check_acl)(struct inode *inode, int mask))
  {
        umode_t                 mode = inode->i_mode;
        else {
                if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
                        int error = check_acl(inode, mask);
 -                      if (error == -EACCES)
 -                              goto check_capabilities;
 -                      else if (error != -EAGAIN)
 +                      if (error != -EAGAIN)
                                return error;
                }
  
         */
        if ((mask & ~mode) == 0)
                return 0;
 +      return -EACCES;
 +}
 +
 +/**
 + * generic_permission  -  check for access rights on a Posix-like filesystem
 + * @inode:    inode to check access rights for
 + * @mask:     right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
 + * @check_acl:        optional callback to check for Posix ACLs
 + *
 + * Used to check for read/write/execute permissions on a file.
 + * We use "fsuid" for this, letting us set arbitrary permissions
 + * for filesystem access without changing the "normal" uids which
 + * are used for other things..
 + */
 +int generic_permission(struct inode *inode, int mask,
 +              int (*check_acl)(struct inode *inode, int mask))
 +{
 +      int ret;
 +
 +      /*
 +       * Do the basic POSIX ACL permission checks.
 +       */
 +      ret = acl_permission_check(inode, mask, check_acl);
 +      if (ret != -EACCES)
 +              return ret;
  
 - check_capabilities:
        /*
         * Read/write DACs are always overridable.
         * Executable DACs are overridable if at least one exec bit is set.
@@@ -275,7 -262,7 +275,7 @@@ int inode_permission(struct inode *inod
        if (inode->i_op->permission)
                retval = inode->i_op->permission(inode, mask);
        else
 -              retval = generic_permission(inode, mask, NULL);
 +              retval = generic_permission(inode, mask, inode->i_op->check_acl);
  
        if (retval)
                return retval;
@@@ -445,22 -432,29 +445,22 @@@ static struct dentry * cached_lookup(st
   */
  static int exec_permission_lite(struct inode *inode)
  {
 -      umode_t mode = inode->i_mode;
 +      int ret;
  
 -      if (inode->i_op->permission)
 -              return -EAGAIN;
 -
 -      if (current_fsuid() == inode->i_uid)
 -              mode >>= 6;
 -      else if (in_group_p(inode->i_gid))
 -              mode >>= 3;
 -
 -      if (mode & MAY_EXEC)
 -              goto ok;
 -
 -      if ((inode->i_mode & S_IXUGO) && capable(CAP_DAC_OVERRIDE))
 -              goto ok;
 -
 -      if (S_ISDIR(inode->i_mode) && capable(CAP_DAC_OVERRIDE))
 +      if (inode->i_op->permission) {
 +              ret = inode->i_op->permission(inode, MAY_EXEC);
 +              if (!ret)
 +                      goto ok;
 +              return ret;
 +      }
 +      ret = acl_permission_check(inode, MAY_EXEC, inode->i_op->check_acl);
 +      if (!ret)
                goto ok;
  
 -      if (S_ISDIR(inode->i_mode) && capable(CAP_DAC_READ_SEARCH))
 +      if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH))
                goto ok;
  
 -      return -EACCES;
 +      return ret;
  ok:
        return security_inode_permission(inode, MAY_EXEC);
  }
@@@ -859,6 -853,12 +859,6 @@@ static int __link_path_walk(const char 
  
                nd->flags |= LOOKUP_CONTINUE;
                err = exec_permission_lite(inode);
 -              if (err == -EAGAIN)
 -                      err = inode_permission(nd->path.dentry->d_inode,
 -                                             MAY_EXEC);
 -              if (!err)
 -                      err = ima_path_check(&nd->path, MAY_EXEC,
 -                                           IMA_COUNT_UPDATE);
                if (err)
                        break;
  
@@@ -1533,9 -1533,11 +1533,11 @@@ int may_open(struct path *path, int acc
        if (error)
                return error;
  
-       error = ima_path_check(path,
-                              acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC),
+       error = ima_path_check(path, acc_mode ?
+                              acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
+                              ACC_MODE(flag) & (MAY_READ | MAY_WRITE),
                               IMA_COUNT_UPDATE);
        if (error)
                return error;
        /*