Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Oct 2012 04:38:48 +0000 (21:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Oct 2012 04:38:48 +0000 (21:38 -0700)
Pull security subsystem updates from James Morris:
 "Highlights:

   - Integrity: add local fs integrity verification to detect offline
     attacks
   - Integrity: add digital signature verification
   - Simple stacking of Yama with other LSMs (per LSS discussions)
   - IBM vTPM support on ppc64
   - Add new driver for Infineon I2C TIS TPM
   - Smack: add rule revocation for subject labels"

Fixed conflicts with the user namespace support in kernel/auditsc.c and
security/integrity/ima/ima_policy.c.

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (39 commits)
  Documentation: Update git repository URL for Smack userland tools
  ima: change flags container data type
  Smack: setprocattr memory leak fix
  Smack: implement revoking all rules for a subject label
  Smack: remove task_wait() hook.
  ima: audit log hashes
  ima: generic IMA action flag handling
  ima: rename ima_must_appraise_or_measure
  audit: export audit_log_task_info
  tpm: fix tpm_acpi sparse warning on different address spaces
  samples/seccomp: fix 31 bit build on s390
  ima: digital signature verification support
  ima: add support for different security.ima data types
  ima: add ima_inode_setxattr/removexattr function and calls
  ima: add inode_post_setattr call
  ima: replace iint spinblock with rwlock/read_lock
  ima: allocating iint improvements
  ima: add appraise action keywords and default rules
  ima: integrity appraisal extension
  vfs: move ima_file_free before releasing the file
  ...

1  2 
Documentation/kernel-parameters.txt
drivers/char/tpm/tpm.c
fs/file_table.c
fs/xattr.c
include/linux/audit.h
include/linux/security.h
include/linux/xattr.h
kernel/auditsc.c
security/integrity/ima/ima_policy.c
security/security.c

index aab409f335bfba9b5f65fe0551a276237452bf2d,949dddcfd17784724c6c6ce59afd8cd697e998de..f777fa96243db4130771cb2dbd85e1a952ef683f
@@@ -1051,6 -1051,14 +1051,14 @@@ bytes respectively. Such letter suffixe
        ihash_entries=  [KNL]
                        Set number of hash buckets for inode cache.
  
+       ima_appraise=   [IMA] appraise integrity measurements
+                       Format: { "off" | "enforce" | "fix" }
+                       default: "enforce"
+       ima_appraise_tcb [IMA]
+                       The builtin appraise policy appraises all files
+                       owned by uid=0.
        ima_audit=      [IMA]
                        Format: { "0" | "1" }
                        0 -- integrity auditing messages. (Default)
                        * nohrst, nosrst, norst: suppress hard, soft
                            and both resets.
  
 +                      * rstonce: only attempt one reset during
 +                        hot-unplug link recovery
 +
                        * dump_id: dump IDENTIFY data.
  
                        If there are multiple matching configurations changing
                        noexec=on: enable non-executable mappings (default)
                        noexec=off: disable non-executable mappings
  
 +      nosmap          [X86]
 +                      Disable SMAP (Supervisor Mode Access Prevention)
 +                      even if it is supported by processor.
 +
        nosmep          [X86]
 -                      Disable SMEP (Supervisor Mode Execution Protection)
 +                      Disable SMEP (Supervisor Mode Execution Prevention)
                        even if it is supported by processor.
  
        noexec32        [X86-64]
                        and restore using xsave. The kernel will fallback to
                        enabling legacy floating-point and sse state.
  
 +      eagerfpu=       [X86]
 +                      on      enable eager fpu restore
 +                      off     disable eager fpu restore
 +                      auto    selects the default scheme, which automatically
 +                              enables eagerfpu restore for xsaveopt.
 +
        nohlt           [BUGS=ARM,SH] Tells the kernel that the sleep(SH) or
                        wfi(ARM) instruction doesn't work correctly and not to
                        use it. This is also useful when using JTAG debugger.
        rcutree.rcu_cpu_stall_timeout= [KNL,BOOT]
                        Set timeout for RCU CPU stall warning messages.
  
 +      rcutree.jiffies_till_first_fqs= [KNL,BOOT]
 +                      Set delay from grace-period initialization to
 +                      first attempt to force quiescent states.
 +                      Units are jiffies, minimum value is zero,
 +                      and maximum value is HZ.
 +
 +      rcutree.jiffies_till_next_fqs= [KNL,BOOT]
 +                      Set delay between subsequent attempts to force
 +                      quiescent states.  Units are jiffies, minimum
 +                      value is one, and maximum value is HZ.
 +
        rcutorture.fqs_duration= [KNL,BOOT]
                        Set duration of force_quiescent_state bursts.
  
        smart2=         [HW]
                        Format: <io1>[,<io2>[,...,<io8>]]
  
 -      smp-alt-once    [X86-32,SMP] On a hotplug CPU system, only
 -                      attempt to substitute SMP alternatives once at boot.
 -
        smsc-ircc2.nopnp        [HW] Don't use PNP to discover SMC devices
        smsc-ircc2.ircc_cfg=    [HW] Device configuration I/O port
        smsc-ircc2.ircc_sir=    [HW] SIR base I/O port
diff --combined drivers/char/tpm/tpm.c
index 3af9f4d1a23f200a27d8c03de477131967d0cbfd,6724615a4fdd1827028a24fff16b91a5f29d16d7..f26afdb1a7026aed8a0173ff7a17ea87524661dd
  #include <linux/freezer.h>
  
  #include "tpm.h"
- enum tpm_const {
-       TPM_MINOR = 224,        /* officially assigned */
-       TPM_BUFSIZE = 4096,
-       TPM_NUM_DEVICES = 256,
- };
+ #include "tpm_eventlog.h"
  
  enum tpm_duration {
        TPM_SHORT = 0,
@@@ -482,6 -477,7 +477,7 @@@ static ssize_t transmit_cmd(struct tpm_
  #define TPM_INTERNAL_RESULT_SIZE 200
  #define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
  #define TPM_ORD_GET_CAP cpu_to_be32(101)
+ #define TPM_ORD_GET_RANDOM cpu_to_be32(70)
  
  static const struct tpm_input_header tpm_getcap_header = {
        .tag = TPM_TAG_RQU_COMMAND,
@@@ -919,7 -915,7 +915,7 @@@ EXPORT_SYMBOL_GPL(tpm_show_pcrs)
  
  #define  READ_PUBEK_RESULT_SIZE 314
  #define TPM_ORD_READPUBEK cpu_to_be32(124)
- struct tpm_input_header tpm_readpubek_header = {
+ static struct tpm_input_header tpm_readpubek_header = {
        .tag = TPM_TAG_RQU_COMMAND,
        .length = cpu_to_be32(30),
        .ordinal = TPM_ORD_READPUBEK
@@@ -1172,10 -1168,10 +1168,10 @@@ int tpm_release(struct inode *inode, st
        struct tpm_chip *chip = file->private_data;
  
        del_singleshot_timer_sync(&chip->user_read_timer);
 -      flush_work_sync(&chip->work);
 +      flush_work(&chip->work);
        file->private_data = NULL;
        atomic_set(&chip->data_pending, 0);
-       kfree(chip->data_buffer);
+       kzfree(chip->data_buffer);
        clear_bit(0, &chip->is_open);
        put_device(chip->dev);
        return 0;
@@@ -1225,9 -1221,8 +1221,8 @@@ ssize_t tpm_read(struct file *file, cha
        int rc;
  
        del_singleshot_timer_sync(&chip->user_read_timer);
 -      flush_work_sync(&chip->work);
 +      flush_work(&chip->work);
        ret_size = atomic_read(&chip->data_pending);
-       atomic_set(&chip->data_pending, 0);
        if (ret_size > 0) {     /* relay data */
                ssize_t orig_ret_size = ret_size;
                if (size < ret_size)
                mutex_unlock(&chip->buffer_mutex);
        }
  
+       atomic_set(&chip->data_pending, 0);
        return ret_size;
  }
  EXPORT_SYMBOL_GPL(tpm_read);
@@@ -1326,6 -1323,58 +1323,58 @@@ int tpm_pm_resume(struct device *dev
  }
  EXPORT_SYMBOL_GPL(tpm_pm_resume);
  
+ #define TPM_GETRANDOM_RESULT_SIZE     18
+ static struct tpm_input_header tpm_getrandom_header = {
+       .tag = TPM_TAG_RQU_COMMAND,
+       .length = cpu_to_be32(14),
+       .ordinal = TPM_ORD_GET_RANDOM
+ };
+ /**
+  * tpm_get_random() - Get random bytes from the tpm's RNG
+  * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+  * @out: destination buffer for the random bytes
+  * @max: the max number of bytes to write to @out
+  *
+  * Returns < 0 on error and the number of bytes read on success
+  */
+ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
+ {
+       struct tpm_chip *chip;
+       struct tpm_cmd_t tpm_cmd;
+       u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+       int err, total = 0, retries = 5;
+       u8 *dest = out;
+       chip = tpm_chip_find_get(chip_num);
+       if (chip == NULL)
+               return -ENODEV;
+       if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+               return -EINVAL;
+       do {
+               tpm_cmd.header.in = tpm_getrandom_header;
+               tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
+               err = transmit_cmd(chip, &tpm_cmd,
+                                  TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+                                  "attempting get random");
+               if (err)
+                       break;
+               recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+               memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
+               dest += recd;
+               total += recd;
+               num_bytes -= recd;
+       } while (retries-- && total < max);
+       return total ? total : -EIO;
+ }
+ EXPORT_SYMBOL_GPL(tpm_get_random);
  /* In case vendor provided release function, call it too.*/
  
  void tpm_dev_vendor_release(struct tpm_chip *chip)
@@@ -1346,7 -1395,7 +1395,7 @@@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_releas
   * Once all references to platform device are down to 0,
   * release all allocated structures.
   */
- void tpm_dev_release(struct device *dev)
static void tpm_dev_release(struct device *dev)
  {
        struct tpm_chip *chip = dev_get_drvdata(dev);
  
@@@ -1427,6 -1476,11 +1476,11 @@@ struct tpm_chip *tpm_register_hardware(
                goto put_device;
        }
  
+       if (sys_add_ppi(&dev->kobj)) {
+               misc_deregister(&chip->vendor.miscdev);
+               goto put_device;
+       }
        chip->bios_dir = tpm_bios_log_setup(devname);
  
        /* Make chip available */
diff --combined fs/file_table.c
index c6780163bf3e911d347c7a553e028c7ba19ce463,a41f23f90b17d932a7da824ed6a3f48053e03fc7..dac67923330f76eff9f4f961d73e5a3b1f1053db
@@@ -243,10 -243,10 +243,10 @@@ static void __fput(struct file *file
                if (file->f_op && file->f_op->fasync)
                        file->f_op->fasync(-1, file, 0);
        }
+       ima_file_free(file);
        if (file->f_op && file->f_op->release)
                file->f_op->release(inode, file);
        security_file_free(file);
-       ima_file_free(file);
        if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&
                     !(file->f_mode & FMODE_PATH))) {
                cdev_put(inode->i_cdev);
@@@ -339,6 -339,112 +339,6 @@@ void __fput_sync(struct file *file
  
  EXPORT_SYMBOL(fput);
  
 -struct file *fget(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 (file->f_mode & FMODE_PATH ||
 -                  !atomic_long_inc_not_zero(&file->f_count))
 -                      file = NULL;
 -      }
 -      rcu_read_unlock();
 -
 -      return file;
 -}
 -
 -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.
 - *
 - * You can use this instead of fget if you satisfy all of the following
 - * conditions:
 - * 1) You must call fput_light before exiting the syscall and returning control
 - *    to userspace (i.e. you cannot remember the returned struct file * after
 - *    returning to userspace).
 - * 2) You must not call filp_close on the returned struct file * in between
 - *    calls to fget_light and fput_light.
 - * 3) You must not clone the current task in between the calls to fget_light
 - *    and fput_light.
 - *
 - * The fput_needed flag returned by fget_light should be passed to the
 - * corresponding fput_light.
 - */
 -struct file *fget_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);
 -              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);
 -              if (file) {
 -                      if (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;
 -}
 -
  void put_filp(struct file *file)
  {
        if (atomic_long_dec_and_test(&file->f_count)) {
diff --combined fs/xattr.c
index ca15fbd391c8741cea09b2fa9f6e627b78b858e3,107f457143c35ffbcb9ad39ae52815a81332fcec..1780f062dbaf1cd504f491af5962f3dfbd8db4ee
@@@ -20,7 -20,6 +20,7 @@@
  #include <linux/fsnotify.h>
  #include <linux/audit.h>
  #include <linux/vmalloc.h>
 +#include <linux/posix_acl_xattr.h>
  
  #include <asm/uaccess.h>
  
@@@ -296,11 -295,13 +296,13 @@@ vfs_removexattr(struct dentry *dentry, 
        if (error)
                return error;
  
+       mutex_lock(&inode->i_mutex);
        error = security_inode_removexattr(dentry, name);
-       if (error)
+       if (error) {
+               mutex_unlock(&inode->i_mutex);
                return error;
+       }
  
-       mutex_lock(&inode->i_mutex);
        error = inode->i_op->removexattr(dentry, name);
        mutex_unlock(&inode->i_mutex);
  
@@@ -348,9 -349,6 +350,9 @@@ setxattr(struct dentry *d, const char _
                        error = -EFAULT;
                        goto out;
                }
 +              if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
 +                  (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
 +                      posix_acl_fix_xattr_from_user(kvalue, size);
        }
  
        error = vfs_setxattr(d, kname, kvalue, size, flags);
@@@ -403,20 -401,22 +405,20 @@@ SYSCALL_DEFINE5(lsetxattr, const char _
  SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
                const void __user *,value, size_t, size, int, flags)
  {
 -      int fput_needed;
 -      struct file *f;
 +      struct fd f = fdget(fd);
        struct dentry *dentry;
        int error = -EBADF;
  
 -      f = fget_light(fd, &fput_needed);
 -      if (!f)
 +      if (!f.file)
                return error;
 -      dentry = f->f_path.dentry;
 +      dentry = f.file->f_path.dentry;
        audit_inode(NULL, dentry);
 -      error = mnt_want_write_file(f);
 +      error = mnt_want_write_file(f.file);
        if (!error) {
                error = setxattr(dentry, name, value, size, flags);
 -              mnt_drop_write_file(f);
 +              mnt_drop_write_file(f.file);
        }
 -      fput_light(f, fput_needed);
 +      fdput(f);
        return error;
  }
  
@@@ -452,9 -452,6 +454,9 @@@ getxattr(struct dentry *d, const char _
  
        error = vfs_getxattr(d, kname, kvalue, size);
        if (error > 0) {
 +              if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
 +                  (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
 +                      posix_acl_fix_xattr_to_user(kvalue, size);
                if (size && copy_to_user(value, kvalue, error))
                        error = -EFAULT;
        } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
@@@ -500,14 -497,16 +502,14 @@@ SYSCALL_DEFINE4(lgetxattr, const char _
  SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
                void __user *, value, size_t, size)
  {
 -      int fput_needed;
 -      struct file *f;
 +      struct fd f = fdget(fd);
        ssize_t error = -EBADF;
  
 -      f = fget_light(fd, &fput_needed);
 -      if (!f)
 +      if (!f.file)
                return error;
 -      audit_inode(NULL, f->f_path.dentry);
 -      error = getxattr(f->f_path.dentry, name, value, size);
 -      fput_light(f, fput_needed);
 +      audit_inode(NULL, f.file->f_path.dentry);
 +      error = getxattr(f.file->f_path.dentry, name, value, size);
 +      fdput(f);
        return error;
  }
  
@@@ -579,14 -578,16 +581,14 @@@ SYSCALL_DEFINE3(llistxattr, const char 
  
  SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
  {
 -      int fput_needed;
 -      struct file *f;
 +      struct fd f = fdget(fd);
        ssize_t error = -EBADF;
  
 -      f = fget_light(fd, &fput_needed);
 -      if (!f)
 +      if (!f.file)
                return error;
 -      audit_inode(NULL, f->f_path.dentry);
 -      error = listxattr(f->f_path.dentry, list, size);
 -      fput_light(f, fput_needed);
 +      audit_inode(NULL, f.file->f_path.dentry);
 +      error = listxattr(f.file->f_path.dentry, list, size);
 +      fdput(f);
        return error;
  }
  
@@@ -646,20 -647,22 +648,20 @@@ SYSCALL_DEFINE2(lremovexattr, const cha
  
  SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
  {
 -      int fput_needed;
 -      struct file *f;
 +      struct fd f = fdget(fd);
        struct dentry *dentry;
        int error = -EBADF;
  
 -      f = fget_light(fd, &fput_needed);
 -      if (!f)
 +      if (!f.file)
                return error;
 -      dentry = f->f_path.dentry;
 +      dentry = f.file->f_path.dentry;
        audit_inode(NULL, dentry);
 -      error = mnt_want_write_file(f);
 +      error = mnt_want_write_file(f.file);
        if (!error) {
                error = removexattr(dentry, name);
 -              mnt_drop_write_file(f);
 +              mnt_drop_write_file(f.file);
        }
 -      fput_light(f, fput_needed);
 +      fdput(f);
        return error;
  }
  
@@@ -790,183 -793,3 +792,183 @@@ EXPORT_SYMBOL(generic_getxattr)
  EXPORT_SYMBOL(generic_listxattr);
  EXPORT_SYMBOL(generic_setxattr);
  EXPORT_SYMBOL(generic_removexattr);
 +
 +/*
 + * Allocate new xattr and copy in the value; but leave the name to callers.
 + */
 +struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
 +{
 +      struct simple_xattr *new_xattr;
 +      size_t len;
 +
 +      /* wrap around? */
 +      len = sizeof(*new_xattr) + size;
 +      if (len <= sizeof(*new_xattr))
 +              return NULL;
 +
 +      new_xattr = kmalloc(len, GFP_KERNEL);
 +      if (!new_xattr)
 +              return NULL;
 +
 +      new_xattr->size = size;
 +      memcpy(new_xattr->value, value, size);
 +      return new_xattr;
 +}
 +
 +/*
 + * xattr GET operation for in-memory/pseudo filesystems
 + */
 +int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
 +                   void *buffer, size_t size)
 +{
 +      struct simple_xattr *xattr;
 +      int ret = -ENODATA;
 +
 +      spin_lock(&xattrs->lock);
 +      list_for_each_entry(xattr, &xattrs->head, list) {
 +              if (strcmp(name, xattr->name))
 +                      continue;
 +
 +              ret = xattr->size;
 +              if (buffer) {
 +                      if (size < xattr->size)
 +                              ret = -ERANGE;
 +                      else
 +                              memcpy(buffer, xattr->value, xattr->size);
 +              }
 +              break;
 +      }
 +      spin_unlock(&xattrs->lock);
 +      return ret;
 +}
 +
 +static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
 +                            const void *value, size_t size, int flags)
 +{
 +      struct simple_xattr *xattr;
 +      struct simple_xattr *uninitialized_var(new_xattr);
 +      int err = 0;
 +
 +      /* value == NULL means remove */
 +      if (value) {
 +              new_xattr = simple_xattr_alloc(value, size);
 +              if (!new_xattr)
 +                      return -ENOMEM;
 +
 +              new_xattr->name = kstrdup(name, GFP_KERNEL);
 +              if (!new_xattr->name) {
 +                      kfree(new_xattr);
 +                      return -ENOMEM;
 +              }
 +      }
 +
 +      spin_lock(&xattrs->lock);
 +      list_for_each_entry(xattr, &xattrs->head, list) {
 +              if (!strcmp(name, xattr->name)) {
 +                      if (flags & XATTR_CREATE) {
 +                              xattr = new_xattr;
 +                              err = -EEXIST;
 +                      } else if (new_xattr) {
 +                              list_replace(&xattr->list, &new_xattr->list);
 +                      } else {
 +                              list_del(&xattr->list);
 +                      }
 +                      goto out;
 +              }
 +      }
 +      if (flags & XATTR_REPLACE) {
 +              xattr = new_xattr;
 +              err = -ENODATA;
 +      } else {
 +              list_add(&new_xattr->list, &xattrs->head);
 +              xattr = NULL;
 +      }
 +out:
 +      spin_unlock(&xattrs->lock);
 +      if (xattr) {
 +              kfree(xattr->name);
 +              kfree(xattr);
 +      }
 +      return err;
 +
 +}
 +
 +/**
 + * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
 + * @xattrs: target simple_xattr list
 + * @name: name of the new extended attribute
 + * @value: value of the new xattr. If %NULL, will remove the attribute
 + * @size: size of the new xattr
 + * @flags: %XATTR_{CREATE|REPLACE}
 + *
 + * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
 + * with -EEXIST.  If %XATTR_REPLACE is set, the xattr should exist;
 + * otherwise, fails with -ENODATA.
 + *
 + * Returns 0 on success, -errno on failure.
 + */
 +int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
 +                   const void *value, size_t size, int flags)
 +{
 +      if (size == 0)
 +              value = ""; /* empty EA, do not remove */
 +      return __simple_xattr_set(xattrs, name, value, size, flags);
 +}
 +
 +/*
 + * xattr REMOVE operation for in-memory/pseudo filesystems
 + */
 +int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name)
 +{
 +      return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE);
 +}
 +
 +static bool xattr_is_trusted(const char *name)
 +{
 +      return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 +}
 +
 +/*
 + * xattr LIST operation for in-memory/pseudo filesystems
 + */
 +ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
 +                        size_t size)
 +{
 +      bool trusted = capable(CAP_SYS_ADMIN);
 +      struct simple_xattr *xattr;
 +      size_t used = 0;
 +
 +      spin_lock(&xattrs->lock);
 +      list_for_each_entry(xattr, &xattrs->head, list) {
 +              size_t len;
 +
 +              /* skip "trusted." attributes for unprivileged callers */
 +              if (!trusted && xattr_is_trusted(xattr->name))
 +                      continue;
 +
 +              len = strlen(xattr->name) + 1;
 +              used += len;
 +              if (buffer) {
 +                      if (size < used) {
 +                              used = -ERANGE;
 +                              break;
 +                      }
 +                      memcpy(buffer, xattr->name, len);
 +                      buffer += len;
 +              }
 +      }
 +      spin_unlock(&xattrs->lock);
 +
 +      return used;
 +}
 +
 +/*
 + * Adds an extended attribute to the list
 + */
 +void simple_xattr_list_add(struct simple_xattrs *xattrs,
 +                         struct simple_xattr *new_xattr)
 +{
 +      spin_lock(&xattrs->lock);
 +      list_add(&new_xattr->list, &xattrs->head);
 +      spin_unlock(&xattrs->lock);
 +}
diff --combined include/linux/audit.h
index 12367cbadfe15c3ddeb01d5c4f920e9ed916f08f,2a5073cf548a0d848f99c7810a124bded3313eb9..e7c836d961ea3e442c6fcf1c63534f549a956e98
@@@ -442,8 -442,6 +442,8 @@@ struct audit_krule 
  struct audit_field {
        u32                             type;
        u32                             val;
 +      kuid_t                          uid;
 +      kgid_t                          gid;
        u32                             op;
        char                            *lsm_str;
        void                            *lsm_rule;
@@@ -527,10 -525,11 +527,11 @@@ static inline void audit_ptrace(struct 
  extern unsigned int audit_serial(void);
  extern int auditsc_get_stamp(struct audit_context *ctx,
                              struct timespec *t, unsigned int *serial);
 -extern int  audit_set_loginuid(uid_t loginuid);
 +extern int  audit_set_loginuid(kuid_t loginuid);
  #define audit_get_loginuid(t) ((t)->loginuid)
  #define audit_get_sessionid(t) ((t)->sessionid)
  extern void audit_log_task_context(struct audit_buffer *ab);
+ extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk);
  extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
  extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode);
  extern int __audit_bprm(struct linux_binprm *bprm);
@@@ -639,9 -638,10 +640,10 @@@ extern int audit_signals
  #define audit_core_dumps(i) do { ; } while (0)
  #define audit_seccomp(i,s,c) do { ; } while (0)
  #define auditsc_get_stamp(c,t,s) (0)
 -#define audit_get_loginuid(t) (-1)
 +#define audit_get_loginuid(t) (INVALID_UID)
  #define audit_get_sessionid(t) (-1)
  #define audit_log_task_context(b) do { ; } while (0)
+ #define audit_log_task_info(b, t) do { ; } while (0)
  #define audit_ipc_obj(i) ((void)0)
  #define audit_ipc_set_perm(q,u,g,m) ((void)0)
  #define audit_bprm(p) ({ 0; })
@@@ -702,10 -702,10 +704,10 @@@ extern void                 audit_log_secctx(stru
  extern int                audit_update_lsm_rules(void);
  
                                /* Private API (for audit.c only) */
 -extern int audit_filter_user(struct netlink_skb_parms *cb);
 +extern int audit_filter_user(void);
  extern int audit_filter_type(int type);
 -extern int  audit_receive_filter(int type, int pid, int uid, int seq,
 -                              void *data, size_t datasz, uid_t loginuid,
 +extern int  audit_receive_filter(int type, int pid, int seq,
 +                              void *data, size_t datasz, kuid_t loginuid,
                                u32 sessionid, u32 sid);
  extern int audit_enabled;
  #else
diff --combined include/linux/security.h
index 145accee9236206d8ae79d4eb7fe0bd80c40892f,01ef030b94099edab9e884de3ebc3cf2d3749fae..5b50c4e1a7c25eeada9bb6756e2ebee3ad8b7473
@@@ -118,7 -118,6 +118,7 @@@ void reset_security_ops(void)
  extern unsigned long mmap_min_addr;
  extern unsigned long dac_mmap_min_addr;
  #else
 +#define mmap_min_addr         0UL
  #define dac_mmap_min_addr     0UL
  #endif
  
@@@ -1436,7 -1435,7 +1436,7 @@@ struct security_operations 
        int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
                            struct path *new_dir, struct dentry *new_dentry);
        int (*path_chmod) (struct path *path, umode_t mode);
 -      int (*path_chown) (struct path *path, uid_t uid, gid_t gid);
 +      int (*path_chown) (struct path *path, kuid_t uid, kgid_t gid);
        int (*path_chroot) (struct path *path);
  #endif
  
@@@ -2831,7 -2830,7 +2831,7 @@@ int security_path_link(struct dentry *o
  int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
                         struct path *new_dir, struct dentry *new_dentry);
  int security_path_chmod(struct path *path, umode_t mode);
 -int security_path_chown(struct path *path, uid_t uid, gid_t gid);
 +int security_path_chown(struct path *path, kuid_t uid, kgid_t gid);
  int security_path_chroot(struct path *path);
  #else /* CONFIG_SECURITY_PATH */
  static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
@@@ -2887,7 -2886,7 +2887,7 @@@ static inline int security_path_chmod(s
        return 0;
  }
  
 -static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid)
 +static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
  {
        return 0;
  }
@@@ -3022,5 -3021,36 +3022,36 @@@ static inline void free_secdata(void *s
  { }
  #endif /* CONFIG_SECURITY */
  
+ #ifdef CONFIG_SECURITY_YAMA
+ extern int yama_ptrace_access_check(struct task_struct *child,
+                                   unsigned int mode);
+ extern int yama_ptrace_traceme(struct task_struct *parent);
+ extern void yama_task_free(struct task_struct *task);
+ extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+                          unsigned long arg4, unsigned long arg5);
+ #else
+ static inline int yama_ptrace_access_check(struct task_struct *child,
+                                          unsigned int mode)
+ {
+       return 0;
+ }
+ static inline int yama_ptrace_traceme(struct task_struct *parent)
+ {
+       return 0;
+ }
+ static inline void yama_task_free(struct task_struct *task)
+ {
+ }
+ static inline int yama_task_prctl(int option, unsigned long arg2,
+                                 unsigned long arg3, unsigned long arg4,
+                                 unsigned long arg5)
+ {
+       return -ENOSYS;
+ }
+ #endif /* CONFIG_SECURITY_YAMA */
  #endif /* ! __LINUX_SECURITY_H */
  
diff --combined include/linux/xattr.h
index 2ace7a60316d9905ae0a8fb419f68e5e1c177144,77a3e686d56627cba522616bd9425ae551b0ce35..cc13e1115970455e4240ff09e69d34f610cf337d
@@@ -33,6 -33,9 +33,9 @@@
  #define XATTR_EVM_SUFFIX "evm"
  #define XATTR_NAME_EVM XATTR_SECURITY_PREFIX XATTR_EVM_SUFFIX
  
+ #define XATTR_IMA_SUFFIX "ima"
+ #define XATTR_NAME_IMA XATTR_SECURITY_PREFIX XATTR_IMA_SUFFIX
  #define XATTR_SELINUX_SUFFIX "selinux"
  #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
  
@@@ -59,9 -62,7 +62,9 @@@
  
  #ifdef  __KERNEL__
  
 +#include <linux/slab.h>
  #include <linux/types.h>
 +#include <linux/spinlock.h>
  
  struct inode;
  struct dentry;
@@@ -98,52 -99,6 +101,52 @@@ ssize_t vfs_getxattr_alloc(struct dentr
                           char **xattr_value, size_t size, gfp_t flags);
  int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
                  const char *value, size_t size, gfp_t flags);
 +
 +struct simple_xattrs {
 +      struct list_head head;
 +      spinlock_t lock;
 +};
 +
 +struct simple_xattr {
 +      struct list_head list;
 +      char *name;
 +      size_t size;
 +      char value[0];
 +};
 +
 +/*
 + * initialize the simple_xattrs structure
 + */
 +static inline void simple_xattrs_init(struct simple_xattrs *xattrs)
 +{
 +      INIT_LIST_HEAD(&xattrs->head);
 +      spin_lock_init(&xattrs->lock);
 +}
 +
 +/*
 + * free all the xattrs
 + */
 +static inline void simple_xattrs_free(struct simple_xattrs *xattrs)
 +{
 +      struct simple_xattr *xattr, *node;
 +
 +      list_for_each_entry_safe(xattr, node, &xattrs->head, list) {
 +              kfree(xattr->name);
 +              kfree(xattr);
 +      }
 +}
 +
 +struct simple_xattr *simple_xattr_alloc(const void *value, size_t size);
 +int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
 +                   void *buffer, size_t size);
 +int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
 +                   const void *value, size_t size, int flags);
 +int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name);
 +ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
 +                        size_t size);
 +void simple_xattr_list_add(struct simple_xattrs *xattrs,
 +                         struct simple_xattr *new_xattr);
 +
  #endif  /*  __KERNEL__  */
  
  #endif        /* _LINUX_XATTR_H */
