]> Git Repo - linux.git/commitdiff
Merge tag 'lsm-pr-20240312' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm
authorLinus Torvalds <[email protected]>
Wed, 13 Mar 2024 03:03:34 +0000 (20:03 -0700)
committerLinus Torvalds <[email protected]>
Wed, 13 Mar 2024 03:03:34 +0000 (20:03 -0700)
Pull lsm updates from Paul Moore:

 - Promote IMA/EVM to a proper LSM

   This is the bulk of the diffstat, and the source of all the changes
   in the VFS code. Prior to the start of the LSM stacking work it was
   important that IMA/EVM were separate from the rest of the LSMs,
   complete with their own hooks, infrastructure, etc. as it was the
   only way to enable IMA/EVM at the same time as a LSM.

   However, now that the bulk of the LSM infrastructure supports
   multiple simultaneous LSMs, we can simplify things greatly by
   bringing IMA/EVM into the LSM infrastructure as proper LSMs. This is
   something I've wanted to see happen for quite some time and Roberto
   was kind enough to put in the work to make it happen.

 - Use the LSM hook default values to simplify the call_int_hook() macro

   Previously the call_int_hook() macro required callers to supply a
   default return value, despite a default value being specified when
   the LSM hook was defined.

   This simplifies the macro by using the defined default return value
   which makes life easier for callers and should also reduce the number
   of return value bugs in the future (we've had a few pop up recently,
   hence this work).

 - Use the KMEM_CACHE() macro instead of kmem_cache_create()

   The guidance appears to be to use the KMEM_CACHE() macro when
   possible and there is no reason why we can't use the macro, so let's
   use it.

 - Fix a number of comment typos in the LSM hook comment blocks

   Not much to say here, we fixed some questionable grammar decisions in
   the LSM hook comment blocks.

* tag 'lsm-pr-20240312' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm: (28 commits)
  cred: Use KMEM_CACHE() instead of kmem_cache_create()
  lsm: use default hook return value in call_int_hook()
  lsm: fix typos in security/security.c comment headers
  integrity: Remove LSM
  ima: Make it independent from 'integrity' LSM
  evm: Make it independent from 'integrity' LSM
  evm: Move to LSM infrastructure
  ima: Move IMA-Appraisal to LSM infrastructure
  ima: Move to LSM infrastructure
  integrity: Move integrity_kernel_module_request() to IMA
  security: Introduce key_post_create_or_update hook
  security: Introduce inode_post_remove_acl hook
  security: Introduce inode_post_set_acl hook
  security: Introduce inode_post_create_tmpfile hook
  security: Introduce path_post_mknod hook
  security: Introduce file_release hook
  security: Introduce file_post_open hook
  security: Introduce inode_post_removexattr hook
  security: Introduce inode_post_setattr hook
  security: Align inode_setattr hook definition with EVM
  ...

1  2 
fs/attr.c
fs/file_table.c
fs/namei.c
fs/nfsd/vfs.c
fs/open.c
fs/posix_acl.c
include/linux/lsm_hook_defs.h
include/linux/security.h
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c

diff --combined fs/attr.c
index 49d23b5dbab4b971bb8756c3fca360c5618cc2c3,4d0d759531079b709493227f071938ba6e83d6af..960a310581ebb9e00d77b323ad812a2fc34ada1b
+++ b/fs/attr.c
@@@ -16,8 -16,6 +16,6 @@@
  #include <linux/fcntl.h>
  #include <linux/filelock.h>
  #include <linux/security.h>
- #include <linux/evm.h>
- #include <linux/ima.h>
  
  #include "internal.h"
  
