Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 4 Oct 2016 21:48:27 +0000 (14:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 4 Oct 2016 21:48:27 +0000 (14:48 -0700)
Pull security subsystem updates from James Morris:

  SELinux/LSM:
   - overlayfs support, necessary for container filesystems

  LSM:
   - finally remove the kernel_module_from_file hook

  Smack:
   - treat signal delivery as an 'append' operation

  TPM:
   - lots of bugfixes & updates

  Audit:
   - new audit data type: LSM_AUDIT_DATA_FILE

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (47 commits)
  Revert "tpm/tpm_crb: implement tpm crb idle state"
  Revert "tmp/tpm_crb: fix Intel PTT hw bug during idle state"
  Revert "tpm/tpm_crb: open code the crb_init into acpi_add"
  Revert "tmp/tpm_crb: implement runtime pm for tpm_crb"
  lsm,audit,selinux: Introduce a new audit data type LSM_AUDIT_DATA_FILE
  tmp/tpm_crb: implement runtime pm for tpm_crb
  tpm/tpm_crb: open code the crb_init into acpi_add
  tmp/tpm_crb: fix Intel PTT hw bug during idle state
  tpm/tpm_crb: implement tpm crb idle state
  tpm: add check for minimum buffer size in tpm_transmit()
  tpm: constify TPM 1.x header structures
  tpm/tpm_crb: fix the over 80 characters checkpatch warring
  tpm/tpm_crb: drop useless cpu_to_le32 when writing to registers
  tpm/tpm_crb: cache cmd_size register value.
  tmp/tpm_crb: drop include to platform_device
  tpm/tpm_tis: remove unused itpm variable
  tpm_crb: fix incorrect values of cmdReady and goIdle bits
  tpm_crb: refine the naming of constants
  tpm_crb: remove wmb()'s
  tpm_crb: fix crb_req_canceled behavior
  ...

1  2 
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
security/lsm_audit.c

diff --combined fs/overlayfs/copy_up.c
@@@ -80,8 -80,6 +80,8 @@@ int ovl_copy_xattr(struct dentry *old, 
        }
  
        for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
 +              if (ovl_is_private_xattr(name))
 +                      continue;
  retry:
                size = vfs_getxattr(old, name, value, value_size);
                if (size == -ERANGE)
                        goto retry;
                }
  
+               error = security_inode_copy_up_xattr(name);
+               if (error < 0 && error != -EOPNOTSUPP)
+                       break;
+               if (error == 1) {
+                       error = 0;
+                       continue; /* Discard */
+               }
                error = vfs_setxattr(new, name, value, size, 0);
                if (error)
                        break;