diff --combined kernel/auditsc.c
index ff4798fcb4884d371f5b393c11dbcd8c585e1fbb,37f52f27828df4890a4dce17c2a8402f013b74f8..29e090cc0e46a45a415d133dd8977d5b1a839368
@@@ -113,8 -113,8 +113,8 @@@ struct audit_names 
        unsigned long   ino;
        dev_t           dev;
        umode_t         mode;
 -      uid_t           uid;
 -      gid_t           gid;
 +      kuid_t          uid;
 +      kgid_t          gid;
        dev_t           rdev;
        u32             osid;
        struct audit_cap_data fcap;
@@@ -149,8 -149,8 +149,8 @@@ struct audit_aux_data_execve 
  struct audit_aux_data_pids {
        struct audit_aux_data   d;
        pid_t                   target_pid[AUDIT_AUX_PIDS];
 -      uid_t                   target_auid[AUDIT_AUX_PIDS];
 -      uid_t                   target_uid[AUDIT_AUX_PIDS];
 +      kuid_t                  target_auid[AUDIT_AUX_PIDS];
 +      kuid_t                  target_uid[AUDIT_AUX_PIDS];
        unsigned int            target_sessionid[AUDIT_AUX_PIDS];
        u32                     target_sid[AUDIT_AUX_PIDS];
        char                    target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
@@@ -208,14 -208,14 +208,14 @@@ struct audit_context 
        size_t sockaddr_len;
                                /* Save things to print about task_struct */
        pid_t               pid, ppid;
 -      uid_t               uid, euid, suid, fsuid;
 -      gid_t               gid, egid, sgid, fsgid;
 +      kuid_t              uid, euid, suid, fsuid;
 +      kgid_t              gid, egid, sgid, fsgid;
        unsigned long       personality;
        int                 arch;
  
        pid_t               target_pid;
 -      uid_t               target_auid;
 -      uid_t               target_uid;
 +      kuid_t              target_auid;
 +      kuid_t              target_uid;
        unsigned int        target_sessionid;
        u32                 target_sid;
        char                target_comm[TASK_COMM_LEN];
                        long args[6];
                } socketcall;
                struct {
 -                      uid_t                   uid;
 -                      gid_t                   gid;
 +                      kuid_t                  uid;
 +                      kgid_t                  gid;
                        umode_t                 mode;
                        u32                     osid;
                        int                     has_perm;
@@@ -464,47 -464,37 +464,47 @@@ static int match_tree_refs(struct audit
        return 0;
  }
  
 -static int audit_compare_id(uid_t uid1,
 -                          struct audit_names *name,
 -                          unsigned long name_offset,
 -                          struct audit_field *f,
 -                          struct audit_context *ctx)
 +static int audit_compare_uid(kuid_t uid,
 +                           struct audit_names *name,
 +                           struct audit_field *f,
 +                           struct audit_context *ctx)
  {
        struct audit_names *n;
 -      unsigned long addr;
 -      uid_t uid2;
        int rc;
 -
 -      BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
 -
 + 
        if (name) {
 -              addr = (unsigned long)name;
 -              addr += name_offset;
 -
 -              uid2 = *(uid_t *)addr;
 -              rc = audit_comparator(uid1, f->op, uid2);
 +              rc = audit_uid_comparator(uid, f->op, name->uid);
                if (rc)
                        return rc;
        }
 -
 + 
        if (ctx) {
                list_for_each_entry(n, &ctx->names_list, list) {
 -                      addr = (unsigned long)n;
 -                      addr += name_offset;
 -
 -                      uid2 = *(uid_t *)addr;
 +                      rc = audit_uid_comparator(uid, f->op, n->uid);
 +                      if (rc)
 +                              return rc;
 +              }
 +      }
 +      return 0;
 +}
  
 -                      rc = audit_comparator(uid1, f->op, uid2);
 +static int audit_compare_gid(kgid_t gid,
 +                           struct audit_names *name,
 +                           struct audit_field *f,
 +                           struct audit_context *ctx)
 +{
 +      struct audit_names *n;
 +      int rc;
 + 
 +      if (name) {
 +              rc = audit_gid_comparator(gid, f->op, name->gid);
 +              if (rc)
 +                      return rc;
 +      }
 + 
 +      if (ctx) {
 +              list_for_each_entry(n, &ctx->names_list, list) {
 +                      rc = audit_gid_comparator(gid, f->op, n->gid);
                        if (rc)
                                return rc;
                }
@@@ -521,62 -511,80 +521,62 @@@ static int audit_field_compare(struct t
        switch (f->val) {
        /* process to file object comparisons */
        case AUDIT_COMPARE_UID_TO_OBJ_UID:
 -              return audit_compare_id(cred->uid,
 -                                      name, offsetof(struct audit_names, uid),
 -                                      f, ctx);
 +              return audit_compare_uid(cred->uid, name, f, ctx);
        case AUDIT_COMPARE_GID_TO_OBJ_GID:
 -              return audit_compare_id(cred->gid,
 -                                      name, offsetof(struct audit_names, gid),
 -                                      f, ctx);
 +              return audit_compare_gid(cred->gid, name, f, ctx);
        case AUDIT_COMPARE_EUID_TO_OBJ_UID:
 -              return audit_compare_id(cred->euid,
 -                                      name, offsetof(struct audit_names, uid),
 -                                      f, ctx);
 +              return audit_compare_uid(cred->euid, name, f, ctx);
        case AUDIT_COMPARE_EGID_TO_OBJ_GID:
 -              return audit_compare_id(cred->egid,
 -                                      name, offsetof(struct audit_names, gid),
 -                                      f, ctx);
 +              return audit_compare_gid(cred->egid, name, f, ctx);
        case AUDIT_COMPARE_AUID_TO_OBJ_UID:
 -              return audit_compare_id(tsk->loginuid,
 -                                      name, offsetof(struct audit_names, uid),
 -                                      f, ctx);
 +              return audit_compare_uid(tsk->loginuid, name, f, ctx);
        case AUDIT_COMPARE_SUID_TO_OBJ_UID:
 -              return audit_compare_id(cred->suid,
 -                                      name, offsetof(struct audit_names, uid),
 -                                      f, ctx);
 +              return audit_compare_uid(cred->suid, name, f, ctx);
        case AUDIT_COMPARE_SGID_TO_OBJ_GID:
 -              return audit_compare_id(cred->sgid,
 -                                      name, offsetof(struct audit_names, gid),
 -                                      f, ctx);
 +              return audit_compare_gid(cred->sgid, name, f, ctx);
        case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
 -              return audit_compare_id(cred->fsuid,
 -                                      name, offsetof(struct audit_names, uid),
 -                                      f, ctx);
 +              return audit_compare_uid(cred->fsuid, name, f, ctx);
        case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
 -              return audit_compare_id(cred->fsgid,
 -                                      name, offsetof(struct audit_names, gid),
 -                                      f, ctx);
 +              return audit_compare_gid(cred->fsgid, name, f, ctx);
        /* uid comparisons */
        case AUDIT_COMPARE_UID_TO_AUID:
 -              return audit_comparator(cred->uid, f->op, tsk->loginuid);
 +              return audit_uid_comparator(cred->uid, f->op, tsk->loginuid);
        case AUDIT_COMPARE_UID_TO_EUID:
 -              return audit_comparator(cred->uid, f->op, cred->euid);
 +              return audit_uid_comparator(cred->uid, f->op, cred->euid);
        case AUDIT_COMPARE_UID_TO_SUID:
 -              return audit_comparator(cred->uid, f->op, cred->suid);
 +              return audit_uid_comparator(cred->uid, f->op, cred->suid);
        case AUDIT_COMPARE_UID_TO_FSUID:
 -              return audit_comparator(cred->uid, f->op, cred->fsuid);
 +              return audit_uid_comparator(cred->uid, f->op, cred->fsuid);
        /* auid comparisons */
        case AUDIT_COMPARE_AUID_TO_EUID:
 -              return audit_comparator(tsk->loginuid, f->op, cred->euid);
 +              return audit_uid_comparator(tsk->loginuid, f->op, cred->euid);
        case AUDIT_COMPARE_AUID_TO_SUID:
 -              return audit_comparator(tsk->loginuid, f->op, cred->suid);
 +              return audit_uid_comparator(tsk->loginuid, f->op, cred->suid);
        case AUDIT_COMPARE_AUID_TO_FSUID:
 -              return audit_comparator(tsk->loginuid, f->op, cred->fsuid);
 +              return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid);
        /* euid comparisons */
        case AUDIT_COMPARE_EUID_TO_SUID:
 -              return audit_comparator(cred->euid, f->op, cred->suid);
 +              return audit_uid_comparator(cred->euid, f->op, cred->suid);
        case AUDIT_COMPARE_EUID_TO_FSUID:
 -              return audit_comparator(cred->euid, f->op, cred->fsuid);
 +              return audit_uid_comparator(cred->euid, f->op, cred->fsuid);
        /* suid comparisons */
        case AUDIT_COMPARE_SUID_TO_FSUID:
 -              return audit_comparator(cred->suid, f->op, cred->fsuid);
 +              return audit_uid_comparator(cred->suid, f->op, cred->fsuid);
        /* gid comparisons */
        case AUDIT_COMPARE_GID_TO_EGID:
 -              return audit_comparator(cred->gid, f->op, cred->egid);
 +              return audit_gid_comparator(cred->gid, f->op, cred->egid);
        case AUDIT_COMPARE_GID_TO_SGID:
 -              return audit_comparator(cred->gid, f->op, cred->sgid);
 +              return audit_gid_comparator(cred->gid, f->op, cred->sgid);
        case AUDIT_COMPARE_GID_TO_FSGID:
 -              return audit_comparator(cred->gid, f->op, cred->fsgid);
 +              return audit_gid_comparator(cred->gid, f->op, cred->fsgid);
        /* egid comparisons */
        case AUDIT_COMPARE_EGID_TO_SGID:
 -              return audit_comparator(cred->egid, f->op, cred->sgid);
 +              return audit_gid_comparator(cred->egid, f->op, cred->sgid);
        case AUDIT_COMPARE_EGID_TO_FSGID:
 -              return audit_comparator(cred->egid, f->op, cred->fsgid);
 +              return audit_gid_comparator(cred->egid, f->op, cred->fsgid);
        /* sgid comparison */
        case AUDIT_COMPARE_SGID_TO_FSGID:
 -              return audit_comparator(cred->sgid, f->op, cred->fsgid);
 +              return audit_gid_comparator(cred->sgid, f->op, cred->fsgid);
        default:
                WARN(1, "Missing AUDIT_COMPARE define.  Report as a bug\n");
                return 0;
@@@ -622,28 -630,28 +622,28 @@@ static int audit_filter_rules(struct ta
                        }
                        break;
                case AUDIT_UID:
 -                      result = audit_comparator(cred->uid, f->op, f->val);
 +                      result = audit_uid_comparator(cred->uid, f->op, f->uid);
                        break;
                case AUDIT_EUID:
 -                      result = audit_comparator(cred->euid, f->op, f->val);
 +                      result = audit_uid_comparator(cred->euid, f->op, f->uid);
                        break;
                case AUDIT_SUID:
 -                      result = audit_comparator(cred->suid, f->op, f->val);
 +                      result = audit_uid_comparator(cred->suid, f->op, f->uid);
                        break;
                case AUDIT_FSUID:
 -                      result = audit_comparator(cred->fsuid, f->op, f->val);
 +                      result = audit_uid_comparator(cred->fsuid, f->op, f->uid);
                        break;
                case AUDIT_GID:
 -                      result = audit_comparator(cred->gid, f->op, f->val);
 +                      result = audit_gid_comparator(cred->gid, f->op, f->gid);
                        break;
                case AUDIT_EGID:
 -                      result = audit_comparator(cred->egid, f->op, f->val);
 +                      result = audit_gid_comparator(cred->egid, f->op, f->gid);
                        break;
                case AUDIT_SGID:
 -                      result = audit_comparator(cred->sgid, f->op, f->val);
 +                      result = audit_gid_comparator(cred->sgid, f->op, f->gid);
                        break;
                case AUDIT_FSGID:
 -                      result = audit_comparator(cred->fsgid, f->op, f->val);
 +                      result = audit_gid_comparator(cred->fsgid, f->op, f->gid);
                        break;
                case AUDIT_PERS:
                        result = audit_comparator(tsk->personality, f->op, f->val);
                        break;
                case AUDIT_OBJ_UID:
                        if (name) {
 -                              result = audit_comparator(name->uid, f->op, f->val);
 +                              result = audit_uid_comparator(name->uid, f->op, f->uid);
                        } else if (ctx) {
                                list_for_each_entry(n, &ctx->names_list, list) {
 -                                      if (audit_comparator(n->uid, f->op, f->val)) {
 +                                      if (audit_uid_comparator(n->uid, f->op, f->uid)) {
                                                ++result;
                                                break;
                                        }
                        break;
                case AUDIT_OBJ_GID:
                        if (name) {
 -                              result = audit_comparator(name->gid, f->op, f->val);
 +                              result = audit_gid_comparator(name->gid, f->op, f->gid);
                        } else if (ctx) {
                                list_for_each_entry(n, &ctx->names_list, list) {
 -                                      if (audit_comparator(n->gid, f->op, f->val)) {
 +                                      if (audit_gid_comparator(n->gid, f->op, f->gid)) {
                                                ++result;
                                                break;
                                        }
                case AUDIT_LOGINUID:
                        result = 0;
                        if (ctx)
 -                              result = audit_comparator(tsk->loginuid, f->op, f->val);
 +                              result = audit_uid_comparator(tsk->loginuid, f->op, f->uid);
                        break;
                case AUDIT_SUBJ_USER:
                case AUDIT_SUBJ_ROLE:
@@@ -1146,13 -1154,38 +1146,44 @@@ error_path
  
  EXPORT_SYMBOL(audit_log_task_context);
  
static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
+ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
  {
+       const struct cred *cred;
        char name[sizeof(tsk->comm)];
        struct mm_struct *mm = tsk->mm;
        struct vm_area_struct *vma;
+       char *tty;
+       if (!ab)
+               return;
  
        /* tsk == current */
 -                       tsk->loginuid, cred->uid, cred->gid,
 -                       cred->euid, cred->suid, cred->fsuid,
 -                       cred->egid, cred->sgid, cred->fsgid,
+       cred = current_cred();
+       spin_lock_irq(&tsk->sighand->siglock);
+       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+               tty = tsk->signal->tty->name;
+       else
+               tty = "(none)";
+       spin_unlock_irq(&tsk->sighand->siglock);
+       audit_log_format(ab,
+                        " ppid=%ld pid=%d auid=%u uid=%u gid=%u"
+                        " euid=%u suid=%u fsuid=%u"
+                        " egid=%u sgid=%u fsgid=%u ses=%u tty=%s",
+                        sys_getppid(),
+                        tsk->pid,
++                       from_kuid(&init_user_ns, tsk->loginuid),
++                       from_kuid(&init_user_ns, cred->uid),
++                       from_kgid(&init_user_ns, cred->gid),
++                       from_kuid(&init_user_ns, cred->euid),
++                       from_kuid(&init_user_ns, cred->suid),
++                       from_kuid(&init_user_ns, cred->fsuid),
++                       from_kgid(&init_user_ns, cred->egid),
++                       from_kgid(&init_user_ns, cred->sgid),
++                       from_kgid(&init_user_ns, cred->fsgid),
+                        tsk->sessionid, tty);
  
        get_task_comm(name, tsk);
        audit_log_format(ab, " comm=");
        audit_log_task_context(ab);
  }
  
+ EXPORT_SYMBOL(audit_log_task_info);
  static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 -                               uid_t auid, uid_t uid, unsigned int sessionid,
 +                               kuid_t auid, kuid_t uid, unsigned int sessionid,
                                 u32 sid, char *comm)
  {
        struct audit_buffer *ab;
        if (!ab)
                return rc;
  
 -      audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid,
 -                       uid, sessionid);
 +      audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
 +                       from_kuid(&init_user_ns, auid),
 +                       from_kuid(&init_user_ns, uid), sessionid);
        if (security_secid_to_secctx(sid, &ctx, &len)) {
                audit_log_format(ab, " obj=(none)");
                rc = 1;
@@@ -1440,9 -1474,7 +1473,9 @@@ static void show_special(struct audit_c
                u32 osid = context->ipc.osid;
  
                audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho",
 -                       context->ipc.uid, context->ipc.gid, context->ipc.mode);
 +                               from_kuid(&init_user_ns, context->ipc.uid),
 +                               from_kgid(&init_user_ns, context->ipc.gid),
 +                               context->ipc.mode);
                if (osid) {
                        char *ctx = NULL;
                        u32 len;
@@@ -1555,8 -1587,8 +1588,8 @@@ static void audit_log_name(struct audit
                                 MAJOR(n->dev),
                                 MINOR(n->dev),
                                 n->mode,
 -                               n->uid,
 -                               n->gid,
 +                               from_kuid(&init_user_ns, n->uid),
 +                               from_kgid(&init_user_ns, n->gid),
                                 MAJOR(n->rdev),
                                 MINOR(n->rdev));
        }
  
  static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
  {
-       const struct cred *cred;
        int i, call_panic = 0;
        struct audit_buffer *ab;
        struct audit_aux_data *aux;
-       const char *tty;
        struct audit_names *n;
  
        /* tsk == current */
-       context->pid = tsk->pid;
-       if (!context->ppid)
-               context->ppid = sys_getppid();
-       cred = current_cred();
-       context->uid   = cred->uid;
-       context->gid   = cred->gid;
-       context->euid  = cred->euid;
-       context->suid  = cred->suid;
-       context->fsuid = cred->fsuid;
-       context->egid  = cred->egid;
-       context->sgid  = cred->sgid;
-       context->fsgid = cred->fsgid;
        context->personality = tsk->personality;
  
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
                                 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
                                 context->return_code);
  
-       spin_lock_irq(&tsk->sighand->siglock);
-       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
-               tty = tsk->signal->tty->name;
-       else
-               tty = "(none)";
-       spin_unlock_irq(&tsk->sighand->siglock);
        audit_log_format(ab,
-                 " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
-                 " ppid=%d pid=%d auid=%u uid=%u gid=%u"
-                 " euid=%u suid=%u fsuid=%u"
-                 " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",
-                 context->argv[0],
-                 context->argv[1],
-                 context->argv[2],
-                 context->argv[3],
-                 context->name_count,
-                 context->ppid,
-                 context->pid,
-                 from_kuid(&init_user_ns, tsk->loginuid),
-                 from_kuid(&init_user_ns, context->uid),
-                 from_kgid(&init_user_ns, context->gid),
-                 from_kuid(&init_user_ns, context->euid),
-                 from_kuid(&init_user_ns, context->suid),
-                 from_kuid(&init_user_ns, context->fsuid),
-                 from_kgid(&init_user_ns, context->egid),
-                 from_kgid(&init_user_ns, context->sgid),
-                 from_kgid(&init_user_ns, context->fsgid),
-                 tty,
-                 tsk->sessionid);
+                        " a0=%lx a1=%lx a2=%lx a3=%lx items=%d",
+                        context->argv[0],
+                        context->argv[1],
+                        context->argv[2],
+                        context->argv[3],
+                        context->name_count);
  
        audit_log_task_info(ab, tsk);
        audit_log_key(ab, context->filterkey);
@@@ -2299,14 -2293,14 +2294,14 @@@ static atomic_t session_id = ATOMIC_INI
   *
   * Called (set) from fs/proc/base.c::proc_loginuid_write().
   */
 -int audit_set_loginuid(uid_t loginuid)
 +int audit_set_loginuid(kuid_t loginuid)
  {
        struct task_struct *task = current;
        struct audit_context *context = task->audit_context;
        unsigned int sessionid;
  
  #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE
 -      if (task->loginuid != -1)
 +      if (uid_valid(task->loginuid))
                return -EPERM;
  #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */
        if (!capable(CAP_AUDIT_CONTROL))
                        audit_log_format(ab, "login pid=%d uid=%u "
                                "old auid=%u new auid=%u"
                                " old ses=%u new ses=%u",
 -                              task->pid, task_uid(task),
 -                              task->loginuid, loginuid,
 +                              task->pid,
 +                              from_kuid(&init_user_ns, task_uid(task)),
 +                              from_kuid(&init_user_ns, task->loginuid),
 +                              from_kuid(&init_user_ns, loginuid),
                                task->sessionid, sessionid);
                        audit_log_end(ab);
                }
@@@ -2548,12 -2540,12 +2543,12 @@@ int __audit_signal_info(int sig, struc
        struct audit_aux_data_pids *axp;
        struct task_struct *tsk = current;
        struct audit_context *ctx = tsk->audit_context;
 -      uid_t uid = current_uid(), t_uid = task_uid(t);
 +      kuid_t uid = current_uid(), t_uid = task_uid(t);
  
        if (audit_pid && t->tgid == audit_pid) {
                if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
                        audit_sig_pid = tsk->pid;
 -                      if (tsk->loginuid != -1)
 +                      if (uid_valid(tsk->loginuid))
                                audit_sig_uid = tsk->loginuid;
                        else
                                audit_sig_uid = uid;
@@@ -2674,8 -2666,8 +2669,8 @@@ void __audit_mmap_fd(int fd, int flags
  
  static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
  {
 -      uid_t auid, uid;
 -      gid_t gid;
 +      kuid_t auid, uid;
 +      kgid_t gid;
        unsigned int sessionid;
  
        auid = audit_get_loginuid(current);
        current_uid_gid(&uid, &gid);
  
        audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
 -                       auid, uid, gid, sessionid);
 +                       from_kuid(&init_user_ns, auid),
 +                       from_kuid(&init_user_ns, uid),
 +                       from_kgid(&init_user_ns, gid),
 +                       sessionid);
        audit_log_task_context(ab);
        audit_log_format(ab, " pid=%d comm=", current->pid);
        audit_log_untrustedstring(ab, current->comm);
index c84df05180cbbda5aa27d3d74d248c6b2545351d,cda903131dbfb2122abb027261db38ed09e83a17..c7dacd2eab7a8eb59de3b00d4963b59b58396b96
  #define IMA_MASK      0x0002
  #define IMA_FSMAGIC   0x0004
  #define IMA_UID               0x0008
+ #define IMA_FOWNER    0x0010
  
- enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE };
+ #define UNKNOWN               0
+ #define MEASURE               0x0001  /* same as IMA_MEASURE */
+ #define DONT_MEASURE  0x0002
+ #define APPRAISE      0x0004  /* same as IMA_APPRAISE */
+ #define DONT_APPRAISE 0x0008
+ #define AUDIT         0x0040
  
  #define MAX_LSM_RULES 6
  enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
        LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
  };
  
- struct ima_measure_rule_entry {
+ struct ima_rule_entry {
        struct list_head list;
-       enum ima_action action;
+       int action;
        unsigned int flags;
        enum ima_hooks func;
        int mask;
        unsigned long fsmagic;
 -      uid_t uid;
 -      uid_t fowner;
 +      kuid_t uid;
++      kuid_t fowner;
        struct {
                void *rule;     /* LSM file metadata specific */
                int type;       /* audit type */
@@@ -48,7 -55,7 +55,7 @@@
  
  /*
   * Without LSM specific knowledge, the default policy can only be
-  * written in terms of .action, .func, .mask, .fsmagic, and .uid
+  * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
   */
  
  /*
@@@ -57,7 -64,7 +64,7 @@@
   * normal users can easily run the machine out of memory simply building
   * and running executables.
   */
- static struct ima_measure_rule_entry default_rules[] = {
+ static struct ima_rule_entry default_rules[] = {
        {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
         .flags = IMA_FUNC | IMA_MASK},
        {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
         .flags = IMA_FUNC | IMA_MASK},
 -      {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0,
 +      {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID,
         .flags = IMA_FUNC | IMA_MASK | IMA_UID},
  };
  
- static LIST_HEAD(measure_default_rules);
- static LIST_HEAD(measure_policy_rules);
- static struct list_head *ima_measure;
+ static struct ima_rule_entry default_appraise_rules[] = {
+       {.action = DONT_APPRAISE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = CGROUP_SUPER_MAGIC,.flags = IMA_FSMAGIC},
 -      {.action = APPRAISE,.fowner = 0,.flags = IMA_FOWNER},
++      {.action = APPRAISE,.fowner = GLOBAL_ROOT_UID,.flags = IMA_FOWNER},
+ };
+ static LIST_HEAD(ima_default_rules);
+ static LIST_HEAD(ima_policy_rules);
+ static struct list_head *ima_rules;
  
- static DEFINE_MUTEX(ima_measure_mutex);
+ static DEFINE_MUTEX(ima_rules_mutex);
  
  static bool ima_use_tcb __initdata;
- static int __init default_policy_setup(char *str)
+ static int __init default_measure_policy_setup(char *str)
  {
        ima_use_tcb = 1;
        return 1;
  }
- __setup("ima_tcb", default_policy_setup);
+ __setup("ima_tcb", default_measure_policy_setup);
+ static bool ima_use_appraise_tcb __initdata;
+ static int __init default_appraise_policy_setup(char *str)
+ {
+       ima_use_appraise_tcb = 1;
+       return 1;
+ }
+ __setup("ima_appraise_tcb", default_appraise_policy_setup);
  
  /**
   * ima_match_rules - determine whether an inode matches the measure rule.
   *
   * Returns true on rule match, false on failure.
   */
- static bool ima_match_rules(struct ima_measure_rule_entry *rule,
+ static bool ima_match_rules(struct ima_rule_entry *rule,
                            struct inode *inode, enum ima_hooks func, int mask)
  {
        struct task_struct *tsk = current;
        if ((rule->flags & IMA_FSMAGIC)
            && rule->fsmagic != inode->i_sb->s_magic)
                return false;
 -      if ((rule->flags & IMA_UID) && rule->uid != cred->uid)
 +      if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
                return false;
 -      if ((rule->flags & IMA_FOWNER) && rule->fowner != inode->i_uid)
++      if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
+               return false;
        for (i = 0; i < MAX_LSM_RULES; i++) {
                int rc = 0;
                u32 osid, sid;
   * as elements in the list are never deleted, nor does the list
   * change.)
   */
- int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
+ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
+                    int flags)
  {
-       struct ima_measure_rule_entry *entry;
+       struct ima_rule_entry *entry;
+       int action = 0, actmask = flags | (flags << 1);
+       list_for_each_entry(entry, ima_rules, list) {
+               if (!(entry->action & actmask))
+                       continue;
+               if (!ima_match_rules(entry, inode, func, mask))
+                       continue;
  
-       list_for_each_entry(entry, ima_measure, list) {
-               bool rc;
+               action |= entry->action & IMA_DO_MASK;
+               if (entry->action & IMA_DO_MASK)
+                       actmask &= ~(entry->action | entry->action << 1);
+               else
+                       actmask &= ~(entry->action | entry->action >> 1);
  
-               rc = ima_match_rules(entry, inode, func, mask);
-               if (rc)
-                       return entry->action;
+               if (!actmask)
+                       break;
        }
-       return 0;
+       return action;
  }
  
  /**
   * ima_init_policy - initialize the default measure rules.
   *
-  * ima_measure points to either the measure_default_rules or the
-  * the new measure_policy_rules.
+  * ima_rules points to either the ima_default_rules or the
+  * the new ima_policy_rules.
   */
  void __init ima_init_policy(void)
  {
-       int i, entries;
+       int i, measure_entries, appraise_entries;
  
        /* if !ima_use_tcb set entries = 0 so we load NO default rules */
-       if (ima_use_tcb)
-               entries = ARRAY_SIZE(default_rules);
-       else
-               entries = 0;
-       for (i = 0; i < entries; i++)
-               list_add_tail(&default_rules[i].list, &measure_default_rules);
-       ima_measure = &measure_default_rules;
+       measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
+       appraise_entries = ima_use_appraise_tcb ?
+                        ARRAY_SIZE(default_appraise_rules) : 0;
+       
+       for (i = 0; i < measure_entries + appraise_entries; i++) {
+               if (i < measure_entries)
+                       list_add_tail(&default_rules[i].list,
+                                     &ima_default_rules);
+               else {
+                       int j = i - measure_entries;
+                       list_add_tail(&default_appraise_rules[j].list,
+                                     &ima_default_rules);
+               }
+       }
+       ima_rules = &ima_default_rules;
  }
  
  /**
@@@ -212,8 -265,8 +265,8 @@@ void ima_update_policy(void
        int result = 1;
        int audit_info = 0;
  
-       if (ima_measure == &measure_default_rules) {
-               ima_measure = &measure_policy_rules;
+       if (ima_rules == &ima_default_rules) {
+               ima_rules = &ima_policy_rules;
                cause = "complete";
                result = 0;
        }
  enum {
        Opt_err = -1,
        Opt_measure = 1, Opt_dont_measure,
+       Opt_appraise, Opt_dont_appraise,
+       Opt_audit,
        Opt_obj_user, Opt_obj_role, Opt_obj_type,
        Opt_subj_user, Opt_subj_role, Opt_subj_type,
-       Opt_func, Opt_mask, Opt_fsmagic, Opt_uid
+       Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner
  };
  
  static match_table_t policy_tokens = {
        {Opt_measure, "measure"},
        {Opt_dont_measure, "dont_measure"},
+       {Opt_appraise, "appraise"},
+       {Opt_dont_appraise, "dont_appraise"},
+       {Opt_audit, "audit"},
        {Opt_obj_user, "obj_user=%s"},
        {Opt_obj_role, "obj_role=%s"},
        {Opt_obj_type, "obj_type=%s"},
        {Opt_mask, "mask=%s"},
        {Opt_fsmagic, "fsmagic=%s"},
        {Opt_uid, "uid=%s"},
+       {Opt_fowner, "fowner=%s"},
        {Opt_err, NULL}
  };
  
- static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
+ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
                             char *args, int lsm_rule, int audit_type)
  {
        int result;
@@@ -269,7 -328,7 +328,7 @@@ static void ima_log_string(struct audit
        audit_log_format(ab, " ");
  }
  
- static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
+ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
  {
        struct audit_buffer *ab;
        char *p;
  
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
  
 -      entry->uid = -1;
 -      entry->fowner = -1;
 +      entry->uid = INVALID_UID;
++      entry->fowner = INVALID_UID;
        entry->action = UNKNOWN;
        while ((p = strsep(&rule, " \t")) != NULL) {
                substring_t args[MAX_OPT_ARGS];
  
                        entry->action = DONT_MEASURE;
                        break;
+               case Opt_appraise:
+                       ima_log_string(ab, "action", "appraise");
+                       if (entry->action != UNKNOWN)
+                               result = -EINVAL;
+                       entry->action = APPRAISE;
+                       break;
+               case Opt_dont_appraise:
+                       ima_log_string(ab, "action", "dont_appraise");
+                       if (entry->action != UNKNOWN)
+                               result = -EINVAL;
+                       entry->action = DONT_APPRAISE;
+                       break;
+               case Opt_audit:
+                       ima_log_string(ab, "action", "audit");
+                       if (entry->action != UNKNOWN)
+                               result = -EINVAL;
+                       entry->action = AUDIT;
+                       break;
                case Opt_func:
                        ima_log_string(ab, "func", args[0].from);
  
                        if (entry->func)
-                               result  = -EINVAL;
+                               result = -EINVAL;
  
                        if (strcmp(args[0].from, "FILE_CHECK") == 0)
                                entry->func = FILE_CHECK;
                case Opt_uid:
                        ima_log_string(ab, "uid", args[0].from);
  
 -                      if (entry->uid != -1) {
 +                      if (uid_valid(entry->uid)) {
                                result = -EINVAL;
                                break;
                        }
  
                        result = strict_strtoul(args[0].from, 10, &lnum);
                        if (!result) {
 -                              entry->uid = (uid_t) lnum;
 -                              if (entry->uid != lnum)
 +                              entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
 +                              if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
                                        result = -EINVAL;
                                else
                                        entry->flags |= IMA_UID;
                        }
                        break;
 -                      if (entry->fowner != -1) {
+               case Opt_fowner:
+                       ima_log_string(ab, "fowner", args[0].from);
 -                              entry->fowner = (uid_t) lnum;
 -                              if (entry->fowner != lnum)
++                      if (uid_valid(entry->fowner)) {
+                               result = -EINVAL;
+                               break;
+                       }
+                       result = strict_strtoul(args[0].from, 10, &lnum);
+                       if (!result) {
++                              entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
++                              if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
+                                       result = -EINVAL;
+                               else
+                                       entry->flags |= IMA_FOWNER;
+                       }
+                       break;
                case Opt_obj_user:
                        ima_log_string(ab, "obj_user", args[0].from);
                        result = ima_lsm_rule_init(entry, args[0].from,
  }
  
  /**
-  * ima_parse_add_rule - add a rule to measure_policy_rules
+  * ima_parse_add_rule - add a rule to ima_policy_rules
   * @rule - ima measurement policy rule
   *
   * Uses a mutex to protect the policy list from multiple concurrent writers.
@@@ -436,12 -537,12 +537,12 @@@ ssize_t ima_parse_add_rule(char *rule
  {
        const char *op = "update_policy";
        char *p;
-       struct ima_measure_rule_entry *entry;
+       struct ima_rule_entry *entry;
        ssize_t result, len;
        int audit_info = 0;
  
        /* Prevent installed policy from changing */
-       if (ima_measure != &measure_default_rules) {
+       if (ima_rules != &ima_default_rules) {
                integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
                                    NULL, op, "already exists",
                                    -EACCES, audit_info);
                return result;
        }
  
-       mutex_lock(&ima_measure_mutex);
-       list_add_tail(&entry->list, &measure_policy_rules);
-       mutex_unlock(&ima_measure_mutex);
+       mutex_lock(&ima_rules_mutex);
+       list_add_tail(&entry->list, &ima_policy_rules);
+       mutex_unlock(&ima_rules_mutex);
  
        return len;
  }
  /* ima_delete_rules called to cleanup invalid policy */
  void ima_delete_rules(void)
  {
-       struct ima_measure_rule_entry *entry, *tmp;
+       struct ima_rule_entry *entry, *tmp;
  
-       mutex_lock(&ima_measure_mutex);
-       list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) {
+       mutex_lock(&ima_rules_mutex);
+       list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
                list_del(&entry->list);
                kfree(entry);
        }
-       mutex_unlock(&ima_measure_mutex);
+       mutex_unlock(&ima_rules_mutex);
  }
diff --combined security/security.c
index f9a2f2ef2454d3f2d30c1056f5cc930d189cad1b,d23b43522a5a3206d87a663175550b9acea7e777..3724029d0f6dd4407a46ff7e4fff23e05f47d445
@@@ -136,11 -136,23 +136,23 @@@ int __init register_security(struct sec
  
  int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
  {
+ #ifdef CONFIG_SECURITY_YAMA_STACKED
+       int rc;
+       rc = yama_ptrace_access_check(child, mode);
+       if (rc)
+               return rc;
+ #endif
        return security_ops->ptrace_access_check(child, mode);
  }
  
  int security_ptrace_traceme(struct task_struct *parent)
  {
+ #ifdef CONFIG_SECURITY_YAMA_STACKED
+       int rc;
+       rc = yama_ptrace_traceme(parent);
+       if (rc)
+               return rc;
+ #endif
        return security_ops->ptrace_traceme(parent);
  }
  
@@@ -434,7 -446,7 +446,7 @@@ int security_path_chmod(struct path *pa
        return security_ops->path_chmod(path, mode);
  }
  
 -int security_path_chown(struct path *path, uid_t uid, gid_t gid)
 +int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
  {
        if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
                return 0;
@@@ -559,6 -571,9 +571,9 @@@ int security_inode_setxattr(struct dent
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
        ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
+       if (ret)
+               return ret;
+       ret = ima_inode_setxattr(dentry, name, value, size);
        if (ret)
                return ret;
        return evm_inode_setxattr(dentry, name, value, size);
@@@ -594,6 -609,9 +609,9 @@@ int security_inode_removexattr(struct d
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
        ret = security_ops->inode_removexattr(dentry, name);
+       if (ret)
+               return ret;
+       ret = ima_inode_removexattr(dentry, name);
        if (ret)
                return ret;
        return evm_inode_removexattr(dentry, name);
@@@ -761,6 -779,9 +779,9 @@@ int security_task_create(unsigned long 
  
  void security_task_free(struct task_struct *task)
  {
+ #ifdef CONFIG_SECURITY_YAMA_STACKED
+       yama_task_free(task);
+ #endif
        security_ops->task_free(task);
  }
  
@@@ -876,6 -897,12 +897,12 @@@ int security_task_wait(struct task_stru
  int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                         unsigned long arg4, unsigned long arg5)
  {
+ #ifdef CONFIG_SECURITY_YAMA_STACKED
+       int rc;
+       rc = yama_task_prctl(option, arg2, arg3, arg4, arg5);
+       if (rc != -ENOSYS)
+               return rc;
+ #endif
        return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
  }