@@@ -352,7 -350,7 +350,7 @@@ int may_setattr(struct mnt_idmap *idmap
  EXPORT_SYMBOL(may_setattr);
  
  /**
 - * notify_change - modify attributes of a filesytem object
 + * notify_change - modify attributes of a filesystem object
   * @idmap:    idmap of the mount the inode was found from
   * @dentry:   object affected
   * @attr:     new attributes
@@@ -502,8 -500,7 +500,7 @@@ int notify_change(struct mnt_idmap *idm
  
        if (!error) {
                fsnotify_change(dentry, ia_valid);
-               ima_inode_post_setattr(idmap, dentry);
-               evm_inode_post_setattr(dentry, ia_valid);
+               security_inode_post_setattr(idmap, dentry, ia_valid);
        }
  
        return error;
diff --combined fs/file_table.c
index 6925522faa0ae53cb9105eaaed56c6a7fcdb305a,1a0962981b48abc4b03de4e825c26da5022d1126..4f03beed47379d7bb60ca18231e8742c8182b391
@@@ -26,7 -26,6 +26,6 @@@
  #include <linux/percpu_counter.h>
  #include <linux/percpu.h>
  #include <linux/task_work.h>
- #include <linux/ima.h>
  #include <linux/swap.h>
  #include <linux/kmemleak.h>
  
@@@ -276,15 -275,21 +275,15 @@@ struct file *alloc_empty_backing_file(i
  }
  
  /**
 - * alloc_file - allocate and initialize a 'struct file'
 + * file_init_path - initialize a 'struct file' based on path
   *
 + * @file: the file to set up
   * @path: the (dentry, vfsmount) pair for the new file
 - * @flags: O_... flags with which the new file will be opened
   * @fop: the 'struct file_operations' for the new file
   */
 -static struct file *alloc_file(const struct path *path, int flags,
 -              const struct file_operations *fop)
 +static void file_init_path(struct file *file, const struct path *path,
 +                         const struct file_operations *fop)
  {
 -      struct file *file;
 -
 -      file = alloc_empty_file(flags, current_cred());
 -      if (IS_ERR(file))
 -              return file;
 -
        file->f_path = *path;
        file->f_inode = path->dentry->d_inode;
        file->f_mapping = path->dentry->d_inode->i_mapping;
        file->f_op = fop;
        if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
                i_readcount_inc(path->dentry->d_inode);
 +}
 +
 +/**
 + * alloc_file - allocate and initialize a 'struct file'
 + *
 + * @path: the (dentry, vfsmount) pair for the new file
 + * @flags: O_... flags with which the new file will be opened
 + * @fop: the 'struct file_operations' for the new file
 + */
 +static struct file *alloc_file(const struct path *path, int flags,
 +              const struct file_operations *fop)
 +{
 +      struct file *file;
 +
 +      file = alloc_empty_file(flags, current_cred());
 +      if (!IS_ERR(file))
 +              file_init_path(file, path, fop);
        return file;
  }
  
 -struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
 -                              const char *name, int flags,
 -                              const struct file_operations *fops)
 +static inline int alloc_path_pseudo(const char *name, struct inode *inode,
 +                                  struct vfsmount *mnt, struct path *path)
  {
        struct qstr this = QSTR_INIT(name, strlen(name));
 +
 +      path->dentry = d_alloc_pseudo(mnt->mnt_sb, &this);
 +      if (!path->dentry)
 +              return -ENOMEM;
 +      path->mnt = mntget(mnt);
 +      d_instantiate(path->dentry, inode);
 +      return 0;
 +}
 +
 +struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
 +                             const char *name, int flags,
 +                             const struct file_operations *fops)
 +{
 +      int ret;
        struct path path;
        struct file *file;
  
 -      path.dentry = d_alloc_pseudo(mnt->mnt_sb, &this);
 -      if (!path.dentry)
 -              return ERR_PTR(-ENOMEM);
 -      path.mnt = mntget(mnt);
 -      d_instantiate(path.dentry, inode);
 +      ret = alloc_path_pseudo(name, inode, mnt, &path);
 +      if (ret)
 +              return ERR_PTR(ret);
 +
        file = alloc_file(&path, flags, fops);
        if (IS_ERR(file)) {
                ihold(inode);
  }
  EXPORT_SYMBOL(alloc_file_pseudo);
  
 +struct file *alloc_file_pseudo_noaccount(struct inode *inode,
 +                                       struct vfsmount *mnt, const char *name,
 +                                       int flags,
 +                                       const struct file_operations *fops)
 +{
 +      int ret;
 +      struct path path;
 +      struct file *file;
 +
 +      ret = alloc_path_pseudo(name, inode, mnt, &path);
 +      if (ret)
 +              return ERR_PTR(ret);
 +
 +      file = alloc_empty_file_noaccount(flags, current_cred());
 +      if (IS_ERR(file)) {
 +              ihold(inode);
 +              path_put(&path);
 +              return file;
 +      }
 +      file_init_path(file, &path, fops);
 +      return file;
 +}
 +EXPORT_SYMBOL_GPL(alloc_file_pseudo_noaccount);
 +
  struct file *alloc_file_clone(struct file *base, int flags,
                                const struct file_operations *fops)
  {
@@@ -414,7 -366,7 +413,7 @@@ static void __fput(struct file *file
        eventpoll_release(file);
        locks_remove_file(file);
  
-       ima_file_free(file);
+       security_file_release(file);
        if (unlikely(file->f_flags & FASYNC)) {
                if (file->f_op->fasync)
                        file->f_op->fasync(-1, file, 0);
diff --combined fs/namei.c
index 97952440277b36fa365dca992f30f7b886462f09,1bf7435cdf76b8374284060e0d222ff52d58d33d..ceb9ddf8dfdd4e3d8b711ab655bc928eeb3b3e50
@@@ -17,8 -17,8 +17,8 @@@
  
  #include <linux/init.h>
  #include <linux/export.h>
 -#include <linux/kernel.h>
  #include <linux/slab.h>
 +#include <linux/wordpart.h>
  #include <linux/fs.h>
  #include <linux/filelock.h>
  #include <linux/namei.h>
@@@ -27,7 -27,6 +27,6 @@@
  #include <linux/fsnotify.h>
  #include <linux/personality.h>
  #include <linux/security.h>
- #include <linux/ima.h>
  #include <linux/syscalls.h>
  #include <linux/mount.h>
  #include <linux/audit.h>
@@@ -1717,11 -1716,7 +1716,11 @@@ static inline int may_lookup(struct mnt
  {
        if (nd->flags & LOOKUP_RCU) {
                int err = inode_permission(idmap, nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
 -              if (err != -ECHILD || !try_to_unlazy(nd))
 +              if (!err)               // success, keep going
 +                      return 0;
 +              if (!try_to_unlazy(nd))
 +                      return -ECHILD; // redo it all non-lazy
 +              if (err != -ECHILD)     // hard error
                        return err;
        }
        return inode_permission(idmap, nd->inode, MAY_EXEC);
@@@ -2680,8 -2675,10 +2679,8 @@@ static int lookup_one_common(struct mnt
        if (!len)
                return -EACCES;
  
 -      if (unlikely(name[0] == '.')) {
 -              if (len < 2 || (len == 2 && name[1] == '.'))
 -                      return -EACCES;
 -      }
 +      if (is_dot_dotdot(name, len))
 +              return -EACCES;
  
        while (len--) {
                unsigned int c = *(const unsigned char *)name++;
@@@ -3642,7 -3639,7 +3641,7 @@@ static int do_open(struct nameidata *nd
        if (!error && !(file->f_mode & FMODE_OPENED))
                error = vfs_open(&nd->path, file);
        if (!error)
-               error = ima_file_check(file, op->acc_mode);
+               error = security_file_post_open(file, op->acc_mode);
        if (!error && do_truncate)
                error = handle_truncate(idmap, file);
        if (unlikely(error > 0)) {
@@@ -3705,7 -3702,7 +3704,7 @@@ static int vfs_tmpfile(struct mnt_idma
                inode->i_state |= I_LINKABLE;
                spin_unlock(&inode->i_lock);
        }
-       ima_post_create_tmpfile(idmap, inode);
+       security_inode_post_create_tmpfile(idmap, inode);
        return 0;
  }
  
@@@ -4051,8 -4048,6 +4050,6 @@@ retry
                case 0: case S_IFREG:
                        error = vfs_create(idmap, path.dentry->d_inode,
                                           dentry, mode, true);
-                       if (!error)
-                               ima_post_path_mknod(idmap, dentry);
                        break;
                case S_IFCHR: case S_IFBLK:
                        error = vfs_mknod(idmap, path.dentry->d_inode,
                                          dentry, mode, 0);
                        break;
        }
+       if (error)
+               goto out2;
+       security_path_post_mknod(idmap, dentry);
  out2:
        done_path_create(&path, dentry);
        if (retry_estale(error, lookup_flags)) {
diff --combined fs/nfsd/vfs.c
index 6a4c506038e00d3903908adb22737a3d97a8467f,4349dde921542bd0a68f7247c4cd353a096e10b3..6a9464262fae6bea461c4764ce98c53ca20f9754
@@@ -25,7 -25,6 +25,6 @@@
  #include <linux/posix_acl_xattr.h>
  #include <linux/xattr.h>
  #include <linux/jhash.h>
- #include <linux/ima.h>
  #include <linux/pagemap.h>
  #include <linux/slab.h>
  #include <linux/uaccess.h>
@@@ -476,6 -475,7 +475,6 @@@ static int __nfsd_setattr(struct dentr
   * @rqstp: controlling RPC transaction
   * @fhp: filehandle of target
   * @attr: attributes to set
 - * @check_guard: set to 1 if guardtime is a valid timestamp
   * @guardtime: do not act if ctime.tv_sec does not match this timestamp
   *
   * This call may adjust the contents of @attr (in particular, this
   */
  __be32
  nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
 -           struct nfsd_attrs *attr,
 -           int check_guard, time64_t guardtime)
 +           struct nfsd_attrs *attr, const struct timespec64 *guardtime)
  {
        struct dentry   *dentry;
        struct inode    *inode;
        int             accmode = NFSD_MAY_SATTR;
        umode_t         ftype = 0;
        __be32          err;
 -      int             host_err;
 +      int             host_err = 0;
        bool            get_write_count;
        bool            size_change = (iap->ia_valid & ATTR_SIZE);
        int             retries;
  
        nfsd_sanitize_attrs(inode, iap);
  
 -      if (check_guard && guardtime != inode_get_ctime_sec(inode))
 -              return nfserr_notsync;
 -
        /*
         * The size case is special, it changes the file in addition to the
         * attributes, and file systems don't expect it to be mixed with
        }
  
        inode_lock(inode);
 +      err = fh_fill_pre_attrs(fhp);
 +      if (err)
 +              goto out_unlock;
 +
 +      if (guardtime) {
 +              struct timespec64 ctime = inode_get_ctime(inode);
 +              if ((u32)guardtime->tv_sec != (u32)ctime.tv_sec ||
 +                  guardtime->tv_nsec != ctime.tv_nsec) {
 +                      err = nfserr_notsync;
 +                      goto out_fill_attrs;
 +              }
 +      }
 +
        for (retries = 1;;) {
                struct iattr attrs;
  
                attr->na_aclerr = set_posix_acl(&nop_mnt_idmap,
                                                dentry, ACL_TYPE_DEFAULT,
                                                attr->na_dpacl);
 +out_fill_attrs:
 +      /*
 +       * RFC 1813 Section 3.3.2 does not mandate that an NFS server
 +       * returns wcc_data for SETATTR. Some client implementations
 +       * depend on receiving wcc_data, however, to sort out partial
 +       * updates (eg., the client requested that size and mode be
 +       * modified, but the server changed only the file mode).
 +       */
 +      fh_fill_post_attrs(fhp);
 +out_unlock:
        inode_unlock(inode);
        if (size_change)
                put_write_access(inode);
  out:
        if (!host_err)
                host_err = commit_metadata(fhp);
 -      return nfserrno(host_err);
 +      return err != 0 ? err : nfserrno(host_err);
  }
  
  #if defined(CONFIG_NFSD_V4)
@@@ -895,7 -876,7 +894,7 @@@ __nfsd_open(struct svc_rqst *rqstp, str
                goto out;
        }
  
-       host_err = ima_file_check(file, may_flags);
+       host_err = security_file_post_open(file, may_flags);
        if (host_err) {
                fput(file);
                goto out;
@@@ -1020,9 -1001,7 +1019,9 @@@ static __be32 nfsd_finish_read(struct s
                               unsigned long *count, u32 *eof, ssize_t host_err)
  {
        if (host_err >= 0) {
 -              nfsd_stats_io_read_add(fhp->fh_export, host_err);
 +              struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 +
 +              nfsd_stats_io_read_add(nn, fhp->fh_export, host_err);
                *eof = nfsd_eof_on_read(file, offset, host_err, *count);
                *count = host_err;
                fsnotify_access(file);
@@@ -1205,7 -1184,7 +1204,7 @@@ nfsd_vfs_write(struct svc_rqst *rqstp, 
                goto out_nfserr;
        }
        *cnt = host_err;
 -      nfsd_stats_io_write_add(exp, *cnt);
 +      nfsd_stats_io_write_add(nn, exp, *cnt);
        fsnotify_modify(file);
        host_err = filemap_check_wb_err(file->f_mapping, since);
        if (host_err < 0)
@@@ -1424,7 -1403,7 +1423,7 @@@ nfsd_create_setattr(struct svc_rqst *rq
         * if the attributes have not changed.
         */
        if (iap->ia_valid)
 -              status = nfsd_setattr(rqstp, resfhp, attrs, 0, (time64_t)0);
 +              status = nfsd_setattr(rqstp, resfhp, attrs, NULL);
        else
                status = nfserrno(commit_metadata(resfhp));
  
@@@ -1926,10 -1905,10 +1925,10 @@@ out_unlock
        fh_drop_write(ffhp);
  
        /*
 -       * If the target dentry has cached open files, then we need to try to
 -       * close them prior to doing the rename. Flushing delayed fput
 -       * shouldn't be done with locks held however, so we delay it until this
 -       * point and then reattempt the whole shebang.
 +       * If the target dentry has cached open files, then we need to
 +       * try to close them prior to doing the rename.  Final fput
 +       * shouldn't be done with locks held however, so we delay it
 +       * until this point and then reattempt the whole shebang.
         */
        if (close_cached) {
                close_cached = false;
@@@ -2197,43 -2176,11 +2196,43 @@@ nfsd_readdir(struct svc_rqst *rqstp, st
        if (err == nfserr_eof || err == nfserr_toosmall)
                err = nfs_ok; /* can still be found in ->err */
  out_close:
 -      fput(file);
 +      nfsd_filp_close(file);
  out:
        return err;
  }
  
 +/**
 + * nfsd_filp_close: close a file synchronously
 + * @fp: the file to close
 + *
 + * nfsd_filp_close() is similar in behaviour to filp_close().
 + * The difference is that if this is the final close on the
 + * file, the that finalisation happens immediately, rather then
 + * being handed over to a work_queue, as it the case for
 + * filp_close().
 + * When a user-space process closes a file (even when using
 + * filp_close() the finalisation happens before returning to
 + * userspace, so it is effectively synchronous.  When a kernel thread
 + * uses file_close(), on the other hand, the handling is completely
 + * asynchronous.  This means that any cost imposed by that finalisation
 + * is not imposed on the nfsd thread, and nfsd could potentually
 + * close files more quickly than the work queue finalises the close,
 + * which would lead to unbounded growth in the queue.
 + *
 + * In some contexts is it not safe to synchronously wait for
 + * close finalisation (see comment for __fput_sync()), but nfsd
 + * does not match those contexts.  In partcilarly it does not, at the
 + * time that this function is called, hold and locks and no finalisation
 + * of any file, socket, or device driver would have any cause to wait
 + * for nfsd to make progress.
 + */
 +void nfsd_filp_close(struct file *fp)
 +{
 +      get_file(fp);
 +      filp_close(fp, NULL);
 +      __fput_sync(fp);
 +}
 +
  /*
   * Get file system stats
   * N.B. After this call fhp needs an fh_put
diff --combined fs/open.c
index a7d4bb2c725f1e9bdde176f769c3a52df0627ab9,1cf05a1413aae04f88e827e9b64fd6c4fee68e18..ee8460c83c779d86a6ed478bcabda88d19b6e977
+++ b/fs/open.c
@@@ -29,7 -29,6 +29,6 @@@
  #include <linux/audit.h>
  #include <linux/falloc.h>
  #include <linux/fs_struct.h>
- #include <linux/ima.h>
  #include <linux/dnotify.h>
  #include <linux/compat.h>
  #include <linux/mnt_idmapping.h>
@@@ -154,52 -153,49 +153,52 @@@ COMPAT_SYSCALL_DEFINE2(truncate, const 
  }
  #endif
  
 -long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
 +long do_ftruncate(struct file *file, loff_t length, int small)
  {
        struct inode *inode;
        struct dentry *dentry;
 -      struct fd f;
        int error;
  
 -      error = -EINVAL;
 -      if (length < 0)
 -              goto out;
 -      error = -EBADF;
 -      f = fdget(fd);
 -      if (!f.file)
 -              goto out;
 -
        /* explicitly opened as large or we are on 64-bit box */
 -      if (f.file->f_flags & O_LARGEFILE)
 +      if (file->f_flags & O_LARGEFILE)
                small = 0;
  
 -      dentry = f.file->f_path.dentry;
 +      dentry = file->f_path.dentry;
        inode = dentry->d_inode;
 -      error = -EINVAL;
 -      if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
 -              goto out_putf;
 +      if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
 +              return -EINVAL;
  
 -      error = -EINVAL;
        /* Cannot ftruncate over 2^31 bytes without large file support */
        if (small && length > MAX_NON_LFS)
 -              goto out_putf;
 +              return -EINVAL;
  
 -      error = -EPERM;
        /* Check IS_APPEND on real upper inode */
 -      if (IS_APPEND(file_inode(f.file)))
 -              goto out_putf;
 +      if (IS_APPEND(file_inode(file)))
 +              return -EPERM;
        sb_start_write(inode->i_sb);
 -      error = security_file_truncate(f.file);
 +      error = security_file_truncate(file);
        if (!error)
 -              error = do_truncate(file_mnt_idmap(f.file), dentry, length,
 -                                  ATTR_MTIME | ATTR_CTIME, f.file);
 +              error = do_truncate(file_mnt_idmap(file), dentry, length,
 +                                  ATTR_MTIME | ATTR_CTIME, file);
        sb_end_write(inode->i_sb);
 -out_putf:
 +
 +      return error;
 +}
 +
 +long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
 +{
 +      struct fd f;
 +      int error;
 +
 +      if (length < 0)
 +              return -EINVAL;
 +      f = fdget(fd);
 +      if (!f.file)
 +              return -EBADF;
 +
 +      error = do_ftruncate(f.file, length, small);
 +
        fdput(f);
 -out:
        return error;
  }
  
@@@ -1367,7 -1363,7 +1366,7 @@@ struct file *filp_open(const char *file
  {
        struct filename *name = getname_kernel(filename);
        struct file *file = ERR_CAST(name);
 -      
 +
        if (!IS_ERR(name)) {
                file = file_open_name(name, flags, mode);
                putname(name);
diff --combined fs/posix_acl.c
index 6bf587d1a9b873ca708ac598a70b8e6fea6bc469,5c90239e3f2b0115e07c32c89c8c475529c4c334..3f87297dbfdb70ea00c1bac533eacada58535be0
@@@ -26,7 -26,6 +26,6 @@@
  #include <linux/mnt_idmapping.h>
  #include <linux/iversion.h>
  #include <linux/security.h>
- #include <linux/evm.h>
  #include <linux/fsnotify.h>
  #include <linux/filelock.h>
  
@@@ -786,12 -785,12 +785,12 @@@ struct posix_acl *posix_acl_from_xattr(
                return ERR_PTR(count);
        if (count == 0)
                return NULL;
 -      
 +
        acl = posix_acl_alloc(count, GFP_NOFS);
        if (!acl)
                return ERR_PTR(-ENOMEM);
        acl_e = acl->a_entries;
 -      
 +
        for (end = entry + count; entry != end; acl_e++, entry++) {
                acl_e->e_tag  = le16_to_cpu(entry->e_tag);
                acl_e->e_perm = le16_to_cpu(entry->e_perm);
@@@ -1137,7 -1136,7 +1136,7 @@@ retry_deleg
                error = -EIO;
        if (!error) {
                fsnotify_xattr(dentry);
-               evm_inode_post_set_acl(dentry, acl_name, kacl);
+               security_inode_post_set_acl(dentry, acl_name, kacl);
        }
  
  out_inode_unlock:
@@@ -1245,7 -1244,7 +1244,7 @@@ retry_deleg
                error = -EIO;
        if (!error) {
                fsnotify_xattr(dentry);
-               evm_inode_post_remove_acl(idmap, dentry, acl_name);
+               security_inode_post_remove_acl(idmap, dentry, acl_name);
        }
  
  out_inode_unlock:
index 642272576582e9133516d233b77ba82ccbff19cf,7e4683035d348f389e19a1a3cf7a49f6052aa84e..a8057a3f8de61959838b5ac0bafd5975cdf475e5
@@@ -94,6 -94,8 +94,8 @@@ LSM_HOOK(int, 0, path_mkdir, const stru
  LSM_HOOK(int, 0, path_rmdir, const struct path *dir, struct dentry *dentry)
  LSM_HOOK(int, 0, path_mknod, const struct path *dir, struct dentry *dentry,
         umode_t mode, unsigned int dev)
+ LSM_HOOK(void, LSM_RET_VOID, path_post_mknod, struct mnt_idmap *idmap,
+        struct dentry *dentry)
  LSM_HOOK(int, 0, path_truncate, const struct path *path)
  LSM_HOOK(int, 0, path_symlink, const struct path *dir, struct dentry *dentry,
         const char *old_name)
@@@ -119,6 -121,8 +121,8 @@@ LSM_HOOK(int, 0, inode_init_security_an
         const struct qstr *name, const struct inode *context_inode)
  LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
         umode_t mode)
+ LSM_HOOK(void, LSM_RET_VOID, inode_post_create_tmpfile, struct mnt_idmap *idmap,
+        struct inode *inode)
  LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir,
         struct dentry *new_dentry)
  LSM_HOOK(int, 0, inode_unlink, struct inode *dir, struct dentry *dentry)
@@@ -135,7 -139,10 +139,10 @@@ LSM_HOOK(int, 0, inode_readlink, struc
  LSM_HOOK(int, 0, inode_follow_link, struct dentry *dentry, struct inode *inode,
         bool rcu)
  LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask)
- LSM_HOOK(int, 0, inode_setattr, struct dentry *dentry, struct iattr *attr)
+ LSM_HOOK(int, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *dentry,
+        struct iattr *attr)
+ LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, struct mnt_idmap *idmap,
+        struct dentry *dentry, int ia_valid)
  LSM_HOOK(int, 0, inode_getattr, const struct path *path)
  LSM_HOOK(int, 0, inode_setxattr, struct mnt_idmap *idmap,
         struct dentry *dentry, const char *name, const void *value,
@@@ -146,12 -153,18 +153,18 @@@ LSM_HOOK(int, 0, inode_getxattr, struc
  LSM_HOOK(int, 0, inode_listxattr, struct dentry *dentry)
  LSM_HOOK(int, 0, inode_removexattr, struct mnt_idmap *idmap,
         struct dentry *dentry, const char *name)
+ LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry,
+        const char *name)
  LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap,
         struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)
+ LSM_HOOK(void, LSM_RET_VOID, inode_post_set_acl, struct dentry *dentry,
+        const char *acl_name, struct posix_acl *kacl)
  LSM_HOOK(int, 0, inode_get_acl, struct mnt_idmap *idmap,
         struct dentry *dentry, const char *acl_name)
  LSM_HOOK(int, 0, inode_remove_acl, struct mnt_idmap *idmap,
         struct dentry *dentry, const char *acl_name)
+ LSM_HOOK(void, LSM_RET_VOID, inode_post_remove_acl, struct mnt_idmap *idmap,
+        struct dentry *dentry, const char *acl_name)
  LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry)
  LSM_HOOK(int, 0, inode_killpriv, struct mnt_idmap *idmap,
         struct dentry *dentry)
@@@ -168,6 -181,7 +181,7 @@@ LSM_HOOK(int, 0, kernfs_init_security, 
         struct kernfs_node *kn)
  LSM_HOOK(int, 0, file_permission, struct file *file, int mask)
  LSM_HOOK(int, 0, file_alloc_security, struct file *file)
+ LSM_HOOK(void, LSM_RET_VOID, file_release, struct file *file)
  LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file)
  LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd,
         unsigned long arg)
@@@ -186,6 -200,7 +200,7 @@@ LSM_HOOK(int, 0, file_send_sigiotask, s
         struct fown_struct *fown, int sig)
  LSM_HOOK(int, 0, file_receive, struct file *file)
  LSM_HOOK(int, 0, file_open, struct file *file)
+ LSM_HOOK(int, 0, file_post_open, struct file *file, int mask)
  LSM_HOOK(int, 0, file_truncate, struct file *file)
  LSM_HOOK(int, 0, task_alloc, struct task_struct *task,
         unsigned long clone_flags)
@@@ -390,6 -405,9 +405,9 @@@ LSM_HOOK(void, LSM_RET_VOID, key_free, 
  LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred,
         enum key_need_perm need_perm)
  LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer)
+ LSM_HOOK(void, LSM_RET_VOID, key_post_create_or_update, struct key *keyring,
+        struct key *key, const void *payload, size_t payload_len,
+        unsigned long flags, bool create)
  #endif /* CONFIG_KEYS */
  
  #ifdef CONFIG_AUDIT
@@@ -404,17 -422,10 +422,17 @@@ LSM_HOOK(void, LSM_RET_VOID, audit_rule
  LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size)
  LSM_HOOK(int, 0, bpf_map, struct bpf_map *map, fmode_t fmode)
  LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog)
 -LSM_HOOK(int, 0, bpf_map_alloc_security, struct bpf_map *map)
 -LSM_HOOK(void, LSM_RET_VOID, bpf_map_free_security, struct bpf_map *map)
 -LSM_HOOK(int, 0, bpf_prog_alloc_security, struct bpf_prog_aux *aux)
 -LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free_security, struct bpf_prog_aux *aux)
 +LSM_HOOK(int, 0, bpf_map_create, struct bpf_map *map, union bpf_attr *attr,
 +       struct bpf_token *token)
 +LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map)
 +LSM_HOOK(int, 0, bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr,
 +       struct bpf_token *token)
 +LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog)
 +LSM_HOOK(int, 0, bpf_token_create, struct bpf_token *token, union bpf_attr *attr,
 +       struct path *path)
 +LSM_HOOK(void, LSM_RET_VOID, bpf_token_free, struct bpf_token *token)
 +LSM_HOOK(int, 0, bpf_token_cmd, const struct bpf_token *token, enum bpf_cmd cmd)
 +LSM_HOOK(int, 0, bpf_token_capable, const struct bpf_token *token, int cap)
  #endif /* CONFIG_BPF_SYSCALL */
  
  LSM_HOOK(int, 0, locked_down, enum lockdown_reason what)
diff --combined include/linux/security.h
index 15804af54f37eb7696b6e7306513a3284d53f214,8436f9abf43d4ca0947f33aa00483df63fa8aa73..f249f5b9a9d754ab5f75203b5a42520fe8ef6132
@@@ -32,7 -32,6 +32,7 @@@
  #include <linux/string.h>
  #include <linux/mm.h>
  #include <linux/sockptr.h>
 +#include <linux/bpf.h>
  #include <uapi/linux/lsm.h>
  
  struct linux_binprm;
@@@ -345,6 -344,8 +345,8 @@@ int security_inode_init_security_anon(s
                                      const struct qstr *name,
                                      const struct inode *context_inode);
  int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode);
+ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap,
+                                       struct inode *inode);
  int security_inode_link(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *new_dentry);
  int security_inode_unlink(struct inode *dir, struct dentry *dentry);
@@@ -362,6 -363,8 +364,8 @@@ int security_inode_follow_link(struct d
  int security_inode_permission(struct inode *inode, int mask);
  int security_inode_setattr(struct mnt_idmap *idmap,
                           struct dentry *dentry, struct iattr *attr);
+ void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                                int ia_valid);
  int security_inode_getattr(const struct path *path);
  int security_inode_setxattr(struct mnt_idmap *idmap,
                            struct dentry *dentry, const char *name,
  int security_inode_set_acl(struct mnt_idmap *idmap,
                           struct dentry *dentry, const char *acl_name,
                           struct posix_acl *kacl);
+ void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
+                                struct posix_acl *kacl);
  int security_inode_get_acl(struct mnt_idmap *idmap,
                           struct dentry *dentry, const char *acl_name);
  int security_inode_remove_acl(struct mnt_idmap *idmap,
                              struct dentry *dentry, const char *acl_name);
+ void security_inode_post_remove_acl(struct mnt_idmap *idmap,
+                                   struct dentry *dentry,
+                                   const char *acl_name);
  void security_inode_post_setxattr(struct dentry *dentry, const char *name,
                                  const void *value, size_t size, int flags);
  int security_inode_getxattr(struct dentry *dentry, const char *name);
  int security_inode_listxattr(struct dentry *dentry);
  int security_inode_removexattr(struct mnt_idmap *idmap,
                               struct dentry *dentry, const char *name);
+ void security_inode_post_removexattr(struct dentry *dentry, const char *name);
  int security_inode_need_killpriv(struct dentry *dentry);
  int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry);
  int security_inode_getsecurity(struct mnt_idmap *idmap,
@@@ -393,6 -402,7 +403,7 @@@ int security_kernfs_init_security(struc
                                  struct kernfs_node *kn);
  int security_file_permission(struct file *file, int mask);
  int security_file_alloc(struct file *file);
+ void security_file_release(struct file *file);
  void security_file_free(struct file *file);
  int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
  int security_file_ioctl_compat(struct file *file, unsigned int cmd,
@@@ -409,6 -419,7 +420,7 @@@ int security_file_send_sigiotask(struc
                                 struct fown_struct *fown, int sig);
  int security_file_receive(struct file *file);
  int security_file_open(struct file *file);
+ int security_file_post_open(struct file *file, int mask);
  int security_file_truncate(struct file *file);
  int security_task_alloc(struct task_struct *task, unsigned long clone_flags);
  void security_task_free(struct task_struct *task);
@@@ -807,6 -818,10 +819,10 @@@ static inline int security_inode_create
        return 0;
  }
  
+ static inline void
+ security_inode_post_create_tmpfile(struct mnt_idmap *idmap, struct inode *inode)
+ { }
  static inline int security_inode_link(struct dentry *old_dentry,
                                       struct inode *dir,
                                       struct dentry *new_dentry)
@@@ -880,6 -895,11 +896,11 @@@ static inline int security_inode_setatt
        return 0;
  }
  
+ static inline void
+ security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                           int ia_valid)
+ { }
  static inline int security_inode_getattr(const struct path *path)
  {
        return 0;
@@@ -900,6 -920,11 +921,11 @@@ static inline int security_inode_set_ac
        return 0;
  }
  
+ static inline void security_inode_post_set_acl(struct dentry *dentry,
+                                              const char *acl_name,
+                                              struct posix_acl *kacl)
+ { }
  static inline int security_inode_get_acl(struct mnt_idmap *idmap,
                                         struct dentry *dentry,
                                         const char *acl_name)
@@@ -914,6 -939,11 +940,11 @@@ static inline int security_inode_remove
        return 0;
  }
  
+ static inline void security_inode_post_remove_acl(struct mnt_idmap *idmap,
+                                                 struct dentry *dentry,
+                                                 const char *acl_name)
+ { }
  static inline void security_inode_post_setxattr(struct dentry *dentry,
                const char *name, const void *value, size_t size, int flags)
  { }
@@@ -936,6 -966,10 +967,10 @@@ static inline int security_inode_remove
        return cap_inode_removexattr(idmap, dentry, name);
  }
  
+ static inline void security_inode_post_removexattr(struct dentry *dentry,
+                                                  const char *name)
+ { }
  static inline int security_inode_need_killpriv(struct dentry *dentry)
  {
        return cap_inode_need_killpriv(dentry);
@@@ -996,6 -1030,9 +1031,9 @@@ static inline int security_file_alloc(s
        return 0;
  }
  
+ static inline void security_file_release(struct file *file)
+ { }
  static inline void security_file_free(struct file *file)
  { }
  
@@@ -1063,6 -1100,11 +1101,11 @@@ static inline int security_file_open(st
        return 0;
  }
  
+ static inline int security_file_post_open(struct file *file, int mask)
+ {
+       return 0;
+ }
  static inline int security_file_truncate(struct file *file)
  {
        return 0;
@@@ -1872,6 -1914,7 +1915,7 @@@ int security_path_mkdir(const struct pa
  int security_path_rmdir(const struct path *dir, struct dentry *dentry);
  int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode,
                        unsigned int dev);
+ void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry);
  int security_path_truncate(const struct path *path);
  int security_path_symlink(const struct path *dir, struct dentry *dentry,
                          const char *old_name);
@@@ -1906,6 -1949,10 +1950,10 @@@ static inline int security_path_mknod(c
        return 0;
  }
  
+ static inline void security_path_post_mknod(struct mnt_idmap *idmap,
+                                           struct dentry *dentry)
+ { }
  static inline int security_path_truncate(const struct path *path)
  {
        return 0;
@@@ -1957,6 -2004,9 +2005,9 @@@ void security_key_free(struct key *key)
  int security_key_permission(key_ref_t key_ref, const struct cred *cred,
                            enum key_need_perm need_perm);
  int security_key_getsecurity(struct key *key, char **_buffer);
+ void security_key_post_create_or_update(struct key *keyring, struct key *key,
+                                       const void *payload, size_t payload_len,
+                                       unsigned long flags, bool create);
  
  #else
  
@@@ -1984,6 -2034,14 +2035,14 @@@ static inline int security_key_getsecur
        return 0;
  }
  
+ static inline void security_key_post_create_or_update(struct key *keyring,
+                                                     struct key *key,
+                                                     const void *payload,
+                                                     size_t payload_len,
+                                                     unsigned long flags,
+                                                     bool create)
+ { }
  #endif
  #endif /* CONFIG_KEYS */
  
@@@ -2065,22 -2123,15 +2124,22 @@@ static inline void securityfs_remove(st
  union bpf_attr;
  struct bpf_map;
  struct bpf_prog;
 -struct bpf_prog_aux;
 +struct bpf_token;
  #ifdef CONFIG_SECURITY
  extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size);
  extern int security_bpf_map(struct bpf_map *map, fmode_t fmode);
  extern int security_bpf_prog(struct bpf_prog *prog);
 -extern int security_bpf_map_alloc(struct bpf_map *map);
 +extern int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
 +                                 struct bpf_token *token);
  extern void security_bpf_map_free(struct bpf_map *map);
 -extern int security_bpf_prog_alloc(struct bpf_prog_aux *aux);
 -extern void security_bpf_prog_free(struct bpf_prog_aux *aux);
 +extern int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
 +                                struct bpf_token *token);
 +extern void security_bpf_prog_free(struct bpf_prog *prog);
 +extern int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
 +                                   struct path *path);
 +extern void security_bpf_token_free(struct bpf_token *token);
 +extern int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cmd);
 +extern int security_bpf_token_capable(const struct bpf_token *token, int cap);
  #else
  static inline int security_bpf(int cmd, union bpf_attr *attr,
                                             unsigned int size)