@@@ -248,6 -253,8 +255,8 @@@ static int ovl_copy_up_locked(struct de
        struct dentry *upper = NULL;
        umode_t mode = stat->mode;
        int err;
+       const struct cred *old_creds = NULL;
+       struct cred *new_creds = NULL;
  
        newdentry = ovl_lookup_temp(workdir, dentry);
        err = PTR_ERR(newdentry);
        if (IS_ERR(upper))
                goto out1;
  
+       err = security_inode_copy_up(dentry, &new_creds);
+       if (err < 0)
+               goto out2;
+       if (new_creds)
+               old_creds = override_creds(new_creds);
        /* Can't properly set mode on creation because of the umask */
        stat->mode &= S_IFMT;
        err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
        stat->mode = mode;
+       if (new_creds) {
+               revert_creds(old_creds);
+               put_cred(new_creds);
+       }
        if (err)
                goto out2;
  
diff --combined fs/overlayfs/dir.c
@@@ -12,8 -12,6 +12,8 @@@
  #include <linux/xattr.h>
  #include <linux/security.h>
  #include <linux/cred.h>
 +#include <linux/posix_acl.h>
 +#include <linux/posix_acl_xattr.h>
  #include "overlayfs.h"
  
  void ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
@@@ -188,9 -186,6 +188,9 @@@ static int ovl_create_upper(struct dent
        struct dentry *newdentry;
        int err;
  
 +      if (!hardlink && !IS_POSIXACL(udir))
 +              stat->mode &= ~current_umask();
 +
        inode_lock_nested(udir, I_MUTEX_PARENT);
        newdentry = lookup_one_len(dentry->d_name.name, upperdir,
                                   dentry->d_name.len);
@@@ -340,32 -335,6 +340,32 @@@ out_free
        return ret;
  }
  
 +static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name,
 +                           const struct posix_acl *acl)
 +{
 +      void *buffer;
 +      size_t size;
 +      int err;
 +
 +      if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !acl)
 +              return 0;
 +
 +      size = posix_acl_to_xattr(NULL, acl, NULL, 0);
 +      buffer = kmalloc(size, GFP_KERNEL);
 +      if (!buffer)
 +              return -ENOMEM;
 +
 +      size = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
 +      err = size;
 +      if (err < 0)
 +              goto out_free;
 +
 +      err = vfs_setxattr(upperdentry, name, buffer, size, XATTR_CREATE);
 +out_free:
 +      kfree(buffer);
 +      return err;
 +}
 +
  static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
                                    struct kstat *stat, const char *link,
                                    struct dentry *hardlink)
        struct dentry *upper;
        struct dentry *newdentry;
        int err;
 +      struct posix_acl *acl, *default_acl;
  
        if (WARN_ON(!workdir))
                return -EROFS;
  
 +      if (!hardlink) {
 +              err = posix_acl_create(dentry->d_parent->d_inode,
 +                                     &stat->mode, &default_acl, &acl);
 +              if (err)
 +                      return err;
 +      }
 +
        err = ovl_lock_rename_workdir(workdir, upperdir);
        if (err)
                goto out;
                if (err)
                        goto out_cleanup;
        }
 +      if (!hardlink) {
 +              err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_ACCESS,
 +                                      acl);
 +              if (err)
 +                      goto out_cleanup;
 +
 +              err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_DEFAULT,
 +                                      default_acl);
 +              if (err)
 +                      goto out_cleanup;
 +      }
  
        if (!hardlink && S_ISDIR(stat->mode)) {
                err = ovl_set_opaque(newdentry);
@@@ -460,10 -410,6 +460,10 @@@ out_dput
  out_unlock:
        unlock_rename(workdir, upperdir);
  out:
 +      if (!hardlink) {
 +              posix_acl_release(acl);
 +              posix_acl_release(default_acl);
 +      }
        return err;
  
  out_cleanup:
@@@ -489,6 -435,15 +489,15 @@@ static int ovl_create_or_link(struct de
        if (override_cred) {
                override_cred->fsuid = inode->i_uid;
                override_cred->fsgid = inode->i_gid;
+               if (!hardlink) {
+                       err = security_dentry_create_files_as(dentry,
+                                       stat->mode, &dentry->d_name, old_cred,
+                                       override_cred);
+                       if (err) {
+                               put_cred(override_cred);
+                               goto out_revert_creds;
+                       }
+               }
                put_cred(override_creds(override_cred));
                put_cred(override_cred);
  
                        err = ovl_create_over_whiteout(dentry, inode, stat,
                                                        link, hardlink);
        }
+ out_revert_creds:
        revert_creds(old_cred);
        if (!err) {
                struct inode *realinode = d_inode(ovl_dentry_upper(dentry));
@@@ -1004,9 -960,9 +1014,9 @@@ const struct inode_operations ovl_dir_i
        .permission     = ovl_permission,
        .getattr        = ovl_dir_getattr,
        .setxattr       = generic_setxattr,
 -      .getxattr       = ovl_getxattr,
 +      .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
 -      .removexattr    = ovl_removexattr,
 +      .removexattr    = generic_removexattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
  };
diff --combined security/lsm_audit.c
@@@ -99,7 -99,7 +99,7 @@@ int ipv4_skb_to_auditdata(struct sk_buf
        }
        return ret;
  }
- #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ #if IS_ENABLED(CONFIG_IPV6)
  /**
   * ipv6_skb_to_auditdata : fill auditdata from skb
   * @skb : the skb
@@@ -220,7 -220,7 +220,7 @@@ static void dump_common_audit_data(stru
         */
        BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
  
 -      audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
 +      audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
        audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm)));
  
        switch (a->type) {
                }
                break;
        }
+       case LSM_AUDIT_DATA_FILE: {
+               struct inode *inode;
+               audit_log_d_path(ab, " path=", &a->u.file->f_path);
+               inode = file_inode(a->u.file);
+               if (inode) {
+                       audit_log_format(ab, " dev=");
+                       audit_log_untrustedstring(ab, inode->i_sb->s_id);
+                       audit_log_format(ab, " ino=%lu", inode->i_ino);
+               }
+               break;
+       }
        case LSM_AUDIT_DATA_IOCTL_OP: {
                struct inode *inode;
  
                        audit_log_format(ab, " ino=%lu", inode->i_ino);
                }
  
-               audit_log_format(ab, " ioctlcmd=%hx", a->u.op->cmd);
+               audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd);
                break;
        }
        case LSM_AUDIT_DATA_DENTRY: {
        case LSM_AUDIT_DATA_TASK: {
                struct task_struct *tsk = a->u.tsk;
                if (tsk) {
 -                      pid_t pid = task_pid_nr(tsk);
 +                      pid_t pid = task_tgid_nr(tsk);
                        if (pid) {
                                char comm[sizeof(tsk->comm)];
                                audit_log_format(ab, " opid=%d ocomm=", pid);