@@@ -2098,8 -2149,7 +2157,8 @@@ static inline int security_bpf_prog(str
        return 0;
  }
  
 -static inline int security_bpf_map_alloc(struct bpf_map *map)
 +static inline int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
 +                                        struct bpf_token *token)
  {
        return 0;
  }
  static inline void security_bpf_map_free(struct bpf_map *map)
  { }
  
 -static inline int security_bpf_prog_alloc(struct bpf_prog_aux *aux)
 +static inline int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
 +                                       struct bpf_token *token)
  {
        return 0;
  }
  
 -static inline void security_bpf_prog_free(struct bpf_prog_aux *aux)
 +static inline void security_bpf_prog_free(struct bpf_prog *prog)
  { }
 +
 +static inline int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
 +                                   struct path *path)
 +{
 +      return 0;
 +}
 +
 +static inline void security_bpf_token_free(struct bpf_token *token)
 +{ }
 +
 +static inline int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cmd)
 +{
 +      return 0;
 +}
 +
 +static inline int security_bpf_token_capable(const struct bpf_token *token, int cap)
 +{
 +      return 0;
 +}
  #endif /* CONFIG_SECURITY */
  #endif /* CONFIG_BPF_SYSCALL */
  
diff --combined security/security.c
index aef69632d0a9e293a841925f290759629b81148e,4cb832b00c407b8063dccbe4f9fa4e6589962216..a07f43c58d656914ae5fa338a76709874aee3bbd
  #include <linux/kernel.h>
  #include <linux/kernel_read_file.h>
  #include <linux/lsm_hooks.h>
- #include <linux/integrity.h>
- #include <linux/ima.h>
- #include <linux/evm.h>
  #include <linux/fsnotify.h>
  #include <linux/mman.h>
  #include <linux/mount.h>
  #include <linux/personality.h>
  #include <linux/backing-dev.h>
  #include <linux/string.h>
+ #include <linux/xattr.h>
  #include <linux/msg.h>
 +#include <linux/overflow.h>
  #include <net/flow.h>
  
  /* How many LSMs were built into the kernel? */
@@@ -51,7 -48,9 +49,9 @@@
        (IS_ENABLED(CONFIG_SECURITY_SAFESETID) ? 1 : 0) + \
        (IS_ENABLED(CONFIG_SECURITY_LOCKDOWN_LSM) ? 1 : 0) + \
        (IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0) + \
-       (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0))
+       (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0) + \
+       (IS_ENABLED(CONFIG_IMA) ? 1 : 0) + \
+       (IS_ENABLED(CONFIG_EVM) ? 1 : 0))
  
  /*
   * These are descriptions of the reasons that can be passed to the
@@@ -856,14 -855,14 +856,14 @@@ out
                        P->hook.FUNC(__VA_ARGS__);              \
        } while (0)
  
- #define call_int_hook(FUNC, IRC, ...) ({                      \
-       int RC = IRC;                                           \
+ #define call_int_hook(FUNC, ...) ({                           \
+       int RC = LSM_RET_DEFAULT(FUNC);                         \
        do {                                                    \
                struct security_hook_list *P;                   \
                                                                \
                hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \
                        RC = P->hook.FUNC(__VA_ARGS__);         \
-                       if (RC != 0)                            \
+                       if (RC != LSM_RET_DEFAULT(FUNC))        \
                                break;                          \
                }                                               \
        } while (0);                                            \
   */
  int security_binder_set_context_mgr(const struct cred *mgr)
  {
-       return call_int_hook(binder_set_context_mgr, 0, mgr);
+       return call_int_hook(binder_set_context_mgr, mgr);
  }
  
  /**
  int security_binder_transaction(const struct cred *from,
                                const struct cred *to)
  {
-       return call_int_hook(binder_transaction, 0, from, to);
+       return call_int_hook(binder_transaction, from, to);
  }
  
  /**
  int security_binder_transfer_binder(const struct cred *from,
                                    const struct cred *to)
  {
-       return call_int_hook(binder_transfer_binder, 0, from, to);
+       return call_int_hook(binder_transfer_binder, from, to);
  }
  
  /**
  int security_binder_transfer_file(const struct cred *from,
                                  const struct cred *to, const struct file *file)
  {
-       return call_int_hook(binder_transfer_file, 0, from, to, file);
+       return call_int_hook(binder_transfer_file, from, to, file);
  }
  
  /**
   */
  int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
  {
-       return call_int_hook(ptrace_access_check, 0, child, mode);
+       return call_int_hook(ptrace_access_check, child, mode);
  }
  
  /**
   */
  int security_ptrace_traceme(struct task_struct *parent)
  {
-       return call_int_hook(ptrace_traceme, 0, parent);
+       return call_int_hook(ptrace_traceme, parent);
  }
  
  /**
@@@ -984,8 -983,7 +984,7 @@@ int security_capget(const struct task_s
                    kernel_cap_t *inheritable,
                    kernel_cap_t *permitted)
  {
-       return call_int_hook(capget, 0, target,
-                            effective, inheritable, permitted);
+       return call_int_hook(capget, target, effective, inheritable, permitted);
  }
  
  /**
@@@ -1006,8 -1004,8 +1005,8 @@@ int security_capset(struct cred *new, c
                    const kernel_cap_t *inheritable,
                    const kernel_cap_t *permitted)
  {
-       return call_int_hook(capset, 0, new, old,
-                            effective, inheritable, permitted);
+       return call_int_hook(capset, new, old, effective, inheritable,
+                            permitted);
  }
  
  /**
@@@ -1028,7 -1026,7 +1027,7 @@@ int security_capable(const struct cred 
                     int cap,
                     unsigned int opts)
  {
-       return call_int_hook(capable, 0, cred, ns, cap, opts);
+       return call_int_hook(capable, cred, ns, cap, opts);
  }
  
  /**
   */
  int security_quotactl(int cmds, int type, int id, const struct super_block *sb)
  {
-       return call_int_hook(quotactl, 0, cmds, type, id, sb);
+       return call_int_hook(quotactl, cmds, type, id, sb);
  }
  
  /**
   */
  int security_quota_on(struct dentry *dentry)
  {
-       return call_int_hook(quota_on, 0, dentry);
+       return call_int_hook(quota_on, dentry);
  }
  
  /**
   */
  int security_syslog(int type)
  {
-       return call_int_hook(syslog, 0, type);
+       return call_int_hook(syslog, type);
  }
  
  /**
   */
  int security_settime64(const struct timespec64 *ts, const struct timezone *tz)
  {
-       return call_int_hook(settime, 0, ts, tz);
+       return call_int_hook(settime, ts, tz);
  }
  
  /**
@@@ -1142,7 -1140,7 +1141,7 @@@ int security_vm_enough_memory_mm(struc
   */
  int security_bprm_creds_for_exec(struct linux_binprm *bprm)
  {
-       return call_int_hook(bprm_creds_for_exec, 0, bprm);
+       return call_int_hook(bprm_creds_for_exec, bprm);
  }
  
  /**
   */
  int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file *file)
  {
-       return call_int_hook(bprm_creds_from_file, 0, bprm, file);
+       return call_int_hook(bprm_creds_from_file, bprm, file);
  }
  
  /**
   */
  int security_bprm_check(struct linux_binprm *bprm)
  {
-       int ret;
-       ret = call_int_hook(bprm_check_security, 0, bprm);
-       if (ret)
-               return ret;
-       return ima_bprm_check(bprm);
+       return call_int_hook(bprm_check_security, bprm);
  }
  
  /**
@@@ -1235,7 -1228,7 +1229,7 @@@ void security_bprm_committed_creds(cons
   */
  int security_fs_context_submount(struct fs_context *fc, struct super_block *reference)
  {
-       return call_int_hook(fs_context_submount, 0, fc, reference);
+       return call_int_hook(fs_context_submount, fc, reference);
  }
  
  /**
   */
  int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
  {
-       return call_int_hook(fs_context_dup, 0, fc, src_fc);
+       return call_int_hook(fs_context_dup, fc, src_fc);
  }
  
  /**
@@@ -1300,7 -1293,7 +1294,7 @@@ int security_sb_alloc(struct super_bloc
  
        if (unlikely(rc))
                return rc;
-       rc = call_int_hook(sb_alloc_security, 0, sb);
+       rc = call_int_hook(sb_alloc_security, sb);
        if (unlikely(rc))
                security_sb_free(sb);
        return rc;
@@@ -1358,7 -1351,7 +1352,7 @@@ EXPORT_SYMBOL(security_free_mnt_opts)
   */
  int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
  {
-       return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts);
+       return call_int_hook(sb_eat_lsm_opts, options, mnt_opts);
  }
  EXPORT_SYMBOL(security_sb_eat_lsm_opts);
  
  int security_sb_mnt_opts_compat(struct super_block *sb,
                                void *mnt_opts)
  {
-       return call_int_hook(sb_mnt_opts_compat, 0, sb, mnt_opts);
+       return call_int_hook(sb_mnt_opts_compat, sb, mnt_opts);
  }
  EXPORT_SYMBOL(security_sb_mnt_opts_compat);
  
  int security_sb_remount(struct super_block *sb,
                        void *mnt_opts)
  {
-       return call_int_hook(sb_remount, 0, sb, mnt_opts);
+       return call_int_hook(sb_remount, sb, mnt_opts);
  }
  EXPORT_SYMBOL(security_sb_remount);
  
   */
  int security_sb_kern_mount(const struct super_block *sb)
  {
-       return call_int_hook(sb_kern_mount, 0, sb);
+       return call_int_hook(sb_kern_mount, sb);
  }
  
  /**
   */
  int security_sb_show_options(struct seq_file *m, struct super_block *sb)
  {
-       return call_int_hook(sb_show_options, 0, m, sb);
+       return call_int_hook(sb_show_options, m, sb);
  }
  
  /**
   */
  int security_sb_statfs(struct dentry *dentry)
  {
-       return call_int_hook(sb_statfs, 0, dentry);
+       return call_int_hook(sb_statfs, dentry);
  }
  
  /**
  int security_sb_mount(const char *dev_name, const struct path *path,
                      const char *type, unsigned long flags, void *data)
  {
-       return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data);
+       return call_int_hook(sb_mount, dev_name, path, type, flags, data);
  }
  
  /**
   */
  int security_sb_umount(struct vfsmount *mnt, int flags)
  {
-       return call_int_hook(sb_umount, 0, mnt, flags);
+       return call_int_hook(sb_umount, mnt, flags);
  }
  
  /**
  int security_sb_pivotroot(const struct path *old_path,
                          const struct path *new_path)
  {
-       return call_int_hook(sb_pivotroot, 0, old_path, new_path);
+       return call_int_hook(sb_pivotroot, old_path, new_path);
  }
  
  /**
@@@ -1505,9 -1498,17 +1499,17 @@@ int security_sb_set_mnt_opts(struct sup
                             unsigned long kern_flags,
                             unsigned long *set_kern_flags)
  {
-       return call_int_hook(sb_set_mnt_opts,
-                            mnt_opts ? -EOPNOTSUPP : 0, sb,
-                            mnt_opts, kern_flags, set_kern_flags);
+       struct security_hook_list *hp;
+       int rc = mnt_opts ? -EOPNOTSUPP : LSM_RET_DEFAULT(sb_set_mnt_opts);
+       hlist_for_each_entry(hp, &security_hook_heads.sb_set_mnt_opts,
+                            list) {
+               rc = hp->hook.sb_set_mnt_opts(sb, mnt_opts, kern_flags,
+                                             set_kern_flags);
+               if (rc != LSM_RET_DEFAULT(sb_set_mnt_opts))
+                       break;
+       }
+       return rc;
  }
  EXPORT_SYMBOL(security_sb_set_mnt_opts);
  
@@@ -1527,7 -1528,7 +1529,7 @@@ int security_sb_clone_mnt_opts(const st
                               unsigned long kern_flags,
                               unsigned long *set_kern_flags)
  {
-       return call_int_hook(sb_clone_mnt_opts, 0, oldsb, newsb,
+       return call_int_hook(sb_clone_mnt_opts, oldsb, newsb,
                             kern_flags, set_kern_flags);
  }
  EXPORT_SYMBOL(security_sb_clone_mnt_opts);
  int security_move_mount(const struct path *from_path,
                        const struct path *to_path)
  {
-       return call_int_hook(move_mount, 0, from_path, to_path);
+       return call_int_hook(move_mount, from_path, to_path);
  }
  
  /**
  int security_path_notify(const struct path *path, u64 mask,
                         unsigned int obj_type)
  {
-       return call_int_hook(path_notify, 0, path, mask, obj_type);
+       return call_int_hook(path_notify, path, mask, obj_type);
  }
  
  /**
@@@ -1580,7 -1581,7 +1582,7 @@@ int security_inode_alloc(struct inode *
  
        if (unlikely(rc))
                return rc;
-       rc = call_int_hook(inode_alloc_security, 0, inode);
+       rc = call_int_hook(inode_alloc_security, inode);
        if (unlikely(rc))
                security_inode_free(inode);
        return rc;
@@@ -1602,7 -1603,6 +1604,6 @@@ static void inode_free_by_rcu(struct rc
   */
  void security_inode_free(struct inode *inode)
  {
-       integrity_inode_free(inode);
        call_void_hook(inode_free_security, inode);
        /*
         * The inode may still be referenced in a path walk and
@@@ -1638,20 -1638,8 +1639,8 @@@ int security_dentry_init_security(struc
                                  const char **xattr_name, void **ctx,
                                  u32 *ctxlen)
  {
-       struct security_hook_list *hp;
-       int rc;
-       /*
-        * Only one module will provide a security context.
-        */
-       hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security,
-                            list) {
-               rc = hp->hook.dentry_init_security(dentry, mode, name,
-                                                  xattr_name, ctx, ctxlen);
-               if (rc != LSM_RET_DEFAULT(dentry_init_security))
-                       return rc;
-       }
-       return LSM_RET_DEFAULT(dentry_init_security);
+       return call_int_hook(dentry_init_security, dentry, mode, name,
+                            xattr_name, ctx, ctxlen);
  }
  EXPORT_SYMBOL(security_dentry_init_security);
  
@@@ -1674,7 -1662,7 +1663,7 @@@ int security_dentry_create_files_as(str
                                    struct qstr *name,
                                    const struct cred *old, struct cred *new)
  {
-       return call_int_hook(dentry_create_files_as, 0, dentry, mode,
+       return call_int_hook(dentry_create_files_as, dentry, mode,
                             name, old, new);
  }
  EXPORT_SYMBOL(security_dentry_create_files_as);
@@@ -1721,8 -1709,8 +1710,8 @@@ int security_inode_init_security(struc
                return 0;
  
        if (initxattrs) {
-               /* Allocate +1 for EVM and +1 as terminator. */
-               new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2,
+               /* Allocate +1 as terminator. */
+               new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 1,
                                     sizeof(*new_xattrs), GFP_NOFS);
                if (!new_xattrs)
                        return -ENOMEM;
        if (!xattr_count)
                goto out;
  
-       ret = evm_inode_init_security(inode, dir, qstr, new_xattrs,
-                                     &xattr_count);
-       if (ret)
-               goto out;
        ret = initxattrs(inode, new_xattrs, fs_data);
  out:
        for (; xattr_count > 0; xattr_count--)
@@@ -1775,7 -1759,7 +1760,7 @@@ int security_inode_init_security_anon(s
                                      const struct qstr *name,
                                      const struct inode *context_inode)
  {
-       return call_int_hook(inode_init_security_anon, 0, inode, name,
+       return call_int_hook(inode_init_security_anon, inode, name,
                             context_inode);
  }
  
@@@ -1797,10 -1781,24 +1782,24 @@@ int security_path_mknod(const struct pa
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return call_int_hook(path_mknod, 0, dir, dentry, mode, dev);
+       return call_int_hook(path_mknod, dir, dentry, mode, dev);
  }
  EXPORT_SYMBOL(security_path_mknod);
  
+ /**
+  * security_path_post_mknod() - Update inode security field after file creation
+  * @idmap: idmap of the mount
+  * @dentry: new file
+  *
+  * Update inode security field after a file has been created.
+  */
+ void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry)
+ {
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+               return;
+       call_void_hook(path_post_mknod, idmap, dentry);
+ }
  /**
   * security_path_mkdir() - Check if creating a new directory is allowed
   * @dir: parent directory
@@@ -1816,7 -1814,7 +1815,7 @@@ int security_path_mkdir(const struct pa
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return call_int_hook(path_mkdir, 0, dir, dentry, mode);
+       return call_int_hook(path_mkdir, dir, dentry, mode);
  }
  EXPORT_SYMBOL(security_path_mkdir);
  
@@@ -1833,7 -1831,7 +1832,7 @@@ int security_path_rmdir(const struct pa
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return call_int_hook(path_rmdir, 0, dir, dentry);
+       return call_int_hook(path_rmdir, dir, dentry);
  }
  
  /**
@@@ -1849,7 -1847,7 +1848,7 @@@ int security_path_unlink(const struct p
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return call_int_hook(path_unlink, 0, dir, dentry);
+       return call_int_hook(path_unlink, dir, dentry);
  }
  EXPORT_SYMBOL(security_path_unlink);
  
@@@ -1868,7 -1866,7 +1867,7 @@@ int security_path_symlink(const struct 
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return call_int_hook(path_symlink, 0, dir, dentry, old_name);
+       return call_int_hook(path_symlink, dir, dentry, old_name);
  }
  
  /**
@@@ -1886,7 -1884,7 +1885,7 @@@ int security_path_link(struct dentry *o
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
                return 0;
-       return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
+       return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
  }
  
  /**
@@@ -1910,7 -1908,7 +1909,7 @@@ int security_path_rename(const struct p
                      IS_PRIVATE(d_backing_inode(new_dentry)))))
                return 0;
  
-       return call_int_hook(path_rename, 0, old_dir, old_dentry, new_dir,
+       return call_int_hook(path_rename, old_dir, old_dentry, new_dir,
                             new_dentry, flags);
  }
  EXPORT_SYMBOL(security_path_rename);
@@@ -1929,7 -1927,7 +1928,7 @@@ int security_path_truncate(const struc
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return call_int_hook(path_truncate, 0, path);
+       return call_int_hook(path_truncate, path);
  }
  
  /**
@@@ -1947,7 -1945,7 +1946,7 @@@ int security_path_chmod(const struct pa
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return call_int_hook(path_chmod, 0, path, mode);
+       return call_int_hook(path_chmod, path, mode);
  }
  
  /**
@@@ -1964,7 -1962,7 +1963,7 @@@ int security_path_chown(const struct pa
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return call_int_hook(path_chown, 0, path, uid, gid);
+       return call_int_hook(path_chown, path, uid, gid);
  }
  
  /**
   */
  int security_path_chroot(const struct path *path)
  {
-       return call_int_hook(path_chroot, 0, path);
+       return call_int_hook(path_chroot, path);
  }
  #endif /* CONFIG_SECURITY_PATH */
  
@@@ -1996,10 -1994,25 +1995,25 @@@ int security_inode_create(struct inode 
  {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return call_int_hook(inode_create, 0, dir, dentry, mode);
+       return call_int_hook(inode_create, dir, dentry, mode);
  }
  EXPORT_SYMBOL_GPL(security_inode_create);
  
+ /**
+  * security_inode_post_create_tmpfile() - Update inode security of new tmpfile
+  * @idmap: idmap of the mount
+  * @inode: inode of the new tmpfile
+  *
+  * Update inode security data after a tmpfile has been created.
+  */
+ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap,
+                                       struct inode *inode)
+ {
+       if (unlikely(IS_PRIVATE(inode)))
+               return;
+       call_void_hook(inode_post_create_tmpfile, idmap, inode);
+ }
  /**
   * security_inode_link() - Check if creating a hard link is allowed
   * @old_dentry: existing file
@@@ -2015,7 -2028,7 +2029,7 @@@ int security_inode_link(struct dentry *
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
                return 0;
-       return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry);
+       return call_int_hook(inode_link, old_dentry, dir, new_dentry);
  }
  
  /**
@@@ -2031,7 -2044,7 +2045,7 @@@ int security_inode_unlink(struct inode 
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return call_int_hook(inode_unlink, 0, dir, dentry);
+       return call_int_hook(inode_unlink, dir, dentry);
  }
  
  /**
@@@ -2049,7 -2062,7 +2063,7 @@@ int security_inode_symlink(struct inod
  {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return call_int_hook(inode_symlink, 0, dir, dentry, old_name);
+       return call_int_hook(inode_symlink, dir, dentry, old_name);
  }
  
  /**
@@@ -2067,7 -2080,7 +2081,7 @@@ int security_inode_mkdir(struct inode *
  {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return call_int_hook(inode_mkdir, 0, dir, dentry, mode);
+       return call_int_hook(inode_mkdir, dir, dentry, mode);
  }
  EXPORT_SYMBOL_GPL(security_inode_mkdir);
  
@@@ -2084,7 -2097,7 +2098,7 @@@ int security_inode_rmdir(struct inode *
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return call_int_hook(inode_rmdir, 0, dir, dentry);
+       return call_int_hook(inode_rmdir, dir, dentry);
  }
  
  /**
@@@ -2106,7 -2119,7 +2120,7 @@@ int security_inode_mknod(struct inode *
  {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return call_int_hook(inode_mknod, 0, dir, dentry, mode, dev);
+       return call_int_hook(inode_mknod, dir, dentry, mode, dev);
  }
  
  /**
@@@ -2131,13 -2144,13 +2145,13 @@@ int security_inode_rename(struct inode 
                return 0;
  
        if (flags & RENAME_EXCHANGE) {
-               int err = call_int_hook(inode_rename, 0, new_dir, new_dentry,
+               int err = call_int_hook(inode_rename, new_dir, new_dentry,
                                        old_dir, old_dentry);
                if (err)
                        return err;
        }
  
-       return call_int_hook(inode_rename, 0, old_dir, old_dentry,
+       return call_int_hook(inode_rename, old_dir, old_dentry,
                             new_dir, new_dentry);
  }
  
@@@ -2153,7 -2166,7 +2167,7 @@@ int security_inode_readlink(struct dent
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return call_int_hook(inode_readlink, 0, dentry);
+       return call_int_hook(inode_readlink, dentry);
  }
  
  /**
@@@ -2172,7 -2185,7 +2186,7 @@@ int security_inode_follow_link(struct d
  {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return call_int_hook(inode_follow_link, 0, dentry, inode, rcu);
+       return call_int_hook(inode_follow_link, dentry, inode, rcu);
  }
  
  /**
@@@ -2193,7 -2206,7 +2207,7 @@@ int security_inode_permission(struct in
  {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return call_int_hook(inode_permission, 0, inode, mask);
+       return call_int_hook(inode_permission, inode, mask);
  }
  
  /**
  int security_inode_setattr(struct mnt_idmap *idmap,
                           struct dentry *dentry, struct iattr *attr)
  {
-       int ret;
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       ret = call_int_hook(inode_setattr, 0, dentry, attr);
-       if (ret)
-               return ret;
-       return evm_inode_setattr(idmap, dentry, attr);
+       return call_int_hook(inode_setattr, idmap, dentry, attr);
  }
  EXPORT_SYMBOL_GPL(security_inode_setattr);
  
+ /**
+  * security_inode_post_setattr() - Update the inode after a setattr operation
+  * @idmap: idmap of the mount
+  * @dentry: file
+  * @ia_valid: file attributes set
+  *
+  * Update inode security field after successful setting file attributes.
+  */
+ void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                                int ia_valid)
+ {
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+               return;
+       call_void_hook(inode_post_setattr, idmap, dentry, ia_valid);
+ }
  /**
   * security_inode_getattr() - Check if getting file attributes is allowed
   * @path: file
@@@ -2235,7 -2259,7 +2260,7 @@@ int security_inode_getattr(const struc
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return call_int_hook(inode_getattr, 0, path);
+       return call_int_hook(inode_getattr, path);
  }
  
  /**
@@@ -2263,17 -2287,12 +2288,12 @@@ int security_inode_setxattr(struct mnt_
         * SELinux and Smack integrate the cap call,
         * so assume that all LSMs supplying this call do so.
         */
-       ret = call_int_hook(inode_setxattr, 1, idmap, dentry, name, value,
-                           size, flags);
+       ret = call_int_hook(inode_setxattr, idmap, dentry, name, value, size,
+                           flags);
  
        if (ret == 1)
                ret = cap_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(idmap, dentry, name, value, size);
+       return ret;
  }
  
  /**
@@@ -2292,18 -2311,26 +2312,26 @@@ int security_inode_set_acl(struct mnt_i
                           struct dentry *dentry, const char *acl_name,
                           struct posix_acl *kacl)
  {
-       int ret;
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       ret = call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name,
-                           kacl);
-       if (ret)
-               return ret;
-       ret = ima_inode_set_acl(idmap, dentry, acl_name, kacl);
-       if (ret)
-               return ret;
-       return evm_inode_set_acl(idmap, dentry, acl_name, kacl);
+       return call_int_hook(inode_set_acl, idmap, dentry, acl_name, kacl);
+ }
+ /**
+  * security_inode_post_set_acl() - Update inode security from posix acls set
+  * @dentry: file
+  * @acl_name: acl name
+  * @kacl: acl struct
+  *
+  * Update inode security data after successfully setting posix acls on @dentry.
+  * The posix acls in @kacl are identified by @acl_name.
+  */
+ void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name,
+                                struct posix_acl *kacl)
+ {
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+               return;
+       call_void_hook(inode_post_set_acl, dentry, acl_name, kacl);
  }
  
  /**
@@@ -2322,7 -2349,7 +2350,7 @@@ int security_inode_get_acl(struct mnt_i
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return call_int_hook(inode_get_acl, 0, idmap, dentry, acl_name);
+       return call_int_hook(inode_get_acl, idmap, dentry, acl_name);
  }
  
  /**
  int security_inode_remove_acl(struct mnt_idmap *idmap,
                              struct dentry *dentry, const char *acl_name)
  {
-       int ret;
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       ret = call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name);
-       if (ret)
-               return ret;
-       ret = ima_inode_remove_acl(idmap, dentry, acl_name);
-       if (ret)
-               return ret;
-       return evm_inode_remove_acl(idmap, dentry, acl_name);
+       return call_int_hook(inode_remove_acl, idmap, dentry, acl_name);
+ }
+ /**
+  * security_inode_post_remove_acl() - Update inode security after rm posix acls
+  * @idmap: idmap of the mount
+  * @dentry: file
+  * @acl_name: acl name
+  *
+  * Update inode security data after successfully removing posix acls on
+  * @dentry in @idmap. The posix acls are identified by @acl_name.
+  */
+ void security_inode_post_remove_acl(struct mnt_idmap *idmap,
+                                   struct dentry *dentry, const char *acl_name)
+ {
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+               return;
+       call_void_hook(inode_post_remove_acl, idmap, dentry, acl_name);
  }
  
  /**
@@@ -2368,7 -2404,6 +2405,6 @@@ void security_inode_post_setxattr(struc
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return;
        call_void_hook(inode_post_setxattr, dentry, name, value, size, flags);
-       evm_inode_post_setxattr(dentry, name, value, size);
  }
  
  /**
@@@ -2385,7 -2420,7 +2421,7 @@@ int security_inode_getxattr(struct dent
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return call_int_hook(inode_getxattr, 0, dentry, name);
+       return call_int_hook(inode_getxattr, dentry, name);
  }
  
  /**
@@@ -2401,7 -2436,7 +2437,7 @@@ int security_inode_listxattr(struct den
  {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return call_int_hook(inode_listxattr, 0, dentry);
+       return call_int_hook(inode_listxattr, dentry);
  }
  
  /**
@@@ -2426,15 -2461,24 +2462,24 @@@ int security_inode_removexattr(struct m
         * SELinux and Smack integrate the cap call,
         * so assume that all LSMs supplying this call do so.
         */
-       ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name);
+       ret = call_int_hook(inode_removexattr, idmap, dentry, name);
        if (ret == 1)
                ret = cap_inode_removexattr(idmap, dentry, name);
-       if (ret)
-               return ret;
-       ret = ima_inode_removexattr(dentry, name);
-       if (ret)
-               return ret;
-       return evm_inode_removexattr(idmap, dentry, name);
+       return ret;
+ }
+ /**
+  * security_inode_post_removexattr() - Update the inode after a removexattr op
+  * @dentry: file
+  * @name: xattr name
+  *
+  * Update the inode after a successful removexattr operation.
+  */
+ void security_inode_post_removexattr(struct dentry *dentry, const char *name)
+ {
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
+               return;
+       call_void_hook(inode_post_removexattr, dentry, name);
  }
  
  /**
   */
  int security_inode_need_killpriv(struct dentry *dentry)
  {
-       return call_int_hook(inode_need_killpriv, 0, dentry);
+       return call_int_hook(inode_need_killpriv, dentry);
  }
  
  /**
  int security_inode_killpriv(struct mnt_idmap *idmap,
                            struct dentry *dentry)
  {
-       return call_int_hook(inode_killpriv, 0, idmap, dentry);
+       return call_int_hook(inode_killpriv, idmap, dentry);
  }
  
  /**
@@@ -2490,21 -2534,11 +2535,11 @@@ int security_inode_getsecurity(struct m
                               struct inode *inode, const char *name,
                               void **buffer, bool alloc)
  {
-       struct security_hook_list *hp;
-       int rc;
        if (unlikely(IS_PRIVATE(inode)))
                return LSM_RET_DEFAULT(inode_getsecurity);
-       /*
-        * Only one module will provide an attribute with a given name.
-        */
-       hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) {
-               rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer,
-                                               alloc);
-               if (rc != LSM_RET_DEFAULT(inode_getsecurity))
-                       return rc;
-       }
-       return LSM_RET_DEFAULT(inode_getsecurity);
+       return call_int_hook(inode_getsecurity, idmap, inode, name, buffer,
+                            alloc);
  }
  
  /**
  int security_inode_setsecurity(struct inode *inode, const char *name,
                               const void *value, size_t size, int flags)
  {
-       struct security_hook_list *hp;
-       int rc;
        if (unlikely(IS_PRIVATE(inode)))
                return LSM_RET_DEFAULT(inode_setsecurity);
-       /*
-        * Only one module will provide an attribute with a given name.
-        */
-       hlist_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) {
-               rc = hp->hook.inode_setsecurity(inode, name, value, size,
-                                               flags);
-               if (rc != LSM_RET_DEFAULT(inode_setsecurity))
-                       return rc;
-       }
-       return LSM_RET_DEFAULT(inode_setsecurity);
+       return call_int_hook(inode_setsecurity, inode, name, value, size,
+                            flags);
  }
  
  /**
@@@ -2560,7 -2584,7 +2585,7 @@@ int security_inode_listsecurity(struct 
  {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return call_int_hook(inode_listsecurity, 0, inode, buffer, buffer_size);
+       return call_int_hook(inode_listsecurity, inode, buffer, buffer_size);
  }
  EXPORT_SYMBOL(security_inode_listsecurity);
  
@@@ -2591,7 -2615,7 +2616,7 @@@ void security_inode_getsecid(struct ino
   */
  int security_inode_copy_up(struct dentry *src, struct cred **new)
  {
-       return call_int_hook(inode_copy_up, 0, src, new);
+       return call_int_hook(inode_copy_up, src, new);
  }
  EXPORT_SYMBOL(security_inode_copy_up);
  
   */
  int security_inode_copy_up_xattr(const char *name)
  {
-       struct security_hook_list *hp;
        int rc;
  
        /*
         * xattr), -EOPNOTSUPP if it does not know anything about the xattr or
         * any other error code in case of an error.
         */
-       hlist_for_each_entry(hp,
-                            &security_hook_heads.inode_copy_up_xattr, list) {
-               rc = hp->hook.inode_copy_up_xattr(name);
-               if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr))
-                       return rc;
-       }
+       rc = call_int_hook(inode_copy_up_xattr, name);
+       if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr))
+               return rc;
  
-       return evm_inode_copy_up_xattr(name);
+       return LSM_RET_DEFAULT(inode_copy_up_xattr);
  }
  EXPORT_SYMBOL(security_inode_copy_up_xattr);
  
  int security_kernfs_init_security(struct kernfs_node *kn_dir,
                                  struct kernfs_node *kn)
  {
-       return call_int_hook(kernfs_init_security, 0, kn_dir, kn);
+       return call_int_hook(kernfs_init_security, kn_dir, kn);
  }
  
  /**
   */
  int security_file_permission(struct file *file, int mask)
  {
-       return call_int_hook(file_permission, 0, file, mask);
+       return call_int_hook(file_permission, file, mask);
  }
  
  /**
@@@ -2683,12 -2703,23 +2704,23 @@@ int security_file_alloc(struct file *fi
  
        if (rc)
                return rc;
-       rc = call_int_hook(file_alloc_security, 0, file);
+       rc = call_int_hook(file_alloc_security, file);
        if (unlikely(rc))
                security_file_free(file);
        return rc;
  }
  
+ /**
+  * security_file_release() - Perform actions before releasing the file ref
+  * @file: the file
+  *
+  * Perform actions before releasing the last reference to a file.
+  */
+ void security_file_release(struct file *file)
+ {
+       call_void_hook(file_release, file);
+ }
  /**
   * security_file_free() - Free a file's LSM blob
   * @file: the file
@@@ -2723,7 -2754,7 +2755,7 @@@ void security_file_free(struct file *fi
   */
  int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
-       return call_int_hook(file_ioctl, 0, file, cmd, arg);
+       return call_int_hook(file_ioctl, file, cmd, arg);
  }
  EXPORT_SYMBOL_GPL(security_file_ioctl);
  
  int security_file_ioctl_compat(struct file *file, unsigned int cmd,
                               unsigned long arg)
  {
-       return call_int_hook(file_ioctl_compat, 0, file, cmd, arg);
+       return call_int_hook(file_ioctl_compat, file, cmd, arg);
  }
  EXPORT_SYMBOL_GPL(security_file_ioctl_compat);
  
@@@ -2792,13 -2823,8 +2824,8 @@@ static inline unsigned long mmap_prot(s
  int security_mmap_file(struct file *file, unsigned long prot,
                       unsigned long flags)
  {
-       unsigned long prot_adj = mmap_prot(file, prot);
-       int ret;
-       ret = call_int_hook(mmap_file, 0, file, prot, prot_adj, flags);
-       if (ret)
-               return ret;
-       return ima_file_mmap(file, prot, prot_adj, flags);
+       return call_int_hook(mmap_file, file, prot, mmap_prot(file, prot),
+                            flags);
  }
  
  /**
   */
  int security_mmap_addr(unsigned long addr)
  {
-       return call_int_hook(mmap_addr, 0, addr);
+       return call_int_hook(mmap_addr, addr);
  }
  
  /**
  int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
                           unsigned long prot)
  {
-       int ret;
-       ret = call_int_hook(file_mprotect, 0, vma, reqprot, prot);
-       if (ret)
-               return ret;
-       return ima_file_mprotect(vma, prot);
+       return call_int_hook(file_mprotect, vma, reqprot, prot);
  }
  
  /**
   */
  int security_file_lock(struct file *file, unsigned int cmd)
  {
-       return call_int_hook(file_lock, 0, file, cmd);
+       return call_int_hook(file_lock, file, cmd);
  }
  
  /**
   */
  int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
  {
-       return call_int_hook(file_fcntl, 0, file, cmd, arg);
+       return call_int_hook(file_fcntl, file, cmd, arg);
  }
  
  /**
@@@ -2900,11 -2921,11 +2922,11 @@@ void security_file_set_fowner(struct fi
  int security_file_send_sigiotask(struct task_struct *tsk,
                                 struct fown_struct *fown, int sig)
  {
-       return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig);
+       return call_int_hook(file_send_sigiotask, tsk, fown, sig);
  }
  
  /**
-  * security_file_receive() - Check is receiving a file via IPC is allowed
+  * security_file_receive() - Check if receiving a file via IPC is allowed
   * @file: file being received
   *
   * This hook allows security modules to control the ability of a process to
   */
  int security_file_receive(struct file *file)
  {
-       return call_int_hook(file_receive, 0, file);
+       return call_int_hook(file_receive, file);
  }
  
  /**
@@@ -2930,13 -2951,30 +2952,30 @@@ int security_file_open(struct file *fil
  {
        int ret;
  
-       ret = call_int_hook(file_open, 0, file);
+       ret = call_int_hook(file_open, file);
        if (ret)
                return ret;
  
        return fsnotify_open_perm(file);
  }
  
+ /**
+  * security_file_post_open() - Evaluate a file after it has been opened
+  * @file: the file
+  * @mask: access mask
+  *
+  * Evaluate an opened file and the access mask requested with open(). The hook
+  * is useful for LSMs that require the file content to be available in order to
+  * make decisions.
+  *
+  * Return: Returns 0 if permission is granted.
+  */
+ int security_file_post_open(struct file *file, int mask)
+ {
+       return call_int_hook(file_post_open, file, mask);
+ }
+ EXPORT_SYMBOL_GPL(security_file_post_open);
  /**
   * security_file_truncate() - Check if truncating a file is allowed
   * @file: file
   */
  int security_file_truncate(struct file *file)
  {
-       return call_int_hook(file_truncate, 0, file);
+       return call_int_hook(file_truncate, file);
  }
  
  /**
@@@ -2967,7 -3005,7 +3006,7 @@@ int security_task_alloc(struct task_str
  
        if (rc)
                return rc;
-       rc = call_int_hook(task_alloc, 0, task, clone_flags);
+       rc = call_int_hook(task_alloc, task, clone_flags);
        if (unlikely(rc))
                security_task_free(task);
        return rc;
@@@ -3005,7 -3043,7 +3044,7 @@@ int security_cred_alloc_blank(struct cr
        if (rc)
                return rc;
  
-       rc = call_int_hook(cred_alloc_blank, 0, cred, gfp);
+       rc = call_int_hook(cred_alloc_blank, cred, gfp);
        if (unlikely(rc))
                security_cred_free(cred);
        return rc;
@@@ -3049,7 -3087,7 +3088,7 @@@ int security_prepare_creds(struct cred 
        if (rc)
                return rc;
  
-       rc = call_int_hook(cred_prepare, 0, new, old, gfp);
+       rc = call_int_hook(cred_prepare, new, old, gfp);
        if (unlikely(rc))
                security_cred_free(new);
        return rc;
@@@ -3094,7 -3132,7 +3133,7 @@@ EXPORT_SYMBOL(security_cred_getsecid)
   */
  int security_kernel_act_as(struct cred *new, u32 secid)
  {
-       return call_int_hook(kernel_act_as, 0, new, secid);
+       return call_int_hook(kernel_act_as, new, secid);
  }
  
  /**
   */
  int security_kernel_create_files_as(struct cred *new, struct inode *inode)
  {
-       return call_int_hook(kernel_create_files_as, 0, new, inode);
+       return call_int_hook(kernel_create_files_as, new, inode);
  }
  
  /**
-  * security_kernel_module_request() - Check is loading a module is allowed
+  * security_kernel_module_request() - Check if loading a module is allowed
   * @kmod_name: module name
   *
   * Ability to trigger the kernel to automatically upcall to userspace for
   */
  int security_kernel_module_request(char *kmod_name)
  {
-       int ret;
-       ret = call_int_hook(kernel_module_request, 0, kmod_name);
-       if (ret)
-               return ret;
-       return integrity_kernel_module_request(kmod_name);
+       return call_int_hook(kernel_module_request, kmod_name);
  }
  
  /**
  int security_kernel_read_file(struct file *file, enum kernel_read_file_id id,
                              bool contents)
  {
-       int ret;
-       ret = call_int_hook(kernel_read_file, 0, file, id, contents);
-       if (ret)
-               return ret;
-       return ima_read_file(file, id, contents);
+       return call_int_hook(kernel_read_file, file, id, contents);
  }
  EXPORT_SYMBOL_GPL(security_kernel_read_file);
  
  int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
                                   enum kernel_read_file_id id)
  {
-       int ret;
-       ret = call_int_hook(kernel_post_read_file, 0, file, buf, size, id);
-       if (ret)
-               return ret;
-       return ima_post_read_file(file, buf, size, id);
+       return call_int_hook(kernel_post_read_file, file, buf, size, id);
  }
  EXPORT_SYMBOL_GPL(security_kernel_post_read_file);
  
   */
  int security_kernel_load_data(enum kernel_load_data_id id, bool contents)
  {
-       int ret;
-       ret = call_int_hook(kernel_load_data, 0, id, contents);
-       if (ret)
-               return ret;
-       return ima_load_data(id, contents);
+       return call_int_hook(kernel_load_data, id, contents);
  }
  EXPORT_SYMBOL_GPL(security_kernel_load_data);
  
@@@ -3217,13 -3235,7 +3236,7 @@@ int security_kernel_post_load_data(cha
                                   enum kernel_load_data_id id,
                                   char *description)
  {
-       int ret;
-       ret = call_int_hook(kernel_post_load_data, 0, buf, size, id,
-                           description);
-       if (ret)
-               return ret;
-       return ima_post_load_data(buf, size, id, description);
+       return call_int_hook(kernel_post_load_data, buf, size, id, description);
  }
  EXPORT_SYMBOL_GPL(security_kernel_post_load_data);
  
  int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags)
  {
-       return call_int_hook(task_fix_setuid, 0, new, old, flags);
+       return call_int_hook(task_fix_setuid, new, old, flags);
  }
  
  /**
  int security_task_fix_setgid(struct cred *new, const struct cred *old,
                             int flags)
  {
-       return call_int_hook(task_fix_setgid, 0, new, old, flags);
+       return call_int_hook(task_fix_setgid, new, old, flags);
  }
  
  /**
   */
  int security_task_fix_setgroups(struct cred *new, const struct cred *old)
  {
-       return call_int_hook(task_fix_setgroups, 0, new, old);
+       return call_int_hook(task_fix_setgroups, new, old);
  }
  
  /**
   */
  int security_task_setpgid(struct task_struct *p, pid_t pgid)
  {
-       return call_int_hook(task_setpgid, 0, p, pgid);
+       return call_int_hook(task_setpgid, p, pgid);
  }
  
  /**
   */
  int security_task_getpgid(struct task_struct *p)
  {
-       return call_int_hook(task_getpgid, 0, p);
+       return call_int_hook(task_getpgid, p);
  }
  
  /**
   */
  int security_task_getsid(struct task_struct *p)
  {
-       return call_int_hook(task_getsid, 0, p);
+       return call_int_hook(task_getsid, p);
  }
  
  /**
@@@ -3366,7 -3378,7 +3379,7 @@@ EXPORT_SYMBOL(security_task_getsecid_ob
   */
  int security_task_setnice(struct task_struct *p, int nice)
  {
-       return call_int_hook(task_setnice, 0, p, nice);
+       return call_int_hook(task_setnice, p, nice);
  }
  
  /**
   */
  int security_task_setioprio(struct task_struct *p, int ioprio)
  {
-       return call_int_hook(task_setioprio, 0, p, ioprio);
+       return call_int_hook(task_setioprio, p, ioprio);
  }
  
  /**
   */
  int security_task_getioprio(struct task_struct *p)
  {
-       return call_int_hook(task_getioprio, 0, p);
+       return call_int_hook(task_getioprio, p);
  }
  
  /**
  int security_task_prlimit(const struct cred *cred, const struct cred *tcred,
                          unsigned int flags)
  {
-       return call_int_hook(task_prlimit, 0, cred, tcred, flags);
+       return call_int_hook(task_prlimit, cred, tcred, flags);
  }
  
  /**
  int security_task_setrlimit(struct task_struct *p, unsigned int resource,
                            struct rlimit *new_rlim)
  {
-       return call_int_hook(task_setrlimit, 0, p, resource, new_rlim);
+       return call_int_hook(task_setrlimit, p, resource, new_rlim);
  }
  
  /**
   */
  int security_task_setscheduler(struct task_struct *p)
  {
-       return call_int_hook(task_setscheduler, 0, p);
+       return call_int_hook(task_setscheduler, p);
  }
  
  /**
   */
  int security_task_getscheduler(struct task_struct *p)
  {
-       return call_int_hook(task_getscheduler, 0, p);
+       return call_int_hook(task_getscheduler, p);
  }
  
  /**
   */
  int security_task_movememory(struct task_struct *p)
  {
-       return call_int_hook(task_movememory, 0, p);
+       return call_int_hook(task_movememory, p);
  }
  
  /**
  int security_task_kill(struct task_struct *p, struct kernel_siginfo *info,
                       int sig, const struct cred *cred)
  {
-       return call_int_hook(task_kill, 0, p, info, sig, cred);
+       return call_int_hook(task_kill, p, info, sig, cred);
  }
  
  /**
@@@ -3547,7 -3559,7 +3560,7 @@@ void security_task_to_inode(struct task
   */
  int security_create_user_ns(const struct cred *cred)
  {
-       return call_int_hook(userns_create, 0, cred);
+       return call_int_hook(userns_create, cred);
  }
  
  /**
   */
  int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
  {
-       return call_int_hook(ipc_permission, 0, ipcp, flag);
+       return call_int_hook(ipc_permission, ipcp, flag);
  }
  
  /**
@@@ -3593,7 -3605,7 +3606,7 @@@ int security_msg_msg_alloc(struct msg_m
  
        if (unlikely(rc))
                return rc;
-       rc = call_int_hook(msg_msg_alloc_security, 0, msg);
+       rc = call_int_hook(msg_msg_alloc_security, msg);
        if (unlikely(rc))
                security_msg_msg_free(msg);
        return rc;
@@@ -3627,7 -3639,7 +3640,7 @@@ int security_msg_queue_alloc(struct ker
  
        if (unlikely(rc))
                return rc;
-       rc = call_int_hook(msg_queue_alloc_security, 0, msq);
+       rc = call_int_hook(msg_queue_alloc_security, msq);
        if (unlikely(rc))
                security_msg_queue_free(msq);
        return rc;
@@@ -3659,7 -3671,7 +3672,7 @@@ void security_msg_queue_free(struct ker
   */
  int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
  {
-       return call_int_hook(msg_queue_associate, 0, msq, msqflg);
+       return call_int_hook(msg_queue_associate, msq, msqflg);
  }
  
  /**
   */
  int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
  {
-       return call_int_hook(msg_queue_msgctl, 0, msq, cmd);
+       return call_int_hook(msg_queue_msgctl, msq, cmd);
  }
  
  /**
  int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
                              struct msg_msg *msg, int msqflg)
  {
-       return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg);
+       return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg);
  }
  
  /**
  int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
                              struct task_struct *target, long type, int mode)
  {
-       return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode);
+       return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode);
  }
  
  /**
@@@ -3730,7 -3742,7 +3743,7 @@@ int security_shm_alloc(struct kern_ipc_
  
        if (unlikely(rc))
                return rc;
-       rc = call_int_hook(shm_alloc_security, 0, shp);
+       rc = call_int_hook(shm_alloc_security, shp);
        if (unlikely(rc))
                security_shm_free(shp);
        return rc;
@@@ -3763,7 -3775,7 +3776,7 @@@ void security_shm_free(struct kern_ipc_
   */
  int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)
  {
-       return call_int_hook(shm_associate, 0, shp, shmflg);
+       return call_int_hook(shm_associate, shp, shmflg);
  }
  
  /**
   */
  int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
  {
-       return call_int_hook(shm_shmctl, 0, shp, cmd);
+       return call_int_hook(shm_shmctl, shp, cmd);
  }
  
  /**
  int security_shm_shmat(struct kern_ipc_perm *shp,
                       char __user *shmaddr, int shmflg)
  {
-       return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg);
+       return call_int_hook(shm_shmat, shp, shmaddr, shmflg);
  }
  
  /**
@@@ -3814,7 -3826,7 +3827,7 @@@ int security_sem_alloc(struct kern_ipc_
  
        if (unlikely(rc))
                return rc;
-       rc = call_int_hook(sem_alloc_security, 0, sma);
+       rc = call_int_hook(sem_alloc_security, sma);
        if (unlikely(rc))
                security_sem_free(sma);
        return rc;
@@@ -3846,7 -3858,7 +3859,7 @@@ void security_sem_free(struct kern_ipc_
   */
  int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
  {
-       return call_int_hook(sem_associate, 0, sma, semflg);
+       return call_int_hook(sem_associate, sma, semflg);
  }
  
  /**
   */
  int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)
  {
-       return call_int_hook(sem_semctl, 0, sma, cmd);
+       return call_int_hook(sem_semctl, sma, cmd);
  }
  
  /**
  int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
                       unsigned nsops, int alter)
  {
-       return call_int_hook(sem_semop, 0, sma, sops, nsops, alter);
+       return call_int_hook(sem_semop, sma, sops, nsops, alter);
  }
  
  /**
@@@ -4016,7 -4028,6 +4029,7 @@@ int security_setselfattr(unsigned int a
        struct security_hook_list *hp;
        struct lsm_ctx *lctx;
        int rc = LSM_RET_DEFAULT(setselfattr);
 +      u64 required_len;
  
        if (flags)
                return -EINVAL;
        if (IS_ERR(lctx))
                return PTR_ERR(lctx);
  
 -      if (size < lctx->len || size < lctx->ctx_len + sizeof(*lctx) ||
 -          lctx->len < lctx->ctx_len + sizeof(*lctx)) {
 +      if (size < lctx->len ||
 +          check_add_overflow(sizeof(*lctx), lctx->ctx_len, &required_len) ||
 +          lctx->len < required_len) {
                rc = -EINVAL;
                goto free_out;
        }
@@@ -4110,11 -4120,11 +4123,11 @@@ int security_setprocattr(int lsmid, con
   */
  int security_netlink_send(struct sock *sk, struct sk_buff *skb)
  {
-       return call_int_hook(netlink_send, 0, sk, skb);
+       return call_int_hook(netlink_send, sk, skb);
  }
  
  /**
-  * security_ismaclabel() - Check is the named attribute is a MAC label
+  * security_ismaclabel() - Check if the named attribute is a MAC label
   * @name: full extended attribute name
   *
   * Check if the extended attribute specified by @name represents a MAC label.
   */
  int security_ismaclabel(const char *name)
  {
-       return call_int_hook(ismaclabel, 0, name);
+       return call_int_hook(ismaclabel, name);
  }
  EXPORT_SYMBOL(security_ismaclabel);
  
   */
  int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  {
-       struct security_hook_list *hp;
-       int rc;
-       /*
-        * Currently, only one LSM can implement secid_to_secctx (i.e this
-        * LSM hook is not "stackable").
-        */
-       hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
-               rc = hp->hook.secid_to_secctx(secid, secdata, seclen);
-               if (rc != LSM_RET_DEFAULT(secid_to_secctx))
-                       return rc;
-       }
-       return LSM_RET_DEFAULT(secid_to_secctx);
+       return call_int_hook(secid_to_secctx, secid, secdata, seclen);
  }
  EXPORT_SYMBOL(security_secid_to_secctx);
  
  int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
  {
        *secid = 0;
-       return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid);
+       return call_int_hook(secctx_to_secid, secdata, seclen, secid);
  }
  EXPORT_SYMBOL(security_secctx_to_secid);
  
@@@ -4219,7 -4216,7 +4219,7 @@@ EXPORT_SYMBOL(security_inode_invalidate
   */
  int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
  {
-       return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen);
+       return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen);
  }
  EXPORT_SYMBOL(security_inode_notifysecctx);
  
   */
  int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
  {
-       return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen);
+       return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen);
  }
  EXPORT_SYMBOL(security_inode_setsecctx);
  
   */
  int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
  {
-       struct security_hook_list *hp;
-       int rc;
-       /*
-        * Only one module will provide a security context.
-        */
-       hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list) {
-               rc = hp->hook.inode_getsecctx(inode, ctx, ctxlen);
-               if (rc != LSM_RET_DEFAULT(inode_getsecctx))
-                       return rc;
-       }
-       return LSM_RET_DEFAULT(inode_getsecctx);
+       return call_int_hook(inode_getsecctx, inode, ctx, ctxlen);
  }
  EXPORT_SYMBOL(security_inode_getsecctx);
  
@@@ -4289,7 -4274,7 +4277,7 @@@ int security_post_notification(const st
                               const struct cred *cred,
                               struct watch_notification *n)
  {
-       return call_int_hook(post_notification, 0, w_cred, cred, n);
+       return call_int_hook(post_notification, w_cred, cred, n);
  }
  #endif /* CONFIG_WATCH_QUEUE */
  
   */
  int security_watch_key(struct key *key)
  {
-       return call_int_hook(watch_key, 0, key);
+       return call_int_hook(watch_key, key);
  }
  #endif /* CONFIG_KEY_NOTIFICATIONS */
  
  int security_unix_stream_connect(struct sock *sock, struct sock *other,
                                 struct sock *newsk)
  {
-       return call_int_hook(unix_stream_connect, 0, sock, other, newsk);
+       return call_int_hook(unix_stream_connect, sock, other, newsk);
  }
  EXPORT_SYMBOL(security_unix_stream_connect);
  
   */
  int security_unix_may_send(struct socket *sock,  struct socket *other)
  {
-       return call_int_hook(unix_may_send, 0, sock, other);
+       return call_int_hook(unix_may_send, sock, other);
  }
  EXPORT_SYMBOL(security_unix_may_send);
  
   */
  int security_socket_create(int family, int type, int protocol, int kern)
  {
-       return call_int_hook(socket_create, 0, family, type, protocol, kern);
+       return call_int_hook(socket_create, family, type, protocol, kern);
  }
  
  /**
  int security_socket_post_create(struct socket *sock, int family,
                                int type, int protocol, int kern)
  {
-       return call_int_hook(socket_post_create, 0, sock, family, type,
+       return call_int_hook(socket_post_create, sock, family, type,
                             protocol, kern);
  }
  
   */
  int security_socket_socketpair(struct socket *socka, struct socket *sockb)
  {
-       return call_int_hook(socket_socketpair, 0, socka, sockb);
+       return call_int_hook(socket_socketpair, socka, sockb);
  }
  EXPORT_SYMBOL(security_socket_socketpair);
  
  int security_socket_bind(struct socket *sock,
                         struct sockaddr *address, int addrlen)
  {
-       return call_int_hook(socket_bind, 0, sock, address, addrlen);
+       return call_int_hook(socket_bind, sock, address, addrlen);
  }
  
  /**
  int security_socket_connect(struct socket *sock,
                            struct sockaddr *address, int addrlen)
  {
-       return call_int_hook(socket_connect, 0, sock, address, addrlen);
+       return call_int_hook(socket_connect, sock, address, addrlen);
  }
  
  /**
   */
  int security_socket_listen(struct socket *sock, int backlog)
  {
-       return call_int_hook(socket_listen, 0, sock, backlog);
+       return call_int_hook(socket_listen, sock, backlog);
  }
  
  /**
   */
  int security_socket_accept(struct socket *sock, struct socket *newsock)
  {
-       return call_int_hook(socket_accept, 0, sock, newsock);
+       return call_int_hook(socket_accept, sock, newsock);
  }
  
  /**
-  * security_socket_sendmsg() - Check is sending a message is allowed
+  * security_socket_sendmsg() - Check if sending a message is allowed
   * @sock: sending socket
   * @msg: message to send
   * @size: size of message
   */
  int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
  {
-       return call_int_hook(socket_sendmsg, 0, sock, msg, size);
+       return call_int_hook(socket_sendmsg, sock, msg, size);
  }
  
  /**
  int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
                            int size, int flags)
  {
-       return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags);
+       return call_int_hook(socket_recvmsg, sock, msg, size, flags);
  }
  
  /**
   */
  int security_socket_getsockname(struct socket *sock)
  {
-       return call_int_hook(socket_getsockname, 0, sock);
+       return call_int_hook(socket_getsockname, sock);
  }
  
  /**
   */
  int security_socket_getpeername(struct socket *sock)
  {
-       return call_int_hook(socket_getpeername, 0, sock);
+       return call_int_hook(socket_getpeername, sock);
  }
  
  /**
   */
  int security_socket_getsockopt(struct socket *sock, int level, int optname)
  {
-       return call_int_hook(socket_getsockopt, 0, sock, level, optname);
+       return call_int_hook(socket_getsockopt, sock, level, optname);
  }
  
  /**
   */
  int security_socket_setsockopt(struct socket *sock, int level, int optname)
  {
-       return call_int_hook(socket_setsockopt, 0, sock, level, optname);
+       return call_int_hook(socket_setsockopt, sock, level, optname);
  }
  
  /**
   */
  int security_socket_shutdown(struct socket *sock, int how)
  {
-       return call_int_hook(socket_shutdown, 0, sock, how);
+       return call_int_hook(socket_shutdown, sock, how);
  }
  
  /**
   */
  int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
  {
-       return call_int_hook(socket_sock_rcv_skb, 0, sk, skb);
+       return call_int_hook(socket_sock_rcv_skb, sk, skb);
  }
  EXPORT_SYMBOL(security_sock_rcv_skb);
  
  int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval,
                                      sockptr_t optlen, unsigned int len)
  {
-       struct security_hook_list *hp;
-       int rc;
-       /*
-        * Only one module will provide a security context.
-        */
-       hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream,
-                            list) {
-               rc = hp->hook.socket_getpeersec_stream(sock, optval, optlen,
-                                                      len);
-               if (rc != LSM_RET_DEFAULT(socket_getpeersec_stream))
-                       return rc;
-       }
-       return LSM_RET_DEFAULT(socket_getpeersec_stream);
+       return call_int_hook(socket_getpeersec_stream, sock, optval, optlen,
+                            len);
  }
  
  /**
  int security_socket_getpeersec_dgram(struct socket *sock,
                                     struct sk_buff *skb, u32 *secid)
  {
-       struct security_hook_list *hp;
-       int rc;
-       /*
-        * Only one module will provide a security context.
-        */
-       hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_dgram,
-                            list) {
-               rc = hp->hook.socket_getpeersec_dgram(sock, skb, secid);
-               if (rc != LSM_RET_DEFAULT(socket_getpeersec_dgram))
-                       return rc;
-       }
-       return LSM_RET_DEFAULT(socket_getpeersec_dgram);
+       return call_int_hook(socket_getpeersec_dgram, sock, skb, secid);
  }
  EXPORT_SYMBOL(security_socket_getpeersec_dgram);
  
   */
  int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
  {
-       return call_int_hook(sk_alloc_security, 0, sk, family, priority);
+       return call_int_hook(sk_alloc_security, sk, family, priority);
  }
  
  /**
@@@ -4770,7 -4731,7 +4734,7 @@@ EXPORT_SYMBOL(security_sock_graft)
  int security_inet_conn_request(const struct sock *sk,
                               struct sk_buff *skb, struct request_sock *req)
  {
-       return call_int_hook(inet_conn_request, 0, sk, skb, req);
+       return call_int_hook(inet_conn_request, sk, skb, req);
  }
  EXPORT_SYMBOL(security_inet_conn_request);
  
@@@ -4811,7 -4772,7 +4775,7 @@@ EXPORT_SYMBOL(security_inet_conn_establ
   */
  int security_secmark_relabel_packet(u32 secid)
  {
-       return call_int_hook(secmark_relabel_packet, 0, secid);
+       return call_int_hook(secmark_relabel_packet, secid);
  }
  EXPORT_SYMBOL(security_secmark_relabel_packet);
  
@@@ -4848,7 -4809,7 +4812,7 @@@ EXPORT_SYMBOL(security_secmark_refcount
   */
  int security_tun_dev_alloc_security(void **security)
  {
-       return call_int_hook(tun_dev_alloc_security, 0, security);
+       return call_int_hook(tun_dev_alloc_security, security);
  }
  EXPORT_SYMBOL(security_tun_dev_alloc_security);
  
@@@ -4873,7 -4834,7 +4837,7 @@@ EXPORT_SYMBOL(security_tun_dev_free_sec
   */
  int security_tun_dev_create(void)
  {
-       return call_int_hook(tun_dev_create, 0);
+       return call_int_hook(tun_dev_create);
  }
  EXPORT_SYMBOL(security_tun_dev_create);
  
   */
  int security_tun_dev_attach_queue(void *security)
  {
-       return call_int_hook(tun_dev_attach_queue, 0, security);
+       return call_int_hook(tun_dev_attach_queue, security);
  }
  EXPORT_SYMBOL(security_tun_dev_attach_queue);
  
   */
  int security_tun_dev_attach(struct sock *sk, void *security)
  {
-       return call_int_hook(tun_dev_attach, 0, sk, security);
+       return call_int_hook(tun_dev_attach, sk, security);
  }
  EXPORT_SYMBOL(security_tun_dev_attach);
  
   */
  int security_tun_dev_open(void *security)
  {
-       return call_int_hook(tun_dev_open, 0, security);
+       return call_int_hook(tun_dev_open, security);
  }
  EXPORT_SYMBOL(security_tun_dev_open);
  
  int security_sctp_assoc_request(struct sctp_association *asoc,
                                struct sk_buff *skb)
  {
-       return call_int_hook(sctp_assoc_request, 0, asoc, skb);
+       return call_int_hook(sctp_assoc_request, asoc, skb);
  }
  EXPORT_SYMBOL(security_sctp_assoc_request);
  
  int security_sctp_bind_connect(struct sock *sk, int optname,
                               struct sockaddr *address, int addrlen)
  {
-       return call_int_hook(sctp_bind_connect, 0, sk, optname,
-                            address, addrlen);
+       return call_int_hook(sctp_bind_connect, sk, optname, address, addrlen);
  }
  EXPORT_SYMBOL(security_sctp_bind_connect);
  
@@@ -4990,7 -4950,7 +4953,7 @@@ EXPORT_SYMBOL(security_sctp_sk_clone)
  int security_sctp_assoc_established(struct sctp_association *asoc,
                                    struct sk_buff *skb)
  {
-       return call_int_hook(sctp_assoc_established, 0, asoc, skb);
+       return call_int_hook(sctp_assoc_established, asoc, skb);
  }
  EXPORT_SYMBOL(security_sctp_assoc_established);
  
   */
  int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
  {
-       return call_int_hook(mptcp_add_subflow, 0, sk, ssk);
+       return call_int_hook(mptcp_add_subflow, sk, ssk);
  }
  
  #endif        /* CONFIG_SECURITY_NETWORK */
   */
  int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey)
  {
-       return call_int_hook(ib_pkey_access, 0, sec, subnet_prefix, pkey);
+       return call_int_hook(ib_pkey_access, sec, subnet_prefix, pkey);
  }
  EXPORT_SYMBOL(security_ib_pkey_access);
  
  int security_ib_endport_manage_subnet(void *sec,
                                      const char *dev_name, u8 port_num)
  {
-       return call_int_hook(ib_endport_manage_subnet, 0, sec,
-                            dev_name, port_num);
+       return call_int_hook(ib_endport_manage_subnet, sec, dev_name, port_num);
  }
  EXPORT_SYMBOL(security_ib_endport_manage_subnet);
  
   */
  int security_ib_alloc_security(void **sec)
  {
-       return call_int_hook(ib_alloc_security, 0, sec);
+       return call_int_hook(ib_alloc_security, sec);
  }
  EXPORT_SYMBOL(security_ib_alloc_security);
  
@@@ -5091,7 -5050,7 +5053,7 @@@ int security_xfrm_policy_alloc(struct x
                               struct xfrm_user_sec_ctx *sec_ctx,
                               gfp_t gfp)
  {
-       return call_int_hook(xfrm_policy_alloc_security, 0, ctxp, sec_ctx, gfp);
+       return call_int_hook(xfrm_policy_alloc_security, ctxp, sec_ctx, gfp);
  }
  EXPORT_SYMBOL(security_xfrm_policy_alloc);
  
  int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
                               struct xfrm_sec_ctx **new_ctxp)
  {
-       return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp);
+       return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp);
  }
  
  /**
@@@ -5133,7 -5092,7 +5095,7 @@@ EXPORT_SYMBOL(security_xfrm_policy_free
   */
  int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
  {
-       return call_int_hook(xfrm_policy_delete_security, 0, ctx);
+       return call_int_hook(xfrm_policy_delete_security, ctx);
  }
  
  /**
  int security_xfrm_state_alloc(struct xfrm_state *x,
                              struct xfrm_user_sec_ctx *sec_ctx)
  {
-       return call_int_hook(xfrm_state_alloc, 0, x, sec_ctx);
+       return call_int_hook(xfrm_state_alloc, x, sec_ctx);
  }
  EXPORT_SYMBOL(security_xfrm_state_alloc);
  
  int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
                                      struct xfrm_sec_ctx *polsec, u32 secid)
  {
-       return call_int_hook(xfrm_state_alloc_acquire, 0, x, polsec, secid);
+       return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid);
  }
  
  /**
   */
  int security_xfrm_state_delete(struct xfrm_state *x)
  {
-       return call_int_hook(xfrm_state_delete_security, 0, x);
+       return call_int_hook(xfrm_state_delete_security, x);
  }
  EXPORT_SYMBOL(security_xfrm_state_delete);
  
@@@ -5211,7 -5170,7 +5173,7 @@@ void security_xfrm_state_free(struct xf
   */
  int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid)
  {
-       return call_int_hook(xfrm_policy_lookup, 0, ctx, fl_secid);
+       return call_int_hook(xfrm_policy_lookup, ctx, fl_secid);
  }
  
  /**
@@@ -5259,12 -5218,12 +5221,12 @@@ int security_xfrm_state_pol_flow_match(
   */
  int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
  {
-       return call_int_hook(xfrm_decode_session, 0, skb, secid, 1);
+       return call_int_hook(xfrm_decode_session, skb, secid, 1);
  }
  
  void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic)
  {
-       int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid,
+       int rc = call_int_hook(xfrm_decode_session, skb, &flic->flowic_secid,
                               0);
  
        BUG_ON(rc);
@@@ -5287,7 -5246,7 +5249,7 @@@ EXPORT_SYMBOL(security_skb_classify_flo
  int security_key_alloc(struct key *key, const struct cred *cred,
                       unsigned long flags)
  {
-       return call_int_hook(key_alloc, 0, key, cred, flags);
+       return call_int_hook(key_alloc, key, cred, flags);
  }
  
  /**
@@@ -5314,7 -5273,7 +5276,7 @@@ void security_key_free(struct key *key
  int security_key_permission(key_ref_t key_ref, const struct cred *cred,
                            enum key_need_perm need_perm)
  {
-       return call_int_hook(key_permission, 0, key_ref, cred, need_perm);
+       return call_int_hook(key_permission, key_ref, cred, need_perm);
  }
  
  /**
  int security_key_getsecurity(struct key *key, char **buffer)
  {
        *buffer = NULL;
-       return call_int_hook(key_getsecurity, 0, key, buffer);
+       return call_int_hook(key_getsecurity, key, buffer);
+ }
+ /**
+  * security_key_post_create_or_update() - Notification of key create or update
+  * @keyring: keyring to which the key is linked to
+  * @key: created or updated key
+  * @payload: data used to instantiate or update the key
+  * @payload_len: length of payload
+  * @flags: key flags
+  * @create: flag indicating whether the key was created or updated
+  *
+  * Notify the caller of a key creation or update.
+  */
+ void security_key_post_create_or_update(struct key *keyring, struct key *key,
+                                       const void *payload, size_t payload_len,
+                                       unsigned long flags, bool create)
+ {
+       call_void_hook(key_post_create_or_update, keyring, key, payload,
+                      payload_len, flags, create);
  }
  #endif        /* CONFIG_KEYS */
  
   */
  int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
  {
-       return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule);
+       return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule);
  }
  
  /**
   */
  int security_audit_rule_known(struct audit_krule *krule)
  {
-       return call_int_hook(audit_rule_known, 0, krule);
+       return call_int_hook(audit_rule_known, krule);
  }
  
  /**
@@@ -5396,7 -5374,7 +5377,7 @@@ void security_audit_rule_free(void *lsm
   */
  int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
  {
-       return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule);
+       return call_int_hook(audit_rule_match, secid, field, op, lsmrule);
  }
  #endif /* CONFIG_AUDIT */
  
   */
  int security_bpf(int cmd, union bpf_attr *attr, unsigned int size)
  {
-       return call_int_hook(bpf, 0, cmd, attr, size);
+       return call_int_hook(bpf, cmd, attr, size);
  }
  
  /**
   */
  int security_bpf_map(struct bpf_map *map, fmode_t fmode)
  {
-       return call_int_hook(bpf_map, 0, map, fmode);
+       return call_int_hook(bpf_map, map, fmode);
  }
  
  /**
   */
  int security_bpf_prog(struct bpf_prog *prog)
  {
-       return call_int_hook(bpf_prog, 0, prog);
+       return call_int_hook(bpf_prog, prog);
  }
  
  /**
 - * security_bpf_map_alloc() - Allocate a bpf map LSM blob
 - * @map: bpf map
 + * security_bpf_map_create() - Check if BPF map creation is allowed
 + * @map: BPF map object
 + * @attr: BPF syscall attributes used to create BPF map
 + * @token: BPF token used to grant user access
 + *
 + * Do a check when the kernel creates a new BPF map. This is also the
 + * point where LSM blob is allocated for LSMs that need them.
 + *
 + * Return: Returns 0 on success, error on failure.
 + */
 +int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
 +                          struct bpf_token *token)
 +{
-       return call_int_hook(bpf_map_create, 0, map, attr, token);
++      return call_int_hook(bpf_map_create, map, attr, token);
 +}
 +
 +/**
 + * security_bpf_prog_load() - Check if loading of BPF program is allowed
 + * @prog: BPF program object
 + * @attr: BPF syscall attributes used to create BPF program
 + * @token: BPF token used to grant user access to BPF subsystem
   *
 - * Initialize the security field inside bpf map.
 + * Perform an access control check when the kernel loads a BPF program and
 + * allocates associated BPF program object. This hook is also responsible for
 + * allocating any required LSM state for the BPF program.
   *
   * Return: Returns 0 on success, error on failure.
   */
 -int security_bpf_map_alloc(struct bpf_map *map)
 +int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
 +                         struct bpf_token *token)
  {
-       return call_int_hook(bpf_prog_load, 0, prog, attr, token);
 -      return call_int_hook(bpf_map_alloc_security, map);
++      return call_int_hook(bpf_prog_load, prog, attr, token);
  }
  
  /**
 - * security_bpf_prog_alloc() - Allocate a bpf program LSM blob
 - * @aux: bpf program aux info struct
 + * security_bpf_token_create() - Check if creating of BPF token is allowed
 + * @token: BPF token object
 + * @attr: BPF syscall attributes used to create BPF token
 + * @path: path pointing to BPF FS mount point from which BPF token is created
   *
 - * Initialize the security field inside bpf program.
 + * Do a check when the kernel instantiates a new BPF token object from BPF FS
 + * instance. This is also the point where LSM blob can be allocated for LSMs.
   *
   * Return: Returns 0 on success, error on failure.
   */
 -int security_bpf_prog_alloc(struct bpf_prog_aux *aux)
 +int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
 +                            struct path *path)
  {
-       return call_int_hook(bpf_token_create, 0, token, attr, path);
 -      return call_int_hook(bpf_prog_alloc_security, aux);
++      return call_int_hook(bpf_token_create, token, attr, path);
 +}
 +
 +/**
 + * security_bpf_token_cmd() - Check if BPF token is allowed to delegate
 + * requested BPF syscall command
 + * @token: BPF token object
 + * @cmd: BPF syscall command requested to be delegated by BPF token
 + *
 + * Do a check when the kernel decides whether provided BPF token should allow
 + * delegation of requested BPF syscall command.
 + *
 + * Return: Returns 0 on success, error on failure.
 + */
 +int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cmd)
 +{
-       return call_int_hook(bpf_token_cmd, 0, token, cmd);
++      return call_int_hook(bpf_token_cmd, token, cmd);
 +}
 +
 +/**
 + * security_bpf_token_capable() - Check if BPF token is allowed to delegate
 + * requested BPF-related capability
 + * @token: BPF token object
 + * @cap: capabilities requested to be delegated by BPF token
 + *
 + * Do a check when the kernel decides whether provided BPF token should allow
 + * delegation of requested BPF-related capabilities.
 + *
 + * Return: Returns 0 on success, error on failure.
 + */
 +int security_bpf_token_capable(const struct bpf_token *token, int cap)
 +{
-       return call_int_hook(bpf_token_capable, 0, token, cap);
++      return call_int_hook(bpf_token_capable, token, cap);
  }
  
  /**
   */
  void security_bpf_map_free(struct bpf_map *map)
  {
 -      call_void_hook(bpf_map_free_security, map);
 +      call_void_hook(bpf_map_free, map);
 +}
 +
 +/**
 + * security_bpf_prog_free() - Free a BPF program's LSM blob
 + * @prog: BPF program struct
 + *
 + * Clean up the security information stored inside BPF program.
 + */
 +void security_bpf_prog_free(struct bpf_prog *prog)
 +{
 +      call_void_hook(bpf_prog_free, prog);
  }
  
  /**
 - * security_bpf_prog_free() - Free a bpf program's LSM blob
 - * @aux: bpf program aux info struct
 + * security_bpf_token_free() - Free a BPF token's LSM blob
 + * @token: BPF token struct
   *
 - * Clean up the security information stored inside bpf prog.
 + * Clean up the security information stored inside BPF token.
   */
 -void security_bpf_prog_free(struct bpf_prog_aux *aux)
 +void security_bpf_token_free(struct bpf_token *token)
  {
 -      call_void_hook(bpf_prog_free_security, aux);
 +      call_void_hook(bpf_token_free, token);
  }
  #endif /* CONFIG_BPF_SYSCALL */
  
   */
  int security_locked_down(enum lockdown_reason what)
  {
-       return call_int_hook(locked_down, 0, what);
+       return call_int_hook(locked_down, what);
  }
  EXPORT_SYMBOL(security_locked_down);
  
   */
  int security_perf_event_open(struct perf_event_attr *attr, int type)
  {
-       return call_int_hook(perf_event_open, 0, attr, type);
+       return call_int_hook(perf_event_open, attr, type);
  }
  
  /**
   */
  int security_perf_event_alloc(struct perf_event *event)
  {
-       return call_int_hook(perf_event_alloc, 0, event);
+       return call_int_hook(perf_event_alloc, event);
  }
  
  /**
@@@ -5629,7 -5538,7 +5610,7 @@@ void security_perf_event_free(struct pe
   */
  int security_perf_event_read(struct perf_event *event)
  {
-       return call_int_hook(perf_event_read, 0, event);
+       return call_int_hook(perf_event_read, event);
  }
  
  /**
   */
  int security_perf_event_write(struct perf_event *event)
  {
-       return call_int_hook(perf_event_write, 0, event);
+       return call_int_hook(perf_event_write, event);
  }
  #endif /* CONFIG_PERF_EVENTS */
  
   */
  int security_uring_override_creds(const struct cred *new)
  {
-       return call_int_hook(uring_override_creds, 0, new);
+       return call_int_hook(uring_override_creds, new);
  }
  
  /**
   */
  int security_uring_sqpoll(void)
  {
-       return call_int_hook(uring_sqpoll, 0);
+       return call_int_hook(uring_sqpoll);
  }
  
  /**
   */
  int security_uring_cmd(struct io_uring_cmd *ioucmd)
  {
-       return call_int_hook(uring_cmd, 0, ioucmd);
+       return call_int_hook(uring_cmd, ioucmd);
  }
  #endif /* CONFIG_IO_URING */
diff --combined security/selinux/hooks.c
index 860e558e9fd5aac4ce29792412cbd91bf9000f05,cedb4cbf072e3f16b7d25b5b7fd058d1c5ce3db1..8db4875164aba261321a13b3532b656fd86d58d7
@@@ -2920,22 -2920,23 +2920,22 @@@ static int selinux_inode_init_security(
        struct superblock_security_struct *sbsec;
        struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
        u32 newsid, clen;
 +      u16 newsclass;
        int rc;
        char *context;
  
        sbsec = selinux_superblock(dir->i_sb);
  
        newsid = tsec->create_sid;
 -
 -      rc = selinux_determine_inode_label(tsec, dir, qstr,
 -              inode_mode_to_security_class(inode->i_mode),
 -              &newsid);
 +      newsclass = inode_mode_to_security_class(inode->i_mode);
 +      rc = selinux_determine_inode_label(tsec, dir, qstr, newsclass, &newsid);
        if (rc)
                return rc;
  
        /* Possibly defer initialization to selinux_complete_init. */
        if (sbsec->flags & SE_SBINITIALIZED) {
                struct inode_security_struct *isec = selinux_inode(inode);
 -              isec->sclass = inode_mode_to_security_class(inode->i_mode);
 +              isec->sclass = newsclass;
                isec->sid = newsid;
                isec->initialized = LABEL_INITIALIZED;
        }
@@@ -3135,7 -3136,8 +3135,8 @@@ static int selinux_inode_permission(str
        return rc;
  }
  
- static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+ static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                                struct iattr *iattr)
  {
        const struct cred *cred = current_cred();
        struct inode *inode = d_backing_inode(dentry);
@@@ -3533,10 -3535,9 +3534,10 @@@ static int selinux_inode_copy_up_xattr(
  {
        /* The copy_up hook above sets the initial context on an inode, but we
         * don't then want to overwrite it by blindly copying all the lower
 -       * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
 +       * xattrs up.  Instead, filter out SELinux-related xattrs following
 +       * policy load.
         */
 -      if (strcmp(name, XATTR_NAME_SELINUX) == 0)
 +      if (selinux_initialized() && strcmp(name, XATTR_NAME_SELINUX) == 0)
                return 1; /* Discard */
        /*
         * Any other attribute apart from SELINUX is not claimed, supported
@@@ -5194,11 -5195,11 +5195,11 @@@ out_len
        return err;
  }
  
 -static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
 +static int selinux_socket_getpeersec_dgram(struct socket *sock,
 +                                         struct sk_buff *skb, u32 *secid)
  {
        u32 peer_secid = SECSID_NULL;
        u16 family;
 -      struct inode_security_struct *isec;
  
        if (skb && skb->protocol == htons(ETH_P_IP))
                family = PF_INET;
                family = PF_INET6;
        else if (sock)
                family = sock->sk->sk_family;
 -      else
 -              goto out;
 +      else {
 +              *secid = SECSID_NULL;
 +              return -EINVAL;
 +      }
  
        if (sock && family == PF_UNIX) {
 +              struct inode_security_struct *isec;
                isec = inode_security_novalidate(SOCK_INODE(sock));
                peer_secid = isec->sid;
        } else if (skb)
                selinux_skb_peerlbl_sid(skb, family, &peer_secid);
  
 -out:
        *secid = peer_secid;
        if (peer_secid == SECSID_NULL)
 -              return -EINVAL;
 +              return -ENOPROTOOPT;
        return 0;
  }
  
@@@ -6561,7 -6560,7 +6562,7 @@@ static int selinux_getselfattr(unsigne
                               size_t *size, u32 flags)
  {
        int rc;
 -      char *val;
 +      char *val = NULL;
        int val_len;
  
        val_len = selinux_lsm_getattr(attr, current, &val);
@@@ -6922,8 -6921,7 +6923,8 @@@ static int selinux_bpf_prog(struct bpf_
                            BPF__PROG_RUN, NULL);
  }
  
 -static int selinux_bpf_map_alloc(struct bpf_map *map)
 +static int selinux_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
 +                                struct bpf_token *token)
  {
        struct bpf_security_struct *bpfsec;
  
@@@ -6945,31 -6943,7 +6946,31 @@@ static void selinux_bpf_map_free(struc
        kfree(bpfsec);
  }
  
 -static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
 +static int selinux_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
 +                               struct bpf_token *token)
 +{
 +      struct bpf_security_struct *bpfsec;
 +
 +      bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
 +      if (!bpfsec)
 +              return -ENOMEM;
 +
 +      bpfsec->sid = current_sid();
 +      prog->aux->security = bpfsec;
 +
 +      return 0;
 +}
 +
 +static void selinux_bpf_prog_free(struct bpf_prog *prog)
 +{
 +      struct bpf_security_struct *bpfsec = prog->aux->security;
 +
 +      prog->aux->security = NULL;
 +      kfree(bpfsec);
 +}
 +
 +static int selinux_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
 +                                  struct path *path)
  {
        struct bpf_security_struct *bpfsec;
  
                return -ENOMEM;
  
        bpfsec->sid = current_sid();
 -      aux->security = bpfsec;
 +      token->security = bpfsec;
  
        return 0;
  }
  
 -static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 +static void selinux_bpf_token_free(struct bpf_token *token)
  {
 -      struct bpf_security_struct *bpfsec = aux->security;
 +      struct bpf_security_struct *bpfsec = token->security;
  
 -      aux->security = NULL;
 +      token->security = NULL;
        kfree(bpfsec);
  }
  #endif
@@@ -7351,9 -7325,8 +7352,9 @@@ static struct security_hook_list selinu
        LSM_HOOK_INIT(bpf, selinux_bpf),
        LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
        LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
 -      LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
 -      LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
 +      LSM_HOOK_INIT(bpf_map_free, selinux_bpf_map_free),
 +      LSM_HOOK_INIT(bpf_prog_free, selinux_bpf_prog_free),
 +      LSM_HOOK_INIT(bpf_token_free, selinux_bpf_token_free),
  #endif
  
  #ifdef CONFIG_PERF_EVENTS
        LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
  #endif
  #ifdef CONFIG_BPF_SYSCALL
 -      LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
 -      LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
 +      LSM_HOOK_INIT(bpf_map_create, selinux_bpf_map_create),
 +      LSM_HOOK_INIT(bpf_prog_load, selinux_bpf_prog_load),
 +      LSM_HOOK_INIT(bpf_token_create, selinux_bpf_token_create),
  #endif
  #ifdef CONFIG_PERF_EVENTS
        LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
index b18b5023294797592023078018db027d7b300da2,1b6abfdf717331022b3dc7f330e2ce6e1c9235bd..28be26712396db6c0b8a4948a9a4e369563f401a
@@@ -994,62 -994,57 +994,62 @@@ static int smack_inode_init_security(st
                                     struct xattr *xattrs, int *xattr_count)
  {
        struct task_smack *tsp = smack_cred(current_cred());
 +      struct inode_smack *issp = smack_inode(inode);
        struct smack_known *skp = smk_of_task(tsp);
        struct smack_known *isp = smk_of_inode(inode);
        struct smack_known *dsp = smk_of_inode(dir);
        struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
        int may;
  
 -      if (xattr) {
 -              /*
 -               * If equal, transmuting already occurred in
 -               * smack_dentry_create_files_as(). No need to check again.
 -               */
 -              if (tsp->smk_task != tsp->smk_transmuted) {
 -                      rcu_read_lock();
 -                      may = smk_access_entry(skp->smk_known, dsp->smk_known,
 -                                             &skp->smk_rules);
 -                      rcu_read_unlock();
 -              }
 +      /*
 +       * If equal, transmuting already occurred in
 +       * smack_dentry_create_files_as(). No need to check again.
 +       */
 +      if (tsp->smk_task != tsp->smk_transmuted) {
 +              rcu_read_lock();
 +              may = smk_access_entry(skp->smk_known, dsp->smk_known,
 +                                     &skp->smk_rules);
 +              rcu_read_unlock();
 +      }
 +
 +      /*
 +       * In addition to having smk_task equal to smk_transmuted,
 +       * if the access rule allows transmutation and the directory
 +       * requests transmutation then by all means transmute.
 +       * Mark the inode as changed.
 +       */
 +      if ((tsp->smk_task == tsp->smk_transmuted) ||
 +          (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
 +           smk_inode_transmutable(dir))) {
 +              struct xattr *xattr_transmute;
  
                /*
 -               * In addition to having smk_task equal to smk_transmuted,
 -               * if the access rule allows transmutation and the directory
 -               * requests transmutation then by all means transmute.
 -               * Mark the inode as changed.
 +               * The caller of smack_dentry_create_files_as()
 +               * should have overridden the current cred, so the
 +               * inode label was already set correctly in
 +               * smack_inode_alloc_security().
                 */
 -              if ((tsp->smk_task == tsp->smk_transmuted) ||
 -                  (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
 -                   smk_inode_transmutable(dir))) {
 -                      struct xattr *xattr_transmute;
 -
 -                      /*
 -                       * The caller of smack_dentry_create_files_as()
 -                       * should have overridden the current cred, so the
 -                       * inode label was already set correctly in
 -                       * smack_inode_alloc_security().
 -                       */
 -                      if (tsp->smk_task != tsp->smk_transmuted)
 -                              isp = dsp;
 -                      xattr_transmute = lsm_get_xattr_slot(xattrs,
 -                                                           xattr_count);
 -                      if (xattr_transmute) {
 -                              xattr_transmute->value = kmemdup(TRANS_TRUE,
 -                                                               TRANS_TRUE_SIZE,
 -                                                               GFP_NOFS);
 -                              if (!xattr_transmute->value)
 -                                      return -ENOMEM;
 -
 -                              xattr_transmute->value_len = TRANS_TRUE_SIZE;
 -                              xattr_transmute->name = XATTR_SMACK_TRANSMUTE;
 -                      }
 +              if (tsp->smk_task != tsp->smk_transmuted)
 +                      isp = issp->smk_inode = dsp;
 +
 +              issp->smk_flags |= SMK_INODE_TRANSMUTE;
 +              xattr_transmute = lsm_get_xattr_slot(xattrs,
 +                                                   xattr_count);
 +              if (xattr_transmute) {
 +                      xattr_transmute->value = kmemdup(TRANS_TRUE,
 +                                                       TRANS_TRUE_SIZE,
 +                                                       GFP_NOFS);
 +                      if (!xattr_transmute->value)
 +                              return -ENOMEM;
 +
 +                      xattr_transmute->value_len = TRANS_TRUE_SIZE;
 +                      xattr_transmute->name = XATTR_SMACK_TRANSMUTE;
                }
 +      }
  
 +      issp->smk_flags |= SMK_INODE_INSTANT;
 +
 +      if (xattr) {
                xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
                if (!xattr->value)
                        return -ENOMEM;
@@@ -1238,12 -1233,14 +1238,14 @@@ static int smack_inode_permission(struc
  
  /**
   * smack_inode_setattr - Smack check for setting attributes
+  * @idmap: idmap of the mount
   * @dentry: the object
   * @iattr: for the force flag
   *
   * Returns 0 if access is permitted, an error code otherwise
   */
- static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+ static int smack_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+                              struct iattr *iattr)
  {
        struct smk_audit_info ad;
        int rc;
@@@ -1319,8 -1316,7 +1321,8 @@@ static int smack_inode_setxattr(struct 
                check_star = 1;
        } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
                check_priv = 1;
 -              if (size != TRANS_TRUE_SIZE ||
 +              if (!S_ISDIR(d_backing_inode(dentry)->i_mode) ||
 +                  size != TRANS_TRUE_SIZE ||
                    strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
                        rc = -EINVAL;
        } else
@@@ -2101,7 -2097,12 +2103,7 @@@ static void smack_cred_transfer(struct 
        struct task_smack *old_tsp = smack_cred(old);
        struct task_smack *new_tsp = smack_cred(new);
  
 -      new_tsp->smk_task = old_tsp->smk_task;
 -      new_tsp->smk_forked = old_tsp->smk_task;
 -      mutex_init(&new_tsp->smk_rules_lock);
 -      INIT_LIST_HEAD(&new_tsp->smk_rules);
 -
 -      /* cbs copy rule list */
 +      init_task_smack(new_tsp, old_tsp->smk_task, old_tsp->smk_task);
  }
  
  /**
@@@ -2856,15 -2857,6 +2858,15 @@@ static int smack_inode_setsecurity(stru
        if (value == NULL || size > SMK_LONGLABEL || size == 0)
                return -EINVAL;
  
 +      if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) {
 +              if (!S_ISDIR(inode->i_mode) || size != TRANS_TRUE_SIZE ||
 +                  strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
 +                      return -EINVAL;
 +
 +              nsp->smk_flags |= SMK_INODE_TRANSMUTE;
 +              return 0;
 +      }
 +
        skp = smk_import_entry(value, size);
        if (IS_ERR(skp))
                return PTR_ERR(skp);
This page took 0.231973 seconds and 4 git commands to generate.