OSDN Git Service

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Jun 2015 20:26:03 +0000 (13:26 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Jun 2015 20:26:03 +0000 (13:26 -0700)
Pull security subsystem updates from James Morris:
 "The main change in this kernel is Casey's generalized LSM stacking
  work, which removes the hard-coding of Capabilities and Yama stacking,
  allowing multiple arbitrary "small" LSMs to be stacked with a default
  monolithic module (e.g.  SELinux, Smack, AppArmor).

  See
        https://lwn.net/Articles/636056/

  This will allow smaller, simpler LSMs to be incorporated into the
  mainline kernel and arbitrarily stacked by users.  Also, this is a
  useful cleanup of the LSM code in its own right"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (38 commits)
  tpm, tpm_crb: fix le64_to_cpu conversions in crb_acpi_add()
  vTPM: set virtual device before passing to ibmvtpm_reset_crq
  tpm_ibmvtpm: remove unneccessary message level.
  ima: update builtin policies
  ima: extend "mask" policy matching support
  ima: add support for new "euid" policy condition
  ima: fix ima_show_template_data_ascii()
  Smack: freeing an error pointer in smk_write_revoke_subj()
  selinux: fix setting of security labels on NFS
  selinux: Remove unused permission definitions
  selinux: enable genfscon labeling for sysfs and pstore files
  selinux: enable per-file labeling for debugfs files.
  selinux: update netlink socket classes
  signals: don't abuse __flush_signals() in selinux_bprm_committed_creds()
  selinux: Print 'sclass' as string when unrecognized netlink message occurs
  Smack: allow multiple labels in onlycap
  Smack: fix seq operations in smackfs
  ima: pass iint to ima_add_violation()
  ima: wrap event related data to the new ima_event_data structure
  integrity: add validity checks for 'path' parameter
  ...

42 files changed:
Documentation/ABI/testing/ima_policy
Documentation/kernel-parameters.txt
Documentation/security/Smack.txt
crypto/asymmetric_keys/asymmetric_keys.h
crypto/asymmetric_keys/asymmetric_type.c
crypto/asymmetric_keys/x509_public_key.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_ibmvtpm.c
drivers/char/tpm/tpm_of.c
fs/xattr.c
include/linux/lsm_hooks.h [new file with mode: 0644]
include/linux/sched.h
include/linux/security.h
kernel/signal.c
security/Makefile
security/apparmor/domain.c
security/apparmor/lsm.c
security/capability.c [deleted file]
security/commoncap.c
security/integrity/digsig.c
security/integrity/evm/evm_main.c
security/integrity/iint.c
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_appraise.c
security/integrity/ima/ima_fs.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/integrity/ima/ima_template_lib.c
security/integrity/ima/ima_template_lib.h
security/integrity/integrity.h
security/security.c
security/selinux/hooks.c
security/selinux/include/classmap.h
security/selinux/include/security.h
security/smack/smack.h
security/smack/smack_access.c
security/smack/smack_lsm.c
security/smack/smackfs.c
security/tomoyo/tomoyo.c
security/yama/yama_lsm.c

index d0d0c57..0a378a8 100644 (file)
@@ -20,17 +20,19 @@ Description:
                action: measure | dont_measure | appraise | dont_appraise | audit
                condition:= base | lsm  [option]
                        base:   [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
-                                [fowner]]
+                               [euid=] [fowner=]]
                        lsm:    [[subj_user=] [subj_role=] [subj_type=]
                                 [obj_user=] [obj_role=] [obj_type=]]
                        option: [[appraise_type=]] [permit_directio]
 
                base:   func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
                                [FIRMWARE_CHECK]
-                       mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
+                       mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
+                              [[^]MAY_EXEC]
                        fsmagic:= hex value
                        fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
                        uid:= decimal value
+                       euid:= decimal value
                        fowner:=decimal value
                lsm:    are LSM specific
                option: appraise_type:= [imasig]
@@ -49,11 +51,25 @@ Description:
                        dont_measure fsmagic=0x01021994
                        dont_appraise fsmagic=0x01021994
                        # RAMFS_MAGIC
-                       dont_measure fsmagic=0x858458f6
                        dont_appraise fsmagic=0x858458f6
+                       # DEVPTS_SUPER_MAGIC
+                       dont_measure fsmagic=0x1cd1
+                       dont_appraise fsmagic=0x1cd1
+                       # BINFMTFS_MAGIC
+                       dont_measure fsmagic=0x42494e4d
+                       dont_appraise fsmagic=0x42494e4d
                        # SECURITYFS_MAGIC
                        dont_measure fsmagic=0x73636673
                        dont_appraise fsmagic=0x73636673
+                       # SELINUX_MAGIC
+                       dont_measure fsmagic=0xf97cff8c
+                       dont_appraise fsmagic=0xf97cff8c
+                       # CGROUP_SUPER_MAGIC
+                       dont_measure fsmagic=0x27e0eb
+                       dont_appraise fsmagic=0x27e0eb
+                       # NSFS_MAGIC
+                       dont_measure fsmagic=0x6e736673
+                       dont_appraise fsmagic=0x6e736673
 
                        measure func=BPRM_CHECK
                        measure func=FILE_MMAP mask=MAY_EXEC
@@ -70,10 +86,6 @@ Description:
                Examples of LSM specific definitions:
 
                SELinux:
-                       # SELINUX_MAGIC
-                       dont_measure fsmagic=0xf97cff8c
-                       dont_appraise fsmagic=0xf97cff8c
-
                        dont_measure obj_type=var_log_t
                        dont_appraise obj_type=var_log_t
                        dont_measure obj_type=auditd_log_t
index 8bb54c9..afe7e2b 100644 (file)
@@ -1413,7 +1413,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        The list of supported hash algorithms is defined
                        in crypto/hash_info.h.
 
-       ima_tcb         [IMA]
+       ima_policy=     [IMA]
+                       The builtin measurement policy to load during IMA
+                       setup.  Specyfing "tcb" as the value, measures all
+                       programs exec'd, files mmap'd for exec, and all files
+                       opened with the read mode bit set by either the
+                       effective uid (euid=0) or uid=0.
+                       Format: "tcb"
+
+       ima_tcb         [IMA] Deprecated.  Use ima_policy= instead.
                        Load a policy which meets the needs of the Trusted
                        Computing Base.  This means IMA will measure all
                        programs exec'd, files mmap'd for exec, and all files
@@ -1421,7 +1429,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        ima_template=   [IMA]
                        Select one of defined IMA measurements template formats.
-                       Formats: { "ima" | "ima-ng" }
+                       Formats: { "ima" | "ima-ng" | "ima-sig" }
                        Default: "ima-ng"
 
        ima_template_fmt=
index abc82f8..de5e1ae 100644 (file)
@@ -206,11 +206,11 @@ netlabel
        label. The format accepted on write is:
                "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
 onlycap
-       This contains the label processes must have for CAP_MAC_ADMIN
+       This contains labels processes must have for CAP_MAC_ADMIN
        and CAP_MAC_OVERRIDE to be effective. If this file is empty
        these capabilities are effective at for processes with any
-       label. The value is set by writing the desired label to the
-       file or cleared by writing "-" to the file.
+       label. The values are set by writing the desired labels, separated
+       by spaces, to the file or cleared by writing "-" to the file.
 ptrace
        This is used to define the current ptrace policy
        0 - default: this is the policy that relies on Smack access rules.
index f973308..3f5b537 100644 (file)
@@ -11,6 +11,9 @@
 
 extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id);
 
+extern int __asymmetric_key_hex_to_key_id(const char *id,
+                                         struct asymmetric_key_id *match_id,
+                                         size_t hexlen);
 static inline
 const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
 {
index bcbbbd7..b0e4ed2 100644 (file)
@@ -104,6 +104,15 @@ static bool asymmetric_match_key_ids(
        return false;
 }
 
+/* helper function can be called directly with pre-allocated memory */
+inline int __asymmetric_key_hex_to_key_id(const char *id,
+                                  struct asymmetric_key_id *match_id,
+                                  size_t hexlen)
+{
+       match_id->len = hexlen;
+       return hex2bin(match_id->data, id, hexlen);
+}
+
 /**
  * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
  * @id: The ID as a hex string.
@@ -111,21 +120,20 @@ static bool asymmetric_match_key_ids(
 struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
 {
        struct asymmetric_key_id *match_id;
-       size_t hexlen;
+       size_t asciihexlen;
        int ret;
 
        if (!*id)
                return ERR_PTR(-EINVAL);
-       hexlen = strlen(id);
-       if (hexlen & 1)
+       asciihexlen = strlen(id);
+       if (asciihexlen & 1)
                return ERR_PTR(-EINVAL);
 
-       match_id = kmalloc(sizeof(struct asymmetric_key_id) + hexlen / 2,
+       match_id = kmalloc(sizeof(struct asymmetric_key_id) + asciihexlen / 2,
                           GFP_KERNEL);
        if (!match_id)
                return ERR_PTR(-ENOMEM);
-       match_id->len = hexlen / 2;
-       ret = hex2bin(match_id->data, id, hexlen / 2);
+       ret = __asymmetric_key_hex_to_key_id(id, match_id, asciihexlen / 2);
        if (ret < 0) {
                kfree(match_id);
                return ERR_PTR(-EINVAL);
index a6c4203..24f17e6 100644 (file)
@@ -28,17 +28,30 @@ static bool use_builtin_keys;
 static struct asymmetric_key_id *ca_keyid;
 
 #ifndef MODULE
+static struct {
+       struct asymmetric_key_id id;
+       unsigned char data[10];
+} cakey;
+
 static int __init ca_keys_setup(char *str)
 {
        if (!str)               /* default system keyring */
                return 1;
 
        if (strncmp(str, "id:", 3) == 0) {
-               struct asymmetric_key_id *p;
-               p = asymmetric_key_hex_to_key_id(str + 3);
-               if (p == ERR_PTR(-EINVAL))
-                       pr_err("Unparsable hex string in ca_keys\n");
-               else if (!IS_ERR(p))
+               struct asymmetric_key_id *p = &cakey.id;
+               size_t hexlen = (strlen(str) - 3) / 2;
+               int ret;
+
+               if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
+                       pr_err("Missing or invalid ca_keys id\n");
+                       return 1;
+               }
+
+               ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
+               if (ret < 0)
+                       pr_err("Unparsable ca_keys id hex string\n");
+               else
                        ca_keyid = p;   /* owner key 'id:xxxxxx' */
        } else if (strcmp(str, "builtin") == 0) {
                use_builtin_keys = true;
index b26ceee..44f9d20 100644 (file)
@@ -267,7 +267,7 @@ static int crb_acpi_add(struct acpi_device *device)
 
        memcpy_fromio(&pa, &priv->cca->cmd_pa, 8);
        pa = le64_to_cpu(pa);
-       priv->cmd = devm_ioremap_nocache(dev, le64_to_cpu(pa),
+       priv->cmd = devm_ioremap_nocache(dev, pa,
                                         ioread32(&priv->cca->cmd_size));
        if (!priv->cmd) {
                dev_err(dev, "ioremap of the command buffer failed\n");
@@ -276,7 +276,7 @@ static int crb_acpi_add(struct acpi_device *device)
 
        memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
        pa = le64_to_cpu(pa);
-       priv->rsp = devm_ioremap_nocache(dev, le64_to_cpu(pa),
+       priv->rsp = devm_ioremap_nocache(dev, pa,
                                         ioread32(&priv->cca->rsp_size));
        if (!priv->rsp) {
                dev_err(dev, "ioremap of the response buffer failed\n");
index 42ffa5e..27ebf95 100644 (file)
@@ -578,6 +578,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
                goto cleanup;
        }
 
+       ibmvtpm->dev = dev;
+       ibmvtpm->vdev = vio_dev;
+
        crq_q = &ibmvtpm->crq_queue;
        crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL);
        if (!crq_q->crq_addr) {
@@ -622,8 +625,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
 
        crq_q->index = 0;
 
-       ibmvtpm->dev = dev;
-       ibmvtpm->vdev = vio_dev;
        TPM_VPRIV(chip) = (void *)ibmvtpm;
 
        spin_lock_init(&ibmvtpm->rtce_lock);
index c002d1b..eebe625 100644 (file)
@@ -49,7 +49,7 @@ int read_log(struct tpm_bios_log *log)
 
        basep = of_get_property(np, "linux,sml-base", NULL);
        if (basep == NULL) {
-               pr_err(KERN_ERR "%s: ERROR - SML not found\n", __func__);
+               pr_err("%s: ERROR - SML not found\n", __func__);
                goto cleanup_eio;
        }
 
index 4ef6985..072fee1 100644 (file)
@@ -298,18 +298,18 @@ vfs_removexattr(struct dentry *dentry, const char *name)
 
        mutex_lock(&inode->i_mutex);
        error = security_inode_removexattr(dentry, name);
-       if (error) {
-               mutex_unlock(&inode->i_mutex);
-               return error;
-       }
+       if (error)
+               goto out;
 
        error = inode->i_op->removexattr(dentry, name);
-       mutex_unlock(&inode->i_mutex);
 
        if (!error) {
                fsnotify_xattr(dentry);
                evm_inode_post_removexattr(dentry, name);
        }
+
+out:
+       mutex_unlock(&inode->i_mutex);
        return error;
 }
 EXPORT_SYMBOL_GPL(vfs_removexattr);
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
new file mode 100644 (file)
index 0000000..9429f05
--- /dev/null
@@ -0,0 +1,1888 @@
+/*
+ * Linux Security Module interfaces
+ *
+ * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
+ * Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
+ * Copyright (C) 2001 James Morris <jmorris@intercode.com.au>
+ * Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
+ * Copyright (C) 2015 Intel Corporation.
+ * Copyright (C) 2015 Casey Schaufler <casey@schaufler-ca.com>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     Due to this file being licensed under the GPL there is controversy over
+ *     whether this permits you to write a module that #includes this file
+ *     without placing your module under the GPL.  Please consult a lawyer for
+ *     advice before doing this.
+ *
+ */
+
+#ifndef __LINUX_LSM_HOOKS_H
+#define __LINUX_LSM_HOOKS_H
+
+#include <linux/security.h>
+#include <linux/init.h>
+#include <linux/rculist.h>
+
+/**
+ * Security hooks for program execution operations.
+ *
+ * @bprm_set_creds:
+ *     Save security information in the bprm->security field, typically based
+ *     on information about the bprm->file, for later use by the apply_creds
+ *     hook.  This hook may also optionally check permissions (e.g. for
+ *     transitions between security domains).
+ *     This hook may be called multiple times during a single execve, e.g. for
+ *     interpreters.  The hook can tell whether it has already been called by
+ *     checking to see if @bprm->security is non-NULL.  If so, then the hook
+ *     may decide either to retain the security information saved earlier or
+ *     to replace it.
+ *     @bprm contains the linux_binprm structure.
+ *     Return 0 if the hook is successful and permission is granted.
+ * @bprm_check_security:
+ *     This hook mediates the point when a search for a binary handler will
+ *     begin.  It allows a check the @bprm->security value which is set in the
+ *     preceding set_creds call.  The primary difference from set_creds is
+ *     that the argv list and envp list are reliably available in @bprm.  This
+ *     hook may be called multiple times during a single execve; and in each
+ *     pass set_creds is called first.
+ *     @bprm contains the linux_binprm structure.
+ *     Return 0 if the hook is successful and permission is granted.
+ * @bprm_committing_creds:
+ *     Prepare to install the new security attributes of a process being
+ *     transformed by an execve operation, based on the old credentials
+ *     pointed to by @current->cred and the information set in @bprm->cred by
+ *     the bprm_set_creds hook.  @bprm points to the linux_binprm structure.
+ *     This hook is a good place to perform state changes on the process such
+ *     as closing open file descriptors to which access will no longer be
+ *     granted when the attributes are changed.  This is called immediately
+ *     before commit_creds().
+ * @bprm_committed_creds:
+ *     Tidy up after the installation of the new security attributes of a
+ *     process being transformed by an execve operation.  The new credentials
+ *     have, by this point, been set to @current->cred.  @bprm points to the
+ *     linux_binprm structure.  This hook is a good place to perform state
+ *     changes on the process such as clearing out non-inheritable signal
+ *     state.  This is called immediately after commit_creds().
+ * @bprm_secureexec:
+ *     Return a boolean value (0 or 1) indicating whether a "secure exec"
+ *     is required.  The flag is passed in the auxiliary table
+ *     on the initial stack to the ELF interpreter to indicate whether libc
+ *     should enable secure mode.
+ *     @bprm contains the linux_binprm structure.
+ *
+ * Security hooks for filesystem operations.
+ *
+ * @sb_alloc_security:
+ *     Allocate and attach a security structure to the sb->s_security field.
+ *     The s_security field is initialized to NULL when the structure is
+ *     allocated.
+ *     @sb contains the super_block structure to be modified.
+ *     Return 0 if operation was successful.
+ * @sb_free_security:
+ *     Deallocate and clear the sb->s_security field.
+ *     @sb contains the super_block structure to be modified.
+ * @sb_statfs:
+ *     Check permission before obtaining filesystem statistics for the @mnt
+ *     mountpoint.
+ *     @dentry is a handle on the superblock for the filesystem.
+ *     Return 0 if permission is granted.
+ * @sb_mount:
+ *     Check permission before an object specified by @dev_name is mounted on
+ *     the mount point named by @nd.  For an ordinary mount, @dev_name
+ *     identifies a device if the file system type requires a device.  For a
+ *     remount (@flags & MS_REMOUNT), @dev_name is irrelevant.  For a
+ *     loopback/bind mount (@flags & MS_BIND), @dev_name identifies the
+ *     pathname of the object being mounted.
+ *     @dev_name contains the name for object being mounted.
+ *     @path contains the path for mount point object.
+ *     @type contains the filesystem type.
+ *     @flags contains the mount flags.
+ *     @data contains the filesystem-specific data.
+ *     Return 0 if permission is granted.
+ * @sb_copy_data:
+ *     Allow mount option data to be copied prior to parsing by the filesystem,
+ *     so that the security module can extract security-specific mount
+ *     options cleanly (a filesystem may modify the data e.g. with strsep()).
+ *     This also allows the original mount data to be stripped of security-
+ *     specific options to avoid having to make filesystems aware of them.
+ *     @type the type of filesystem being mounted.
+ *     @orig the original mount data copied from userspace.
+ *     @copy copied data which will be passed to the security module.
+ *     Returns 0 if the copy was successful.
+ * @sb_remount:
+ *     Extracts security system specific mount options and verifies no changes
+ *     are being made to those options.
+ *     @sb superblock being remounted
+ *     @data contains the filesystem-specific data.
+ *     Return 0 if permission is granted.
+ * @sb_umount:
+ *     Check permission before the @mnt file system is unmounted.
+ *     @mnt contains the mounted file system.
+ *     @flags contains the unmount flags, e.g. MNT_FORCE.
+ *     Return 0 if permission is granted.
+ * @sb_pivotroot:
+ *     Check permission before pivoting the root filesystem.
+ *     @old_path contains the path for the new location of the
+ *     current root (put_old).
+ *     @new_path contains the path for the new root (new_root).
+ *     Return 0 if permission is granted.
+ * @sb_set_mnt_opts:
+ *     Set the security relevant mount options used for a superblock
+ *     @sb the superblock to set security mount options for
+ *     @opts binary data structure containing all lsm mount data
+ * @sb_clone_mnt_opts:
+ *     Copy all security options from a given superblock to another
+ *     @oldsb old superblock which contain information to clone
+ *     @newsb new superblock which needs filled in
+ * @sb_parse_opts_str:
+ *     Parse a string of security data filling in the opts structure
+ *     @options string containing all mount options known by the LSM
+ *     @opts binary data structure usable by the LSM
+ * @dentry_init_security:
+ *     Compute a context for a dentry as the inode is not yet available
+ *     since NFSv4 has no label backed by an EA anyway.
+ *     @dentry dentry to use in calculating the context.
+ *     @mode mode used to determine resource type.
+ *     @name name of the last path component used to create file
+ *     @ctx pointer to place the pointer to the resulting context in.
+ *     @ctxlen point to place the length of the resulting context.
+ *
+ *
+ * Security hooks for inode operations.
+ *
+ * @inode_alloc_security:
+ *     Allocate and attach a security structure to @inode->i_security.  The
+ *     i_security field is initialized to NULL when the inode structure is
+ *     allocated.
+ *     @inode contains the inode structure.
+ *     Return 0 if operation was successful.
+ * @inode_free_security:
+ *     @inode contains the inode structure.
+ *     Deallocate the inode security structure and set @inode->i_security to
+ *     NULL.
+ * @inode_init_security:
+ *     Obtain the security attribute name suffix and value to set on a newly
+ *     created inode and set up the incore security field for the new inode.
+ *     This hook is called by the fs code as part of the inode creation
+ *     transaction and provides for atomic labeling of the inode, unlike
+ *     the post_create/mkdir/... hooks called by the VFS.  The hook function
+ *     is expected to allocate the name and value via kmalloc, with the caller
+ *     being responsible for calling kfree after using them.
+ *     If the security module does not use security attributes or does
+ *     not wish to put a security attribute on this particular inode,
+ *     then it should return -EOPNOTSUPP to skip this processing.
+ *     @inode contains the inode structure of the newly created inode.
+ *     @dir contains the inode structure of the parent directory.
+ *     @qstr contains the last path component of the new object
+ *     @name will be set to the allocated name suffix (e.g. selinux).
+ *     @value will be set to the allocated attribute value.
+ *     @len will be set to the length of the value.
+ *     Returns 0 if @name and @value have been successfully set,
+ *             -EOPNOTSUPP if no security attribute is needed, or
+ *             -ENOMEM on memory allocation failure.
+ * @inode_create:
+ *     Check permission to create a regular file.
+ *     @dir contains inode structure of the parent of the new file.
+ *     @dentry contains the dentry structure for the file to be created.
+ *     @mode contains the file mode of the file to be created.
+ *     Return 0 if permission is granted.
+ * @inode_link:
+ *     Check permission before creating a new hard link to a file.
+ *     @old_dentry contains the dentry structure for an existing
+ *     link to the file.
+ *     @dir contains the inode structure of the parent directory
+ *     of the new link.
+ *     @new_dentry contains the dentry structure for the new link.
+ *     Return 0 if permission is granted.
+ * @path_link:
+ *     Check permission before creating a new hard link to a file.
+ *     @old_dentry contains the dentry structure for an existing link
+ *     to the file.
+ *     @new_dir contains the path structure of the parent directory of
+ *     the new link.
+ *     @new_dentry contains the dentry structure for the new link.
+ *     Return 0 if permission is granted.
+ * @inode_unlink:
+ *     Check the permission to remove a hard link to a file.
+ *     @dir contains the inode structure of parent directory of the file.
+ *     @dentry contains the dentry structure for file to be unlinked.
+ *     Return 0 if permission is granted.
+ * @path_unlink:
+ *     Check the permission to remove a hard link to a file.
+ *     @dir contains the path structure of parent directory of the file.
+ *     @dentry contains the dentry structure for file to be unlinked.
+ *     Return 0 if permission is granted.
+ * @inode_symlink:
+ *     Check the permission to create a symbolic link to a file.
+ *     @dir contains the inode structure of parent directory of
+ *     the symbolic link.
+ *     @dentry contains the dentry structure of the symbolic link.
+ *     @old_name contains the pathname of file.
+ *     Return 0 if permission is granted.
+ * @path_symlink:
+ *     Check the permission to create a symbolic link to a file.
+ *     @dir contains the path structure of parent directory of
+ *     the symbolic link.
+ *     @dentry contains the dentry structure of the symbolic link.
+ *     @old_name contains the pathname of file.
+ *     Return 0 if permission is granted.
+ * @inode_mkdir:
+ *     Check permissions to create a new directory in the existing directory
+ *     associated with inode structure @dir.
+ *     @dir contains the inode structure of parent of the directory
+ *     to be created.
+ *     @dentry contains the dentry structure of new directory.
+ *     @mode contains the mode of new directory.
+ *     Return 0 if permission is granted.
+ * @path_mkdir:
+ *     Check permissions to create a new directory in the existing directory
+ *     associated with path structure @path.
+ *     @dir contains the path structure of parent of the directory
+ *     to be created.
+ *     @dentry contains the dentry structure of new directory.
+ *     @mode contains the mode of new directory.
+ *     Return 0 if permission is granted.
+ * @inode_rmdir:
+ *     Check the permission to remove a directory.
+ *     @dir contains the inode structure of parent of the directory
+ *     to be removed.
+ *     @dentry contains the dentry structure of directory to be removed.
+ *     Return 0 if permission is granted.
+ * @path_rmdir:
+ *     Check the permission to remove a directory.
+ *     @dir contains the path structure of parent of the directory to be
+ *     removed.
+ *     @dentry contains the dentry structure of directory to be removed.
+ *     Return 0 if permission is granted.
+ * @inode_mknod:
+ *     Check permissions when creating a special file (or a socket or a fifo
+ *     file created via the mknod system call).  Note that if mknod operation
+ *     is being done for a regular file, then the create hook will be called
+ *     and not this hook.
+ *     @dir contains the inode structure of parent of the new file.
+ *     @dentry contains the dentry structure of the new file.
+ *     @mode contains the mode of the new file.
+ *     @dev contains the device number.
+ *     Return 0 if permission is granted.
+ * @path_mknod:
+ *     Check permissions when creating a file. Note that this hook is called
+ *     even if mknod operation is being done for a regular file.
+ *     @dir contains the path structure of parent of the new file.
+ *     @dentry contains the dentry structure of the new file.
+ *     @mode contains the mode of the new file.
+ *     @dev contains the undecoded device number. Use new_decode_dev() to get
+ *     the decoded device number.
+ *     Return 0 if permission is granted.
+ * @inode_rename:
+ *     Check for permission to rename a file or directory.
+ *     @old_dir contains the inode structure for parent of the old link.
+ *     @old_dentry contains the dentry structure of the old link.
+ *     @new_dir contains the inode structure for parent of the new link.
+ *     @new_dentry contains the dentry structure of the new link.
+ *     Return 0 if permission is granted.
+ * @path_rename:
+ *     Check for permission to rename a file or directory.
+ *     @old_dir contains the path structure for parent of the old link.
+ *     @old_dentry contains the dentry structure of the old link.
+ *     @new_dir contains the path structure for parent of the new link.
+ *     @new_dentry contains the dentry structure of the new link.
+ *     Return 0 if permission is granted.
+ * @path_chmod:
+ *     Check for permission to change DAC's permission of a file or directory.
+ *     @dentry contains the dentry structure.
+ *     @mnt contains the vfsmnt structure.
+ *     @mode contains DAC's mode.
+ *     Return 0 if permission is granted.
+ * @path_chown:
+ *     Check for permission to change owner/group of a file or directory.
+ *     @path contains the path structure.
+ *     @uid contains new owner's ID.
+ *     @gid contains new group's ID.
+ *     Return 0 if permission is granted.
+ * @path_chroot:
+ *     Check for permission to change root directory.
+ *     @path contains the path structure.
+ *     Return 0 if permission is granted.
+ * @inode_readlink:
+ *     Check the permission to read the symbolic link.
+ *     @dentry contains the dentry structure for the file link.
+ *     Return 0 if permission is granted.
+ * @inode_follow_link:
+ *     Check permission to follow a symbolic link when looking up a pathname.
+ *     @dentry contains the dentry structure for the link.
+ *     @inode contains the inode, which itself is not stable in RCU-walk
+ *     @rcu indicates whether we are in RCU-walk mode.
+ *     Return 0 if permission is granted.
+ * @inode_permission:
+ *     Check permission before accessing an inode.  This hook is called by the
+ *     existing Linux permission function, so a security module can use it to
+ *     provide additional checking for existing Linux permission checks.
+ *     Notice that this hook is called when a file is opened (as well as many
+ *     other operations), whereas the file_security_ops permission hook is
+ *     called when the actual read/write operations are performed.
+ *     @inode contains the inode structure to check.
+ *     @mask contains the permission mask.
+ *     Return 0 if permission is granted.
+ * @inode_setattr:
+ *     Check permission before setting file attributes.  Note that the kernel
+ *     call to notify_change is performed from several locations, whenever
+ *     file attributes change (such as when a file is truncated, chown/chmod
+ *     operations, transferring disk quotas, etc).
+ *     @dentry contains the dentry structure for the file.
+ *     @attr is the iattr structure containing the new file attributes.
+ *     Return 0 if permission is granted.
+ * @path_truncate:
+ *     Check permission before truncating a file.
+ *     @path contains the path structure for the file.
+ *     Return 0 if permission is granted.
+ * @inode_getattr:
+ *     Check permission before obtaining file attributes.
+ *     @mnt is the vfsmount where the dentry was looked up
+ *     @dentry contains the dentry structure for the file.
+ *     Return 0 if permission is granted.
+ * @inode_setxattr:
+ *     Check permission before setting the extended attributes
+ *     @value identified by @name for @dentry.
+ *     Return 0 if permission is granted.
+ * @inode_post_setxattr:
+ *     Update inode security field after successful setxattr operation.
+ *     @value identified by @name for @dentry.
+ * @inode_getxattr:
+ *     Check permission before obtaining the extended attributes
+ *     identified by @name for @dentry.
+ *     Return 0 if permission is granted.
+ * @inode_listxattr:
+ *     Check permission before obtaining the list of extended attribute
+ *     names for @dentry.
+ *     Return 0 if permission is granted.
+ * @inode_removexattr:
+ *     Check permission before removing the extended attribute
+ *     identified by @name for @dentry.
+ *     Return 0 if permission is granted.
+ * @inode_getsecurity:
+ *     Retrieve a copy of the extended attribute representation of the
+ *     security label associated with @name for @inode via @buffer.  Note that
+ *     @name is the remainder of the attribute name after the security prefix
+ *     has been removed. @alloc is used to specify of the call should return a
+ *     value via the buffer or just the value length Return size of buffer on
+ *     success.
+ * @inode_setsecurity:
+ *     Set the security label associated with @name for @inode from the
+ *     extended attribute value @value.  @size indicates the size of the
+ *     @value in bytes.  @flags may be XATTR_CREATE, XATTR_REPLACE, or 0.
+ *     Note that @name is the remainder of the attribute name after the
+ *     security. prefix has been removed.
+ *     Return 0 on success.
+ * @inode_listsecurity:
+ *     Copy the extended attribute names for the security labels
+ *     associated with @inode into @buffer.  The maximum size of @buffer
+ *     is specified by @buffer_size.  @buffer may be NULL to request
+ *     the size of the buffer required.
+ *     Returns number of bytes used/required on success.
+ * @inode_need_killpriv:
+ *     Called when an inode has been changed.
+ *     @dentry is the dentry being changed.
+ *     Return <0 on error to abort the inode change operation.
+ *     Return 0 if inode_killpriv does not need to be called.
+ *     Return >0 if inode_killpriv does need to be called.
+ * @inode_killpriv:
+ *     The setuid bit is being removed.  Remove similar security labels.
+ *     Called with the dentry->d_inode->i_mutex held.
+ *     @dentry is the dentry being changed.
+ *     Return 0 on success.  If error is returned, then the operation
+ *     causing setuid bit removal is failed.
+ * @inode_getsecid:
+ *     Get the secid associated with the node.
+ *     @inode contains a pointer to the inode.
+ *     @secid contains a pointer to the location where result will be saved.
+ *     In case of failure, @secid will be set to zero.
+ *
+ * Security hooks for file operations
+ *
+ * @file_permission:
+ *     Check file permissions before accessing an open file.  This hook is
+ *     called by various operations that read or write files.  A security
+ *     module can use this hook to perform additional checking on these
+ *     operations, e.g.  to revalidate permissions on use to support privilege
+ *     bracketing or policy changes.  Notice that this hook is used when the
+ *     actual read/write operations are performed, whereas the
+ *     inode_security_ops hook is called when a file is opened (as well as
+ *     many other operations).
+ *     Caveat:  Although this hook can be used to revalidate permissions for
+ *     various system call operations that read or write files, it does not
+ *     address the revalidation of permissions for memory-mapped files.
+ *     Security modules must handle this separately if they need such
+ *     revalidation.
+ *     @file contains the file structure being accessed.
+ *     @mask contains the requested permissions.
+ *     Return 0 if permission is granted.
+ * @file_alloc_security:
+ *     Allocate and attach a security structure to the file->f_security field.
+ *     The security field is initialized to NULL when the structure is first
+ *     created.
+ *     @file contains the file structure to secure.
+ *     Return 0 if the hook is successful and permission is granted.
+ * @file_free_security:
+ *     Deallocate and free any security structures stored in file->f_security.
+ *     @file contains the file structure being modified.
+ * @file_ioctl:
+ *     @file contains the file structure.
+ *     @cmd contains the operation to perform.
+ *     @arg contains the operational arguments.
+ *     Check permission for an ioctl operation on @file.  Note that @arg
+ *     sometimes represents a user space pointer; in other cases, it may be a
+ *     simple integer value.  When @arg represents a user space pointer, it
+ *     should never be used by the security module.
+ *     Return 0 if permission is granted.
+ * @mmap_addr :
+ *     Check permissions for a mmap operation at @addr.
+ *     @addr contains virtual address that will be used for the operation.
+ *     Return 0 if permission is granted.
+ * @mmap_file :
+ *     Check permissions for a mmap operation.  The @file may be NULL, e.g.
+ *     if mapping anonymous memory.
+ *     @file contains the file structure for file to map (may be NULL).
+ *     @reqprot contains the protection requested by the application.
+ *     @prot contains the protection that will be applied by the kernel.
+ *     @flags contains the operational flags.
+ *     Return 0 if permission is granted.
+ * @file_mprotect:
+ *     Check permissions before changing memory access permissions.
+ *     @vma contains the memory region to modify.
+ *     @reqprot contains the protection requested by the application.
+ *     @prot contains the protection that will be applied by the kernel.
+ *     Return 0 if permission is granted.
+ * @file_lock:
+ *     Check permission before performing file locking operations.
+ *     Note: this hook mediates both flock and fcntl style locks.
+ *     @file contains the file structure.
+ *     @cmd contains the posix-translated lock operation to perform
+ *     (e.g. F_RDLCK, F_WRLCK).
+ *     Return 0 if permission is granted.
+ * @file_fcntl:
+ *     Check permission before allowing the file operation specified by @cmd
+ *     from being performed on the file @file.  Note that @arg sometimes
+ *     represents a user space pointer; in other cases, it may be a simple
+ *     integer value.  When @arg represents a user space pointer, it should
+ *     never be used by the security module.
+ *     @file contains the file structure.
+ *     @cmd contains the operation to be performed.
+ *     @arg contains the operational arguments.
+ *     Return 0 if permission is granted.
+ * @file_set_fowner:
+ *     Save owner security information (typically from current->security) in
+ *     file->f_security for later use by the send_sigiotask hook.
+ *     @file contains the file structure to update.
+ *     Return 0 on success.
+ * @file_send_sigiotask:
+ *     Check permission for the file owner @fown to send SIGIO or SIGURG to the
+ *     process @tsk.  Note that this hook is sometimes called from interrupt.
+ *     Note that the fown_struct, @fown, is never outside the context of a
+ *     struct file, so the file structure (and associated security information)
+ *     can always be obtained:
+ *             container_of(fown, struct file, f_owner)
+ *     @tsk contains the structure of task receiving signal.
+ *     @fown contains the file owner information.
+ *     @sig is the signal that will be sent.  When 0, kernel sends SIGIO.
+ *     Return 0 if permission is granted.
+ * @file_receive:
+ *     This hook allows security modules to control the ability of a process
+ *     to receive an open file descriptor via socket IPC.
+ *     @file contains the file structure being received.
+ *     Return 0 if permission is granted.
+ * @file_open
+ *     Save open-time permission checking state for later use upon
+ *     file_permission, and recheck access if anything has changed
+ *     since inode_permission.
+ *
+ * Security hooks for task operations.
+ *
+ * @task_create:
+ *     Check permission before creating a child process.  See the clone(2)
+ *     manual page for definitions of the @clone_flags.
+ *     @clone_flags contains the flags indicating what should be shared.
+ *     Return 0 if permission is granted.
+ * @task_free:
+ *     @task task being freed
+ *     Handle release of task-related resources. (Note that this can be called
+ *     from interrupt context.)
+ * @cred_alloc_blank:
+ *     @cred points to the credentials.
+ *     @gfp indicates the atomicity of any memory allocations.
+ *     Only allocate sufficient memory and attach to @cred such that
+ *     cred_transfer() will not get ENOMEM.
+ * @cred_free:
+ *     @cred points to the credentials.
+ *     Deallocate and clear the cred->security field in a set of credentials.
+ * @cred_prepare:
+ *     @new points to the new credentials.
+ *     @old points to the original credentials.
+ *     @gfp indicates the atomicity of any memory allocations.
+ *     Prepare a new set of credentials by copying the data from the old set.
+ * @cred_transfer:
+ *     @new points to the new credentials.
+ *     @old points to the original credentials.
+ *     Transfer data from original creds to new creds
+ * @kernel_act_as:
+ *     Set the credentials for a kernel service to act as (subjective context).
+ *     @new points to the credentials to be modified.
+ *     @secid specifies the security ID to be set
+ *     The current task must be the one that nominated @secid.
+ *     Return 0 if successful.
+ * @kernel_create_files_as:
+ *     Set the file creation context in a set of credentials to be the same as
+ *     the objective context of the specified inode.
+ *     @new points to the credentials to be modified.
+ *     @inode points to the inode to use as a reference.
+ *     The current task must be the one that nominated @inode.
+ *     Return 0 if successful.
+ * @kernel_fw_from_file:
+ *     Load firmware from userspace (not called for built-in firmware).
+ *     @file contains the file structure pointing to the file containing
+ *     the firmware to load. This argument will be NULL if the firmware
+ *     was loaded via the uevent-triggered blob-based interface exposed
+ *     by CONFIG_FW_LOADER_USER_HELPER.
+ *     @buf pointer to buffer containing firmware contents.
+ *     @size length of the firmware contents.
+ *     Return 0 if permission is granted.
+ * @kernel_module_request:
+ *     Ability to trigger the kernel to automatically upcall to userspace for
+ *     userspace to load a kernel module with the given name.
+ *     @kmod_name name of the module requested by the kernel
+ *     Return 0 if successful.
+ * @kernel_module_from_file:
+ *     Load a kernel module from userspace.
+ *     @file contains the file structure pointing to the file containing
+ *     the kernel module to load. If the module is being loaded from a blob,
+ *     this argument will be NULL.
+ *     Return 0 if permission is granted.
+ * @task_fix_setuid:
+ *     Update the module's state after setting one or more of the user
+ *     identity attributes of the current process.  The @flags parameter
+ *     indicates which of the set*uid system calls invoked this hook.  If
+ *     @new is the set of credentials that will be installed.  Modifications
+ *     should be made to this rather than to @current->cred.
+ *     @old is the set of credentials that are being replaces
+ *     @flags contains one of the LSM_SETID_* values.
+ *     Return 0 on success.
+ * @task_setpgid:
+ *     Check permission before setting the process group identifier of the
+ *     process @p to @pgid.
+ *     @p contains the task_struct for process being modified.
+ *     @pgid contains the new pgid.
+ *     Return 0 if permission is granted.
+ * @task_getpgid:
+ *     Check permission before getting the process group identifier of the
+ *     process @p.
+ *     @p contains the task_struct for the process.
+ *     Return 0 if permission is granted.
+ * @task_getsid:
+ *     Check permission before getting the session identifier of the process
+ *     @p.
+ *     @p contains the task_struct for the process.
+ *     Return 0 if permission is granted.
+ * @task_getsecid:
+ *     Retrieve the security identifier of the process @p.
+ *     @p contains the task_struct for the process and place is into @secid.
+ *     In case of failure, @secid will be set to zero.
+ *
+ * @task_setnice:
+ *     Check permission before setting the nice value of @p to @nice.
+ *     @p contains the task_struct of process.
+ *     @nice contains the new nice value.
+ *     Return 0 if permission is granted.
+ * @task_setioprio
+ *     Check permission before setting the ioprio value of @p to @ioprio.
+ *     @p contains the task_struct of process.
+ *     @ioprio contains the new ioprio value
+ *     Return 0 if permission is granted.
+ * @task_getioprio
+ *     Check permission before getting the ioprio value of @p.
+ *     @p contains the task_struct of process.
+ *     Return 0 if permission is granted.
+ * @task_setrlimit:
+ *     Check permission before setting the resource limits of the current
+ *     process for @resource to @new_rlim.  The old resource limit values can
+ *     be examined by dereferencing (current->signal->rlim + resource).
+ *     @resource contains the resource whose limit is being set.
+ *     @new_rlim contains the new limits for @resource.
+ *     Return 0 if permission is granted.
+ * @task_setscheduler:
+ *     Check permission before setting scheduling policy and/or parameters of
+ *     process @p based on @policy and @lp.
+ *     @p contains the task_struct for process.
+ *     @policy contains the scheduling policy.
+ *     @lp contains the scheduling parameters.
+ *     Return 0 if permission is granted.
+ * @task_getscheduler:
+ *     Check permission before obtaining scheduling information for process
+ *     @p.
+ *     @p contains the task_struct for process.
+ *     Return 0 if permission is granted.
+ * @task_movememory
+ *     Check permission before moving memory owned by process @p.
+ *     @p contains the task_struct for process.
+ *     Return 0 if permission is granted.
+ * @task_kill:
+ *     Check permission before sending signal @sig to @p.  @info can be NULL,
+ *     the constant 1, or a pointer to a siginfo structure.  If @info is 1 or
+ *     SI_FROMKERNEL(info) is true, then the signal should be viewed as coming
+ *     from the kernel and should typically be permitted.
+ *     SIGIO signals are handled separately by the send_sigiotask hook in
+ *     file_security_ops.
+ *     @p contains the task_struct for process.
+ *     @info contains the signal information.
+ *     @sig contains the signal value.
+ *     @secid contains the sid of the process where the signal originated
+ *     Return 0 if permission is granted.
+ * @task_wait:
+ *     Check permission before allowing a process to reap a child process @p
+ *     and collect its status information.
+ *     @p contains the task_struct for process.
+ *     Return 0 if permission is granted.
+ * @task_prctl:
+ *     Check permission before performing a process control operation on the
+ *     current process.
+ *     @option contains the operation.
+ *     @arg2 contains a argument.
+ *     @arg3 contains a argument.
+ *     @arg4 contains a argument.
+ *     @arg5 contains a argument.
+ *     Return -ENOSYS if no-one wanted to handle this op, any other value to
+ *     cause prctl() to return immediately with that value.
+ * @task_to_inode:
+ *     Set the security attributes for an inode based on an associated task's
+ *     security attributes, e.g. for /proc/pid inodes.
+ *     @p contains the task_struct for the task.
+ *     @inode contains the inode structure for the inode.
+ *
+ * Security hooks for Netlink messaging.
+ *
+ * @netlink_send:
+ *     Save security information for a netlink message so that permission
+ *     checking can be performed when the message is processed.  The security
+ *     information can be saved using the eff_cap field of the
+ *     netlink_skb_parms structure.  Also may be used to provide fine
+ *     grained control over message transmission.
+ *     @sk associated sock of task sending the message.
+ *     @skb contains the sk_buff structure for the netlink message.
+ *     Return 0 if the information was successfully saved and message
+ *     is allowed to be transmitted.
+ *
+ * Security hooks for Unix domain networking.
+ *
+ * @unix_stream_connect:
+ *     Check permissions before establishing a Unix domain stream connection
+ *     between @sock and @other.
+ *     @sock contains the sock structure.
+ *     @other contains the peer sock structure.
+ *     @newsk contains the new sock structure.
+ *     Return 0 if permission is granted.
+ * @unix_may_send:
+ *     Check permissions before connecting or sending datagrams from @sock to
+ *     @other.
+ *     @sock contains the socket structure.
+ *     @other contains the peer socket structure.
+ *     Return 0 if permission is granted.
+ *
+ * The @unix_stream_connect and @unix_may_send hooks were necessary because
+ * Linux provides an alternative to the conventional file name space for Unix
+ * domain sockets.  Whereas binding and connecting to sockets in the file name
+ * space is mediated by the typical file permissions (and caught by the mknod
+ * and permission hooks in inode_security_ops), binding and connecting to
+ * sockets in the abstract name space is completely unmediated.  Sufficient
+ * control of Unix domain sockets in the abstract name space isn't possible
+ * using only the socket layer hooks, since we need to know the actual target
+ * socket, which is not looked up until we are inside the af_unix code.
+ *
+ * Security hooks for socket operations.
+ *
+ * @socket_create:
+ *     Check permissions prior to creating a new socket.
+ *     @family contains the requested protocol family.
+ *     @type contains the requested communications type.
+ *     @protocol contains the requested protocol.
+ *     @kern set to 1 if a kernel socket.
+ *     Return 0 if permission is granted.
+ * @socket_post_create:
+ *     This hook allows a module to update or allocate a per-socket security
+ *     structure. Note that the security field was not added directly to the
+ *     socket structure, but rather, the socket security information is stored
+ *     in the associated inode.  Typically, the inode alloc_security hook will
+ *     allocate and and attach security information to
+ *     sock->inode->i_security.  This hook may be used to update the
+ *     sock->inode->i_security field with additional information that wasn't
+ *     available when the inode was allocated.
+ *     @sock contains the newly created socket structure.
+ *     @family contains the requested protocol family.
+ *     @type contains the requested communications type.
+ *     @protocol contains the requested protocol.
+ *     @kern set to 1 if a kernel socket.
+ * @socket_bind:
+ *     Check permission before socket protocol layer bind operation is
+ *     performed and the socket @sock is bound to the address specified in the
+ *     @address parameter.
+ *     @sock contains the socket structure.
+ *     @address contains the address to bind to.
+ *     @addrlen contains the length of address.
+ *     Return 0 if permission is granted.
+ * @socket_connect:
+ *     Check permission before socket protocol layer connect operation
+ *     attempts to connect socket @sock to a remote address, @address.
+ *     @sock contains the socket structure.
+ *     @address contains the address of remote endpoint.
+ *     @addrlen contains the length of address.
+ *     Return 0 if permission is granted.
+ * @socket_listen:
+ *     Check permission before socket protocol layer listen operation.
+ *     @sock contains the socket structure.
+ *     @backlog contains the maximum length for the pending connection queue.
+ *     Return 0 if permission is granted.
+ * @socket_accept:
+ *     Check permission before accepting a new connection.  Note that the new
+ *     socket, @newsock, has been created and some information copied to it,
+ *     but the accept operation has not actually been performed.
+ *     @sock contains the listening socket structure.
+ *     @newsock contains the newly created server socket for connection.
+ *     Return 0 if permission is granted.
+ * @socket_sendmsg:
+ *     Check permission before transmitting a message to another socket.
+ *     @sock contains the socket structure.
+ *     @msg contains the message to be transmitted.
+ *     @size contains the size of message.
+ *     Return 0 if permission is granted.
+ * @socket_recvmsg:
+ *     Check permission before receiving a message from a socket.
+ *     @sock contains the socket structure.
+ *     @msg contains the message structure.
+ *     @size contains the size of message structure.
+ *     @flags contains the operational flags.
+ *     Return 0 if permission is granted.
+ * @socket_getsockname:
+ *     Check permission before the local address (name) of the socket object
+ *     @sock is retrieved.
+ *     @sock contains the socket structure.
+ *     Return 0 if permission is granted.
+ * @socket_getpeername:
+ *     Check permission before the remote address (name) of a socket object
+ *     @sock is retrieved.
+ *     @sock contains the socket structure.
+ *     Return 0 if permission is granted.
+ * @socket_getsockopt:
+ *     Check permissions before retrieving the options associated with socket
+ *     @sock.
+ *     @sock contains the socket structure.
+ *     @level contains the protocol level to retrieve option from.
+ *     @optname contains the name of option to retrieve.
+ *     Return 0 if permission is granted.
+ * @socket_setsockopt:
+ *     Check permissions before setting the options associated with socket
+ *     @sock.
+ *     @sock contains the socket structure.
+ *     @level contains the protocol level to set options for.
+ *     @optname contains the name of the option to set.
+ *     Return 0 if permission is granted.
+ * @socket_shutdown:
+ *     Checks permission before all or part of a connection on the socket
+ *     @sock is shut down.
+ *     @sock contains the socket structure.
+ *     @how contains the flag indicating how future sends and receives
+ *     are handled.
+ *     Return 0 if permission is granted.
+ * @socket_sock_rcv_skb:
+ *     Check permissions on incoming network packets.  This hook is distinct
+ *     from Netfilter's IP input hooks since it is the first time that the
+ *     incoming sk_buff @skb has been associated with a particular socket, @sk.
+ *     Must not sleep inside this hook because some callers hold spinlocks.
+ *     @sk contains the sock (not socket) associated with the incoming sk_buff.
+ *     @skb contains the incoming network data.
+ * @socket_getpeersec_stream:
+ *     This hook allows the security module to provide peer socket security
+ *     state for unix or connected tcp sockets to userspace via getsockopt
+ *     SO_GETPEERSEC.  For tcp sockets this can be meaningful if the
+ *     socket is associated with an ipsec SA.
+ *     @sock is the local socket.
+ *     @optval userspace memory where the security state is to be copied.
+ *     @optlen userspace int where the module should copy the actual length
+ *     of the security state.
+ *     @len as input is the maximum length to copy to userspace provided
+ *     by the caller.
+ *     Return 0 if all is well, otherwise, typical getsockopt return
+ *     values.
+ * @socket_getpeersec_dgram:
+ *     This hook allows the security module to provide peer socket security
+ *     state for udp sockets on a per-packet basis to userspace via
+ *     getsockopt SO_GETPEERSEC.  The application must first have indicated
+ *     the IP_PASSSEC option via getsockopt.  It can then retrieve the
+ *     security state returned by this hook for a packet via the SCM_SECURITY
+ *     ancillary message type.
+ *     @skb is the skbuff for the packet being queried
+ *     @secdata is a pointer to a buffer in which to copy the security data
+ *     @seclen is the maximum length for @secdata
+ *     Return 0 on success, error on failure.
+ * @sk_alloc_security:
+ *     Allocate and attach a security structure to the sk->sk_security field,
+ *     which is used to copy security attributes between local stream sockets.
+ * @sk_free_security:
+ *     Deallocate security structure.
+ * @sk_clone_security:
+ *     Clone/copy security structure.
+ * @sk_getsecid:
+ *     Retrieve the LSM-specific secid for the sock to enable caching
+ *     of network authorizations.
+ * @sock_graft:
+ *     Sets the socket's isec sid to the sock's sid.
+ * @inet_conn_request:
+ *     Sets the openreq's sid to socket's sid with MLS portion taken
+ *     from peer sid.
+ * @inet_csk_clone:
+ *     Sets the new child socket's sid to the openreq sid.
+ * @inet_conn_established:
+ *     Sets the connection's peersid to the secmark on skb.
+ * @secmark_relabel_packet:
+ *     check if the process should be allowed to relabel packets to
+ *     the given secid
+ * @security_secmark_refcount_inc
+ *     tells the LSM to increment the number of secmark labeling rules loaded
+ * @security_secmark_refcount_dec
+ *     tells the LSM to decrement the number of secmark labeling rules loaded
+ * @req_classify_flow:
+ *     Sets the flow's sid to the openreq sid.
+ * @tun_dev_alloc_security:
+ *     This hook allows a module to allocate a security structure for a TUN
+ *     device.
+ *     @security pointer to a security structure pointer.
+ *     Returns a zero on success, negative values on failure.
+ * @tun_dev_free_security:
+ *     This hook allows a module to free the security structure for a TUN
+ *     device.
+ *     @security pointer to the TUN device's security structure
+ * @tun_dev_create:
+ *     Check permissions prior to creating a new TUN device.
+ * @tun_dev_attach_queue:
+ *     Check permissions prior to attaching to a TUN device queue.
+ *     @security pointer to the TUN device's security structure.
+ * @tun_dev_attach:
+ *     This hook can be used by the module to update any security state
+ *     associated with the TUN device's sock structure.
+ *     @sk contains the existing sock structure.
+ *     @security pointer to the TUN device's security structure.
+ * @tun_dev_open:
+ *     This hook can be used by the module to update any security state
+ *     associated with the TUN device's security structure.
+ *     @security pointer to the TUN devices's security structure.
+ *
+ * Security hooks for XFRM operations.
+ *
+ * @xfrm_policy_alloc_security:
+ *     @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy
+ *     Database used by the XFRM system.
+ *     @sec_ctx contains the security context information being provided by
+ *     the user-level policy update program (e.g., setkey).
+ *     Allocate a security structure to the xp->security field; the security
+ *     field is initialized to NULL when the xfrm_policy is allocated.
+ *     Return 0 if operation was successful (memory to allocate, legal context)
+ *     @gfp is to specify the context for the allocation
+ * @xfrm_policy_clone_security:
+ *     @old_ctx contains an existing xfrm_sec_ctx.
+ *     @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
+ *     Allocate a security structure in new_ctxp that contains the
+ *     information from the old_ctx structure.
+ *     Return 0 if operation was successful (memory to allocate).
+ * @xfrm_policy_free_security:
+ *     @ctx contains the xfrm_sec_ctx
+ *     Deallocate xp->security.
+ * @xfrm_policy_delete_security:
+ *     @ctx contains the xfrm_sec_ctx.
+ *     Authorize deletion of xp->security.
+ * @xfrm_state_alloc:
+ *     @x contains the xfrm_state being added to the Security Association
+ *     Database by the XFRM system.
+ *     @sec_ctx contains the security context information being provided by
+ *     the user-level SA generation program (e.g., setkey or racoon).
+ *     Allocate a security structure to the x->security field; the security
+ *     field is initialized to NULL when the xfrm_state is allocated. Set the
+ *     context to correspond to sec_ctx. Return 0 if operation was successful
+ *     (memory to allocate, legal context).
+ * @xfrm_state_alloc_acquire:
+ *     @x contains the xfrm_state being added to the Security Association
+ *     Database by the XFRM system.
+ *     @polsec contains the policy's security context.
+ *     @secid contains the secid from which to take the mls portion of the
+ *     context.
+ *     Allocate a security structure to the x->security field; the security
+ *     field is initialized to NULL when the xfrm_state is allocated. Set the
+ *     context to correspond to secid. Return 0 if operation was successful
+ *     (memory to allocate, legal context).
+ * @xfrm_state_free_security:
+ *     @x contains the xfrm_state.
+ *     Deallocate x->security.
+ * @xfrm_state_delete_security:
+ *     @x contains the xfrm_state.
+ *     Authorize deletion of x->security.
+ * @xfrm_policy_lookup:
+ *     @ctx contains the xfrm_sec_ctx for which the access control is being
+ *     checked.
+ *     @fl_secid contains the flow security label that is used to authorize
+ *     access to the policy xp.
+ *     @dir contains the direction of the flow (input or output).
+ *     Check permission when a flow selects a xfrm_policy for processing
+ *     XFRMs on a packet.  The hook is called when selecting either a
+ *     per-socket policy or a generic xfrm policy.
+ *     Return 0 if permission is granted, -ESRCH otherwise, or -errno
+ *     on other errors.
+ * @xfrm_state_pol_flow_match:
+ *     @x contains the state to match.
+ *     @xp contains the policy to check for a match.
+ *     @fl contains the flow to check for a match.
+ *     Return 1 if there is a match.
+ * @xfrm_decode_session:
+ *     @skb points to skb to decode.
+ *     @secid points to the flow key secid to set.
+ *     @ckall says if all xfrms used should be checked for same secid.
+ *     Return 0 if ckall is zero or all xfrms used have the same secid.
+ *
+ * Security hooks affecting all Key Management operations
+ *
+ * @key_alloc:
+ *     Permit allocation of a key and assign security data. Note that key does
+ *     not have a serial number assigned at this point.
+ *     @key points to the key.
+ *     @flags is the allocation flags
+ *     Return 0 if permission is granted, -ve error otherwise.
+ * @key_free:
+ *     Notification of destruction; free security data.
+ *     @key points to the key.
+ *     No return value.
+ * @key_permission:
+ *     See whether a specific operational right is granted to a process on a
+ *     key.
+ *     @key_ref refers to the key (key pointer + possession attribute bit).
+ *     @cred points to the credentials to provide the context against which to
+ *     evaluate the security data on the key.
+ *     @perm describes the combination of permissions required of this key.
+ *     Return 0 if permission is granted, -ve error otherwise.
+ * @key_getsecurity:
+ *     Get a textual representation of the security context attached to a key
+ *     for the purposes of honouring KEYCTL_GETSECURITY.  This function
+ *     allocates the storage for the NUL-terminated string and the caller
+ *     should free it.
+ *     @key points to the key to be queried.
+ *     @_buffer points to a pointer that should be set to point to the
+ *     resulting string (if no label or an error occurs).
+ *     Return the length of the string (including terminating NUL) or -ve if
+ *     an error.
+ *     May also return 0 (and a NULL buffer pointer) if there is no label.
+ *
+ * Security hooks affecting all System V IPC operations.
+ *
+ * @ipc_permission:
+ *     Check permissions for access to IPC
+ *     @ipcp contains the kernel IPC permission structure
+ *     @flag contains the desired (requested) permission set
+ *     Return 0 if permission is granted.
+ * @ipc_getsecid:
+ *     Get the secid associated with the ipc object.
+ *     @ipcp contains the kernel IPC permission structure.
+ *     @secid contains a pointer to the location where result will be saved.
+ *     In case of failure, @secid will be set to zero.
+ *
+ * Security hooks for individual messages held in System V IPC message queues
+ * @msg_msg_alloc_security:
+ *     Allocate and attach a security structure to the msg->security field.
+ *     The security field is initialized to NULL when the structure is first
+ *     created.
+ *     @msg contains the message structure to be modified.
+ *     Return 0 if operation was successful and permission is granted.
+ * @msg_msg_free_security:
+ *     Deallocate the security structure for this message.
+ *     @msg contains the message structure to be modified.
+ *
+ * Security hooks for System V IPC Message Queues
+ *
+ * @msg_queue_alloc_security:
+ *     Allocate and attach a security structure to the
+ *     msq->q_perm.security field. The security field is initialized to
+ *     NULL when the structure is first created.
+ *     @msq contains the message queue structure to be modified.
+ *     Return 0 if operation was successful and permission is granted.
+ * @msg_queue_free_security:
+ *     Deallocate security structure for this message queue.
+ *     @msq contains the message queue structure to be modified.
+ * @msg_queue_associate:
+ *     Check permission when a message queue is requested through the
+ *     msgget system call.  This hook is only called when returning the
+ *     message queue identifier for an existing message queue, not when a
+ *     new message queue is created.
+ *     @msq contains the message queue to act upon.
+ *     @msqflg contains the operation control flags.
+ *     Return 0 if permission is granted.
+ * @msg_queue_msgctl:
+ *     Check permission when a message control operation specified by @cmd
+ *     is to be performed on the message queue @msq.
+ *     The @msq may be NULL, e.g. for IPC_INFO or MSG_INFO.
+ *     @msq contains the message queue to act upon.  May be NULL.
+ *     @cmd contains the operation to be performed.
+ *     Return 0 if permission is granted.
+ * @msg_queue_msgsnd:
+ *     Check permission before a message, @msg, is enqueued on the message
+ *     queue, @msq.
+ *     @msq contains the message queue to send message to.
+ *     @msg contains the message to be enqueued.
+ *     @msqflg contains operational flags.
+ *     Return 0 if permission is granted.
+ * @msg_queue_msgrcv:
+ *     Check permission before a message, @msg, is removed from the message
+ *     queue, @msq.  The @target task structure contains a pointer to the
+ *     process that will be receiving the message (not equal to the current
+ *     process when inline receives are being performed).
+ *     @msq contains the message queue to retrieve message from.
+ *     @msg contains the message destination.
+ *     @target contains the task structure for recipient process.
+ *     @type contains the type of message requested.
+ *     @mode contains the operational flags.
+ *     Return 0 if permission is granted.
+ *
+ * Security hooks for System V Shared Memory Segments
+ *
+ * @shm_alloc_security:
+ *     Allocate and attach a security structure to the shp->shm_perm.security
+ *     field.  The security field is initialized to NULL when the structure is
+ *     first created.
+ *     @shp contains the shared memory structure to be modified.
+ *     Return 0 if operation was successful and permission is granted.
+ * @shm_free_security:
+ *     Deallocate the security struct for this memory segment.
+ *     @shp contains the shared memory structure to be modified.
+ * @shm_associate:
+ *     Check permission when a shared memory region is requested through the
+ *     shmget system call.  This hook is only called when returning the shared
+ *     memory region identifier for an existing region, not when a new shared
+ *     memory region is created.
+ *     @shp contains the shared memory structure to be modified.
+ *     @shmflg contains the operation control flags.
+ *     Return 0 if permission is granted.
+ * @shm_shmctl:
+ *     Check permission when a shared memory control operation specified by
+ *     @cmd is to be performed on the shared memory region @shp.
+ *     The @shp may be NULL, e.g. for IPC_INFO or SHM_INFO.
+ *     @shp contains shared memory structure to be modified.
+ *     @cmd contains the operation to be performed.
+ *     Return 0 if permission is granted.
+ * @shm_shmat:
+ *     Check permissions prior to allowing the shmat system call to attach the
+ *     shared memory segment @shp to the data segment of the calling process.
+ *     The attaching address is specified by @shmaddr.
+ *     @shp contains the shared memory structure to be modified.
+ *     @shmaddr contains the address to attach memory region to.
+ *     @shmflg contains the operational flags.
+ *     Return 0 if permission is granted.
+ *
+ * Security hooks for System V Semaphores
+ *
+ * @sem_alloc_security:
+ *     Allocate and attach a security structure to the sma->sem_perm.security
+ *     field.  The security field is initialized to NULL when the structure is
+ *     first created.
+ *     @sma contains the semaphore structure
+ *     Return 0 if operation was successful and permission is granted.
+ * @sem_free_security:
+ *     deallocate security struct for this semaphore
+ *     @sma contains the semaphore structure.
+ * @sem_associate:
+ *     Check permission when a semaphore is requested through the semget
+ *     system call.  This hook is only called when returning the semaphore
+ *     identifier for an existing semaphore, not when a new one must be
+ *     created.
+ *     @sma contains the semaphore structure.
+ *     @semflg contains the operation control flags.
+ *     Return 0 if permission is granted.
+ * @sem_semctl:
+ *     Check permission when a semaphore operation specified by @cmd is to be
+ *     performed on the semaphore @sma.  The @sma may be NULL, e.g. for
+ *     IPC_INFO or SEM_INFO.
+ *     @sma contains the semaphore structure.  May be NULL.
+ *     @cmd contains the operation to be performed.
+ *     Return 0 if permission is granted.
+ * @sem_semop
+ *     Check permissions before performing operations on members of the
+ *     semaphore set @sma.  If the @alter flag is nonzero, the semaphore set
+ *     may be modified.
+ *     @sma contains the semaphore structure.
+ *     @sops contains the operations to perform.
+ *     @nsops contains the number of operations to perform.
+ *     @alter contains the flag indicating whether changes are to be made.
+ *     Return 0 if permission is granted.
+ *
+ * @binder_set_context_mgr
+ *     Check whether @mgr is allowed to be the binder context manager.
+ *     @mgr contains the task_struct for the task being registered.
+ *     Return 0 if permission is granted.
+ * @binder_transaction
+ *     Check whether @from is allowed to invoke a binder transaction call
+ *     to @to.
+ *     @from contains the task_struct for the sending task.
+ *     @to contains the task_struct for the receiving task.
+ * @binder_transfer_binder
+ *     Check whether @from is allowed to transfer a binder reference to @to.
+ *     @from contains the task_struct for the sending task.
+ *     @to contains the task_struct for the receiving task.
+ * @binder_transfer_file
+ *     Check whether @from is allowed to transfer @file to @to.
+ *     @from contains the task_struct for the sending task.
+ *     @file contains the struct file being transferred.
+ *     @to contains the task_struct for the receiving task.
+ *
+ * @ptrace_access_check:
+ *     Check permission before allowing the current process to trace the
+ *     @child process.
+ *     Security modules may also want to perform a process tracing check
+ *     during an execve in the set_security or apply_creds hooks of
+ *     tracing check during an execve in the bprm_set_creds hook of
+ *     binprm_security_ops if the process is being traced and its security
+ *     attributes would be changed by the execve.
+ *     @child contains the task_struct structure for the target process.
+ *     @mode contains the PTRACE_MODE flags indicating the form of access.
+ *     Return 0 if permission is granted.
+ * @ptrace_traceme:
+ *     Check that the @parent process has sufficient permission to trace the
+ *     current process before allowing the current process to present itself
+ *     to the @parent process for tracing.
+ *     @parent contains the task_struct structure for debugger process.
+ *     Return 0 if permission is granted.
+ * @capget:
+ *     Get the @effective, @inheritable, and @permitted capability sets for
+ *     the @target process.  The hook may also perform permission checking to
+ *     determine if the current process is allowed to see the capability sets
+ *     of the @target process.
+ *     @target contains the task_struct structure for target process.
+ *     @effective contains the effective capability set.
+ *     @inheritable contains the inheritable capability set.
+ *     @permitted contains the permitted capability set.
+ *     Return 0 if the capability sets were successfully obtained.
+ * @capset:
+ *     Set the @effective, @inheritable, and @permitted capability sets for
+ *     the current process.
+ *     @new contains the new credentials structure for target process.
+ *     @old contains the current credentials structure for target process.
+ *     @effective contains the effective capability set.
+ *     @inheritable contains the inheritable capability set.
+ *     @permitted contains the permitted capability set.
+ *     Return 0 and update @new if permission is granted.
+ * @capable:
+ *     Check whether the @tsk process has the @cap capability in the indicated
+ *     credentials.
+ *     @cred contains the credentials to use.
+ *     @ns contains the user namespace we want the capability in
+ *     @cap contains the capability <include/linux/capability.h>.
+ *     @audit: Whether to write an audit message or not
+ *     Return 0 if the capability is granted for @tsk.
+ * @syslog:
+ *     Check permission before accessing the kernel message ring or changing
+ *     logging to the console.
+ *     See the syslog(2) manual page for an explanation of the @type values.
+ *     @type contains the type of action.
+ *     @from_file indicates the context of action (if it came from /proc).
+ *     Return 0 if permission is granted.
+ * @settime:
+ *     Check permission to change the system time.
+ *     struct timespec and timezone are defined in include/linux/time.h
+ *     @ts contains new time
+ *     @tz contains new timezone
+ *     Return 0 if permission is granted.
+ * @vm_enough_memory:
+ *     Check permissions for allocating a new virtual mapping.
+ *     @mm contains the mm struct it is being added to.
+ *     @pages contains the number of pages.
+ *     Return 0 if permission is granted.
+ *
+ * @ismaclabel:
+ *     Check if the extended attribute specified by @name
+ *     represents a MAC label. Returns 1 if name is a MAC
+ *     attribute otherwise returns 0.
+ *     @name full extended attribute name to check against
+ *     LSM as a MAC label.
+ *
+ * @secid_to_secctx:
+ *     Convert secid to security context.  If secdata is NULL the length of
+ *     the result will be returned in seclen, but no secdata will be returned.
+ *     This does mean that the length could change between calls to check the
+ *     length and the next call which actually allocates and returns the
+ *     secdata.
+ *     @secid contains the security ID.
+ *     @secdata contains the pointer that stores the converted security
+ *     context.
+ *     @seclen pointer which contains the length of the data
+ * @secctx_to_secid:
+ *     Convert security context to secid.
+ *     @secid contains the pointer to the generated security ID.
+ *     @secdata contains the security context.
+ *
+ * @release_secctx:
+ *     Release the security context.
+ *     @secdata contains the security context.
+ *     @seclen contains the length of the security context.
+ *
+ * Security hooks for Audit
+ *
+ * @audit_rule_init:
+ *     Allocate and initialize an LSM audit rule structure.
+ *     @field contains the required Audit action.
+ *     Fields flags are defined in include/linux/audit.h
+ *     @op contains the operator the rule uses.
+ *     @rulestr contains the context where the rule will be applied to.
+ *     @lsmrule contains a pointer to receive the result.
+ *     Return 0 if @lsmrule has been successfully set,
+ *     -EINVAL in case of an invalid rule.
+ *
+ * @audit_rule_known:
+ *     Specifies whether given @rule contains any fields related to
+ *     current LSM.
+ *     @rule contains the audit rule of interest.
+ *     Return 1 in case of relation found, 0 otherwise.
+ *
+ * @audit_rule_match:
+ *     Determine if given @secid matches a rule previously approved
+ *     by @audit_rule_known.
+ *     @secid contains the security id in question.
+ *     @field contains the field which relates to current LSM.
+ *     @op contains the operator that will be used for matching.
+ *     @rule points to the audit rule that will be checked against.
+ *     @actx points to the audit context associated with the check.
+ *     Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
+ *
+ * @audit_rule_free:
+ *     Deallocate the LSM audit rule structure previously allocated by
+ *     audit_rule_init.
+ *     @rule contains the allocated rule
+ *
+ * @inode_notifysecctx:
+ *     Notify the security module of what the security context of an inode
+ *     should be.  Initializes the incore security context managed by the
+ *     security module for this inode.  Example usage:  NFS client invokes
+ *     this hook to initialize the security context in its incore inode to the
+ *     value provided by the server for the file when the server returned the
+ *     file's attributes to the client.
+ *
+ *     Must be called with inode->i_mutex locked.
+ *
+ *     @inode we wish to set the security context of.
+ *     @ctx contains the string which we wish to set in the inode.
+ *     @ctxlen contains the length of @ctx.
+ *
+ * @inode_setsecctx:
+ *     Change the security context of an inode.  Updates the
+ *     incore security context managed by the security module and invokes the
+ *     fs code as needed (via __vfs_setxattr_noperm) to update any backing
+ *     xattrs that represent the context.  Example usage:  NFS server invokes
+ *     this hook to change the security context in its incore inode and on the
+ *     backing filesystem to a value provided by the client on a SETATTR
+ *     operation.
+ *
+ *     Must be called with inode->i_mutex locked.
+ *
+ *     @dentry contains the inode we wish to set the security context of.
+ *     @ctx contains the string which we wish to set in the inode.
+ *     @ctxlen contains the length of @ctx.
+ *
+ * @inode_getsecctx:
+ *     On success, returns 0 and fills out @ctx and @ctxlen with the security
+ *     context for the given @inode.
+ *
+ *     @inode we wish to get the security context of.
+ *     @ctx is a pointer in which to place the allocated security context.
+ *     @ctxlen points to the place to put the length of @ctx.
+ * This is the main security structure.
+ */
+
+union security_list_options {
+       int (*binder_set_context_mgr)(struct task_struct *mgr);
+       int (*binder_transaction)(struct task_struct *from,
+                                       struct task_struct *to);
+       int (*binder_transfer_binder)(struct task_struct *from,
+                                       struct task_struct *to);
+       int (*binder_transfer_file)(struct task_struct *from,
+                                       struct task_struct *to,
+                                       struct file *file);
+
+       int (*ptrace_access_check)(struct task_struct *child,
+                                       unsigned int mode);
+       int (*ptrace_traceme)(struct task_struct *parent);
+       int (*capget)(struct task_struct *target, kernel_cap_t *effective,
+                       kernel_cap_t *inheritable, kernel_cap_t *permitted);
+       int (*capset)(struct cred *new, const struct cred *old,
+                       const kernel_cap_t *effective,
+                       const kernel_cap_t *inheritable,
+                       const kernel_cap_t *permitted);
+       int (*capable)(const struct cred *cred, struct user_namespace *ns,
+                       int cap, int audit);
+       int (*quotactl)(int cmds, int type, int id, struct super_block *sb);
+       int (*quota_on)(struct dentry *dentry);
+       int (*syslog)(int type);
+       int (*settime)(const struct timespec *ts, const struct timezone *tz);
+       int (*vm_enough_memory)(struct mm_struct *mm, long pages);
+
+       int (*bprm_set_creds)(struct linux_binprm *bprm);
+       int (*bprm_check_security)(struct linux_binprm *bprm);
+       int (*bprm_secureexec)(struct linux_binprm *bprm);
+       void (*bprm_committing_creds)(struct linux_binprm *bprm);
+       void (*bprm_committed_creds)(struct linux_binprm *bprm);
+
+       int (*sb_alloc_security)(struct super_block *sb);
+       void (*sb_free_security)(struct super_block *sb);
+       int (*sb_copy_data)(char *orig, char *copy);
+       int (*sb_remount)(struct super_block *sb, void *data);
+       int (*sb_kern_mount)(struct super_block *sb, int flags, void *data);
+       int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
+       int (*sb_statfs)(struct dentry *dentry);
+       int (*sb_mount)(const char *dev_name, struct path *path,
+                       const char *type, unsigned long flags, void *data);
+       int (*sb_umount)(struct vfsmount *mnt, int flags);
+       int (*sb_pivotroot)(struct path *old_path, struct path *new_path);
+       int (*sb_set_mnt_opts)(struct super_block *sb,
+                               struct security_mnt_opts *opts,
+                               unsigned long kern_flags,
+                               unsigned long *set_kern_flags);
+       int (*sb_clone_mnt_opts)(const struct super_block *oldsb,
+                                       struct super_block *newsb);
+       int (*sb_parse_opts_str)(char *options, struct security_mnt_opts *opts);
+       int (*dentry_init_security)(struct dentry *dentry, int mode,
+                                       struct qstr *name, void **ctx,
+                                       u32 *ctxlen);
+
+
+#ifdef CONFIG_SECURITY_PATH
+       int (*path_unlink)(struct path *dir, struct dentry *dentry);
+       int (*path_mkdir)(struct path *dir, struct dentry *dentry,
+                               umode_t mode);
+       int (*path_rmdir)(struct path *dir, struct dentry *dentry);
+       int (*path_mknod)(struct path *dir, struct dentry *dentry,
+                               umode_t mode, unsigned int dev);
+       int (*path_truncate)(struct path *path);
+       int (*path_symlink)(struct path *dir, struct dentry *dentry,
+                               const char *old_name);
+       int (*path_link)(struct dentry *old_dentry, struct path *new_dir,
+                               struct dentry *new_dentry);
+       int (*path_rename)(struct path *old_dir, struct dentry *old_dentry,
+                               struct path *new_dir,
+                               struct dentry *new_dentry);
+       int (*path_chmod)(struct path *path, umode_t mode);
+       int (*path_chown)(struct path *path, kuid_t uid, kgid_t gid);
+       int (*path_chroot)(struct path *path);
+#endif
+
+       int (*inode_alloc_security)(struct inode *inode);
+       void (*inode_free_security)(struct inode *inode);
+       int (*inode_init_security)(struct inode *inode, struct inode *dir,
+                                       const struct qstr *qstr,
+                                       const char **name, void **value,
+                                       size_t *len);
+       int (*inode_create)(struct inode *dir, struct dentry *dentry,
+                               umode_t mode);
+       int (*inode_link)(struct dentry *old_dentry, struct inode *dir,
+                               struct dentry *new_dentry);
+       int (*inode_unlink)(struct inode *dir, struct dentry *dentry);
+       int (*inode_symlink)(struct inode *dir, struct dentry *dentry,
+                               const char *old_name);
+       int (*inode_mkdir)(struct inode *dir, struct dentry *dentry,
+                               umode_t mode);
+       int (*inode_rmdir)(struct inode *dir, struct dentry *dentry);
+       int (*inode_mknod)(struct inode *dir, struct dentry *dentry,
+                               umode_t mode, dev_t dev);
+       int (*inode_rename)(struct inode *old_dir, struct dentry *old_dentry,
+                               struct inode *new_dir,
+                               struct dentry *new_dentry);
+       int (*inode_readlink)(struct dentry *dentry);
+       int (*inode_follow_link)(struct dentry *dentry, struct inode *inode,
+                                bool rcu);
+       int (*inode_permission)(struct inode *inode, int mask);
+       int (*inode_setattr)(struct dentry *dentry, struct iattr *attr);
+       int (*inode_getattr)(const struct path *path);
+       int (*inode_setxattr)(struct dentry *dentry, const char *name,
+                               const void *value, size_t size, int flags);
+       void (*inode_post_setxattr)(struct dentry *dentry, const char *name,
+                                       const void *value, size_t size,
+                                       int flags);
+       int (*inode_getxattr)(struct dentry *dentry, const char *name);
+       int (*inode_listxattr)(struct dentry *dentry);
+       int (*inode_removexattr)(struct dentry *dentry, const char *name);
+       int (*inode_need_killpriv)(struct dentry *dentry);
+       int (*inode_killpriv)(struct dentry *dentry);
+       int (*inode_getsecurity)(const struct inode *inode, const char *name,
+                                       void **buffer, bool alloc);
+       int (*inode_setsecurity)(struct inode *inode, const char *name,
+                                       const void *value, size_t size,
+                                       int flags);
+       int (*inode_listsecurity)(struct inode *inode, char *buffer,
+                                       size_t buffer_size);
+       void (*inode_getsecid)(const struct inode *inode, u32 *secid);
+
+       int (*file_permission)(struct file *file, int mask);
+       int (*file_alloc_security)(struct file *file);
+       void (*file_free_security)(struct file *file);
+       int (*file_ioctl)(struct file *file, unsigned int cmd,
+                               unsigned long arg);
+       int (*mmap_addr)(unsigned long addr);
+       int (*mmap_file)(struct file *file, unsigned long reqprot,
+                               unsigned long prot, unsigned long flags);
+       int (*file_mprotect)(struct vm_area_struct *vma, unsigned long reqprot,
+                               unsigned long prot);
+       int (*file_lock)(struct file *file, unsigned int cmd);
+       int (*file_fcntl)(struct file *file, unsigned int cmd,
+                               unsigned long arg);
+       void (*file_set_fowner)(struct file *file);
+       int (*file_send_sigiotask)(struct task_struct *tsk,
+                                       struct fown_struct *fown, int sig);
+       int (*file_receive)(struct file *file);
+       int (*file_open)(struct file *file, const struct cred *cred);
+
+       int (*task_create)(unsigned long clone_flags);
+       void (*task_free)(struct task_struct *task);
+       int (*cred_alloc_blank)(struct cred *cred, gfp_t gfp);
+       void (*cred_free)(struct cred *cred);
+       int (*cred_prepare)(struct cred *new, const struct cred *old,
+                               gfp_t gfp);
+       void (*cred_transfer)(struct cred *new, const struct cred *old);
+       int (*kernel_act_as)(struct cred *new, u32 secid);
+       int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
+       int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
+       int (*kernel_module_request)(char *kmod_name);
+       int (*kernel_module_from_file)(struct file *file);
+       int (*task_fix_setuid)(struct cred *new, const struct cred *old,
+                               int flags);
+       int (*task_setpgid)(struct task_struct *p, pid_t pgid);
+       int (*task_getpgid)(struct task_struct *p);
+       int (*task_getsid)(struct task_struct *p);
+       void (*task_getsecid)(struct task_struct *p, u32 *secid);
+       int (*task_setnice)(struct task_struct *p, int nice);
+       int (*task_setioprio)(struct task_struct *p, int ioprio);
+       int (*task_getioprio)(struct task_struct *p);
+       int (*task_setrlimit)(struct task_struct *p, unsigned int resource,
+                               struct rlimit *new_rlim);
+       int (*task_setscheduler)(struct task_struct *p);
+       int (*task_getscheduler)(struct task_struct *p);
+       int (*task_movememory)(struct task_struct *p);
+       int (*task_kill)(struct task_struct *p, struct siginfo *info,
+                               int sig, u32 secid);
+       int (*task_wait)(struct task_struct *p);
+       int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3,
+                               unsigned long arg4, unsigned long arg5);
+       void (*task_to_inode)(struct task_struct *p, struct inode *inode);
+
+       int (*ipc_permission)(struct kern_ipc_perm *ipcp, short flag);
+       void (*ipc_getsecid)(struct kern_ipc_perm *ipcp, u32 *secid);
+
+       int (*msg_msg_alloc_security)(struct msg_msg *msg);
+       void (*msg_msg_free_security)(struct msg_msg *msg);
+
+       int (*msg_queue_alloc_security)(struct msg_queue *msq);
+       void (*msg_queue_free_security)(struct msg_queue *msq);
+       int (*msg_queue_associate)(struct msg_queue *msq, int msqflg);
+       int (*msg_queue_msgctl)(struct msg_queue *msq, int cmd);
+       int (*msg_queue_msgsnd)(struct msg_queue *msq, struct msg_msg *msg,
+                               int msqflg);
+       int (*msg_queue_msgrcv)(struct msg_queue *msq, struct msg_msg *msg,
+                               struct task_struct *target, long type,
+                               int mode);
+
+       int (*shm_alloc_security)(struct shmid_kernel *shp);
+       void (*shm_free_security)(struct shmid_kernel *shp);
+       int (*shm_associate)(struct shmid_kernel *shp, int shmflg);
+       int (*shm_shmctl)(struct shmid_kernel *shp, int cmd);
+       int (*shm_shmat)(struct shmid_kernel *shp, char __user *shmaddr,
+                               int shmflg);
+
+       int (*sem_alloc_security)(struct sem_array *sma);
+       void (*sem_free_security)(struct sem_array *sma);
+       int (*sem_associate)(struct sem_array *sma, int semflg);
+       int (*sem_semctl)(struct sem_array *sma, int cmd);
+       int (*sem_semop)(struct sem_array *sma, struct sembuf *sops,
+                               unsigned nsops, int alter);
+
+       int (*netlink_send)(struct sock *sk, struct sk_buff *skb);
+
+       void (*d_instantiate)(struct dentry *dentry, struct inode *inode);
+
+       int (*getprocattr)(struct task_struct *p, char *name, char **value);
+       int (*setprocattr)(struct task_struct *p, char *name, void *value,
+                               size_t size);
+       int (*ismaclabel)(const char *name);
+       int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
+       int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid);
+       void (*release_secctx)(char *secdata, u32 seclen);
+
+       int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
+       int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
+       int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen);
+
+#ifdef CONFIG_SECURITY_NETWORK
+       int (*unix_stream_connect)(struct sock *sock, struct sock *other,
+                                       struct sock *newsk);
+       int (*unix_may_send)(struct socket *sock, struct socket *other);
+
+       int (*socket_create)(int family, int type, int protocol, int kern);
+       int (*socket_post_create)(struct socket *sock, int family, int type,
+                                       int protocol, int kern);
+       int (*socket_bind)(struct socket *sock, struct sockaddr *address,
+                               int addrlen);
+       int (*socket_connect)(struct socket *sock, struct sockaddr *address,
+                               int addrlen);
+       int (*socket_listen)(struct socket *sock, int backlog);
+       int (*socket_accept)(struct socket *sock, struct socket *newsock);
+       int (*socket_sendmsg)(struct socket *sock, struct msghdr *msg,
+                               int size);
+       int (*socket_recvmsg)(struct socket *sock, struct msghdr *msg,
+                               int size, int flags);
+       int (*socket_getsockname)(struct socket *sock);
+       int (*socket_getpeername)(struct socket *sock);
+       int (*socket_getsockopt)(struct socket *sock, int level, int optname);
+       int (*socket_setsockopt)(struct socket *sock, int level, int optname);
+       int (*socket_shutdown)(struct socket *sock, int how);
+       int (*socket_sock_rcv_skb)(struct sock *sk, struct sk_buff *skb);
+       int (*socket_getpeersec_stream)(struct socket *sock,
+                                       char __user *optval,
+                                       int __user *optlen, unsigned len);
+       int (*socket_getpeersec_dgram)(struct socket *sock,
+                                       struct sk_buff *skb, u32 *secid);
+       int (*sk_alloc_security)(struct sock *sk, int family, gfp_t priority);
+       void (*sk_free_security)(struct sock *sk);
+       void (*sk_clone_security)(const struct sock *sk, struct sock *newsk);
+       void (*sk_getsecid)(struct sock *sk, u32 *secid);
+       void (*sock_graft)(struct sock *sk, struct socket *parent);
+       int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb,
+                                       struct request_sock *req);
+       void (*inet_csk_clone)(struct sock *newsk,
+                               const struct request_sock *req);
+       void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
+       int (*secmark_relabel_packet)(u32 secid);
+       void (*secmark_refcount_inc)(void);
+       void (*secmark_refcount_dec)(void);
+       void (*req_classify_flow)(const struct request_sock *req,
+                                       struct flowi *fl);
+       int (*tun_dev_alloc_security)(void **security);
+       void (*tun_dev_free_security)(void *security);
+       int (*tun_dev_create)(void);
+       int (*tun_dev_attach_queue)(void *security);
+       int (*tun_dev_attach)(struct sock *sk, void *security);
+       int (*tun_dev_open)(void *security);
+#endif /* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+       int (*xfrm_policy_alloc_security)(struct xfrm_sec_ctx **ctxp,
+                                         struct xfrm_user_sec_ctx *sec_ctx,
+                                               gfp_t gfp);
+       int (*xfrm_policy_clone_security)(struct xfrm_sec_ctx *old_ctx,
+                                               struct xfrm_sec_ctx **new_ctx);
+       void (*xfrm_policy_free_security)(struct xfrm_sec_ctx *ctx);
+       int (*xfrm_policy_delete_security)(struct xfrm_sec_ctx *ctx);
+       int (*xfrm_state_alloc)(struct xfrm_state *x,
+                               struct xfrm_user_sec_ctx *sec_ctx);
+       int (*xfrm_state_alloc_acquire)(struct xfrm_state *x,
+                                       struct xfrm_sec_ctx *polsec,
+                                       u32 secid);
+       void (*xfrm_state_free_security)(struct xfrm_state *x);
+       int (*xfrm_state_delete_security)(struct xfrm_state *x);
+       int (*xfrm_policy_lookup)(struct xfrm_sec_ctx *ctx, u32 fl_secid,
+                                       u8 dir);
+       int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
+                                               struct xfrm_policy *xp,
+                                               const struct flowi *fl);
+       int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+
+       /* key management security hooks */
+#ifdef CONFIG_KEYS
+       int (*key_alloc)(struct key *key, const struct cred *cred,
+                               unsigned long flags);
+       void (*key_free)(struct key *key);
+       int (*key_permission)(key_ref_t key_ref, const struct cred *cred,
+                               unsigned perm);
+       int (*key_getsecurity)(struct key *key, char **_buffer);
+#endif /* CONFIG_KEYS */
+
+#ifdef CONFIG_AUDIT
+       int (*audit_rule_init)(u32 field, u32 op, char *rulestr,
+                               void **lsmrule);
+       int (*audit_rule_known)(struct audit_krule *krule);
+       int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule,
+                               struct audit_context *actx);
+       void (*audit_rule_free)(void *lsmrule);
+#endif /* CONFIG_AUDIT */
+};
+
+struct security_hook_heads {
+       struct list_head binder_set_context_mgr;
+       struct list_head binder_transaction;
+       struct list_head binder_transfer_binder;
+       struct list_head binder_transfer_file;
+       struct list_head ptrace_access_check;
+       struct list_head ptrace_traceme;
+       struct list_head capget;
+       struct list_head capset;
+       struct list_head capable;
+       struct list_head quotactl;
+       struct list_head quota_on;
+       struct list_head syslog;
+       struct list_head settime;
+       struct list_head vm_enough_memory;
+       struct list_head bprm_set_creds;
+       struct list_head bprm_check_security;
+       struct list_head bprm_secureexec;
+       struct list_head bprm_committing_creds;
+       struct list_head bprm_committed_creds;
+       struct list_head sb_alloc_security;
+       struct list_head sb_free_security;
+       struct list_head sb_copy_data;
+       struct list_head sb_remount;
+       struct list_head sb_kern_mount;
+       struct list_head sb_show_options;
+       struct list_head sb_statfs;
+       struct list_head sb_mount;
+       struct list_head sb_umount;
+       struct list_head sb_pivotroot;
+       struct list_head sb_set_mnt_opts;
+       struct list_head sb_clone_mnt_opts;
+       struct list_head sb_parse_opts_str;
+       struct list_head dentry_init_security;
+#ifdef CONFIG_SECURITY_PATH
+       struct list_head path_unlink;
+       struct list_head path_mkdir;
+       struct list_head path_rmdir;
+       struct list_head path_mknod;
+       struct list_head path_truncate;
+       struct list_head path_symlink;
+       struct list_head path_link;
+       struct list_head path_rename;
+       struct list_head path_chmod;
+       struct list_head path_chown;
+       struct list_head path_chroot;
+#endif
+       struct list_head inode_alloc_security;
+       struct list_head inode_free_security;
+       struct list_head inode_init_security;
+       struct list_head inode_create;
+       struct list_head inode_link;
+       struct list_head inode_unlink;
+       struct list_head inode_symlink;
+       struct list_head inode_mkdir;
+       struct list_head inode_rmdir;
+       struct list_head inode_mknod;
+       struct list_head inode_rename;
+       struct list_head inode_readlink;
+       struct list_head inode_follow_link;
+       struct list_head inode_permission;
+       struct list_head inode_setattr;
+       struct list_head inode_getattr;
+       struct list_head inode_setxattr;
+       struct list_head inode_post_setxattr;
+       struct list_head inode_getxattr;
+       struct list_head inode_listxattr;
+       struct list_head inode_removexattr;
+       struct list_head inode_need_killpriv;
+       struct list_head inode_killpriv;
+       struct list_head inode_getsecurity;
+       struct list_head inode_setsecurity;
+       struct list_head inode_listsecurity;
+       struct list_head inode_getsecid;
+       struct list_head file_permission;
+       struct list_head file_alloc_security;
+       struct list_head file_free_security;
+       struct list_head file_ioctl;
+       struct list_head mmap_addr;
+       struct list_head mmap_file;
+       struct list_head file_mprotect;
+       struct list_head file_lock;
+       struct list_head file_fcntl;
+       struct list_head file_set_fowner;
+       struct list_head file_send_sigiotask;
+       struct list_head file_receive;
+       struct list_head file_open;
+       struct list_head task_create;
+       struct list_head task_free;
+       struct list_head cred_alloc_blank;
+       struct list_head cred_free;
+       struct list_head cred_prepare;
+       struct list_head cred_transfer;
+       struct list_head kernel_act_as;
+       struct list_head kernel_create_files_as;
+       struct list_head kernel_fw_from_file;
+       struct list_head kernel_module_request;
+       struct list_head kernel_module_from_file;
+       struct list_head task_fix_setuid;
+       struct list_head task_setpgid;
+       struct list_head task_getpgid;
+       struct list_head task_getsid;
+       struct list_head task_getsecid;
+       struct list_head task_setnice;
+       struct list_head task_setioprio;
+       struct list_head task_getioprio;
+       struct list_head task_setrlimit;
+       struct list_head task_setscheduler;
+       struct list_head task_getscheduler;
+       struct list_head task_movememory;
+       struct list_head task_kill;
+       struct list_head task_wait;
+       struct list_head task_prctl;
+       struct list_head task_to_inode;
+       struct list_head ipc_permission;
+       struct list_head ipc_getsecid;
+       struct list_head msg_msg_alloc_security;
+       struct list_head msg_msg_free_security;
+       struct list_head msg_queue_alloc_security;
+       struct list_head msg_queue_free_security;
+       struct list_head msg_queue_associate;
+       struct list_head msg_queue_msgctl;
+       struct list_head msg_queue_msgsnd;
+       struct list_head msg_queue_msgrcv;
+       struct list_head shm_alloc_security;
+       struct list_head shm_free_security;
+       struct list_head shm_associate;
+       struct list_head shm_shmctl;
+       struct list_head shm_shmat;
+       struct list_head sem_alloc_security;
+       struct list_head sem_free_security;
+       struct list_head sem_associate;
+       struct list_head sem_semctl;
+       struct list_head sem_semop;
+       struct list_head netlink_send;
+       struct list_head d_instantiate;
+       struct list_head getprocattr;
+       struct list_head setprocattr;
+       struct list_head ismaclabel;
+       struct list_head secid_to_secctx;
+       struct list_head secctx_to_secid;
+       struct list_head release_secctx;
+       struct list_head inode_notifysecctx;
+       struct list_head inode_setsecctx;
+       struct list_head inode_getsecctx;
+#ifdef CONFIG_SECURITY_NETWORK
+       struct list_head unix_stream_connect;
+       struct list_head unix_may_send;
+       struct list_head socket_create;
+       struct list_head socket_post_create;
+       struct list_head socket_bind;
+       struct list_head socket_connect;
+       struct list_head socket_listen;
+       struct list_head socket_accept;
+       struct list_head socket_sendmsg;
+       struct list_head socket_recvmsg;
+       struct list_head socket_getsockname;
+       struct list_head socket_getpeername;
+       struct list_head socket_getsockopt;
+       struct list_head socket_setsockopt;
+       struct list_head socket_shutdown;
+       struct list_head socket_sock_rcv_skb;
+       struct list_head socket_getpeersec_stream;
+       struct list_head socket_getpeersec_dgram;
+       struct list_head sk_alloc_security;
+       struct list_head sk_free_security;
+       struct list_head sk_clone_security;
+       struct list_head sk_getsecid;
+       struct list_head sock_graft;
+       struct list_head inet_conn_request;
+       struct list_head inet_csk_clone;
+       struct list_head inet_conn_established;
+       struct list_head secmark_relabel_packet;
+       struct list_head secmark_refcount_inc;
+       struct list_head secmark_refcount_dec;
+       struct list_head req_classify_flow;
+       struct list_head tun_dev_alloc_security;
+       struct list_head tun_dev_free_security;
+       struct list_head tun_dev_create;
+       struct list_head tun_dev_attach_queue;
+       struct list_head tun_dev_attach;
+       struct list_head tun_dev_open;
+       struct list_head skb_owned_by;
+#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+       struct list_head xfrm_policy_alloc_security;
+       struct list_head xfrm_policy_clone_security;
+       struct list_head xfrm_policy_free_security;
+       struct list_head xfrm_policy_delete_security;
+       struct list_head xfrm_state_alloc;
+       struct list_head xfrm_state_alloc_acquire;
+       struct list_head xfrm_state_free_security;
+       struct list_head xfrm_state_delete_security;
+       struct list_head xfrm_policy_lookup;
+       struct list_head xfrm_state_pol_flow_match;
+       struct list_head xfrm_decode_session;
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+#ifdef CONFIG_KEYS
+       struct list_head key_alloc;
+       struct list_head key_free;
+       struct list_head key_permission;
+       struct list_head key_getsecurity;
+#endif /* CONFIG_KEYS */
+#ifdef CONFIG_AUDIT
+       struct list_head audit_rule_init;
+       struct list_head audit_rule_known;
+       struct list_head audit_rule_match;
+       struct list_head audit_rule_free;
+#endif /* CONFIG_AUDIT */
+};
+
+/*
+ * Security module hook list structure.
+ * For use with generic list macros for common operations.
+ */
+struct security_hook_list {
+       struct list_head                list;
+       struct list_head                *head;
+       union security_list_options     hook;
+};
+
+/*
+ * Initializing a security_hook_list structure takes
+ * up a lot of space in a source file. This macro takes
+ * care of the common case and reduces the amount of
+ * text involved.
+ */
+#define LSM_HOOK_INIT(HEAD, HOOK) \
+       { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }
+
+extern struct security_hook_heads security_hook_heads;
+
+static inline void security_add_hooks(struct security_hook_list *hooks,
+                                     int count)
+{
+       int i;
+
+       for (i = 0; i < count; i++)
+               list_add_tail_rcu(&hooks[i].list, hooks[i].head);
+}
+
+#ifdef CONFIG_SECURITY_SELINUX_DISABLE
+/*
+ * Assuring the safety of deleting a security module is up to
+ * the security module involved. This may entail ordering the
+ * module's hook list in a particular way, refusing to disable
+ * the module once a policy is loaded or any number of other
+ * actions better imagined than described.
+ *
+ * The name of the configuration option reflects the only module
+ * that currently uses the mechanism. Any developer who thinks
+ * disabling their module is a good idea needs to be at least as
+ * careful as the SELinux team.
+ */
+static inline void security_delete_hooks(struct security_hook_list *hooks,
+                                               int count)
+{
+       int i;
+
+       for (i = 0; i < count; i++)
+               list_del_rcu(&hooks[i].list);
+}
+#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
+
+extern int __init security_module_enable(const char *module);
+extern void __init capability_add_hooks(void);
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+void __init yama_add_hooks(void);
+#endif
+
+#endif /* ! __LINUX_LSM_HOOKS_H */
index a09ece3..8aa4a25 100644 (file)
@@ -2421,7 +2421,6 @@ extern void sched_dead(struct task_struct *p);
 
 extern void proc_caches_init(void);
 extern void flush_signals(struct task_struct *);
-extern void __flush_signals(struct task_struct *);
 extern void ignore_signals(struct task_struct *);
 extern void flush_signal_handlers(struct task_struct *, int force_default);
 extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info);
index 52febde..79d85dd 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/string.h>
+#include <linux/mm.h>
 
 struct linux_binprm;
 struct cred;
@@ -53,9 +54,6 @@ struct xattr;
 struct xfrm_sec_ctx;
 struct mm_struct;
 
-/* Maximum number of letters for an LSM name string */
-#define SECURITY_NAME_MAX      10
-
 /* If capable should audit the security request */
 #define SECURITY_CAP_NOAUDIT 0
 #define SECURITY_CAP_AUDIT 1
@@ -68,10 +66,7 @@ struct audit_krule;
 struct user_namespace;
 struct timezone;
 
-/*
- * These functions are in security/capability.c and are used
- * as the default capabilities functions
- */
+/* These functions are in security/commoncap.c */
 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
                       int cap, int audit);
 extern int cap_settime(const struct timespec *ts, const struct timezone *tz);
@@ -113,10 +108,6 @@ struct xfrm_state;
 struct xfrm_user_sec_ctx;
 struct seq_file;
 
-extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
-
-void reset_security_ops(void);
-
 #ifdef CONFIG_MMU
 extern unsigned long mmap_min_addr;
 extern unsigned long dac_mmap_min_addr;
@@ -187,1583 +178,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
        opts->num_mnt_opts = 0;
 }
 
-/**
- * struct security_operations - main security structure
- *
- * Security module identifier.
- *
- * @name:
- *     A string that acts as a unique identifier for the LSM with max number
- *     of characters = SECURITY_NAME_MAX.
- *
- * Security hooks for program execution operations.
- *
- * @bprm_set_creds:
- *     Save security information in the bprm->security field, typically based
- *     on information about the bprm->file, for later use by the apply_creds
- *     hook.  This hook may also optionally check permissions (e.g. for
- *     transitions between security domains).
- *     This hook may be called multiple times during a single execve, e.g. for
- *     interpreters.  The hook can tell whether it has already been called by
- *     checking to see if @bprm->security is non-NULL.  If so, then the hook
- *     may decide either to retain the security information saved earlier or
- *     to replace it.
- *     @bprm contains the linux_binprm structure.
- *     Return 0 if the hook is successful and permission is granted.
- * @bprm_check_security:
- *     This hook mediates the point when a search for a binary handler will
- *     begin.  It allows a check the @bprm->security value which is set in the
- *     preceding set_creds call.  The primary difference from set_creds is
- *     that the argv list and envp list are reliably available in @bprm.  This
- *     hook may be called multiple times during a single execve; and in each
- *     pass set_creds is called first.
- *     @bprm contains the linux_binprm structure.
- *     Return 0 if the hook is successful and permission is granted.
- * @bprm_committing_creds:
- *     Prepare to install the new security attributes of a process being
- *     transformed by an execve operation, based on the old credentials
- *     pointed to by @current->cred and the information set in @bprm->cred by
- *     the bprm_set_creds hook.  @bprm points to the linux_binprm structure.
- *     This hook is a good place to perform state changes on the process such
- *     as closing open file descriptors to which access will no longer be
- *     granted when the attributes are changed.  This is called immediately
- *     before commit_creds().
- * @bprm_committed_creds:
- *     Tidy up after the installation of the new security attributes of a
- *     process being transformed by an execve operation.  The new credentials
- *     have, by this point, been set to @current->cred.  @bprm points to the
- *     linux_binprm structure.  This hook is a good place to perform state
- *     changes on the process such as clearing out non-inheritable signal
- *     state.  This is called immediately after commit_creds().
- * @bprm_secureexec:
- *     Return a boolean value (0 or 1) indicating whether a "secure exec"
- *     is required.  The flag is passed in the auxiliary table
- *     on the initial stack to the ELF interpreter to indicate whether libc
- *     should enable secure mode.
- *     @bprm contains the linux_binprm structure.
- *
- * Security hooks for filesystem operations.
- *
- * @sb_alloc_security:
- *     Allocate and attach a security structure to the sb->s_security field.
- *     The s_security field is initialized to NULL when the structure is
- *     allocated.
- *     @sb contains the super_block structure to be modified.
- *     Return 0 if operation was successful.
- * @sb_free_security:
- *     Deallocate and clear the sb->s_security field.
- *     @sb contains the super_block structure to be modified.
- * @sb_statfs:
- *     Check permission before obtaining filesystem statistics for the @mnt
- *     mountpoint.
- *     @dentry is a handle on the superblock for the filesystem.
- *     Return 0 if permission is granted.
- * @sb_mount:
- *     Check permission before an object specified by @dev_name is mounted on
- *     the mount point named by @nd.  For an ordinary mount, @dev_name
- *     identifies a device if the file system type requires a device.  For a
- *     remount (@flags & MS_REMOUNT), @dev_name is irrelevant.  For a
- *     loopback/bind mount (@flags & MS_BIND), @dev_name identifies the
- *     pathname of the object being mounted.
- *     @dev_name contains the name for object being mounted.
- *     @path contains the path for mount point object.
- *     @type contains the filesystem type.
- *     @flags contains the mount flags.
- *     @data contains the filesystem-specific data.
- *     Return 0 if permission is granted.
- * @sb_copy_data:
- *     Allow mount option data to be copied prior to parsing by the filesystem,
- *     so that the security module can extract security-specific mount
- *     options cleanly (a filesystem may modify the data e.g. with strsep()).
- *     This also allows the original mount data to be stripped of security-
- *     specific options to avoid having to make filesystems aware of them.
- *     @type the type of filesystem being mounted.
- *     @orig the original mount data copied from userspace.
- *     @copy copied data which will be passed to the security module.
- *     Returns 0 if the copy was successful.
- * @sb_remount:
- *     Extracts security system specific mount options and verifies no changes
- *     are being made to those options.
- *     @sb superblock being remounted
- *     @data contains the filesystem-specific data.
- *     Return 0 if permission is granted.
- * @sb_umount:
- *     Check permission before the @mnt file system is unmounted.
- *     @mnt contains the mounted file system.
- *     @flags contains the unmount flags, e.g. MNT_FORCE.
- *     Return 0 if permission is granted.
- * @sb_pivotroot:
- *     Check permission before pivoting the root filesystem.
- *     @old_path contains the path for the new location of the current root (put_old).
- *     @new_path contains the path for the new root (new_root).
- *     Return 0 if permission is granted.
- * @sb_set_mnt_opts:
- *     Set the security relevant mount options used for a superblock
- *     @sb the superblock to set security mount options for
- *     @opts binary data structure containing all lsm mount data
- * @sb_clone_mnt_opts:
- *     Copy all security options from a given superblock to another
- *     @oldsb old superblock which contain information to clone
- *     @newsb new superblock which needs filled in
- * @sb_parse_opts_str:
- *     Parse a string of security data filling in the opts structure
- *     @options string containing all mount options known by the LSM
- *     @opts binary data structure usable by the LSM
- * @dentry_init_security:
- *     Compute a context for a dentry as the inode is not yet available
- *     since NFSv4 has no label backed by an EA anyway.
- *     @dentry dentry to use in calculating the context.
- *     @mode mode used to determine resource type.
- *     @name name of the last path component used to create file
- *     @ctx pointer to place the pointer to the resulting context in.
- *     @ctxlen point to place the length of the resulting context.
- *
- *
- * Security hooks for inode operations.
- *
- * @inode_alloc_security:
- *     Allocate and attach a security structure to @inode->i_security.  The
- *     i_security field is initialized to NULL when the inode structure is
- *     allocated.
- *     @inode contains the inode structure.
- *     Return 0 if operation was successful.
- * @inode_free_security:
- *     @inode contains the inode structure.
- *     Deallocate the inode security structure and set @inode->i_security to
- *     NULL.
- * @inode_init_security:
- *     Obtain the security attribute name suffix and value to set on a newly
- *     created inode and set up the incore security field for the new inode.
- *     This hook is called by the fs code as part of the inode creation
- *     transaction and provides for atomic labeling of the inode, unlike
- *     the post_create/mkdir/... hooks called by the VFS.  The hook function
- *     is expected to allocate the name and value via kmalloc, with the caller
- *     being responsible for calling kfree after using them.
- *     If the security module does not use security attributes or does
- *     not wish to put a security attribute on this particular inode,
- *     then it should return -EOPNOTSUPP to skip this processing.
- *     @inode contains the inode structure of the newly created inode.
- *     @dir contains the inode structure of the parent directory.
- *     @qstr contains the last path component of the new object
- *     @name will be set to the allocated name suffix (e.g. selinux).
- *     @value will be set to the allocated attribute value.
- *     @len will be set to the length of the value.
- *     Returns 0 if @name and @value have been successfully set,
- *             -EOPNOTSUPP if no security attribute is needed, or
- *             -ENOMEM on memory allocation failure.
- * @inode_create:
- *     Check permission to create a regular file.
- *     @dir contains inode structure of the parent of the new file.
- *     @dentry contains the dentry structure for the file to be created.
- *     @mode contains the file mode of the file to be created.
- *     Return 0 if permission is granted.
- * @inode_link:
- *     Check permission before creating a new hard link to a file.
- *     @old_dentry contains the dentry structure for an existing link to the file.
- *     @dir contains the inode structure of the parent directory of the new link.
- *     @new_dentry contains the dentry structure for the new link.
- *     Return 0 if permission is granted.
- * @path_link:
- *     Check permission before creating a new hard link to a file.
- *     @old_dentry contains the dentry structure for an existing link
- *     to the file.
- *     @new_dir contains the path structure of the parent directory of
- *     the new link.
- *     @new_dentry contains the dentry structure for the new link.
- *     Return 0 if permission is granted.
- * @inode_unlink:
- *     Check the permission to remove a hard link to a file.
- *     @dir contains the inode structure of parent directory of the file.
- *     @dentry contains the dentry structure for file to be unlinked.
- *     Return 0 if permission is granted.
- * @path_unlink:
- *     Check the permission to remove a hard link to a file.
- *     @dir contains the path structure of parent directory of the file.
- *     @dentry contains the dentry structure for file to be unlinked.
- *     Return 0 if permission is granted.
- * @inode_symlink:
- *     Check the permission to create a symbolic link to a file.
- *     @dir contains the inode structure of parent directory of the symbolic link.
- *     @dentry contains the dentry structure of the symbolic link.
- *     @old_name contains the pathname of file.
- *     Return 0 if permission is granted.
- * @path_symlink:
- *     Check the permission to create a symbolic link to a file.
- *     @dir contains the path structure of parent directory of
- *     the symbolic link.
- *     @dentry contains the dentry structure of the symbolic link.
- *     @old_name contains the pathname of file.
- *     Return 0 if permission is granted.
- * @inode_mkdir:
- *     Check permissions to create a new directory in the existing directory
- *     associated with inode structure @dir.
- *     @dir contains the inode structure of parent of the directory to be created.
- *     @dentry contains the dentry structure of new directory.
- *     @mode contains the mode of new directory.
- *     Return 0 if permission is granted.
- * @path_mkdir:
- *     Check permissions to create a new directory in the existing directory
- *     associated with path structure @path.
- *     @dir contains the path structure of parent of the directory
- *     to be created.
- *     @dentry contains the dentry structure of new directory.
- *     @mode contains the mode of new directory.
- *     Return 0 if permission is granted.
- * @inode_rmdir:
- *     Check the permission to remove a directory.
- *     @dir contains the inode structure of parent of the directory to be removed.
- *     @dentry contains the dentry structure of directory to be removed.
- *     Return 0 if permission is granted.
- * @path_rmdir:
- *     Check the permission to remove a directory.
- *     @dir contains the path structure of parent of the directory to be
- *     removed.
- *     @dentry contains the dentry structure of directory to be removed.
- *     Return 0 if permission is granted.
- * @inode_mknod:
- *     Check permissions when creating a special file (or a socket or a fifo
- *     file created via the mknod system call).  Note that if mknod operation
- *     is being done for a regular file, then the create hook will be called
- *     and not this hook.
- *     @dir contains the inode structure of parent of the new file.
- *     @dentry contains the dentry structure of the new file.
- *     @mode contains the mode of the new file.
- *     @dev contains the device number.
- *     Return 0 if permission is granted.
- * @path_mknod:
- *     Check permissions when creating a file. Note that this hook is called
- *     even if mknod operation is being done for a regular file.
- *     @dir contains the path structure of parent of the new file.
- *     @dentry contains the dentry structure of the new file.
- *     @mode contains the mode of the new file.
- *     @dev contains the undecoded device number. Use new_decode_dev() to get
- *     the decoded device number.
- *     Return 0 if permission is granted.
- * @inode_rename:
- *     Check for permission to rename a file or directory.
- *     @old_dir contains the inode structure for parent of the old link.
- *     @old_dentry contains the dentry structure of the old link.
- *     @new_dir contains the inode structure for parent of the new link.
- *     @new_dentry contains the dentry structure of the new link.
- *     Return 0 if permission is granted.
- * @path_rename:
- *     Check for permission to rename a file or directory.
- *     @old_dir contains the path structure for parent of the old link.
- *     @old_dentry contains the dentry structure of the old link.
- *     @new_dir contains the path structure for parent of the new link.
- *     @new_dentry contains the dentry structure of the new link.
- *     Return 0 if permission is granted.
- * @path_chmod:
- *     Check for permission to change DAC's permission of a file or directory.
- *     @dentry contains the dentry structure.
- *     @mnt contains the vfsmnt structure.
- *     @mode contains DAC's mode.
- *     Return 0 if permission is granted.
- * @path_chown:
- *     Check for permission to change owner/group of a file or directory.
- *     @path contains the path structure.
- *     @uid contains new owner's ID.
- *     @gid contains new group's ID.
- *     Return 0 if permission is granted.
- * @path_chroot:
- *     Check for permission to change root directory.
- *     @path contains the path structure.
- *     Return 0 if permission is granted.
- * @inode_readlink:
- *     Check the permission to read the symbolic link.
- *     @dentry contains the dentry structure for the file link.
- *     Return 0 if permission is granted.
- * @inode_follow_link:
- *     Check permission to follow a symbolic link when looking up a pathname.
- *     @dentry contains the dentry structure for the link.
- *     @inode contains the inode, which itself is not stable in RCU-walk
- *     @rcu indicates whether we are in RCU-walk mode.
- *     Return 0 if permission is granted.
- * @inode_permission:
- *     Check permission before accessing an inode.  This hook is called by the
- *     existing Linux permission function, so a security module can use it to
- *     provide additional checking for existing Linux permission checks.
- *     Notice that this hook is called when a file is opened (as well as many
- *     other operations), whereas the file_security_ops permission hook is
- *     called when the actual read/write operations are performed.
- *     @inode contains the inode structure to check.
- *     @mask contains the permission mask.
- *     Return 0 if permission is granted.
- * @inode_setattr:
- *     Check permission before setting file attributes.  Note that the kernel
- *     call to notify_change is performed from several locations, whenever
- *     file attributes change (such as when a file is truncated, chown/chmod
- *     operations, transferring disk quotas, etc).
- *     @dentry contains the dentry structure for the file.
- *     @attr is the iattr structure containing the new file attributes.
- *     Return 0 if permission is granted.
- * @path_truncate:
- *     Check permission before truncating a file.
- *     @path contains the path structure for the file.
- *     Return 0 if permission is granted.
- * @inode_getattr:
- *     Check permission before obtaining file attributes.
- *     @mnt is the vfsmount where the dentry was looked up
- *     @dentry contains the dentry structure for the file.
- *     Return 0 if permission is granted.
- * @inode_setxattr:
- *     Check permission before setting the extended attributes
- *     @value identified by @name for @dentry.
- *     Return 0 if permission is granted.
- * @inode_post_setxattr:
- *     Update inode security field after successful setxattr operation.
- *     @value identified by @name for @dentry.
- * @inode_getxattr:
- *     Check permission before obtaining the extended attributes
- *     identified by @name for @dentry.
- *     Return 0 if permission is granted.
- * @inode_listxattr:
- *     Check permission before obtaining the list of extended attribute
- *     names for @dentry.
- *     Return 0 if permission is granted.
- * @inode_removexattr:
- *     Check permission before removing the extended attribute
- *     identified by @name for @dentry.
- *     Return 0 if permission is granted.
- * @inode_getsecurity:
- *     Retrieve a copy of the extended attribute representation of the
- *     security label associated with @name for @inode via @buffer.  Note that
- *     @name is the remainder of the attribute name after the security prefix
- *     has been removed. @alloc is used to specify of the call should return a
- *     value via the buffer or just the value length Return size of buffer on
- *     success.
- * @inode_setsecurity:
- *     Set the security label associated with @name for @inode from the
- *     extended attribute value @value.  @size indicates the size of the
- *     @value in bytes.  @flags may be XATTR_CREATE, XATTR_REPLACE, or 0.
- *     Note that @name is the remainder of the attribute name after the
- *     security. prefix has been removed.
- *     Return 0 on success.
- * @inode_listsecurity:
- *     Copy the extended attribute names for the security labels
- *     associated with @inode into @buffer.  The maximum size of @buffer
- *     is specified by @buffer_size.  @buffer may be NULL to request
- *     the size of the buffer required.
- *     Returns number of bytes used/required on success.
- * @inode_need_killpriv:
- *     Called when an inode has been changed.
- *     @dentry is the dentry being changed.
- *     Return <0 on error to abort the inode change operation.
- *     Return 0 if inode_killpriv does not need to be called.
- *     Return >0 if inode_killpriv does need to be called.
- * @inode_killpriv:
- *     The setuid bit is being removed.  Remove similar security labels.
- *     Called with the dentry->d_inode->i_mutex held.
- *     @dentry is the dentry being changed.
- *     Return 0 on success.  If error is returned, then the operation
- *     causing setuid bit removal is failed.
- * @inode_getsecid:
- *     Get the secid associated with the node.
- *     @inode contains a pointer to the inode.
- *     @secid contains a pointer to the location where result will be saved.
- *     In case of failure, @secid will be set to zero.
- *
- * Security hooks for file operations
- *
- * @file_permission:
- *     Check file permissions before accessing an open file.  This hook is
- *     called by various operations that read or write files.  A security
- *     module can use this hook to perform additional checking on these
- *     operations, e.g.  to revalidate permissions on use to support privilege
- *     bracketing or policy changes.  Notice that this hook is used when the
- *     actual read/write operations are performed, whereas the
- *     inode_security_ops hook is called when a file is opened (as well as
- *     many other operations).
- *     Caveat:  Although this hook can be used to revalidate permissions for
- *     various system call operations that read or write files, it does not
- *     address the revalidation of permissions for memory-mapped files.
- *     Security modules must handle this separately if they need such
- *     revalidation.
- *     @file contains the file structure being accessed.
- *     @mask contains the requested permissions.
- *     Return 0 if permission is granted.
- * @file_alloc_security:
- *     Allocate and attach a security structure to the file->f_security field.
- *     The security field is initialized to NULL when the structure is first
- *     created.
- *     @file contains the file structure to secure.
- *     Return 0 if the hook is successful and permission is granted.
- * @file_free_security:
- *     Deallocate and free any security structures stored in file->f_security.
- *     @file contains the file structure being modified.
- * @file_ioctl:
- *     @file contains the file structure.
- *     @cmd contains the operation to perform.
- *     @arg contains the operational arguments.
- *     Check permission for an ioctl operation on @file.  Note that @arg
- *     sometimes represents a user space pointer; in other cases, it may be a
- *     simple integer value.  When @arg represents a user space pointer, it
- *     should never be used by the security module.
- *     Return 0 if permission is granted.
- * @mmap_addr :
- *     Check permissions for a mmap operation at @addr.
- *     @addr contains virtual address that will be used for the operation.
- *     Return 0 if permission is granted.
- * @mmap_file :
- *     Check permissions for a mmap operation.  The @file may be NULL, e.g.
- *     if mapping anonymous memory.
- *     @file contains the file structure for file to map (may be NULL).
- *     @reqprot contains the protection requested by the application.
- *     @prot contains the protection that will be applied by the kernel.
- *     @flags contains the operational flags.
- *     Return 0 if permission is granted.
- * @file_mprotect:
- *     Check permissions before changing memory access permissions.
- *     @vma contains the memory region to modify.
- *     @reqprot contains the protection requested by the application.
- *     @prot contains the protection that will be applied by the kernel.
- *     Return 0 if permission is granted.
- * @file_lock:
- *     Check permission before performing file locking operations.
- *     Note: this hook mediates both flock and fcntl style locks.
- *     @file contains the file structure.
- *     @cmd contains the posix-translated lock operation to perform
- *     (e.g. F_RDLCK, F_WRLCK).
- *     Return 0 if permission is granted.
- * @file_fcntl:
- *     Check permission before allowing the file operation specified by @cmd
- *     from being performed on the file @file.  Note that @arg sometimes
- *     represents a user space pointer; in other cases, it may be a simple
- *     integer value.  When @arg represents a user space pointer, it should
- *     never be used by the security module.
- *     @file contains the file structure.
- *     @cmd contains the operation to be performed.
- *     @arg contains the operational arguments.
- *     Return 0 if permission is granted.
- * @file_set_fowner:
- *     Save owner security information (typically from current->security) in
- *     file->f_security for later use by the send_sigiotask hook.
- *     @file contains the file structure to update.
- *     Return 0 on success.
- * @file_send_sigiotask:
- *     Check permission for the file owner @fown to send SIGIO or SIGURG to the
- *     process @tsk.  Note that this hook is sometimes called from interrupt.
- *     Note that the fown_struct, @fown, is never outside the context of a
- *     struct file, so the file structure (and associated security information)
- *     can always be obtained:
- *             container_of(fown, struct file, f_owner)
- *     @tsk contains the structure of task receiving signal.
- *     @fown contains the file owner information.
- *     @sig is the signal that will be sent.  When 0, kernel sends SIGIO.
- *     Return 0 if permission is granted.
- * @file_receive:
- *     This hook allows security modules to control the ability of a process
- *     to receive an open file descriptor via socket IPC.
- *     @file contains the file structure being received.
- *     Return 0 if permission is granted.
- * @file_open
- *     Save open-time permission checking state for later use upon
- *     file_permission, and recheck access if anything has changed
- *     since inode_permission.
- *
- * Security hooks for task operations.
- *
- * @task_create:
- *     Check permission before creating a child process.  See the clone(2)
- *     manual page for definitions of the @clone_flags.
- *     @clone_flags contains the flags indicating what should be shared.
- *     Return 0 if permission is granted.
- * @task_free:
- *     @task task being freed
- *     Handle release of task-related resources. (Note that this can be called
- *     from interrupt context.)
- * @cred_alloc_blank:
- *     @cred points to the credentials.
- *     @gfp indicates the atomicity of any memory allocations.
- *     Only allocate sufficient memory and attach to @cred such that
- *     cred_transfer() will not get ENOMEM.
- * @cred_free:
- *     @cred points to the credentials.
- *     Deallocate and clear the cred->security field in a set of credentials.
- * @cred_prepare:
- *     @new points to the new credentials.
- *     @old points to the original credentials.
- *     @gfp indicates the atomicity of any memory allocations.
- *     Prepare a new set of credentials by copying the data from the old set.
- * @cred_transfer:
- *     @new points to the new credentials.
- *     @old points to the original credentials.
- *     Transfer data from original creds to new creds
- * @kernel_act_as:
- *     Set the credentials for a kernel service to act as (subjective context).
- *     @new points to the credentials to be modified.
- *     @secid specifies the security ID to be set
- *     The current task must be the one that nominated @secid.
- *     Return 0 if successful.
- * @kernel_create_files_as:
- *     Set the file creation context in a set of credentials to be the same as
- *     the objective context of the specified inode.
- *     @new points to the credentials to be modified.
- *     @inode points to the inode to use as a reference.
- *     The current task must be the one that nominated @inode.
- *     Return 0 if successful.
- * @kernel_fw_from_file:
- *     Load firmware from userspace (not called for built-in firmware).
- *     @file contains the file structure pointing to the file containing
- *     the firmware to load. This argument will be NULL if the firmware
- *     was loaded via the uevent-triggered blob-based interface exposed
- *     by CONFIG_FW_LOADER_USER_HELPER.
- *     @buf pointer to buffer containing firmware contents.
- *     @size length of the firmware contents.
- *     Return 0 if permission is granted.
- * @kernel_module_request:
- *     Ability to trigger the kernel to automatically upcall to userspace for
- *     userspace to load a kernel module with the given name.
- *     @kmod_name name of the module requested by the kernel
- *     Return 0 if successful.
- * @kernel_module_from_file:
- *     Load a kernel module from userspace.
- *     @file contains the file structure pointing to the file containing
- *     the kernel module to load. If the module is being loaded from a blob,
- *     this argument will be NULL.
- *     Return 0 if permission is granted.
- * @task_fix_setuid:
- *     Update the module's state after setting one or more of the user
- *     identity attributes of the current process.  The @flags parameter
- *     indicates which of the set*uid system calls invoked this hook.  If
- *     @new is the set of credentials that will be installed.  Modifications
- *     should be made to this rather than to @current->cred.
- *     @old is the set of credentials that are being replaces
- *     @flags contains one of the LSM_SETID_* values.
- *     Return 0 on success.
- * @task_setpgid:
- *     Check permission before setting the process group identifier of the
- *     process @p to @pgid.
- *     @p contains the task_struct for process being modified.
- *     @pgid contains the new pgid.
- *     Return 0 if permission is granted.
- * @task_getpgid:
- *     Check permission before getting the process group identifier of the
- *     process @p.
- *     @p contains the task_struct for the process.
- *     Return 0 if permission is granted.
- * @task_getsid:
- *     Check permission before getting the session identifier of the process
- *     @p.
- *     @p contains the task_struct for the process.
- *     Return 0 if permission is granted.
- * @task_getsecid:
- *     Retrieve the security identifier of the process @p.
- *     @p contains the task_struct for the process and place is into @secid.
- *     In case of failure, @secid will be set to zero.
- *
- * @task_setnice:
- *     Check permission before setting the nice value of @p to @nice.
- *     @p contains the task_struct of process.
- *     @nice contains the new nice value.
- *     Return 0 if permission is granted.
- * @task_setioprio
- *     Check permission before setting the ioprio value of @p to @ioprio.
- *     @p contains the task_struct of process.
- *     @ioprio contains the new ioprio value
- *     Return 0 if permission is granted.
- * @task_getioprio
- *     Check permission before getting the ioprio value of @p.
- *     @p contains the task_struct of process.
- *     Return 0 if permission is granted.
- * @task_setrlimit:
- *     Check permission before setting the resource limits of the current
- *     process for @resource to @new_rlim.  The old resource limit values can
- *     be examined by dereferencing (current->signal->rlim + resource).
- *     @resource contains the resource whose limit is being set.
- *     @new_rlim contains the new limits for @resource.
- *     Return 0 if permission is granted.
- * @task_setscheduler:
- *     Check permission before setting scheduling policy and/or parameters of
- *     process @p based on @policy and @lp.
- *     @p contains the task_struct for process.
- *     @policy contains the scheduling policy.
- *     @lp contains the scheduling parameters.
- *     Return 0 if permission is granted.
- * @task_getscheduler:
- *     Check permission before obtaining scheduling information for process
- *     @p.
- *     @p contains the task_struct for process.
- *     Return 0 if permission is granted.
- * @task_movememory
- *     Check permission before moving memory owned by process @p.
- *     @p contains the task_struct for process.
- *     Return 0 if permission is granted.
- * @task_kill:
- *     Check permission before sending signal @sig to @p.  @info can be NULL,
- *     the constant 1, or a pointer to a siginfo structure.  If @info is 1 or
- *     SI_FROMKERNEL(info) is true, then the signal should be viewed as coming
- *     from the kernel and should typically be permitted.
- *     SIGIO signals are handled separately by the send_sigiotask hook in
- *     file_security_ops.
- *     @p contains the task_struct for process.
- *     @info contains the signal information.
- *     @sig contains the signal value.
- *     @secid contains the sid of the process where the signal originated
- *     Return 0 if permission is granted.
- * @task_wait:
- *     Check permission before allowing a process to reap a child process @p
- *     and collect its status information.
- *     @p contains the task_struct for process.
- *     Return 0 if permission is granted.
- * @task_prctl:
- *     Check permission before performing a process control operation on the
- *     current process.
- *     @option contains the operation.
- *     @arg2 contains a argument.
- *     @arg3 contains a argument.
- *     @arg4 contains a argument.
- *     @arg5 contains a argument.
- *     Return -ENOSYS if no-one wanted to handle this op, any other value to
- *     cause prctl() to return immediately with that value.
- * @task_to_inode:
- *     Set the security attributes for an inode based on an associated task's
- *     security attributes, e.g. for /proc/pid inodes.
- *     @p contains the task_struct for the task.
- *     @inode contains the inode structure for the inode.
- *
- * Security hooks for Netlink messaging.
- *
- * @netlink_send:
- *     Save security information for a netlink message so that permission
- *     checking can be performed when the message is processed.  The security
- *     information can be saved using the eff_cap field of the
- *     netlink_skb_parms structure.  Also may be used to provide fine
- *     grained control over message transmission.
- *     @sk associated sock of task sending the message.
- *     @skb contains the sk_buff structure for the netlink message.
- *     Return 0 if the information was successfully saved and message
- *     is allowed to be transmitted.
- *
- * Security hooks for Unix domain networking.
- *
- * @unix_stream_connect:
- *     Check permissions before establishing a Unix domain stream connection
- *     between @sock and @other.
- *     @sock contains the sock structure.
- *     @other contains the peer sock structure.
- *     @newsk contains the new sock structure.
- *     Return 0 if permission is granted.
- * @unix_may_send:
- *     Check permissions before connecting or sending datagrams from @sock to
- *     @other.
- *     @sock contains the socket structure.
- *     @other contains the peer socket structure.
- *     Return 0 if permission is granted.
- *
- * The @unix_stream_connect and @unix_may_send hooks were necessary because
- * Linux provides an alternative to the conventional file name space for Unix
- * domain sockets.  Whereas binding and connecting to sockets in the file name
- * space is mediated by the typical file permissions (and caught by the mknod
- * and permission hooks in inode_security_ops), binding and connecting to
- * sockets in the abstract name space is completely unmediated.  Sufficient
- * control of Unix domain sockets in the abstract name space isn't possible
- * using only the socket layer hooks, since we need to know the actual target
- * socket, which is not looked up until we are inside the af_unix code.
- *
- * Security hooks for socket operations.
- *
- * @socket_create:
- *     Check permissions prior to creating a new socket.
- *     @family contains the requested protocol family.
- *     @type contains the requested communications type.
- *     @protocol contains the requested protocol.
- *     @kern set to 1 if a kernel socket.
- *     Return 0 if permission is granted.
- * @socket_post_create:
- *     This hook allows a module to update or allocate a per-socket security
- *     structure. Note that the security field was not added directly to the
- *     socket structure, but rather, the socket security information is stored
- *     in the associated inode.  Typically, the inode alloc_security hook will
- *     allocate and and attach security information to
- *     sock->inode->i_security.  This hook may be used to update the
- *     sock->inode->i_security field with additional information that wasn't
- *     available when the inode was allocated.
- *     @sock contains the newly created socket structure.
- *     @family contains the requested protocol family.
- *     @type contains the requested communications type.
- *     @protocol contains the requested protocol.
- *     @kern set to 1 if a kernel socket.
- * @socket_bind:
- *     Check permission before socket protocol layer bind operation is
- *     performed and the socket @sock is bound to the address specified in the
- *     @address parameter.
- *     @sock contains the socket structure.
- *     @address contains the address to bind to.
- *     @addrlen contains the length of address.
- *     Return 0 if permission is granted.
- * @socket_connect:
- *     Check permission before socket protocol layer connect operation
- *     attempts to connect socket @sock to a remote address, @address.
- *     @sock contains the socket structure.
- *     @address contains the address of remote endpoint.
- *     @addrlen contains the length of address.
- *     Return 0 if permission is granted.
- * @socket_listen:
- *     Check permission before socket protocol layer listen operation.
- *     @sock contains the socket structure.
- *     @backlog contains the maximum length for the pending connection queue.
- *     Return 0 if permission is granted.
- * @socket_accept:
- *     Check permission before accepting a new connection.  Note that the new
- *     socket, @newsock, has been created and some information copied to it,
- *     but the accept operation has not actually been performed.
- *     @sock contains the listening socket structure.
- *     @newsock contains the newly created server socket for connection.
- *     Return 0 if permission is granted.
- * @socket_sendmsg:
- *     Check permission before transmitting a message to another socket.
- *     @sock contains the socket structure.
- *     @msg contains the message to be transmitted.
- *     @size contains the size of message.
- *     Return 0 if permission is granted.
- * @socket_recvmsg:
- *     Check permission before receiving a message from a socket.
- *     @sock contains the socket structure.
- *     @msg contains the message structure.
- *     @size contains the size of message structure.
- *     @flags contains the operational flags.
- *     Return 0 if permission is granted.
- * @socket_getsockname:
- *     Check permission before the local address (name) of the socket object
- *     @sock is retrieved.
- *     @sock contains the socket structure.
- *     Return 0 if permission is granted.
- * @socket_getpeername:
- *     Check permission before the remote address (name) of a socket object
- *     @sock is retrieved.
- *     @sock contains the socket structure.
- *     Return 0 if permission is granted.
- * @socket_getsockopt:
- *     Check permissions before retrieving the options associated with socket
- *     @sock.
- *     @sock contains the socket structure.
- *     @level contains the protocol level to retrieve option from.
- *     @optname contains the name of option to retrieve.
- *     Return 0 if permission is granted.
- * @socket_setsockopt:
- *     Check permissions before setting the options associated with socket
- *     @sock.
- *     @sock contains the socket structure.
- *     @level contains the protocol level to set options for.
- *     @optname contains the name of the option to set.
- *     Return 0 if permission is granted.
- * @socket_shutdown:
- *     Checks permission before all or part of a connection on the socket
- *     @sock is shut down.
- *     @sock contains the socket structure.
- *     @how contains the flag indicating how future sends and receives are handled.
- *     Return 0 if permission is granted.
- * @socket_sock_rcv_skb:
- *     Check permissions on incoming network packets.  This hook is distinct
- *     from Netfilter's IP input hooks since it is the first time that the
- *     incoming sk_buff @skb has been associated with a particular socket, @sk.
- *     Must not sleep inside this hook because some callers hold spinlocks.
- *     @sk contains the sock (not socket) associated with the incoming sk_buff.
- *     @skb contains the incoming network data.
- * @socket_getpeersec_stream:
- *     This hook allows the security module to provide peer socket security
- *     state for unix or connected tcp sockets to userspace via getsockopt
- *     SO_GETPEERSEC.  For tcp sockets this can be meaningful if the
- *     socket is associated with an ipsec SA.
- *     @sock is the local socket.
- *     @optval userspace memory where the security state is to be copied.
- *     @optlen userspace int where the module should copy the actual length
- *     of the security state.
- *     @len as input is the maximum length to copy to userspace provided
- *     by the caller.
- *     Return 0 if all is well, otherwise, typical getsockopt return
- *     values.
- * @socket_getpeersec_dgram:
- *     This hook allows the security module to provide peer socket security
- *     state for udp sockets on a per-packet basis to userspace via
- *     getsockopt SO_GETPEERSEC.  The application must first have indicated
- *     the IP_PASSSEC option via getsockopt.  It can then retrieve the
- *     security state returned by this hook for a packet via the SCM_SECURITY
- *     ancillary message type.
- *     @skb is the skbuff for the packet being queried
- *     @secdata is a pointer to a buffer in which to copy the security data
- *     @seclen is the maximum length for @secdata
- *     Return 0 on success, error on failure.
- * @sk_alloc_security:
- *     Allocate and attach a security structure to the sk->sk_security field,
- *     which is used to copy security attributes between local stream sockets.
- * @sk_free_security:
- *     Deallocate security structure.
- * @sk_clone_security:
- *     Clone/copy security structure.
- * @sk_getsecid:
- *     Retrieve the LSM-specific secid for the sock to enable caching of network
- *     authorizations.
- * @sock_graft:
- *     Sets the socket's isec sid to the sock's sid.
- * @inet_conn_request:
- *     Sets the openreq's sid to socket's sid with MLS portion taken from peer sid.
- * @inet_csk_clone:
- *     Sets the new child socket's sid to the openreq sid.
- * @inet_conn_established:
- *     Sets the connection's peersid to the secmark on skb.
- * @secmark_relabel_packet:
- *     check if the process should be allowed to relabel packets to the given secid
- * @security_secmark_refcount_inc
- *     tells the LSM to increment the number of secmark labeling rules loaded
- * @security_secmark_refcount_dec
- *     tells the LSM to decrement the number of secmark labeling rules loaded
- * @req_classify_flow:
- *     Sets the flow's sid to the openreq sid.
- * @tun_dev_alloc_security:
- *     This hook allows a module to allocate a security structure for a TUN
- *     device.
- *     @security pointer to a security structure pointer.
- *     Returns a zero on success, negative values on failure.
- * @tun_dev_free_security:
- *     This hook allows a module to free the security structure for a TUN
- *     device.
- *     @security pointer to the TUN device's security structure
- * @tun_dev_create:
- *     Check permissions prior to creating a new TUN device.
- * @tun_dev_attach_queue:
- *     Check permissions prior to attaching to a TUN device queue.
- *     @security pointer to the TUN device's security structure.
- * @tun_dev_attach:
- *     This hook can be used by the module to update any security state
- *     associated with the TUN device's sock structure.
- *     @sk contains the existing sock structure.
- *     @security pointer to the TUN device's security structure.
- * @tun_dev_open:
- *     This hook can be used by the module to update any security state
- *     associated with the TUN device's security structure.
- *     @security pointer to the TUN devices's security structure.
- * @skb_owned_by:
- *     This hook sets the packet's owning sock.
- *     @skb is the packet.
- *     @sk the sock which owns the packet.
- *
- * Security hooks for XFRM operations.
- *
- * @xfrm_policy_alloc_security:
- *     @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy
- *     Database used by the XFRM system.
- *     @sec_ctx contains the security context information being provided by
- *     the user-level policy update program (e.g., setkey).
- *     Allocate a security structure to the xp->security field; the security
- *     field is initialized to NULL when the xfrm_policy is allocated.
- *     Return 0 if operation was successful (memory to allocate, legal context)
- *     @gfp is to specify the context for the allocation
- * @xfrm_policy_clone_security:
- *     @old_ctx contains an existing xfrm_sec_ctx.
- *     @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
- *     Allocate a security structure in new_ctxp that contains the
- *     information from the old_ctx structure.
- *     Return 0 if operation was successful (memory to allocate).
- * @xfrm_policy_free_security:
- *     @ctx contains the xfrm_sec_ctx
- *     Deallocate xp->security.
- * @xfrm_policy_delete_security:
- *     @ctx contains the xfrm_sec_ctx.
- *     Authorize deletion of xp->security.
- * @xfrm_state_alloc:
- *     @x contains the xfrm_state being added to the Security Association
- *     Database by the XFRM system.
- *     @sec_ctx contains the security context information being provided by
- *     the user-level SA generation program (e.g., setkey or racoon).
- *     Allocate a security structure to the x->security field; the security
- *     field is initialized to NULL when the xfrm_state is allocated. Set the
- *     context to correspond to sec_ctx. Return 0 if operation was successful
- *     (memory to allocate, legal context).
- * @xfrm_state_alloc_acquire:
- *     @x contains the xfrm_state being added to the Security Association
- *     Database by the XFRM system.
- *     @polsec contains the policy's security context.
- *     @secid contains the secid from which to take the mls portion of the
- *     context.
- *     Allocate a security structure to the x->security field; the security
- *     field is initialized to NULL when the xfrm_state is allocated. Set the
- *     context to correspond to secid. Return 0 if operation was successful
- *     (memory to allocate, legal context).
- * @xfrm_state_free_security:
- *     @x contains the xfrm_state.
- *     Deallocate x->security.
- * @xfrm_state_delete_security:
- *     @x contains the xfrm_state.
- *     Authorize deletion of x->security.
- * @xfrm_policy_lookup:
- *     @ctx contains the xfrm_sec_ctx for which the access control is being
- *     checked.
- *     @fl_secid contains the flow security label that is used to authorize
- *     access to the policy xp.
- *     @dir contains the direction of the flow (input or output).
- *     Check permission when a flow selects a xfrm_policy for processing
- *     XFRMs on a packet.  The hook is called when selecting either a
- *     per-socket policy or a generic xfrm policy.
- *     Return 0 if permission is granted, -ESRCH otherwise, or -errno
- *     on other errors.
- * @xfrm_state_pol_flow_match:
- *     @x contains the state to match.
- *     @xp contains the policy to check for a match.
- *     @fl contains the flow to check for a match.
- *     Return 1 if there is a match.
- * @xfrm_decode_session:
- *     @skb points to skb to decode.
- *     @secid points to the flow key secid to set.
- *     @ckall says if all xfrms used should be checked for same secid.
- *     Return 0 if ckall is zero or all xfrms used have the same secid.
- *
- * Security hooks affecting all Key Management operations
- *
- * @key_alloc:
- *     Permit allocation of a key and assign security data. Note that key does
- *     not have a serial number assigned at this point.
- *     @key points to the key.
- *     @flags is the allocation flags
- *     Return 0 if permission is granted, -ve error otherwise.
- * @key_free:
- *     Notification of destruction; free security data.
- *     @key points to the key.
- *     No return value.
- * @key_permission:
- *     See whether a specific operational right is granted to a process on a
- *     key.
- *     @key_ref refers to the key (key pointer + possession attribute bit).
- *     @cred points to the credentials to provide the context against which to
- *     evaluate the security data on the key.
- *     @perm describes the combination of permissions required of this key.
- *     Return 0 if permission is granted, -ve error otherwise.
- * @key_getsecurity:
- *     Get a textual representation of the security context attached to a key
- *     for the purposes of honouring KEYCTL_GETSECURITY.  This function
- *     allocates the storage for the NUL-terminated string and the caller
- *     should free it.
- *     @key points to the key to be queried.
- *     @_buffer points to a pointer that should be set to point to the
- *     resulting string (if no label or an error occurs).
- *     Return the length of the string (including terminating NUL) or -ve if
- *     an error.
- *     May also return 0 (and a NULL buffer pointer) if there is no label.
- *
- * Security hooks affecting all System V IPC operations.
- *
- * @ipc_permission:
- *     Check permissions for access to IPC
- *     @ipcp contains the kernel IPC permission structure
- *     @flag contains the desired (requested) permission set
- *     Return 0 if permission is granted.
- * @ipc_getsecid:
- *     Get the secid associated with the ipc object.
- *     @ipcp contains the kernel IPC permission structure.
- *     @secid contains a pointer to the location where result will be saved.
- *     In case of failure, @secid will be set to zero.
- *
- * Security hooks for individual messages held in System V IPC message queues
- * @msg_msg_alloc_security:
- *     Allocate and attach a security structure to the msg->security field.
- *     The security field is initialized to NULL when the structure is first
- *     created.
- *     @msg contains the message structure to be modified.
- *     Return 0 if operation was successful and permission is granted.
- * @msg_msg_free_security:
- *     Deallocate the security structure for this message.
- *     @msg contains the message structure to be modified.
- *
- * Security hooks for System V IPC Message Queues
- *
- * @msg_queue_alloc_security:
- *     Allocate and attach a security structure to the
- *     msq->q_perm.security field. The security field is initialized to
- *     NULL when the structure is first created.
- *     @msq contains the message queue structure to be modified.
- *     Return 0 if operation was successful and permission is granted.
- * @msg_queue_free_security:
- *     Deallocate security structure for this message queue.
- *     @msq contains the message queue structure to be modified.
- * @msg_queue_associate:
- *     Check permission when a message queue is requested through the
- *     msgget system call.  This hook is only called when returning the
- *     message queue identifier for an existing message queue, not when a
- *     new message queue is created.
- *     @msq contains the message queue to act upon.
- *     @msqflg contains the operation control flags.
- *     Return 0 if permission is granted.
- * @msg_queue_msgctl:
- *     Check permission when a message control operation specified by @cmd
- *     is to be performed on the message queue @msq.
- *     The @msq may be NULL, e.g. for IPC_INFO or MSG_INFO.
- *     @msq contains the message queue to act upon.  May be NULL.
- *     @cmd contains the operation to be performed.
- *     Return 0 if permission is granted.
- * @msg_queue_msgsnd:
- *     Check permission before a message, @msg, is enqueued on the message
- *     queue, @msq.
- *     @msq contains the message queue to send message to.
- *     @msg contains the message to be enqueued.
- *     @msqflg contains operational flags.
- *     Return 0 if permission is granted.
- * @msg_queue_msgrcv:
- *     Check permission before a message, @msg, is removed from the message
- *     queue, @msq.  The @target task structure contains a pointer to the
- *     process that will be receiving the message (not equal to the current
- *     process when inline receives are being performed).
- *     @msq contains the message queue to retrieve message from.
- *     @msg contains the message destination.
- *     @target contains the task structure for recipient process.
- *     @type contains the type of message requested.
- *     @mode contains the operational flags.
- *     Return 0 if permission is granted.
- *
- * Security hooks for System V Shared Memory Segments
- *
- * @shm_alloc_security:
- *     Allocate and attach a security structure to the shp->shm_perm.security
- *     field.  The security field is initialized to NULL when the structure is
- *     first created.
- *     @shp contains the shared memory structure to be modified.
- *     Return 0 if operation was successful and permission is granted.
- * @shm_free_security:
- *     Deallocate the security struct for this memory segment.
- *     @shp contains the shared memory structure to be modified.
- * @shm_associate:
- *     Check permission when a shared memory region is requested through the
- *     shmget system call.  This hook is only called when returning the shared
- *     memory region identifier for an existing region, not when a new shared
- *     memory region is created.
- *     @shp contains the shared memory structure to be modified.
- *     @shmflg contains the operation control flags.
- *     Return 0 if permission is granted.
- * @shm_shmctl:
- *     Check permission when a shared memory control operation specified by
- *     @cmd is to be performed on the shared memory region @shp.
- *     The @shp may be NULL, e.g. for IPC_INFO or SHM_INFO.
- *     @shp contains shared memory structure to be modified.
- *     @cmd contains the operation to be performed.
- *     Return 0 if permission is granted.
- * @shm_shmat:
- *     Check permissions prior to allowing the shmat system call to attach the
- *     shared memory segment @shp to the data segment of the calling process.
- *     The attaching address is specified by @shmaddr.
- *     @shp contains the shared memory structure to be modified.
- *     @shmaddr contains the address to attach memory region to.
- *     @shmflg contains the operational flags.
- *     Return 0 if permission is granted.
- *
- * Security hooks for System V Semaphores
- *
- * @sem_alloc_security:
- *     Allocate and attach a security structure to the sma->sem_perm.security
- *     field.  The security field is initialized to NULL when the structure is
- *     first created.
- *     @sma contains the semaphore structure
- *     Return 0 if operation was successful and permission is granted.
- * @sem_free_security:
- *     deallocate security struct for this semaphore
- *     @sma contains the semaphore structure.
- * @sem_associate:
- *     Check permission when a semaphore is requested through the semget
- *     system call.  This hook is only called when returning the semaphore
- *     identifier for an existing semaphore, not when a new one must be
- *     created.
- *     @sma contains the semaphore structure.
- *     @semflg contains the operation control flags.
- *     Return 0 if permission is granted.
- * @sem_semctl:
- *     Check permission when a semaphore operation specified by @cmd is to be
- *     performed on the semaphore @sma.  The @sma may be NULL, e.g. for
- *     IPC_INFO or SEM_INFO.
- *     @sma contains the semaphore structure.  May be NULL.
- *     @cmd contains the operation to be performed.
- *     Return 0 if permission is granted.
- * @sem_semop
- *     Check permissions before performing operations on members of the
- *     semaphore set @sma.  If the @alter flag is nonzero, the semaphore set
- *     may be modified.
- *     @sma contains the semaphore structure.
- *     @sops contains the operations to perform.
- *     @nsops contains the number of operations to perform.
- *     @alter contains the flag indicating whether changes are to be made.
- *     Return 0 if permission is granted.
- *
- * @binder_set_context_mgr
- *     Check whether @mgr is allowed to be the binder context manager.
- *     @mgr contains the task_struct for the task being registered.
- *     Return 0 if permission is granted.
- * @binder_transaction
- *     Check whether @from is allowed to invoke a binder transaction call
- *     to @to.
- *     @from contains the task_struct for the sending task.
- *     @to contains the task_struct for the receiving task.
- * @binder_transfer_binder
- *     Check whether @from is allowed to transfer a binder reference to @to.
- *     @from contains the task_struct for the sending task.
- *     @to contains the task_struct for the receiving task.
- * @binder_transfer_file
- *     Check whether @from is allowed to transfer @file to @to.
- *     @from contains the task_struct for the sending task.
- *     @file contains the struct file being transferred.
- *     @to contains the task_struct for the receiving task.
- *
- * @ptrace_access_check:
- *     Check permission before allowing the current process to trace the
- *     @child process.
- *     Security modules may also want to perform a process tracing check
- *     during an execve in the set_security or apply_creds hooks of
- *     tracing check during an execve in the bprm_set_creds hook of
- *     binprm_security_ops if the process is being traced and its security
- *     attributes would be changed by the execve.
- *     @child contains the task_struct structure for the target process.
- *     @mode contains the PTRACE_MODE flags indicating the form of access.
- *     Return 0 if permission is granted.
- * @ptrace_traceme:
- *     Check that the @parent process has sufficient permission to trace the
- *     current process before allowing the current process to present itself
- *     to the @parent process for tracing.
- *     @parent contains the task_struct structure for debugger process.
- *     Return 0 if permission is granted.
- * @capget:
- *     Get the @effective, @inheritable, and @permitted capability sets for
- *     the @target process.  The hook may also perform permission checking to
- *     determine if the current process is allowed to see the capability sets
- *     of the @target process.
- *     @target contains the task_struct structure for target process.
- *     @effective contains the effective capability set.
- *     @inheritable contains the inheritable capability set.
- *     @permitted contains the permitted capability set.
- *     Return 0 if the capability sets were successfully obtained.
- * @capset:
- *     Set the @effective, @inheritable, and @permitted capability sets for
- *     the current process.
- *     @new contains the new credentials structure for target process.
- *     @old contains the current credentials structure for target process.
- *     @effective contains the effective capability set.
- *     @inheritable contains the inheritable capability set.
- *     @permitted contains the permitted capability set.
- *     Return 0 and update @new if permission is granted.
- * @capable:
- *     Check whether the @tsk process has the @cap capability in the indicated
- *     credentials.
- *     @cred contains the credentials to use.
- *     @ns contains the user namespace we want the capability in
- *     @cap contains the capability <include/linux/capability.h>.
- *     @audit: Whether to write an audit message or not
- *     Return 0 if the capability is granted for @tsk.
- * @syslog:
- *     Check permission before accessing the kernel message ring or changing
- *     logging to the console.
- *     See the syslog(2) manual page for an explanation of the @type values.
- *     @type contains the type of action.
- *     @from_file indicates the context of action (if it came from /proc).
- *     Return 0 if permission is granted.
- * @settime:
- *     Check permission to change the system time.
- *     struct timespec and timezone are defined in include/linux/time.h
- *     @ts contains new time
- *     @tz contains new timezone
- *     Return 0 if permission is granted.
- * @vm_enough_memory:
- *     Check permissions for allocating a new virtual mapping.
- *     @mm contains the mm struct it is being added to.
- *     @pages contains the number of pages.
- *     Return 0 if permission is granted.
- *
- * @ismaclabel:
- *     Check if the extended attribute specified by @name
- *     represents a MAC label. Returns 1 if name is a MAC
- *     attribute otherwise returns 0.
- *     @name full extended attribute name to check against
- *     LSM as a MAC label.
- *
- * @secid_to_secctx:
- *     Convert secid to security context.  If secdata is NULL the length of
- *     the result will be returned in seclen, but no secdata will be returned.
- *     This does mean that the length could change between calls to check the
- *     length and the next call which actually allocates and returns the secdata.
- *     @secid contains the security ID.
- *     @secdata contains the pointer that stores the converted security context.
- *     @seclen pointer which contains the length of the data
- * @secctx_to_secid:
- *     Convert security context to secid.
- *     @secid contains the pointer to the generated security ID.
- *     @secdata contains the security context.
- *
- * @release_secctx:
- *     Release the security context.
- *     @secdata contains the security context.
- *     @seclen contains the length of the security context.
- *
- * Security hooks for Audit
- *
- * @audit_rule_init:
- *     Allocate and initialize an LSM audit rule structure.
- *     @field contains the required Audit action. Fields flags are defined in include/linux/audit.h
- *     @op contains the operator the rule uses.
- *     @rulestr contains the context where the rule will be applied to.
- *     @lsmrule contains a pointer to receive the result.
- *     Return 0 if @lsmrule has been successfully set,
- *     -EINVAL in case of an invalid rule.
- *
- * @audit_rule_known:
- *     Specifies whether given @rule contains any fields related to current LSM.
- *     @rule contains the audit rule of interest.
- *     Return 1 in case of relation found, 0 otherwise.
- *
- * @audit_rule_match:
- *     Determine if given @secid matches a rule previously approved
- *     by @audit_rule_known.
- *     @secid contains the security id in question.
- *     @field contains the field which relates to current LSM.
- *     @op contains the operator that will be used for matching.
- *     @rule points to the audit rule that will be checked against.
- *     @actx points to the audit context associated with the check.
- *     Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
- *
- * @audit_rule_free:
- *     Deallocate the LSM audit rule structure previously allocated by
- *     audit_rule_init.
- *     @rule contains the allocated rule
- *
- * @inode_notifysecctx:
- *     Notify the security module of what the security context of an inode
- *     should be.  Initializes the incore security context managed by the
- *     security module for this inode.  Example usage:  NFS client invokes
- *     this hook to initialize the security context in its incore inode to the
- *     value provided by the server for the file when the server returned the
- *     file's attributes to the client.
- *
- *     Must be called with inode->i_mutex locked.
- *
- *     @inode we wish to set the security context of.
- *     @ctx contains the string which we wish to set in the inode.
- *     @ctxlen contains the length of @ctx.
- *
- * @inode_setsecctx:
- *     Change the security context of an inode.  Updates the
- *     incore security context managed by the security module and invokes the
- *     fs code as needed (via __vfs_setxattr_noperm) to update any backing
- *     xattrs that represent the context.  Example usage:  NFS server invokes
- *     this hook to change the security context in its incore inode and on the
- *     backing filesystem to a value provided by the client on a SETATTR
- *     operation.
- *
- *     Must be called with inode->i_mutex locked.
- *
- *     @dentry contains the inode we wish to set the security context of.
- *     @ctx contains the string which we wish to set in the inode.
- *     @ctxlen contains the length of @ctx.
- *
- * @inode_getsecctx:
- *     On success, returns 0 and fills out @ctx and @ctxlen with the security
- *     context for the given @inode.
- *
- *     @inode we wish to get the security context of.
- *     @ctx is a pointer in which to place the allocated security context.
- *     @ctxlen points to the place to put the length of @ctx.
- * This is the main security structure.
- */
-struct security_operations {
-       char name[SECURITY_NAME_MAX + 1];
-
-       int (*binder_set_context_mgr) (struct task_struct *mgr);
-       int (*binder_transaction) (struct task_struct *from,
-                                  struct task_struct *to);
-       int (*binder_transfer_binder) (struct task_struct *from,
-                                      struct task_struct *to);
-       int (*binder_transfer_file) (struct task_struct *from,
-                                    struct task_struct *to, struct file *file);
-
-       int (*ptrace_access_check) (struct task_struct *child, unsigned int mode);
-       int (*ptrace_traceme) (struct task_struct *parent);
-       int (*capget) (struct task_struct *target,
-                      kernel_cap_t *effective,
-                      kernel_cap_t *inheritable, kernel_cap_t *permitted);
-       int (*capset) (struct cred *new,
-                      const struct cred *old,
-                      const kernel_cap_t *effective,
-                      const kernel_cap_t *inheritable,
-                      const kernel_cap_t *permitted);
-       int (*capable) (const struct cred *cred, struct user_namespace *ns,
-                       int cap, int audit);
-       int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
-       int (*quota_on) (struct dentry *dentry);
-       int (*syslog) (int type);
-       int (*settime) (const struct timespec *ts, const struct timezone *tz);
-       int (*vm_enough_memory) (struct mm_struct *mm, long pages);
-
-       int (*bprm_set_creds) (struct linux_binprm *bprm);
-       int (*bprm_check_security) (struct linux_binprm *bprm);
-       int (*bprm_secureexec) (struct linux_binprm *bprm);
-       void (*bprm_committing_creds) (struct linux_binprm *bprm);
-       void (*bprm_committed_creds) (struct linux_binprm *bprm);
-
-       int (*sb_alloc_security) (struct super_block *sb);
-       void (*sb_free_security) (struct super_block *sb);
-       int (*sb_copy_data) (char *orig, char *copy);
-       int (*sb_remount) (struct super_block *sb, void *data);
-       int (*sb_kern_mount) (struct super_block *sb, int flags, void *data);
-       int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
-       int (*sb_statfs) (struct dentry *dentry);
-       int (*sb_mount) (const char *dev_name, struct path *path,
-                        const char *type, unsigned long flags, void *data);
-       int (*sb_umount) (struct vfsmount *mnt, int flags);
-       int (*sb_pivotroot) (struct path *old_path,
-                            struct path *new_path);
-       int (*sb_set_mnt_opts) (struct super_block *sb,
-                               struct security_mnt_opts *opts,
-                               unsigned long kern_flags,
-                               unsigned long *set_kern_flags);
-       int (*sb_clone_mnt_opts) (const struct super_block *oldsb,
-                                  struct super_block *newsb);
-       int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
-       int (*dentry_init_security) (struct dentry *dentry, int mode,
-                                       struct qstr *name, void **ctx,
-                                       u32 *ctxlen);
-
-
-#ifdef CONFIG_SECURITY_PATH
-       int (*path_unlink) (struct path *dir, struct dentry *dentry);
-       int (*path_mkdir) (struct path *dir, struct dentry *dentry, umode_t mode);
-       int (*path_rmdir) (struct path *dir, struct dentry *dentry);
-       int (*path_mknod) (struct path *dir, struct dentry *dentry, umode_t mode,
-                          unsigned int dev);
-       int (*path_truncate) (struct path *path);
-       int (*path_symlink) (struct path *dir, struct dentry *dentry,
-                            const char *old_name);
-       int (*path_link) (struct dentry *old_dentry, struct path *new_dir,
-                         struct dentry *new_dentry);
-       int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
-                           struct path *new_dir, struct dentry *new_dentry);
-       int (*path_chmod) (struct path *path, umode_t mode);
-       int (*path_chown) (struct path *path, kuid_t uid, kgid_t gid);
-       int (*path_chroot) (struct path *path);
-#endif
-
-       int (*inode_alloc_security) (struct inode *inode);
-       void (*inode_free_security) (struct inode *inode);
-       int (*inode_init_security) (struct inode *inode, struct inode *dir,
-                                   const struct qstr *qstr, const char **name,
-                                   void **value, size_t *len);
-       int (*inode_create) (struct inode *dir,
-                            struct dentry *dentry, umode_t mode);
-       int (*inode_link) (struct dentry *old_dentry,
-                          struct inode *dir, struct dentry *new_dentry);
-       int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
-       int (*inode_symlink) (struct inode *dir,
-                             struct dentry *dentry, const char *old_name);
-       int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, umode_t mode);
-       int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
-       int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
-                           umode_t mode, dev_t dev);
-       int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
-                            struct inode *new_dir, struct dentry *new_dentry);
-       int (*inode_readlink) (struct dentry *dentry);
-       int (*inode_follow_link) (struct dentry *dentry, struct inode *inode,
-                                 bool rcu);
-       int (*inode_permission) (struct inode *inode, int mask);
-       int (*inode_setattr)    (struct dentry *dentry, struct iattr *attr);
-       int (*inode_getattr) (const struct path *path);
-       int (*inode_setxattr) (struct dentry *dentry, const char *name,
-                              const void *value, size_t size, int flags);
-       void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
-                                    const void *value, size_t size, int flags);
-       int (*inode_getxattr) (struct dentry *dentry, const char *name);
-       int (*inode_listxattr) (struct dentry *dentry);
-       int (*inode_removexattr) (struct dentry *dentry, const char *name);
-       int (*inode_need_killpriv) (struct dentry *dentry);
-       int (*inode_killpriv) (struct dentry *dentry);
-       int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
-       int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
-       int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
-       void (*inode_getsecid) (const struct inode *inode, u32 *secid);
-
-       int (*file_permission) (struct file *file, int mask);
-       int (*file_alloc_security) (struct file *file);
-       void (*file_free_security) (struct file *file);
-       int (*file_ioctl) (struct file *file, unsigned int cmd,
-                          unsigned long arg);
-       int (*mmap_addr) (unsigned long addr);
-       int (*mmap_file) (struct file *file,
-                         unsigned long reqprot, unsigned long prot,
-                         unsigned long flags);
-       int (*file_mprotect) (struct vm_area_struct *vma,
-                             unsigned long reqprot,
-                             unsigned long prot);
-       int (*file_lock) (struct file *file, unsigned int cmd);
-       int (*file_fcntl) (struct file *file, unsigned int cmd,
-                          unsigned long arg);
-       void (*file_set_fowner) (struct file *file);
-       int (*file_send_sigiotask) (struct task_struct *tsk,
-                                   struct fown_struct *fown, int sig);
-       int (*file_receive) (struct file *file);
-       int (*file_open) (struct file *file, const struct cred *cred);
-
-       int (*task_create) (unsigned long clone_flags);
-       void (*task_free) (struct task_struct *task);
-       int (*cred_alloc_blank) (struct cred *cred, gfp_t gfp);
-       void (*cred_free) (struct cred *cred);
-       int (*cred_prepare)(struct cred *new, const struct cred *old,
-                           gfp_t gfp);
-       void (*cred_transfer)(struct cred *new, const struct cred *old);
-       int (*kernel_act_as)(struct cred *new, u32 secid);
-       int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
-       int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
-       int (*kernel_module_request)(char *kmod_name);
-       int (*kernel_module_from_file)(struct file *file);
-       int (*task_fix_setuid) (struct cred *new, const struct cred *old,
-                               int flags);
-       int (*task_setpgid) (struct task_struct *p, pid_t pgid);
-       int (*task_getpgid) (struct task_struct *p);
-       int (*task_getsid) (struct task_struct *p);
-       void (*task_getsecid) (struct task_struct *p, u32 *secid);
-       int (*task_setnice) (struct task_struct *p, int nice);
-       int (*task_setioprio) (struct task_struct *p, int ioprio);
-       int (*task_getioprio) (struct task_struct *p);
-       int (*task_setrlimit) (struct task_struct *p, unsigned int resource,
-                       struct rlimit *new_rlim);
-       int (*task_setscheduler) (struct task_struct *p);
-       int (*task_getscheduler) (struct task_struct *p);
-       int (*task_movememory) (struct task_struct *p);
-       int (*task_kill) (struct task_struct *p,
-                         struct siginfo *info, int sig, u32 secid);
-       int (*task_wait) (struct task_struct *p);
-       int (*task_prctl) (int option, unsigned long arg2,
-                          unsigned long arg3, unsigned long arg4,
-                          unsigned long arg5);
-       void (*task_to_inode) (struct task_struct *p, struct inode *inode);
-
-       int (*ipc_permission) (struct kern_ipc_perm *ipcp, short flag);
-       void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid);
-
-       int (*msg_msg_alloc_security) (struct msg_msg *msg);
-       void (*msg_msg_free_security) (struct msg_msg *msg);
-
-       int (*msg_queue_alloc_security) (struct msg_queue *msq);
-       void (*msg_queue_free_security) (struct msg_queue *msq);
-       int (*msg_queue_associate) (struct msg_queue *msq, int msqflg);
-       int (*msg_queue_msgctl) (struct msg_queue *msq, int cmd);
-       int (*msg_queue_msgsnd) (struct msg_queue *msq,
-                                struct msg_msg *msg, int msqflg);
-       int (*msg_queue_msgrcv) (struct msg_queue *msq,
-                                struct msg_msg *msg,
-                                struct task_struct *target,
-                                long type, int mode);
-
-       int (*shm_alloc_security) (struct shmid_kernel *shp);
-       void (*shm_free_security) (struct shmid_kernel *shp);
-       int (*shm_associate) (struct shmid_kernel *shp, int shmflg);
-       int (*shm_shmctl) (struct shmid_kernel *shp, int cmd);
-       int (*shm_shmat) (struct shmid_kernel *shp,
-                         char __user *shmaddr, int shmflg);
-
-       int (*sem_alloc_security) (struct sem_array *sma);
-       void (*sem_free_security) (struct sem_array *sma);
-       int (*sem_associate) (struct sem_array *sma, int semflg);
-       int (*sem_semctl) (struct sem_array *sma, int cmd);
-       int (*sem_semop) (struct sem_array *sma,
-                         struct sembuf *sops, unsigned nsops, int alter);
-
-       int (*netlink_send) (struct sock *sk, struct sk_buff *skb);
-
-       void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
-
-       int (*getprocattr) (struct task_struct *p, char *name, char **value);
-       int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size);
-       int (*ismaclabel) (const char *name);
-       int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen);
-       int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
-       void (*release_secctx) (char *secdata, u32 seclen);
-
-       int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
-       int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
-       int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen);
-
-#ifdef CONFIG_SECURITY_NETWORK
-       int (*unix_stream_connect) (struct sock *sock, struct sock *other, struct sock *newsk);
-       int (*unix_may_send) (struct socket *sock, struct socket *other);
-
-       int (*socket_create) (int family, int type, int protocol, int kern);
-       int (*socket_post_create) (struct socket *sock, int family,
-                                  int type, int protocol, int kern);
-       int (*socket_bind) (struct socket *sock,
-                           struct sockaddr *address, int addrlen);
-       int (*socket_connect) (struct socket *sock,
-                              struct sockaddr *address, int addrlen);
-       int (*socket_listen) (struct socket *sock, int backlog);
-       int (*socket_accept) (struct socket *sock, struct socket *newsock);
-       int (*socket_sendmsg) (struct socket *sock,
-                              struct msghdr *msg, int size);
-       int (*socket_recvmsg) (struct socket *sock,
-                              struct msghdr *msg, int size, int flags);
-       int (*socket_getsockname) (struct socket *sock);
-       int (*socket_getpeername) (struct socket *sock);
-       int (*socket_getsockopt) (struct socket *sock, int level, int optname);
-       int (*socket_setsockopt) (struct socket *sock, int level, int optname);
-       int (*socket_shutdown) (struct socket *sock, int how);
-       int (*socket_sock_rcv_skb) (struct sock *sk, struct sk_buff *skb);
-       int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
-       int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid);
-       int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
-       void (*sk_free_security) (struct sock *sk);
-       void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
-       void (*sk_getsecid) (struct sock *sk, u32 *secid);
-       void (*sock_graft) (struct sock *sk, struct socket *parent);
-       int (*inet_conn_request) (struct sock *sk, struct sk_buff *skb,
-                                 struct request_sock *req);
-       void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
-       void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
-       int (*secmark_relabel_packet) (u32 secid);
-       void (*secmark_refcount_inc) (void);
-       void (*secmark_refcount_dec) (void);
-       void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
-       int (*tun_dev_alloc_security) (void **security);
-       void (*tun_dev_free_security) (void *security);
-       int (*tun_dev_create) (void);
-       int (*tun_dev_attach_queue) (void *security);
-       int (*tun_dev_attach) (struct sock *sk, void *security);
-       int (*tun_dev_open) (void *security);
-#endif /* CONFIG_SECURITY_NETWORK */
-
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
-       int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp,
-                       struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp);
-       int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
-       void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
-       int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
-       int (*xfrm_state_alloc) (struct xfrm_state *x,
-                                struct xfrm_user_sec_ctx *sec_ctx);
-       int (*xfrm_state_alloc_acquire) (struct xfrm_state *x,
-                                        struct xfrm_sec_ctx *polsec,
-                                        u32 secid);
-       void (*xfrm_state_free_security) (struct xfrm_state *x);
-       int (*xfrm_state_delete_security) (struct xfrm_state *x);
-       int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
-       int (*xfrm_state_pol_flow_match) (struct xfrm_state *x,
-                                         struct xfrm_policy *xp,
-                                         const struct flowi *fl);
-       int (*xfrm_decode_session) (struct sk_buff *skb, u32 *secid, int ckall);
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-
-       /* key management security hooks */
-#ifdef CONFIG_KEYS
-       int (*key_alloc) (struct key *key, const struct cred *cred, unsigned long flags);
-       void (*key_free) (struct key *key);
-       int (*key_permission) (key_ref_t key_ref,
-                              const struct cred *cred,
-                              unsigned perm);
-       int (*key_getsecurity)(struct key *key, char **_buffer);
-#endif /* CONFIG_KEYS */
-
-#ifdef CONFIG_AUDIT
-       int (*audit_rule_init) (u32 field, u32 op, char *rulestr, void **lsmrule);
-       int (*audit_rule_known) (struct audit_krule *krule);
-       int (*audit_rule_match) (u32 secid, u32 field, u32 op, void *lsmrule,
-                                struct audit_context *actx);
-       void (*audit_rule_free) (void *lsmrule);
-#endif /* CONFIG_AUDIT */
-};
-
 /* prototypes */
 extern int security_init(void);
-extern int security_module_enable(struct security_operations *ops);
-extern int register_security(struct security_operations *ops);
-extern void __init security_fixup_ops(struct security_operations *ops);
-
 
 /* Security operations */
 int security_binder_set_context_mgr(struct task_struct *mgr);
@@ -2049,7 +465,7 @@ static inline int security_settime(const struct timespec *ts,
 
 static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
 {
-       return cap_vm_enough_memory(mm, pages);
+       return __vm_enough_memory(mm, pages, cap_vm_enough_memory(mm, pages));
 }
 
 static inline int security_bprm_set_creds(struct linux_binprm *bprm)
@@ -2653,7 +1069,7 @@ static inline int security_setprocattr(struct task_struct *p, char *name, void *
 
 static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
-       return cap_netlink_send(sk, skb);
+       return 0;
 }
 
 static inline int security_ismaclabel(const char *name)
@@ -3221,36 +1637,5 @@ static inline void free_secdata(void *secdata)
 { }
 #endif /* CONFIG_SECURITY */
 
-#ifdef CONFIG_SECURITY_YAMA
-extern int yama_ptrace_access_check(struct task_struct *child,
-                                   unsigned int mode);
-extern int yama_ptrace_traceme(struct task_struct *parent);
-extern void yama_task_free(struct task_struct *task);
-extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
-                          unsigned long arg4, unsigned long arg5);
-#else
-static inline int yama_ptrace_access_check(struct task_struct *child,
-                                          unsigned int mode)
-{
-       return 0;
-}
-
-static inline int yama_ptrace_traceme(struct task_struct *parent)
-{
-       return 0;
-}
-
-static inline void yama_task_free(struct task_struct *task)
-{
-}
-
-static inline int yama_task_prctl(int option, unsigned long arg2,
-                                 unsigned long arg3, unsigned long arg4,
-                                 unsigned long arg5)
-{
-       return -ENOSYS;
-}
-#endif /* CONFIG_SECURITY_YAMA */
-
 #endif /* ! __LINUX_SECURITY_H */
 
index f19833b..836df8d 100644 (file)
@@ -414,21 +414,16 @@ void flush_sigqueue(struct sigpending *queue)
 }
 
 /*
- * Flush all pending signals for a task.
+ * Flush all pending signals for this kthread.
  */
-void __flush_signals(struct task_struct *t)
-{
-       clear_tsk_thread_flag(t, TIF_SIGPENDING);
-       flush_sigqueue(&t->pending);
-       flush_sigqueue(&t->signal->shared_pending);
-}
-
 void flush_signals(struct task_struct *t)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&t->sighand->siglock, flags);
-       __flush_signals(t);
+       clear_tsk_thread_flag(t, TIF_SIGPENDING);
+       flush_sigqueue(&t->pending);
+       flush_sigqueue(&t->signal->shared_pending);
        spin_unlock_irqrestore(&t->sighand->siglock, flags);
 }
 
index 05f1c93..c9bfbc8 100644 (file)
@@ -14,7 +14,7 @@ obj-y                                 += commoncap.o
 obj-$(CONFIG_MMU)                      += min_addr.o
 
 # Object file lists
-obj-$(CONFIG_SECURITY)                 += security.o capability.o
+obj-$(CONFIG_SECURITY)                 += security.o
 obj-$(CONFIG_SECURITYFS)               += inode.o
 obj-$(CONFIG_SECURITY_SELINUX)         += selinux/
 obj-$(CONFIG_SECURITY_SMACK)           += smack/
index d97cba3..dc0027b 100644 (file)
@@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
                file_inode(bprm->file)->i_mode
        };
        const char *name = NULL, *target = NULL, *info = NULL;
-       int error = cap_bprm_set_creds(bprm);
-       if (error)
-               return error;
+       int error = 0;
 
        if (bprm->cred_prepared)
                return 0;
@@ -531,15 +529,13 @@ cleanup:
  */
 int apparmor_bprm_secureexec(struct linux_binprm *bprm)
 {
-       int ret = cap_bprm_secureexec(bprm);
-
        /* the decision to use secure exec is computed in set_creds
         * and stored in bprm->unsafe.
         */
-       if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
-               ret = 1;
+       if (bprm->unsafe & AA_SECURE_X_NEEDED)
+               return 1;
 
-       return ret;
+       return 0;
 }
 
 /**
index e5f1561..5696874 100644 (file)
@@ -12,7 +12,7 @@
  * License.
  */
 
-#include <linux/security.h>
+#include <linux/lsm_hooks.h>
 #include <linux/moduleparam.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
 static int apparmor_ptrace_access_check(struct task_struct *child,
                                        unsigned int mode)
 {
-       int error = cap_ptrace_access_check(child, mode);
-       if (error)
-               return error;
-
        return aa_ptrace(current, child, mode);
 }
 
 static int apparmor_ptrace_traceme(struct task_struct *parent)
 {
-       int error = cap_ptrace_traceme(parent);
-       if (error)
-               return error;
-
        return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
 }
 
@@ -123,10 +115,10 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
        cred = __task_cred(target);
        profile = aa_cred_profile(cred);
 
-       *effective = cred->cap_effective;
-       *inheritable = cred->cap_inheritable;
-       *permitted = cred->cap_permitted;
-
+       /*
+        * cap_capget is stacked ahead of this and will
+        * initialize effective and permitted.
+        */
        if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
                *effective = cap_intersect(*effective, profile->caps.allow);
                *permitted = cap_intersect(*permitted, profile->caps.allow);
@@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
                            int cap, int audit)
 {
        struct aa_profile *profile;
-       /* cap_capable returns 0 on success, else -EPERM */
-       int error = cap_capable(cred, ns, cap, audit);
-       if (!error) {
-               profile = aa_cred_profile(cred);
-               if (!unconfined(profile))
-                       error = aa_capable(profile, cap, audit);
-       }
+       int error = 0;
+
+       profile = aa_cred_profile(cred);
+       if (!unconfined(profile))
+               error = aa_capable(profile, cap, audit);
        return error;
 }
 
@@ -615,49 +605,46 @@ static int apparmor_task_setrlimit(struct task_struct *task,
        return error;
 }
 
-static struct security_operations apparmor_ops = {
-       .name =                         "apparmor",
-
-       .ptrace_access_check =          apparmor_ptrace_access_check,
-       .ptrace_traceme =               apparmor_ptrace_traceme,
-       .capget =                       apparmor_capget,
-       .capable =                      apparmor_capable,
-
-       .path_link =                    apparmor_path_link,
-       .path_unlink =                  apparmor_path_unlink,
-       .path_symlink =                 apparmor_path_symlink,
-       .path_mkdir =                   apparmor_path_mkdir,
-       .path_rmdir =                   apparmor_path_rmdir,
-       .path_mknod =                   apparmor_path_mknod,
-       .path_rename =                  apparmor_path_rename,
-       .path_chmod =                   apparmor_path_chmod,
-       .path_chown =                   apparmor_path_chown,
-       .path_truncate =                apparmor_path_truncate,
-       .inode_getattr =                apparmor_inode_getattr,
-
-       .file_open =                    apparmor_file_open,
-       .file_permission =              apparmor_file_permission,
-       .file_alloc_security =          apparmor_file_alloc_security,
-       .file_free_security =           apparmor_file_free_security,
-       .mmap_file =                    apparmor_mmap_file,
-       .mmap_addr =                    cap_mmap_addr,
-       .file_mprotect =                apparmor_file_mprotect,
-       .file_lock =                    apparmor_file_lock,
-
-       .getprocattr =                  apparmor_getprocattr,
-       .setprocattr =                  apparmor_setprocattr,
-
-       .cred_alloc_blank =             apparmor_cred_alloc_blank,
-       .cred_free =                    apparmor_cred_free,
-       .cred_prepare =                 apparmor_cred_prepare,
-       .cred_transfer =                apparmor_cred_transfer,
-
-       .bprm_set_creds =               apparmor_bprm_set_creds,
-       .bprm_committing_creds =        apparmor_bprm_committing_creds,
-       .bprm_committed_creds =         apparmor_bprm_committed_creds,
-       .bprm_secureexec =              apparmor_bprm_secureexec,
-
-       .task_setrlimit =               apparmor_task_setrlimit,
+static struct security_hook_list apparmor_hooks[] = {
+       LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
+       LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
+       LSM_HOOK_INIT(capget, apparmor_capget),
+       LSM_HOOK_INIT(capable, apparmor_capable),
+
+       LSM_HOOK_INIT(path_link, apparmor_path_link),
+       LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
+       LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
+       LSM_HOOK_INIT(path_mkdir, apparmor_path_mkdir),
+       LSM_HOOK_INIT(path_rmdir, apparmor_path_rmdir),
+       LSM_HOOK_INIT(path_mknod, apparmor_path_mknod),
+       LSM_HOOK_INIT(path_rename, apparmor_path_rename),
+       LSM_HOOK_INIT(path_chmod, apparmor_path_chmod),
+       LSM_HOOK_INIT(path_chown, apparmor_path_chown),
+       LSM_HOOK_INIT(path_truncate, apparmor_path_truncate),
+       LSM_HOOK_INIT(inode_getattr, apparmor_inode_getattr),
+
+       LSM_HOOK_INIT(file_open, apparmor_file_open),
+       LSM_HOOK_INIT(file_permission, apparmor_file_permission),
+       LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security),
+       LSM_HOOK_INIT(file_free_security, apparmor_file_free_security),
+       LSM_HOOK_INIT(mmap_file, apparmor_mmap_file),
+       LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect),
+       LSM_HOOK_INIT(file_lock, apparmor_file_lock),
+
+       LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
+       LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
+
+       LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
+       LSM_HOOK_INIT(cred_free, apparmor_cred_free),
+       LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
+       LSM_HOOK_INIT(cred_transfer, apparmor_cred_transfer),
+
+       LSM_HOOK_INIT(bprm_set_creds, apparmor_bprm_set_creds),
+       LSM_HOOK_INIT(bprm_committing_creds, apparmor_bprm_committing_creds),
+       LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds),
+       LSM_HOOK_INIT(bprm_secureexec, apparmor_bprm_secureexec),
+
+       LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
 };
 
 /*
@@ -898,7 +885,7 @@ static int __init apparmor_init(void)
 {
        int error;
 
-       if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
+       if (!apparmor_enabled || !security_module_enable("apparmor")) {
                aa_info_message("AppArmor disabled by boot time parameter");
                apparmor_enabled = 0;
                return 0;
@@ -913,17 +900,10 @@ static int __init apparmor_init(void)
        error = set_init_cxt();
        if (error) {
                AA_ERROR("Failed to set context on init task\n");
-               goto register_security_out;
-       }
-
-       error = register_security(&apparmor_ops);
-       if (error) {
-               struct cred *cred = (struct cred *)current->real_cred;
-               aa_free_task_context(cred_cxt(cred));
-               cred_cxt(cred) = NULL;
-               AA_ERROR("Unable to register AppArmor\n");
-               goto register_security_out;
+               aa_free_root_ns();
+               goto alloc_out;
        }
+       security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks));
 
        /* Report that AppArmor successfully initialized */
        apparmor_initialized = 1;
@@ -936,9 +916,6 @@ static int __init apparmor_init(void)
 
        return error;
 
-register_security_out:
-       aa_free_root_ns();
-
 alloc_out:
        aa_destroy_aafs();
 
diff --git a/security/capability.c b/security/capability.c
deleted file mode 100644 (file)
index 7d3f38f..0000000
+++ /dev/null
@@ -1,1158 +0,0 @@
-/*
- *  Capabilities Linux Security Module
- *
- *  This is the default security module in case no other module is loaded.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- */
-
-#include <linux/security.h>
-
-static int cap_binder_set_context_mgr(struct task_struct *mgr)
-{
-       return 0;
-}
-
-static int cap_binder_transaction(struct task_struct *from,
-                                 struct task_struct *to)
-{
-       return 0;
-}
-
-static int cap_binder_transfer_binder(struct task_struct *from,
-                                     struct task_struct *to)
-{
-       return 0;
-}
-
-static int cap_binder_transfer_file(struct task_struct *from,
-                                   struct task_struct *to, struct file *file)
-{
-       return 0;
-}
-
-static int cap_syslog(int type)
-{
-       return 0;
-}
-
-static int cap_quotactl(int cmds, int type, int id, struct super_block *sb)
-{
-       return 0;
-}
-
-static int cap_quota_on(struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_bprm_check_security(struct linux_binprm *bprm)
-{
-       return 0;
-}
-
-static void cap_bprm_committing_creds(struct linux_binprm *bprm)
-{
-}
-
-static void cap_bprm_committed_creds(struct linux_binprm *bprm)
-{
-}
-
-static int cap_sb_alloc_security(struct super_block *sb)
-{
-       return 0;
-}
-
-static void cap_sb_free_security(struct super_block *sb)
-{
-}
-
-static int cap_sb_copy_data(char *orig, char *copy)
-{
-       return 0;
-}
-
-static int cap_sb_remount(struct super_block *sb, void *data)
-{
-       return 0;
-}
-
-static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data)
-{
-       return 0;
-}
-
-static int cap_sb_show_options(struct seq_file *m, struct super_block *sb)
-{
-       return 0;
-}
-
-static int cap_sb_statfs(struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_sb_mount(const char *dev_name, struct path *path,
-                       const char *type, unsigned long flags, void *data)
-{
-       return 0;
-}
-
-static int cap_sb_umount(struct vfsmount *mnt, int flags)
-{
-       return 0;
-}
-
-static int cap_sb_pivotroot(struct path *old_path, struct path *new_path)
-{
-       return 0;
-}
-
-static int cap_sb_set_mnt_opts(struct super_block *sb,
-                              struct security_mnt_opts *opts,
-                              unsigned long kern_flags,
-                              unsigned long *set_kern_flags)
-
-{
-       if (unlikely(opts->num_mnt_opts))
-               return -EOPNOTSUPP;
-       return 0;
-}
-
-static int cap_sb_clone_mnt_opts(const struct super_block *oldsb,
-                                 struct super_block *newsb)
-{
-       return 0;
-}
-
-static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
-{
-       return 0;
-}
-
-static int cap_dentry_init_security(struct dentry *dentry, int mode,
-                                       struct qstr *name, void **ctx,
-                                       u32 *ctxlen)
-{
-       return -EOPNOTSUPP;
-}
-
-static int cap_inode_alloc_security(struct inode *inode)
-{
-       return 0;
-}
-
-static void cap_inode_free_security(struct inode *inode)
-{
-}
-
-static int cap_inode_init_security(struct inode *inode, struct inode *dir,
-                                  const struct qstr *qstr, const char **name,
-                                  void **value, size_t *len)
-{
-       return -EOPNOTSUPP;
-}
-
-static int cap_inode_create(struct inode *inode, struct dentry *dentry,
-                           umode_t mask)
-{
-       return 0;
-}
-
-static int cap_inode_link(struct dentry *old_dentry, struct inode *inode,
-                         struct dentry *new_dentry)
-{
-       return 0;
-}
-
-static int cap_inode_unlink(struct inode *inode, struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_inode_symlink(struct inode *inode, struct dentry *dentry,
-                            const char *name)
-{
-       return 0;
-}
-
-static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry,
-                          umode_t mask)
-{
-       return 0;
-}
-
-static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_inode_mknod(struct inode *inode, struct dentry *dentry,
-                          umode_t mode, dev_t dev)
-{
-       return 0;
-}
-
-static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
-                           struct inode *new_inode, struct dentry *new_dentry)
-{
-       return 0;
-}
-
-static int cap_inode_readlink(struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_inode_follow_link(struct dentry *dentry, struct inode *inode,
-                                bool rcu)
-{
-       return 0;
-}
-
-static int cap_inode_permission(struct inode *inode, int mask)
-{
-       return 0;
-}
-
-static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
-{
-       return 0;
-}
-
-static int cap_inode_getattr(const struct path *path)
-{
-       return 0;
-}
-
-static void cap_inode_post_setxattr(struct dentry *dentry, const char *name,
-                                   const void *value, size_t size, int flags)
-{
-}
-
-static int cap_inode_getxattr(struct dentry *dentry, const char *name)
-{
-       return 0;
-}
-
-static int cap_inode_listxattr(struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_inode_getsecurity(const struct inode *inode, const char *name,
-                                void **buffer, bool alloc)
-{
-       return -EOPNOTSUPP;
-}
-
-static int cap_inode_setsecurity(struct inode *inode, const char *name,
-                                const void *value, size_t size, int flags)
-{
-       return -EOPNOTSUPP;
-}
-
-static int cap_inode_listsecurity(struct inode *inode, char *buffer,
-                                 size_t buffer_size)
-{
-       return 0;
-}
-
-static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
-{
-       *secid = 0;
-}
-
-#ifdef CONFIG_SECURITY_PATH
-static int cap_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
-                         unsigned int dev)
-{
-       return 0;
-}
-
-static int cap_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
-{
-       return 0;
-}
-
-static int cap_path_rmdir(struct path *dir, struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_path_unlink(struct path *dir, struct dentry *dentry)
-{
-       return 0;
-}
-
-static int cap_path_symlink(struct path *dir, struct dentry *dentry,
-                           const char *old_name)
-{
-       return 0;
-}
-
-static int cap_path_link(struct dentry *old_dentry, struct path *new_dir,
-                        struct dentry *new_dentry)
-{
-       return 0;
-}
-
-static int cap_path_rename(struct path *old_path, struct dentry *old_dentry,
-                          struct path *new_path, struct dentry *new_dentry)
-{
-       return 0;
-}
-
-static int cap_path_truncate(struct path *path)
-{
-       return 0;
-}
-
-static int cap_path_chmod(struct path *path, umode_t mode)
-{
-       return 0;
-}
-
-static int cap_path_chown(struct path *path, kuid_t uid, kgid_t gid)
-{
-       return 0;
-}
-
-static int cap_path_chroot(struct path *root)
-{
-       return 0;
-}
-#endif
-
-static int cap_file_permission(struct file *file, int mask)
-{
-       return 0;
-}
-
-static int cap_file_alloc_security(struct file *file)
-{
-       return 0;
-}
-
-static void cap_file_free_security(struct file *file)
-{
-}
-
-static int cap_file_ioctl(struct file *file, unsigned int command,
-                         unsigned long arg)
-{
-       return 0;
-}
-
-static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
-                            unsigned long prot)
-{
-       return 0;
-}
-
-static int cap_file_lock(struct file *file, unsigned int cmd)
-{
-       return 0;
-}
-
-static int cap_file_fcntl(struct file *file, unsigned int cmd,
-                         unsigned long arg)
-{
-       return 0;
-}
-
-static void cap_file_set_fowner(struct file *file)
-{
-       return;
-}
-
-static int cap_file_send_sigiotask(struct task_struct *tsk,
-                                  struct fown_struct *fown, int sig)
-{
-       return 0;
-}
-
-static int cap_file_receive(struct file *file)
-{
-       return 0;
-}
-
-static int cap_file_open(struct file *file, const struct cred *cred)
-{
-       return 0;
-}
-
-static int cap_task_create(unsigned long clone_flags)
-{
-       return 0;
-}
-
-static void cap_task_free(struct task_struct *task)
-{
-}
-
-static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp)
-{
-       return 0;
-}
-
-static void cap_cred_free(struct cred *cred)
-{
-}
-
-static int cap_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp)
-{
-       return 0;
-}
-
-static void cap_cred_transfer(struct cred *new, const struct cred *old)
-{
-}
-
-static int cap_kernel_act_as(struct cred *new, u32 secid)
-{
-       return 0;
-}
-
-static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
-{
-       return 0;
-}
-
-static int cap_kernel_fw_from_file(struct file *file, char *buf, size_t size)
-{
-       return 0;
-}
-
-static int cap_kernel_module_request(char *kmod_name)
-{
-       return 0;
-}
-
-static int cap_kernel_module_from_file(struct file *file)
-{
-       return 0;
-}
-
-static int cap_task_setpgid(struct task_struct *p, pid_t pgid)
-{
-       return 0;
-}
-
-static int cap_task_getpgid(struct task_struct *p)
-{
-       return 0;
-}
-
-static int cap_task_getsid(struct task_struct *p)
-{
-       return 0;
-}
-
-static void cap_task_getsecid(struct task_struct *p, u32 *secid)
-{
-       *secid = 0;
-}
-
-static int cap_task_getioprio(struct task_struct *p)
-{
-       return 0;
-}
-
-static int cap_task_setrlimit(struct task_struct *p, unsigned int resource,
-               struct rlimit *new_rlim)
-{
-       return 0;
-}
-
-static int cap_task_getscheduler(struct task_struct *p)
-{
-       return 0;
-}
-
-static int cap_task_movememory(struct task_struct *p)
-{
-       return 0;
-}
-
-static int cap_task_wait(struct task_struct *p)
-{
-       return 0;
-}
-
-static int cap_task_kill(struct task_struct *p, struct siginfo *info,
-                        int sig, u32 secid)
-{
-       return 0;
-}
-
-static void cap_task_to_inode(struct task_struct *p, struct inode *inode)
-{
-}
-
-static int cap_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
-{
-       return 0;
-}
-
-static void cap_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
-{
-       *secid = 0;
-}
-
-static int cap_msg_msg_alloc_security(struct msg_msg *msg)
-{
-       return 0;
-}
-
-static void cap_msg_msg_free_security(struct msg_msg *msg)
-{
-}
-
-static int cap_msg_queue_alloc_security(struct msg_queue *msq)
-{
-       return 0;
-}
-
-static void cap_msg_queue_free_security(struct msg_queue *msq)
-{
-}
-
-static int cap_msg_queue_associate(struct msg_queue *msq, int msqflg)
-{
-       return 0;
-}
-
-static int cap_msg_queue_msgctl(struct msg_queue *msq, int cmd)
-{
-       return 0;
-}
-
-static int cap_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
-                               int msgflg)
-{
-       return 0;
-}
-
-static int cap_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
-                               struct task_struct *target, long type, int mode)
-{
-       return 0;
-}
-
-static int cap_shm_alloc_security(struct shmid_kernel *shp)
-{
-       return 0;
-}
-
-static void cap_shm_free_security(struct shmid_kernel *shp)
-{
-}
-
-static int cap_shm_associate(struct shmid_kernel *shp, int shmflg)
-{
-       return 0;
-}
-
-static int cap_shm_shmctl(struct shmid_kernel *shp, int cmd)
-{
-       return 0;
-}
-
-static int cap_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
-                        int shmflg)
-{
-       return 0;
-}
-
-static int cap_sem_alloc_security(struct sem_array *sma)
-{
-       return 0;
-}
-
-static void cap_sem_free_security(struct sem_array *sma)
-{
-}
-
-static int cap_sem_associate(struct sem_array *sma, int semflg)
-{
-       return 0;
-}
-
-static int cap_sem_semctl(struct sem_array *sma, int cmd)
-{
-       return 0;
-}
-
-static int cap_sem_semop(struct sem_array *sma, struct sembuf *sops,
-                        unsigned nsops, int alter)
-{
-       return 0;
-}
-
-#ifdef CONFIG_SECURITY_NETWORK
-static int cap_unix_stream_connect(struct sock *sock, struct sock *other,
-                                  struct sock *newsk)
-{
-       return 0;
-}
-
-static int cap_unix_may_send(struct socket *sock, struct socket *other)
-{
-       return 0;
-}
-
-static int cap_socket_create(int family, int type, int protocol, int kern)
-{
-       return 0;
-}
-
-static int cap_socket_post_create(struct socket *sock, int family, int type,
-                                 int protocol, int kern)
-{
-       return 0;
-}
-
-static int cap_socket_bind(struct socket *sock, struct sockaddr *address,
-                          int addrlen)
-{
-       return 0;
-}
-
-static int cap_socket_connect(struct socket *sock, struct sockaddr *address,
-                             int addrlen)
-{
-       return 0;
-}
-
-static int cap_socket_listen(struct socket *sock, int backlog)
-{
-       return 0;
-}
-
-static int cap_socket_accept(struct socket *sock, struct socket *newsock)
-{
-       return 0;
-}
-
-static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
-{
-       return 0;
-}
-
-static int cap_socket_recvmsg(struct socket *sock, struct msghdr *msg,
-                             int size, int flags)
-{
-       return 0;
-}
-
-static int cap_socket_getsockname(struct socket *sock)
-{
-       return 0;
-}
-
-static int cap_socket_getpeername(struct socket *sock)
-{
-       return 0;
-}
-
-static int cap_socket_setsockopt(struct socket *sock, int level, int optname)
-{
-       return 0;
-}
-
-static int cap_socket_getsockopt(struct socket *sock, int level, int optname)
-{
-       return 0;
-}
-
-static int cap_socket_shutdown(struct socket *sock, int how)
-{
-       return 0;
-}
-
-static int cap_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
-       return 0;
-}
-
-static int cap_socket_getpeersec_stream(struct socket *sock,
-                                       char __user *optval,
-                                       int __user *optlen, unsigned len)
-{
-       return -ENOPROTOOPT;
-}
-
-static int cap_socket_getpeersec_dgram(struct socket *sock,
-                                      struct sk_buff *skb, u32 *secid)
-{
-       return -ENOPROTOOPT;
-}
-
-static int cap_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
-{
-       return 0;
-}
-
-static void cap_sk_free_security(struct sock *sk)
-{
-}
-
-static void cap_sk_clone_security(const struct sock *sk, struct sock *newsk)
-{
-}
-
-static void cap_sk_getsecid(struct sock *sk, u32 *secid)
-{
-}
-
-static void cap_sock_graft(struct sock *sk, struct socket *parent)
-{
-}
-
-static int cap_inet_conn_request(struct sock *sk, struct sk_buff *skb,
-                                struct request_sock *req)
-{
-       return 0;
-}
-
-static void cap_inet_csk_clone(struct sock *newsk,
-                              const struct request_sock *req)
-{
-}
-
-static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb)
-{
-}
-
-static int cap_secmark_relabel_packet(u32 secid)
-{
-       return 0;
-}
-
-static void cap_secmark_refcount_inc(void)
-{
-}
-
-static void cap_secmark_refcount_dec(void)
-{
-}
-
-static void cap_req_classify_flow(const struct request_sock *req,
-                                 struct flowi *fl)
-{
-}
-
-static int cap_tun_dev_alloc_security(void **security)
-{
-       return 0;
-}
-
-static void cap_tun_dev_free_security(void *security)
-{
-}
-
-static int cap_tun_dev_create(void)
-{
-       return 0;
-}
-
-static int cap_tun_dev_attach_queue(void *security)
-{
-       return 0;
-}
-
-static int cap_tun_dev_attach(struct sock *sk, void *security)
-{
-       return 0;
-}
-
-static int cap_tun_dev_open(void *security)
-{
-       return 0;
-}
-#endif /* CONFIG_SECURITY_NETWORK */
-
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
-static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
-                                         struct xfrm_user_sec_ctx *sec_ctx,
-                                         gfp_t gfp)
-{
-       return 0;
-}
-
-static int cap_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx,
-                                         struct xfrm_sec_ctx **new_ctxp)
-{
-       return 0;
-}
-
-static void cap_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx)
-{
-}
-
-static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
-{
-       return 0;
-}
-
-static int cap_xfrm_state_alloc(struct xfrm_state *x,
-                               struct xfrm_user_sec_ctx *sec_ctx)
-{
-       return 0;
-}
-
-static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x,
-                                       struct xfrm_sec_ctx *polsec,
-                                       u32 secid)
-{
-       return 0;
-}
-
-static void cap_xfrm_state_free_security(struct xfrm_state *x)
-{
-}
-
-static int cap_xfrm_state_delete_security(struct xfrm_state *x)
-{
-       return 0;
-}
-
-static int cap_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 sk_sid, u8 dir)
-{
-       return 0;
-}
-
-static int cap_xfrm_state_pol_flow_match(struct xfrm_state *x,
-                                        struct xfrm_policy *xp,
-                                        const struct flowi *fl)
-{
-       return 1;
-}
-
-static int cap_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
-{
-       return 0;
-}
-
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-static void cap_d_instantiate(struct dentry *dentry, struct inode *inode)
-{
-}
-
-static int cap_getprocattr(struct task_struct *p, char *name, char **value)
-{
-       return -EINVAL;
-}
-
-static int cap_setprocattr(struct task_struct *p, char *name, void *value,
-                          size_t size)
-{
-       return -EINVAL;
-}
-
-static int cap_ismaclabel(const char *name)
-{
-       return 0;
-}
-
-static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
-{
-       return -EOPNOTSUPP;
-}
-
-static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
-{
-       *secid = 0;
-       return 0;
-}
-
-static void cap_release_secctx(char *secdata, u32 seclen)
-{
-}
-
-static int cap_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
-{
-       return 0;
-}
-
-static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
-{
-       return 0;
-}
-
-static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
-{
-       return -EOPNOTSUPP;
-}
-#ifdef CONFIG_KEYS
-static int cap_key_alloc(struct key *key, const struct cred *cred,
-                        unsigned long flags)
-{
-       return 0;
-}
-
-static void cap_key_free(struct key *key)
-{
-}
-
-static int cap_key_permission(key_ref_t key_ref, const struct cred *cred,
-                             unsigned perm)
-{
-       return 0;
-}
-
-static int cap_key_getsecurity(struct key *key, char **_buffer)
-{
-       *_buffer = NULL;
-       return 0;
-}
-
-#endif /* CONFIG_KEYS */
-
-#ifdef CONFIG_AUDIT
-static int cap_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
-{
-       return 0;
-}
-
-static int cap_audit_rule_known(struct audit_krule *krule)
-{
-       return 0;
-}
-
-static int cap_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
-                               struct audit_context *actx)
-{
-       return 0;
-}
-
-static void cap_audit_rule_free(void *lsmrule)
-{
-}
-#endif /* CONFIG_AUDIT */
-
-#define set_to_cap_if_null(ops, function)                              \
-       do {                                                            \
-               if (!ops->function) {                                   \
-                       ops->function = cap_##function;                 \
-                       pr_debug("Had to override the " #function       \
-                                " security operation with the default.\n");\
-                       }                                               \
-       } while (0)
-
-void __init security_fixup_ops(struct security_operations *ops)
-{
-       set_to_cap_if_null(ops, binder_set_context_mgr);
-       set_to_cap_if_null(ops, binder_transaction);
-       set_to_cap_if_null(ops, binder_transfer_binder);
-       set_to_cap_if_null(ops, binder_transfer_file);
-       set_to_cap_if_null(ops, ptrace_access_check);
-       set_to_cap_if_null(ops, ptrace_traceme);
-       set_to_cap_if_null(ops, capget);
-       set_to_cap_if_null(ops, capset);
-       set_to_cap_if_null(ops, capable);
-       set_to_cap_if_null(ops, quotactl);
-       set_to_cap_if_null(ops, quota_on);
-       set_to_cap_if_null(ops, syslog);
-       set_to_cap_if_null(ops, settime);
-       set_to_cap_if_null(ops, vm_enough_memory);
-       set_to_cap_if_null(ops, bprm_set_creds);
-       set_to_cap_if_null(ops, bprm_committing_creds);
-       set_to_cap_if_null(ops, bprm_committed_creds);
-       set_to_cap_if_null(ops, bprm_check_security);
-       set_to_cap_if_null(ops, bprm_secureexec);
-       set_to_cap_if_null(ops, sb_alloc_security);
-       set_to_cap_if_null(ops, sb_free_security);
-       set_to_cap_if_null(ops, sb_copy_data);
-       set_to_cap_if_null(ops, sb_remount);
-       set_to_cap_if_null(ops, sb_kern_mount);
-       set_to_cap_if_null(ops, sb_show_options);
-       set_to_cap_if_null(ops, sb_statfs);
-       set_to_cap_if_null(ops, sb_mount);
-       set_to_cap_if_null(ops, sb_umount);
-       set_to_cap_if_null(ops, sb_pivotroot);
-       set_to_cap_if_null(ops, sb_set_mnt_opts);
-       set_to_cap_if_null(ops, sb_clone_mnt_opts);
-       set_to_cap_if_null(ops, sb_parse_opts_str);
-       set_to_cap_if_null(ops, dentry_init_security);
-       set_to_cap_if_null(ops, inode_alloc_security);
-       set_to_cap_if_null(ops, inode_free_security);
-       set_to_cap_if_null(ops, inode_init_security);
-       set_to_cap_if_null(ops, inode_create);
-       set_to_cap_if_null(ops, inode_link);
-       set_to_cap_if_null(ops, inode_unlink);
-       set_to_cap_if_null(ops, inode_symlink);
-       set_to_cap_if_null(ops, inode_mkdir);
-       set_to_cap_if_null(ops, inode_rmdir);
-       set_to_cap_if_null(ops, inode_mknod);
-       set_to_cap_if_null(ops, inode_rename);
-       set_to_cap_if_null(ops, inode_readlink);
-       set_to_cap_if_null(ops, inode_follow_link);
-       set_to_cap_if_null(ops, inode_permission);
-       set_to_cap_if_null(ops, inode_setattr);
-       set_to_cap_if_null(ops, inode_getattr);
-       set_to_cap_if_null(ops, inode_setxattr);
-       set_to_cap_if_null(ops, inode_post_setxattr);
-       set_to_cap_if_null(ops, inode_getxattr);
-       set_to_cap_if_null(ops, inode_listxattr);
-       set_to_cap_if_null(ops, inode_removexattr);
-       set_to_cap_if_null(ops, inode_need_killpriv);
-       set_to_cap_if_null(ops, inode_killpriv);
-       set_to_cap_if_null(ops, inode_getsecurity);
-       set_to_cap_if_null(ops, inode_setsecurity);
-       set_to_cap_if_null(ops, inode_listsecurity);
-       set_to_cap_if_null(ops, inode_getsecid);
-#ifdef CONFIG_SECURITY_PATH
-       set_to_cap_if_null(ops, path_mknod);
-       set_to_cap_if_null(ops, path_mkdir);
-       set_to_cap_if_null(ops, path_rmdir);
-       set_to_cap_if_null(ops, path_unlink);
-       set_to_cap_if_null(ops, path_symlink);
-       set_to_cap_if_null(ops, path_link);
-       set_to_cap_if_null(ops, path_rename);
-       set_to_cap_if_null(ops, path_truncate);
-       set_to_cap_if_null(ops, path_chmod);
-       set_to_cap_if_null(ops, path_chown);
-       set_to_cap_if_null(ops, path_chroot);
-#endif
-       set_to_cap_if_null(ops, file_permission);
-       set_to_cap_if_null(ops, file_alloc_security);
-       set_to_cap_if_null(ops, file_free_security);
-       set_to_cap_if_null(ops, file_ioctl);
-       set_to_cap_if_null(ops, mmap_addr);
-       set_to_cap_if_null(ops, mmap_file);
-       set_to_cap_if_null(ops, file_mprotect);
-       set_to_cap_if_null(ops, file_lock);
-       set_to_cap_if_null(ops, file_fcntl);
-       set_to_cap_if_null(ops, file_set_fowner);
-       set_to_cap_if_null(ops, file_send_sigiotask);
-       set_to_cap_if_null(ops, file_receive);
-       set_to_cap_if_null(ops, file_open);
-       set_to_cap_if_null(ops, task_create);
-       set_to_cap_if_null(ops, task_free);
-       set_to_cap_if_null(ops, cred_alloc_blank);
-       set_to_cap_if_null(ops, cred_free);
-       set_to_cap_if_null(ops, cred_prepare);
-       set_to_cap_if_null(ops, cred_transfer);
-       set_to_cap_if_null(ops, kernel_act_as);
-       set_to_cap_if_null(ops, kernel_create_files_as);
-       set_to_cap_if_null(ops, kernel_fw_from_file);
-       set_to_cap_if_null(ops, kernel_module_request);
-       set_to_cap_if_null(ops, kernel_module_from_file);
-       set_to_cap_if_null(ops, task_fix_setuid);
-       set_to_cap_if_null(ops, task_setpgid);
-       set_to_cap_if_null(ops, task_getpgid);
-       set_to_cap_if_null(ops, task_getsid);
-       set_to_cap_if_null(ops, task_getsecid);
-       set_to_cap_if_null(ops, task_setnice);
-       set_to_cap_if_null(ops, task_setioprio);
-       set_to_cap_if_null(ops, task_getioprio);
-       set_to_cap_if_null(ops, task_setrlimit);
-       set_to_cap_if_null(ops, task_setscheduler);
-       set_to_cap_if_null(ops, task_getscheduler);
-       set_to_cap_if_null(ops, task_movememory);
-       set_to_cap_if_null(ops, task_wait);
-       set_to_cap_if_null(ops, task_kill);
-       set_to_cap_if_null(ops, task_prctl);
-       set_to_cap_if_null(ops, task_to_inode);
-       set_to_cap_if_null(ops, ipc_permission);
-       set_to_cap_if_null(ops, ipc_getsecid);
-       set_to_cap_if_null(ops, msg_msg_alloc_security);
-       set_to_cap_if_null(ops, msg_msg_free_security);
-       set_to_cap_if_null(ops, msg_queue_alloc_security);
-       set_to_cap_if_null(ops, msg_queue_free_security);
-       set_to_cap_if_null(ops, msg_queue_associate);
-       set_to_cap_if_null(ops, msg_queue_msgctl);
-       set_to_cap_if_null(ops, msg_queue_msgsnd);
-       set_to_cap_if_null(ops, msg_queue_msgrcv);
-       set_to_cap_if_null(ops, shm_alloc_security);
-       set_to_cap_if_null(ops, shm_free_security);
-       set_to_cap_if_null(ops, shm_associate);
-       set_to_cap_if_null(ops, shm_shmctl);
-       set_to_cap_if_null(ops, shm_shmat);
-       set_to_cap_if_null(ops, sem_alloc_security);
-       set_to_cap_if_null(ops, sem_free_security);
-       set_to_cap_if_null(ops, sem_associate);
-       set_to_cap_if_null(ops, sem_semctl);
-       set_to_cap_if_null(ops, sem_semop);
-       set_to_cap_if_null(ops, netlink_send);
-       set_to_cap_if_null(ops, d_instantiate);
-       set_to_cap_if_null(ops, getprocattr);
-       set_to_cap_if_null(ops, setprocattr);
-       set_to_cap_if_null(ops, ismaclabel);
-       set_to_cap_if_null(ops, secid_to_secctx);
-       set_to_cap_if_null(ops, secctx_to_secid);
-       set_to_cap_if_null(ops, release_secctx);
-       set_to_cap_if_null(ops, inode_notifysecctx);
-       set_to_cap_if_null(ops, inode_setsecctx);
-       set_to_cap_if_null(ops, inode_getsecctx);
-#ifdef CONFIG_SECURITY_NETWORK
-       set_to_cap_if_null(ops, unix_stream_connect);
-       set_to_cap_if_null(ops, unix_may_send);
-       set_to_cap_if_null(ops, socket_create);
-       set_to_cap_if_null(ops, socket_post_create);
-       set_to_cap_if_null(ops, socket_bind);
-       set_to_cap_if_null(ops, socket_connect);
-       set_to_cap_if_null(ops, socket_listen);
-       set_to_cap_if_null(ops, socket_accept);
-       set_to_cap_if_null(ops, socket_sendmsg);
-       set_to_cap_if_null(ops, socket_recvmsg);
-       set_to_cap_if_null(ops, socket_getsockname);
-       set_to_cap_if_null(ops, socket_getpeername);
-       set_to_cap_if_null(ops, socket_setsockopt);
-       set_to_cap_if_null(ops, socket_getsockopt);
-       set_to_cap_if_null(ops, socket_shutdown);
-       set_to_cap_if_null(ops, socket_sock_rcv_skb);
-       set_to_cap_if_null(ops, socket_getpeersec_stream);
-       set_to_cap_if_null(ops, socket_getpeersec_dgram);
-       set_to_cap_if_null(ops, sk_alloc_security);
-       set_to_cap_if_null(ops, sk_free_security);
-       set_to_cap_if_null(ops, sk_clone_security);
-       set_to_cap_if_null(ops, sk_getsecid);
-       set_to_cap_if_null(ops, sock_graft);
-       set_to_cap_if_null(ops, inet_conn_request);
-       set_to_cap_if_null(ops, inet_csk_clone);
-       set_to_cap_if_null(ops, inet_conn_established);
-       set_to_cap_if_null(ops, secmark_relabel_packet);
-       set_to_cap_if_null(ops, secmark_refcount_inc);
-       set_to_cap_if_null(ops, secmark_refcount_dec);
-       set_to_cap_if_null(ops, req_classify_flow);
-       set_to_cap_if_null(ops, tun_dev_alloc_security);
-       set_to_cap_if_null(ops, tun_dev_free_security);
-       set_to_cap_if_null(ops, tun_dev_create);
-       set_to_cap_if_null(ops, tun_dev_open);
-       set_to_cap_if_null(ops, tun_dev_attach_queue);
-       set_to_cap_if_null(ops, tun_dev_attach);
-#endif /* CONFIG_SECURITY_NETWORK */
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
-       set_to_cap_if_null(ops, xfrm_policy_alloc_security);
-       set_to_cap_if_null(ops, xfrm_policy_clone_security);
-       set_to_cap_if_null(ops, xfrm_policy_free_security);
-       set_to_cap_if_null(ops, xfrm_policy_delete_security);
-       set_to_cap_if_null(ops, xfrm_state_alloc);
-       set_to_cap_if_null(ops, xfrm_state_alloc_acquire);
-       set_to_cap_if_null(ops, xfrm_state_free_security);
-       set_to_cap_if_null(ops, xfrm_state_delete_security);
-       set_to_cap_if_null(ops, xfrm_policy_lookup);
-       set_to_cap_if_null(ops, xfrm_state_pol_flow_match);
-       set_to_cap_if_null(ops, xfrm_decode_session);
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-#ifdef CONFIG_KEYS
-       set_to_cap_if_null(ops, key_alloc);
-       set_to_cap_if_null(ops, key_free);
-       set_to_cap_if_null(ops, key_permission);
-       set_to_cap_if_null(ops, key_getsecurity);
-#endif /* CONFIG_KEYS */
-#ifdef CONFIG_AUDIT
-       set_to_cap_if_null(ops, audit_rule_init);
-       set_to_cap_if_null(ops, audit_rule_known);
-       set_to_cap_if_null(ops, audit_rule_match);
-       set_to_cap_if_null(ops, audit_rule_free);
-#endif
-}
index f2875cd..d103f5a 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/security.h>
+#include <linux/lsm_hooks.h>
 #include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
@@ -53,11 +53,6 @@ static void warn_setuid_and_fcaps_mixed(const char *fname)
        }
 }
 
-int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
-{
-       return 0;
-}
-
 /**
  * cap_capable - Determine whether a task has a particular effective capability
  * @cred: The credentials to use
@@ -941,7 +936,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
  * @pages: The size of the mapping
  *
  * Determine whether the allocation of a new virtual mapping by the current
- * task is permitted, returning 0 if permission is granted, -ve if not.
+ * task is permitted, returning 1 if permission is granted, 0 if not.
  */
 int cap_vm_enough_memory(struct mm_struct *mm, long pages)
 {
@@ -950,7 +945,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
        if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
                        SECURITY_CAP_NOAUDIT) == 0)
                cap_sys_admin = 1;
-       return __vm_enough_memory(mm, pages, cap_sys_admin);
+       return cap_sys_admin;
 }
 
 /*
@@ -981,3 +976,33 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
 {
        return 0;
 }
+
+#ifdef CONFIG_SECURITY
+
+struct security_hook_list capability_hooks[] = {
+       LSM_HOOK_INIT(capable, cap_capable),
+       LSM_HOOK_INIT(settime, cap_settime),
+       LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
+       LSM_HOOK_INIT(ptrace_traceme, cap_ptrace_traceme),
+       LSM_HOOK_INIT(capget, cap_capget),
+       LSM_HOOK_INIT(capset, cap_capset),
+       LSM_HOOK_INIT(bprm_set_creds, cap_bprm_set_creds),
+       LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec),
+       LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
+       LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv),
+       LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
+       LSM_HOOK_INIT(mmap_file, cap_mmap_file),
+       LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid),
+       LSM_HOOK_INIT(task_prctl, cap_task_prctl),
+       LSM_HOOK_INIT(task_setscheduler, cap_task_setscheduler),
+       LSM_HOOK_INIT(task_setioprio, cap_task_setioprio),
+       LSM_HOOK_INIT(task_setnice, cap_task_setnice),
+       LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
+};
+
+void __init capability_add_hooks(void)
+{
+       security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks));
+}
+
+#endif /* CONFIG_SECURITY */
index 5e3bd72..36fb6b5 100644 (file)
@@ -85,7 +85,7 @@ int __init integrity_init_keyring(const unsigned int id)
        return err;
 }
 
-int __init integrity_load_x509(const unsigned int id, char *path)
+int __init integrity_load_x509(const unsigned int id, const char *path)
 {
        key_ref_t key;
        char *data;
index 10f9943..1334e02 100644 (file)
@@ -296,6 +296,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
                iint = integrity_iint_find(d_backing_inode(dentry));
                if (iint && (iint->flags & IMA_NEW_FILE))
                        return 0;
+
+               /* exception for pseudo filesystems */
+               if (dentry->d_inode->i_sb->s_magic == TMPFS_MAGIC
+                   || dentry->d_inode->i_sb->s_magic == SYSFS_MAGIC)
+                       return 0;
+
+               integrity_audit_msg(AUDIT_INTEGRITY_METADATA,
+                                   dentry->d_inode, dentry->d_name.name,
+                                   "update_metadata",
+                                   integrity_status_msg[evm_status],
+                                   -EPERM, 0);
        }
 out:
        if (evm_status != INTEGRITY_PASS)
@@ -376,17 +387,16 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
  * @xattr_name: pointer to the affected extended attribute name
  *
  * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
+ *
+ * No need to take the i_mutex lock here, as this function is called from
+ * vfs_removexattr() which takes the i_mutex.
  */
 void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
 {
-       struct inode *inode = d_backing_inode(dentry);
-
        if (!evm_initialized || !evm_protected_xattr(xattr_name))
                return;
 
-       mutex_lock(&inode->i_mutex);
        evm_update_evmxattr(dentry, xattr_name, NULL, 0);
-       mutex_unlock(&inode->i_mutex);
 }
 
 /**
index dbb6d14..3d2f5b4 100644 (file)
@@ -213,6 +213,9 @@ int __init integrity_read_file(const char *path, char **data)
        char *buf;
        int rc = -EINVAL;
 
+       if (!path || !*path)
+               return -EINVAL;
+
        file = filp_open(path, O_RDONLY, 0);
        if (IS_ERR(file)) {
                rc = PTR_ERR(file);
index 8ee997d..e2a60c3 100644 (file)
@@ -52,6 +52,16 @@ extern int ima_used_chip;
 extern int ima_hash_algo;
 extern int ima_appraise;
 
+/* IMA event related data */
+struct ima_event_data {
+       struct integrity_iint_cache *iint;
+       struct file *file;
+       const unsigned char *filename;
+       struct evm_ima_xattr_data *xattr_value;
+       int xattr_len;
+       const char *violation;
+};
+
 /* IMA template field data definition */
 struct ima_field_data {
        u8 *data;
@@ -61,12 +71,10 @@ struct ima_field_data {
 /* IMA template field definition */
 struct ima_template_field {
        const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN];
-       int (*field_init) (struct integrity_iint_cache *iint, struct file *file,
-                          const unsigned char *filename,
-                          struct evm_ima_xattr_data *xattr_value,
-                          int xattr_len, struct ima_field_data *field_data);
-       void (*field_show) (struct seq_file *m, enum ima_show_type show,
-                           struct ima_field_data *field_data);
+       int (*field_init)(struct ima_event_data *event_data,
+                         struct ima_field_data *field_data);
+       void (*field_show)(struct seq_file *m, enum ima_show_type show,
+                          struct ima_field_data *field_data);
 };
 
 /* IMA template descriptor definition */
@@ -103,10 +111,11 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
                              struct ima_digest_data *hash);
 int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
 void ima_add_violation(struct file *file, const unsigned char *filename,
+                      struct integrity_iint_cache *iint,
                       const char *op, const char *cause);
 int ima_init_crypto(void);
 void ima_putc(struct seq_file *m, void *data, int datalen);
-void ima_print_digest(struct seq_file *m, u8 *digest, int size);
+void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
 struct ima_template_desc *ima_template_desc_current(void);
 int ima_init_template(void);
 
@@ -140,10 +149,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
                           int xattr_len);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
                           const unsigned char *filename);
-int ima_alloc_init_template(struct integrity_iint_cache *iint,
-                           struct file *file, const unsigned char *filename,
-                           struct evm_ima_xattr_data *xattr_value,
-                           int xattr_len, struct ima_template_entry **entry);
+int ima_alloc_init_template(struct ima_event_data *event_data,
+                           struct ima_template_entry **entry);
 int ima_store_template(struct ima_template_entry *entry, int violation,
                       struct inode *inode, const unsigned char *filename);
 void ima_free_template_entry(struct ima_template_entry *entry);
index b8a27c5..1d950fb 100644 (file)
@@ -37,10 +37,8 @@ void ima_free_template_entry(struct ima_template_entry *entry)
 /*
  * ima_alloc_init_template - create and initialize a new template entry
  */
-int ima_alloc_init_template(struct integrity_iint_cache *iint,
-                           struct file *file, const unsigned char *filename,
-                           struct evm_ima_xattr_data *xattr_value,
-                           int xattr_len, struct ima_template_entry **entry)
+int ima_alloc_init_template(struct ima_event_data *event_data,
+                           struct ima_template_entry **entry)
 {
        struct ima_template_desc *template_desc = ima_template_desc_current();
        int i, result = 0;
@@ -55,8 +53,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
                struct ima_template_field *field = template_desc->fields[i];
                u32 len;
 
-               result = field->field_init(iint, file, filename,
-                                          xattr_value, xattr_len,
+               result = field->field_init(event_data,
                                           &((*entry)->template_data[i]));
                if (result != 0)
                        goto out;
@@ -129,18 +126,20 @@ int ima_store_template(struct ima_template_entry *entry,
  * value is invalidated.
  */
 void ima_add_violation(struct file *file, const unsigned char *filename,
+                      struct integrity_iint_cache *iint,
                       const char *op, const char *cause)
 {
        struct ima_template_entry *entry;
        struct inode *inode = file_inode(file);
+       struct ima_event_data event_data = {iint, file, filename, NULL, 0,
+                                           cause};
        int violation = 1;
        int result;
 
        /* can overflow, only indicator */
        atomic_long_inc(&ima_htable.violations);
 
-       result = ima_alloc_init_template(NULL, file, filename,
-                                        NULL, 0, &entry);
+       result = ima_alloc_init_template(&event_data, &entry);
        if (result < 0) {
                result = -ENOMEM;
                goto err_out;
@@ -267,13 +266,14 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        int result = -ENOMEM;
        struct inode *inode = file_inode(file);
        struct ima_template_entry *entry;
+       struct ima_event_data event_data = {iint, file, filename, xattr_value,
+                                           xattr_len, NULL};
        int violation = 0;
 
        if (iint->flags & IMA_MEASURED)
                return;
 
-       result = ima_alloc_init_template(iint, file, filename,
-                                        xattr_value, xattr_len, &entry);
+       result = ima_alloc_init_template(&event_data, &entry);
        if (result < 0) {
                integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
                                    op, audit_cause, result, 0);
index 4df493e..1873b55 100644 (file)
@@ -378,10 +378,14 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
        result = ima_protect_xattr(dentry, xattr_name, xattr_value,
                                   xattr_value_len);
        if (result == 1) {
+               bool digsig;
+
                if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
                        return -EINVAL;
-               ima_reset_appraise_flags(d_backing_inode(dentry),
-                        (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
+               digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
+               if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE))
+                       return -EPERM;
+               ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
                result = 0;
        }
        return result;
index 461215e..816d175 100644 (file)
@@ -190,9 +190,9 @@ static const struct file_operations ima_measurements_ops = {
        .release = seq_release,
 };
 
-void ima_print_digest(struct seq_file *m, u8 *digest, int size)
+void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
 {
-       int i;
+       u32 i;
 
        for (i = 0; i < size; i++)
                seq_printf(m, "%02x", *(digest + i));
index 5e4c29d..e600cad 100644 (file)
 #include <crypto/hash_info.h>
 #include "ima.h"
 
-#ifdef CONFIG_IMA_X509_PATH
-#define IMA_X509_PATH  CONFIG_IMA_X509_PATH
-#else
-#define IMA_X509_PATH  "/etc/keys/x509_ima.der"
-#endif
-
 /* name for boot aggregate entry */
 static const char *boot_aggregate_name = "boot_aggregate";
 int ima_used_chip;
@@ -55,6 +49,8 @@ static int __init ima_add_boot_aggregate(void)
        const char *audit_cause = "ENOMEM";
        struct ima_template_entry *entry;
        struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
+       struct ima_event_data event_data = {iint, NULL, boot_aggregate_name,
+                                           NULL, 0, NULL};
        int result = -ENOMEM;
        int violation = 0;
        struct {
@@ -76,8 +72,7 @@ static int __init ima_add_boot_aggregate(void)
                }
        }
 
-       result = ima_alloc_init_template(iint, NULL, boot_aggregate_name,
-                                        NULL, 0, &entry);
+       result = ima_alloc_init_template(&event_data, &entry);
        if (result < 0) {
                audit_cause = "alloc_entry";
                goto err_out;
@@ -103,7 +98,7 @@ void __init ima_load_x509(void)
        int unset_flags = ima_policy_flag & IMA_APPRAISE;
 
        ima_policy_flag &= ~unset_flags;
-       integrity_load_x509(INTEGRITY_KEYRING_IMA, IMA_X509_PATH);
+       integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
        ima_policy_flag |= unset_flags;
 }
 #endif
index eeee00d..c21f09b 100644 (file)
@@ -106,9 +106,10 @@ static void ima_rdwr_violation_check(struct file *file,
        *pathname = ima_d_path(&file->f_path, pathbuf);
 
        if (send_tomtou)
-               ima_add_violation(file, *pathname, "invalid_pcr", "ToMToU");
+               ima_add_violation(file, *pathname, iint,
+                                 "invalid_pcr", "ToMToU");
        if (send_writers)
-               ima_add_violation(file, *pathname,
+               ima_add_violation(file, *pathname, iint,
                                  "invalid_pcr", "open_writers");
 }
 
index d1eefb9..3997e20 100644 (file)
@@ -27,6 +27,8 @@
 #define IMA_UID                0x0008
 #define IMA_FOWNER     0x0010
 #define IMA_FSUUID     0x0020
+#define IMA_INMASK     0x0040
+#define IMA_EUID       0x0080
 
 #define UNKNOWN                0
 #define MEASURE                0x0001  /* same as IMA_MEASURE */
@@ -42,6 +44,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
        LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
 };
 
+enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
+
 struct ima_rule_entry {
        struct list_head list;
        int action;
@@ -70,7 +74,7 @@ struct ima_rule_entry {
  * normal users can easily run the machine out of memory simply building
  * and running executables.
  */
-static struct ima_rule_entry default_rules[] = {
+static struct ima_rule_entry dont_measure_rules[] = {
        {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
@@ -79,12 +83,31 @@ static struct ima_rule_entry default_rules[] = {
        {.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
+        .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
+};
+
+static struct ima_rule_entry original_measurement_rules[] = {
        {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
         .flags = IMA_FUNC | IMA_MASK},
        {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
         .flags = IMA_FUNC | IMA_MASK},
-       {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID,
-        .flags = IMA_FUNC | IMA_MASK | IMA_UID},
+       {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
+        .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_MASK | IMA_UID},
+       {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
+       {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
+};
+
+static struct ima_rule_entry default_measurement_rules[] = {
+       {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
+        .flags = IMA_FUNC | IMA_MASK},
+       {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
+        .flags = IMA_FUNC | IMA_MASK},
+       {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
+        .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_EUID},
+       {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
+        .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
        {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
        {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
 };
@@ -99,6 +122,7 @@ static struct ima_rule_entry default_appraise_rules[] = {
        {.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
 #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
        {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
@@ -115,14 +139,29 @@ static struct list_head *ima_rules;
 
 static DEFINE_MUTEX(ima_rules_mutex);
 
-static bool ima_use_tcb __initdata;
+static int ima_policy __initdata;
 static int __init default_measure_policy_setup(char *str)
 {
-       ima_use_tcb = 1;
+       if (ima_policy)
+               return 1;
+
+       ima_policy = ORIGINAL_TCB;
        return 1;
 }
 __setup("ima_tcb", default_measure_policy_setup);
 
+static int __init policy_setup(char *str)
+{
+       if (ima_policy)
+               return 1;
+
+       if (strcmp(str, "tcb") == 0)
+               ima_policy = DEFAULT_TCB;
+
+       return 1;
+}
+__setup("ima_policy=", policy_setup);
+
 static bool ima_use_appraise_tcb __initdata;
 static int __init default_appraise_policy_setup(char *str)
 {
@@ -182,6 +221,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
        if ((rule->flags & IMA_MASK) &&
            (rule->mask != mask && func != POST_SETATTR))
                return false;
+       if ((rule->flags & IMA_INMASK) &&
+           (!(rule->mask & mask) && func != POST_SETATTR))
+               return false;
        if ((rule->flags & IMA_FSMAGIC)
            && rule->fsmagic != inode->i_sb->s_magic)
                return false;
@@ -190,6 +232,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
                return false;
        if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
                return false;
+       if (rule->flags & IMA_EUID) {
+               if (has_capability_noaudit(current, CAP_SETUID)) {
+                       if (!uid_eq(rule->uid, cred->euid)
+                           && !uid_eq(rule->uid, cred->suid)
+                           && !uid_eq(rule->uid, cred->uid))
+                               return false;
+               } else if (!uid_eq(rule->uid, cred->euid))
+                       return false;
+       }
+
        if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
                return false;
        for (i = 0; i < MAX_LSM_RULES; i++) {
@@ -333,21 +385,31 @@ void __init ima_init_policy(void)
 {
        int i, measure_entries, appraise_entries;
 
-       /* if !ima_use_tcb set entries = 0 so we load NO default rules */
-       measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
+       /* if !ima_policy set entries = 0 so we load NO default rules */
+       measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
        appraise_entries = ima_use_appraise_tcb ?
                         ARRAY_SIZE(default_appraise_rules) : 0;
 
-       for (i = 0; i < measure_entries + appraise_entries; i++) {
-               if (i < measure_entries)
-                       list_add_tail(&default_rules[i].list,
-                                     &ima_default_rules);
-               else {
-                       int j = i - measure_entries;
+       for (i = 0; i < measure_entries; i++)
+               list_add_tail(&dont_measure_rules[i].list, &ima_default_rules);
 
-                       list_add_tail(&default_appraise_rules[j].list,
+       switch (ima_policy) {
+       case ORIGINAL_TCB:
+               for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
+                       list_add_tail(&original_measurement_rules[i].list,
                                      &ima_default_rules);
-               }
+               break;
+       case DEFAULT_TCB:
+               for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
+                       list_add_tail(&default_measurement_rules[i].list,
+                                     &ima_default_rules);
+       default:
+               break;
+       }
+
+       for (i = 0; i < appraise_entries; i++) {
+               list_add_tail(&default_appraise_rules[i].list,
+                             &ima_default_rules);
        }
 
        ima_rules = &ima_default_rules;
@@ -373,7 +435,8 @@ enum {
        Opt_audit,
        Opt_obj_user, Opt_obj_role, Opt_obj_type,
        Opt_subj_user, Opt_subj_role, Opt_subj_type,
-       Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
+       Opt_func, Opt_mask, Opt_fsmagic,
+       Opt_uid, Opt_euid, Opt_fowner,
        Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
 };
 
@@ -394,6 +457,7 @@ static match_table_t policy_tokens = {
        {Opt_fsmagic, "fsmagic=%s"},
        {Opt_fsuuid, "fsuuid=%s"},
        {Opt_uid, "uid=%s"},
+       {Opt_euid, "euid=%s"},
        {Opt_fowner, "fowner=%s"},
        {Opt_appraise_type, "appraise_type=%s"},
        {Opt_permit_directio, "permit_directio"},
@@ -435,6 +499,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
 static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 {
        struct audit_buffer *ab;
+       char *from;
        char *p;
        int result = 0;
 
@@ -525,18 +590,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                        if (entry->mask)
                                result = -EINVAL;
 
-                       if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
+                       from = args[0].from;
+                       if (*from == '^')
+                               from++;
+
+                       if ((strcmp(from, "MAY_EXEC")) == 0)
                                entry->mask = MAY_EXEC;
-                       else if (strcmp(args[0].from, "MAY_WRITE") == 0)
+                       else if (strcmp(from, "MAY_WRITE") == 0)
                                entry->mask = MAY_WRITE;
-                       else if (strcmp(args[0].from, "MAY_READ") == 0)
+                       else if (strcmp(from, "MAY_READ") == 0)
                                entry->mask = MAY_READ;
-                       else if (strcmp(args[0].from, "MAY_APPEND") == 0)
+                       else if (strcmp(from, "MAY_APPEND") == 0)
                                entry->mask = MAY_APPEND;
                        else
                                result = -EINVAL;
                        if (!result)
-                               entry->flags |= IMA_MASK;
+                               entry->flags |= (*args[0].from == '^')
+                                    ? IMA_INMASK : IMA_MASK;
                        break;
                case Opt_fsmagic:
                        ima_log_string(ab, "fsmagic", args[0].from);
@@ -566,6 +636,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                        break;
                case Opt_uid:
                        ima_log_string(ab, "uid", args[0].from);
+               case Opt_euid:
+                       if (token == Opt_euid)
+                               ima_log_string(ab, "euid", args[0].from);
 
                        if (uid_valid(entry->uid)) {
                                result = -EINVAL;
@@ -574,11 +647,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 
                        result = kstrtoul(args[0].from, 10, &lnum);
                        if (!result) {
-                               entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
-                               if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
+                               entry->uid = make_kuid(current_user_ns(),
+                                                      (uid_t) lnum);
+                               if (!uid_valid(entry->uid) ||
+                                   (uid_t)lnum != lnum)
                                        result = -EINVAL;
                                else
-                                       entry->flags |= IMA_UID;
+                                       entry->flags |= (token == Opt_uid)
+                                           ? IMA_UID : IMA_EUID;
                        }
                        break;
                case Opt_fowner:
index bcfc36c..2934e3d 100644 (file)
@@ -70,7 +70,8 @@ static void ima_show_template_data_ascii(struct seq_file *m,
                                         enum data_formats datafmt,
                                         struct ima_field_data *field_data)
 {
-       u8 *buf_ptr = field_data->data, buflen = field_data->len;
+       u8 *buf_ptr = field_data->data;
+       u32 buflen = field_data->len;
 
        switch (datafmt) {
        case DATA_FMT_DIGEST_WITH_ALGO:
@@ -195,9 +196,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
 /*
  * This function writes the digest of an event (with size limit).
  */
-int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
-                        const unsigned char *filename,
-                        struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventdigest_init(struct ima_event_data *event_data,
                         struct ima_field_data *field_data)
 {
        struct {
@@ -211,25 +210,25 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
 
        memset(&hash, 0, sizeof(hash));
 
-       if (!iint)              /* recording a violation. */
+       if (event_data->violation)      /* recording a violation. */
                goto out;
 
-       if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) {
-               cur_digest = iint->ima_hash->digest;
-               cur_digestsize = iint->ima_hash->length;
+       if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) {
+               cur_digest = event_data->iint->ima_hash->digest;
+               cur_digestsize = event_data->iint->ima_hash->length;
                goto out;
        }
 
-       if (!file)              /* missing info to re-calculate the digest */
+       if (!event_data->file)  /* missing info to re-calculate the digest */
                return -EINVAL;
 
-       inode = file_inode(file);
+       inode = file_inode(event_data->file);
        hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
            ima_hash_algo : HASH_ALGO_SHA1;
-       result = ima_calc_file_hash(file, &hash.hdr);
+       result = ima_calc_file_hash(event_data->file, &hash.hdr);
        if (result) {
                integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
-                                   filename, "collect_data",
+                                   event_data->filename, "collect_data",
                                    "failed", result, 0);
                return result;
        }
@@ -243,48 +242,43 @@ out:
 /*
  * This function writes the digest of an event (without size limit).
  */
-int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
-                           struct file *file, const unsigned char *filename,
-                           struct evm_ima_xattr_data *xattr_value,
-                           int xattr_len, struct ima_field_data *field_data)
+int ima_eventdigest_ng_init(struct ima_event_data *event_data,
+                           struct ima_field_data *field_data)
 {
        u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1;
        u32 cur_digestsize = 0;
 
-       /* If iint is NULL, we are recording a violation. */
-       if (!iint)
+       if (event_data->violation)      /* recording a violation. */
                goto out;
 
-       cur_digest = iint->ima_hash->digest;
-       cur_digestsize = iint->ima_hash->length;
+       cur_digest = event_data->iint->ima_hash->digest;
+       cur_digestsize = event_data->iint->ima_hash->length;
 
-       hash_algo = iint->ima_hash->algo;
+       hash_algo = event_data->iint->ima_hash->algo;
 out:
        return ima_eventdigest_init_common(cur_digest, cur_digestsize,
                                           hash_algo, field_data);
 }
 
-static int ima_eventname_init_common(struct integrity_iint_cache *iint,
-                                    struct file *file,
-                                    const unsigned char *filename,
+static int ima_eventname_init_common(struct ima_event_data *event_data,
                                     struct ima_field_data *field_data,
                                     bool size_limit)
 {
        const char *cur_filename = NULL;
        u32 cur_filename_len = 0;
 
-       BUG_ON(filename == NULL && file == NULL);
+       BUG_ON(event_data->filename == NULL && event_data->file == NULL);
 
-       if (filename) {
-               cur_filename = filename;
-               cur_filename_len = strlen(filename);
+       if (event_data->filename) {
+               cur_filename = event_data->filename;
+               cur_filename_len = strlen(event_data->filename);
 
                if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
                        goto out;
        }
 
-       if (file) {
-               cur_filename = file->f_path.dentry->d_name.name;
+       if (event_data->file) {
+               cur_filename = event_data->file->f_path.dentry->d_name.name;
                cur_filename_len = strlen(cur_filename);
        } else
                /*
@@ -300,36 +294,30 @@ out:
 /*
  * This function writes the name of an event (with size limit).
  */
-int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
-                      const unsigned char *filename,
-                      struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventname_init(struct ima_event_data *event_data,
                       struct ima_field_data *field_data)
 {
-       return ima_eventname_init_common(iint, file, filename,
-                                        field_data, true);
+       return ima_eventname_init_common(event_data, field_data, true);
 }
 
 /*
  * This function writes the name of an event (without size limit).
  */
-int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
-                         const unsigned char *filename,
-                         struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventname_ng_init(struct ima_event_data *event_data,
                          struct ima_field_data *field_data)
 {
-       return ima_eventname_init_common(iint, file, filename,
-                                        field_data, false);
+       return ima_eventname_init_common(event_data, field_data, false);
 }
 
 /*
  *  ima_eventsig_init - include the file signature as part of the template data
  */
-int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
-                     const unsigned char *filename,
-                     struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventsig_init(struct ima_event_data *event_data,
                      struct ima_field_data *field_data)
 {
        enum data_formats fmt = DATA_FMT_HEX;
+       struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
+       int xattr_len = event_data->xattr_len;
        int rc = 0;
 
        if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
index 63f6b52..c344530 100644 (file)
@@ -26,24 +26,14 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
                              struct ima_field_data *field_data);
 void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
                           struct ima_field_data *field_data);
-int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
-                        const unsigned char *filename,
-                        struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventdigest_init(struct ima_event_data *event_data,
                         struct ima_field_data *field_data);
-int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
-                      const unsigned char *filename,
-                      struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventname_init(struct ima_event_data *event_data,
                       struct ima_field_data *field_data);
-int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
-                           struct file *file, const unsigned char *filename,
-                           struct evm_ima_xattr_data *xattr_value,
-                           int xattr_len, struct ima_field_data *field_data);
-int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
-                         const unsigned char *filename,
-                         struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventdigest_ng_init(struct ima_event_data *event_data,
+                           struct ima_field_data *field_data);
+int ima_eventname_ng_init(struct ima_event_data *event_data,
                          struct ima_field_data *field_data);
-int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
-                     const unsigned char *filename,
-                     struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventsig_init(struct ima_event_data *event_data,
                      struct ima_field_data *field_data);
 #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
index 0fc9519..9c61687 100644 (file)
@@ -135,7 +135,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
                            const char *digest, int digestlen);
 
 int __init integrity_init_keyring(const unsigned int id);
-int __init integrity_load_x509(const unsigned int id, char *path);
+int __init integrity_load_x509(const unsigned int id, const char *path);
 #else
 
 static inline int integrity_digsig_verify(const unsigned int id,
index 04c8fec..595fffa 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/security.h>
+#include <linux/lsm_hooks.h>
 #include <linux/integrity.h>
 #include <linux/ima.h>
 #include <linux/evm.h>
 
 #define MAX_LSM_EVM_XATTR      2
 
+/* Maximum number of letters for an LSM name string */
+#define SECURITY_NAME_MAX      10
+
 /* Boot-time LSM user choice */
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
        CONFIG_DEFAULT_SECURITY;
 
-static struct security_operations *security_ops;
-static struct security_operations default_security_ops = {
-       .name   = "default",
-};
-
-static inline int __init verify(struct security_operations *ops)
-{
-       /* verify the security_operations structure exists */
-       if (!ops)
-               return -EINVAL;
-       security_fixup_ops(ops);
-       return 0;
-}
-
 static void __init do_security_initcalls(void)
 {
        initcall_t *call;
@@ -64,20 +53,27 @@ static void __init do_security_initcalls(void)
  */
 int __init security_init(void)
 {
-       printk(KERN_INFO "Security Framework initialized\n");
+       pr_info("Security Framework initialized\n");
 
-       security_fixup_ops(&default_security_ops);
-       security_ops = &default_security_ops;
+       /*
+        * Always load the capability module.
+        */
+       capability_add_hooks();
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+       /*
+        * If Yama is configured for stacking load it next.
+        */
+       yama_add_hooks();
+#endif
+       /*
+        * Load the chosen module if there is one.
+        * This will also find yama if it is stacking
+        */
        do_security_initcalls();
 
        return 0;
 }
 
-void reset_security_ops(void)
-{
-       security_ops = &default_security_ops;
-}
-
 /* Save user chosen LSM */
 static int __init choose_lsm(char *str)
 {
@@ -88,7 +84,7 @@ __setup("security=", choose_lsm);
 
 /**
  * security_module_enable - Load given security module on boot ?
- * @ops: a pointer to the struct security_operations that is to be checked.
+ * @module: the name of the module
  *
  * Each LSM must pass this method before registering its own operations
  * to avoid security registration races. This method may also be used
@@ -100,84 +96,76 @@ __setup("security=", choose_lsm);
  *      choose an alternate LSM at boot time.
  * Otherwise, return false.
  */
-int __init security_module_enable(struct security_operations *ops)
+int __init security_module_enable(const char *module)
 {
-       return !strcmp(ops->name, chosen_lsm);
+       return !strcmp(module, chosen_lsm);
 }
 
-/**
- * register_security - registers a security framework with the kernel
- * @ops: a pointer to the struct security_options that is to be registered
+/*
+ * Hook list operation macros.
  *
- * This function allows a security module to register itself with the
- * kernel security subsystem.  Some rudimentary checking is done on the @ops
- * value passed to this function. You'll need to check first if your LSM
- * is allowed to register its @ops by calling security_module_enable(@ops).
+ * call_void_hook:
+ *     This is a hook that does not return a value.
  *
- * If there is already a security module registered with the kernel,
- * an error will be returned.  Otherwise %0 is returned on success.
+ * call_int_hook:
+ *     This is a hook that returns a value.
  */
-int __init register_security(struct security_operations *ops)
-{
-       if (verify(ops)) {
-               printk(KERN_DEBUG "%s could not verify "
-                      "security_operations structure.\n", __func__);
-               return -EINVAL;
-       }
-
-       if (security_ops != &default_security_ops)
-               return -EAGAIN;
 
-       security_ops = ops;
-
-       return 0;
-}
+#define call_void_hook(FUNC, ...)                              \
+       do {                                                    \
+               struct security_hook_list *P;                   \
+                                                               \
+               list_for_each_entry(P, &security_hook_heads.FUNC, list) \
+                       P->hook.FUNC(__VA_ARGS__);              \
+       } while (0)
+
+#define call_int_hook(FUNC, IRC, ...) ({                       \
+       int RC = IRC;                                           \
+       do {                                                    \
+               struct security_hook_list *P;                   \
+                                                               \
+               list_for_each_entry(P, &security_hook_heads.FUNC, list) { \
+                       RC = P->hook.FUNC(__VA_ARGS__);         \
+                       if (RC != 0)                            \
+                               break;                          \
+               }                                               \
+       } while (0);                                            \
+       RC;                                                     \
+})
 
 /* Security operations */
 
 int security_binder_set_context_mgr(struct task_struct *mgr)
 {
-       return security_ops->binder_set_context_mgr(mgr);
+       return call_int_hook(binder_set_context_mgr, 0, mgr);
 }
 
 int security_binder_transaction(struct task_struct *from,
                                struct task_struct *to)
 {
-       return security_ops->binder_transaction(from, to);
+       return call_int_hook(binder_transaction, 0, from, to);
 }
 
 int security_binder_transfer_binder(struct task_struct *from,
                                    struct task_struct *to)
 {
-       return security_ops->binder_transfer_binder(from, to);
+       return call_int_hook(binder_transfer_binder, 0, from, to);
 }
 
 int security_binder_transfer_file(struct task_struct *from,
                                  struct task_struct *to, struct file *file)
 {
-       return security_ops->binder_transfer_file(from, to, file);
+       return call_int_hook(binder_transfer_file, 0, from, to, file);
 }
 
 int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       int rc;
-       rc = yama_ptrace_access_check(child, mode);
-       if (rc)
-               return rc;
-#endif
-       return security_ops->ptrace_access_check(child, mode);
+       return call_int_hook(ptrace_access_check, 0, child, mode);
 }
 
 int security_ptrace_traceme(struct task_struct *parent)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       int rc;
-       rc = yama_ptrace_traceme(parent);
-       if (rc)
-               return rc;
-#endif
-       return security_ops->ptrace_traceme(parent);
+       return call_int_hook(ptrace_traceme, 0, parent);
 }
 
 int security_capget(struct task_struct *target,
@@ -185,7 +173,8 @@ int security_capget(struct task_struct *target,
                     kernel_cap_t *inheritable,
                     kernel_cap_t *permitted)
 {
-       return security_ops->capget(target, effective, inheritable, permitted);
+       return call_int_hook(capget, 0, target,
+                               effective, inheritable, permitted);
 }
 
 int security_capset(struct cred *new, const struct cred *old,
@@ -193,57 +182,75 @@ int security_capset(struct cred *new, const struct cred *old,
                    const kernel_cap_t *inheritable,
                    const kernel_cap_t *permitted)
 {
-       return security_ops->capset(new, old,
-                                   effective, inheritable, permitted);
+       return call_int_hook(capset, 0, new, old,
+                               effective, inheritable, permitted);
 }
 
 int security_capable(const struct cred *cred, struct user_namespace *ns,
                     int cap)
 {
-       return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT);
+       return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_AUDIT);
 }
 
 int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
                             int cap)
 {
-       return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
+       return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_NOAUDIT);
 }
 
 int security_quotactl(int cmds, int type, int id, struct super_block *sb)
 {
-       return security_ops->quotactl(cmds, type, id, sb);
+       return call_int_hook(quotactl, 0, cmds, type, id, sb);
 }
 
 int security_quota_on(struct dentry *dentry)
 {
-       return security_ops->quota_on(dentry);
+       return call_int_hook(quota_on, 0, dentry);
 }
 
 int security_syslog(int type)
 {
-       return security_ops->syslog(type);
+       return call_int_hook(syslog, 0, type);
 }
 
 int security_settime(const struct timespec *ts, const struct timezone *tz)
 {
-       return security_ops->settime(ts, tz);
+       return call_int_hook(settime, 0, ts, tz);
 }
 
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
 {
-       return security_ops->vm_enough_memory(mm, pages);
+       struct security_hook_list *hp;
+       int cap_sys_admin = 1;
+       int rc;
+
+       /*
+        * The module will respond with a positive value if
+        * it thinks the __vm_enough_memory() call should be
+        * made with the cap_sys_admin set. If all of the modules
+        * agree that it should be set it will. If any module
+        * thinks it should not be set it won't.
+        */
+       list_for_each_entry(hp, &security_hook_heads.vm_enough_memory, list) {
+               rc = hp->hook.vm_enough_memory(mm, pages);
+               if (rc <= 0) {
+                       cap_sys_admin = 0;
+                       break;
+               }
+       }
+       return __vm_enough_memory(mm, pages, cap_sys_admin);
 }
 
 int security_bprm_set_creds(struct linux_binprm *bprm)
 {
-       return security_ops->bprm_set_creds(bprm);
+       return call_int_hook(bprm_set_creds, 0, bprm);
 }
 
 int security_bprm_check(struct linux_binprm *bprm)
 {
        int ret;
 
-       ret = security_ops->bprm_check_security(bprm);
+       ret = call_int_hook(bprm_check_security, 0, bprm);
        if (ret)
                return ret;
        return ima_bprm_check(bprm);
@@ -251,69 +258,69 @@ int security_bprm_check(struct linux_binprm *bprm)
 
 void security_bprm_committing_creds(struct linux_binprm *bprm)
 {
-       security_ops->bprm_committing_creds(bprm);
+       call_void_hook(bprm_committing_creds, bprm);
 }
 
 void security_bprm_committed_creds(struct linux_binprm *bprm)
 {
-       security_ops->bprm_committed_creds(bprm);
+       call_void_hook(bprm_committed_creds, bprm);
 }
 
 int security_bprm_secureexec(struct linux_binprm *bprm)
 {
-       return security_ops->bprm_secureexec(bprm);
+       return call_int_hook(bprm_secureexec, 0, bprm);
 }
 
 int security_sb_alloc(struct super_block *sb)
 {
-       return security_ops->sb_alloc_security(sb);
+       return call_int_hook(sb_alloc_security, 0, sb);
 }
 
 void security_sb_free(struct super_block *sb)
 {
-       security_ops->sb_free_security(sb);
+       call_void_hook(sb_free_security, sb);
 }
 
 int security_sb_copy_data(char *orig, char *copy)
 {
-       return security_ops->sb_copy_data(orig, copy);
+       return call_int_hook(sb_copy_data, 0, orig, copy);
 }
 EXPORT_SYMBOL(security_sb_copy_data);
 
 int security_sb_remount(struct super_block *sb, void *data)
 {
-       return security_ops->sb_remount(sb, data);
+       return call_int_hook(sb_remount, 0, sb, data);
 }
 
 int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
-       return security_ops->sb_kern_mount(sb, flags, data);
+       return call_int_hook(sb_kern_mount, 0, sb, flags, data);
 }
 
 int security_sb_show_options(struct seq_file *m, struct super_block *sb)
 {
-       return security_ops->sb_show_options(m, sb);
+       return call_int_hook(sb_show_options, 0, m, sb);
 }
 
 int security_sb_statfs(struct dentry *dentry)
 {
-       return security_ops->sb_statfs(dentry);
+       return call_int_hook(sb_statfs, 0, dentry);
 }
 
 int security_sb_mount(const char *dev_name, struct path *path,
                        const char *type, unsigned long flags, void *data)
 {
-       return security_ops->sb_mount(dev_name, path, type, flags, data);
+       return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data);
 }
 
 int security_sb_umount(struct vfsmount *mnt, int flags)
 {
-       return security_ops->sb_umount(mnt, flags);
+       return call_int_hook(sb_umount, 0, mnt, flags);
 }
 
 int security_sb_pivotroot(struct path *old_path, struct path *new_path)
 {
-       return security_ops->sb_pivotroot(old_path, new_path);
+       return call_int_hook(sb_pivotroot, 0, old_path, new_path);
 }
 
 int security_sb_set_mnt_opts(struct super_block *sb,
@@ -321,42 +328,43 @@ int security_sb_set_mnt_opts(struct super_block *sb,
                                unsigned long kern_flags,
                                unsigned long *set_kern_flags)
 {
-       return security_ops->sb_set_mnt_opts(sb, opts, kern_flags,
-                                               set_kern_flags);
+       return call_int_hook(sb_set_mnt_opts,
+                               opts->num_mnt_opts ? -EOPNOTSUPP : 0, sb,
+                               opts, kern_flags, set_kern_flags);
 }
 EXPORT_SYMBOL(security_sb_set_mnt_opts);
 
 int security_sb_clone_mnt_opts(const struct super_block *oldsb,
                                struct super_block *newsb)
 {
-       return security_ops->sb_clone_mnt_opts(oldsb, newsb);
+       return call_int_hook(sb_clone_mnt_opts, 0, oldsb, newsb);
 }
 EXPORT_SYMBOL(security_sb_clone_mnt_opts);
 
 int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
 {
-       return security_ops->sb_parse_opts_str(options, opts);
+       return call_int_hook(sb_parse_opts_str, 0, options, opts);
 }
 EXPORT_SYMBOL(security_sb_parse_opts_str);
 
 int security_inode_alloc(struct inode *inode)
 {
        inode->i_security = NULL;
-       return security_ops->inode_alloc_security(inode);
+       return call_int_hook(inode_alloc_security, 0, inode);
 }
 
 void security_inode_free(struct inode *inode)
 {
        integrity_inode_free(inode);
-       security_ops->inode_free_security(inode);
+       call_void_hook(inode_free_security, inode);
 }
 
 int security_dentry_init_security(struct dentry *dentry, int mode,
                                        struct qstr *name, void **ctx,
                                        u32 *ctxlen)
 {
-       return security_ops->dentry_init_security(dentry, mode, name,
-                                                       ctx, ctxlen);
+       return call_int_hook(dentry_init_security, -EOPNOTSUPP, dentry, mode,
+                               name, ctx, ctxlen);
 }
 EXPORT_SYMBOL(security_dentry_init_security);
 
@@ -372,11 +380,11 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
                return 0;
 
        if (!initxattrs)
-               return security_ops->inode_init_security(inode, dir, qstr,
+               return call_int_hook(inode_init_security, 0, inode, dir, qstr,
                                                         NULL, NULL, NULL);
        memset(new_xattrs, 0, sizeof(new_xattrs));
        lsm_xattr = new_xattrs;
-       ret = security_ops->inode_init_security(inode, dir, qstr,
+       ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
                                                &lsm_xattr->name,
                                                &lsm_xattr->value,
                                                &lsm_xattr->value_len);
@@ -401,8 +409,8 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
 {
        if (unlikely(IS_PRIVATE(inode)))
                return -EOPNOTSUPP;
-       return security_ops->inode_init_security(inode, dir, qstr, name, value,
-                                                len);
+       return call_int_hook(inode_init_security, 0, inode, dir, qstr,
+                               name, value, len);
 }
 EXPORT_SYMBOL(security_old_inode_init_security);
 
@@ -412,7 +420,7 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return security_ops->path_mknod(dir, dentry, mode, dev);
+       return call_int_hook(path_mknod, 0, dir, dentry, mode, dev);
 }
 EXPORT_SYMBOL(security_path_mknod);
 
@@ -420,7 +428,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return security_ops->path_mkdir(dir, dentry, mode);
+       return call_int_hook(path_mkdir, 0, dir, dentry, mode);
 }
 EXPORT_SYMBOL(security_path_mkdir);
 
@@ -428,14 +436,14 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return security_ops->path_rmdir(dir, dentry);
+       return call_int_hook(path_rmdir, 0, dir, dentry);
 }
 
 int security_path_unlink(struct path *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return security_ops->path_unlink(dir, dentry);
+       return call_int_hook(path_unlink, 0, dir, dentry);
 }
 EXPORT_SYMBOL(security_path_unlink);
 
@@ -444,7 +452,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
-       return security_ops->path_symlink(dir, dentry, old_name);
+       return call_int_hook(path_symlink, 0, dir, dentry, old_name);
 }
 
 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -452,7 +460,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
                return 0;
-       return security_ops->path_link(old_dentry, new_dir, new_dentry);
+       return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
 }
 
 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
@@ -464,14 +472,14 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
                return 0;
 
        if (flags & RENAME_EXCHANGE) {
-               int err = security_ops->path_rename(new_dir, new_dentry,
-                                                   old_dir, old_dentry);
+               int err = call_int_hook(path_rename, 0, new_dir, new_dentry,
+                                       old_dir, old_dentry);
                if (err)
                        return err;
        }
 
-       return security_ops->path_rename(old_dir, old_dentry, new_dir,
-                                        new_dentry);
+       return call_int_hook(path_rename, 0, old_dir, old_dentry, new_dir,
+                               new_dentry);
 }
 EXPORT_SYMBOL(security_path_rename);
 
@@ -479,26 +487,26 @@ int security_path_truncate(struct path *path)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return security_ops->path_truncate(path);
+       return call_int_hook(path_truncate, 0, path);
 }
 
 int security_path_chmod(struct path *path, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return security_ops->path_chmod(path, mode);
+       return call_int_hook(path_chmod, 0, path, mode);
 }
 
 int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return security_ops->path_chown(path, uid, gid);
+       return call_int_hook(path_chown, 0, path, uid, gid);
 }
 
 int security_path_chroot(struct path *path)
 {
-       return security_ops->path_chroot(path);
+       return call_int_hook(path_chroot, 0, path);
 }
 #endif
 
@@ -506,7 +514,7 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return security_ops->inode_create(dir, dentry, mode);
+       return call_int_hook(inode_create, 0, dir, dentry, mode);
 }
 EXPORT_SYMBOL_GPL(security_inode_create);
 
@@ -515,14 +523,14 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir,
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
                return 0;
-       return security_ops->inode_link(old_dentry, dir, new_dentry);
+       return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry);
 }
 
 int security_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return security_ops->inode_unlink(dir, dentry);
+       return call_int_hook(inode_unlink, 0, dir, dentry);
 }
 
 int security_inode_symlink(struct inode *dir, struct dentry *dentry,
@@ -530,14 +538,14 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return security_ops->inode_symlink(dir, dentry, old_name);
+       return call_int_hook(inode_symlink, 0, dir, dentry, old_name);
 }
 
 int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return security_ops->inode_mkdir(dir, dentry, mode);
+       return call_int_hook(inode_mkdir, 0, dir, dentry, mode);
 }
 EXPORT_SYMBOL_GPL(security_inode_mkdir);
 
@@ -545,14 +553,14 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return security_ops->inode_rmdir(dir, dentry);
+       return call_int_hook(inode_rmdir, 0, dir, dentry);
 }
 
 int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
-       return security_ops->inode_mknod(dir, dentry, mode, dev);
+       return call_int_hook(inode_mknod, 0, dir, dentry, mode, dev);
 }
 
 int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -564,13 +572,13 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
                return 0;
 
        if (flags & RENAME_EXCHANGE) {
-               int err = security_ops->inode_rename(new_dir, new_dentry,
+               int err = call_int_hook(inode_rename, 0, new_dir, new_dentry,
                                                     old_dir, old_dentry);
                if (err)
                        return err;
        }
 
-       return security_ops->inode_rename(old_dir, old_dentry,
+       return call_int_hook(inode_rename, 0, old_dir, old_dentry,
                                           new_dir, new_dentry);
 }
 
@@ -578,7 +586,7 @@ int security_inode_readlink(struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return security_ops->inode_readlink(dentry);
+       return call_int_hook(inode_readlink, 0, dentry);
 }
 
 int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
@@ -586,14 +594,14 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
 {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return security_ops->inode_follow_link(dentry, inode, rcu);
+       return call_int_hook(inode_follow_link, 0, dentry, inode, rcu);
 }
 
 int security_inode_permission(struct inode *inode, int mask)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return security_ops->inode_permission(inode, mask);
+       return call_int_hook(inode_permission, 0, inode, mask);
 }
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
@@ -602,7 +610,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       ret = security_ops->inode_setattr(dentry, attr);
+       ret = call_int_hook(inode_setattr, 0, dentry, attr);
        if (ret)
                return ret;
        return evm_inode_setattr(dentry, attr);
@@ -613,7 +621,7 @@ int security_inode_getattr(const struct path *path)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
-       return security_ops->inode_getattr(path);
+       return call_int_hook(inode_getattr, 0, path);
 }
 
 int security_inode_setxattr(struct dentry *dentry, const char *name,
@@ -623,7 +631,15 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
 
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
+       /*
+        * SELinux and Smack integrate the cap call,
+        * so assume that all LSMs supplying this call do so.
+        */
+       ret = call_int_hook(inode_setxattr, 1, 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);
@@ -637,7 +653,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return;
-       security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+       call_void_hook(inode_post_setxattr, dentry, name, value, size, flags);
        evm_inode_post_setxattr(dentry, name, value, size);
 }
 
@@ -645,14 +661,14 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return security_ops->inode_getxattr(dentry, name);
+       return call_int_hook(inode_getxattr, 0, dentry, name);
 }
 
 int security_inode_listxattr(struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       return security_ops->inode_listxattr(dentry);
+       return call_int_hook(inode_listxattr, 0, dentry);
 }
 
 int security_inode_removexattr(struct dentry *dentry, const char *name)
@@ -661,7 +677,13 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
 
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
-       ret = security_ops->inode_removexattr(dentry, name);
+       /*
+        * SELinux and Smack integrate the cap call,
+        * so assume that all LSMs supplying this call do so.
+        */
+       ret = call_int_hook(inode_removexattr, 1, dentry, name);
+       if (ret == 1)
+               ret = cap_inode_removexattr(dentry, name);
        if (ret)
                return ret;
        ret = ima_inode_removexattr(dentry, name);
@@ -672,46 +694,48 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
 
 int security_inode_need_killpriv(struct dentry *dentry)
 {
-       return security_ops->inode_need_killpriv(dentry);
+       return call_int_hook(inode_need_killpriv, 0, dentry);
 }
 
 int security_inode_killpriv(struct dentry *dentry)
 {
-       return security_ops->inode_killpriv(dentry);
+       return call_int_hook(inode_killpriv, 0, dentry);
 }
 
 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return -EOPNOTSUPP;
-       return security_ops->inode_getsecurity(inode, name, buffer, alloc);
+       return call_int_hook(inode_getsecurity, -EOPNOTSUPP, inode, name,
+                               buffer, alloc);
 }
 
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return -EOPNOTSUPP;
-       return security_ops->inode_setsecurity(inode, name, value, size, flags);
+       return call_int_hook(inode_setsecurity, -EOPNOTSUPP, inode, name,
+                               value, size, flags);
 }
 
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
-       return security_ops->inode_listsecurity(inode, buffer, buffer_size);
+       return call_int_hook(inode_listsecurity, 0, inode, buffer, buffer_size);
 }
 EXPORT_SYMBOL(security_inode_listsecurity);
 
 void security_inode_getsecid(const struct inode *inode, u32 *secid)
 {
-       security_ops->inode_getsecid(inode, secid);
+       call_void_hook(inode_getsecid, inode, secid);
 }
 
 int security_file_permission(struct file *file, int mask)
 {
        int ret;
 
-       ret = security_ops->file_permission(file, mask);
+       ret = call_int_hook(file_permission, 0, file, mask);
        if (ret)
                return ret;
 
@@ -720,17 +744,17 @@ int security_file_permission(struct file *file, int mask)
 
 int security_file_alloc(struct file *file)
 {
-       return security_ops->file_alloc_security(file);
+       return call_int_hook(file_alloc_security, 0, file);
 }
 
 void security_file_free(struct file *file)
 {
-       security_ops->file_free_security(file);
+       call_void_hook(file_free_security, file);
 }
 
 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       return security_ops->file_ioctl(file, cmd, arg);
+       return call_int_hook(file_ioctl, 0, file, cmd, arg);
 }
 
 static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
@@ -770,7 +794,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
                        unsigned long flags)
 {
        int ret;
-       ret = security_ops->mmap_file(file, prot,
+       ret = call_int_hook(mmap_file, 0, file, prot,
                                        mmap_prot(file, prot), flags);
        if (ret)
                return ret;
@@ -779,46 +803,46 @@ int security_mmap_file(struct file *file, unsigned long prot,
 
 int security_mmap_addr(unsigned long addr)
 {
-       return security_ops->mmap_addr(addr);
+       return call_int_hook(mmap_addr, 0, addr);
 }
 
 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
                            unsigned long prot)
 {
-       return security_ops->file_mprotect(vma, reqprot, prot);
+       return call_int_hook(file_mprotect, 0, vma, reqprot, prot);
 }
 
 int security_file_lock(struct file *file, unsigned int cmd)
 {
-       return security_ops->file_lock(file, cmd);
+       return call_int_hook(file_lock, 0, file, cmd);
 }
 
 int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       return security_ops->file_fcntl(file, cmd, arg);
+       return call_int_hook(file_fcntl, 0, file, cmd, arg);
 }
 
 void security_file_set_fowner(struct file *file)
 {
-       security_ops->file_set_fowner(file);
+       call_void_hook(file_set_fowner, file);
 }
 
 int security_file_send_sigiotask(struct task_struct *tsk,
                                  struct fown_struct *fown, int sig)
 {
-       return security_ops->file_send_sigiotask(tsk, fown, sig);
+       return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig);
 }
 
 int security_file_receive(struct file *file)
 {
-       return security_ops->file_receive(file);
+       return call_int_hook(file_receive, 0, file);
 }
 
 int security_file_open(struct file *file, const struct cred *cred)
 {
        int ret;
 
-       ret = security_ops->file_open(file, cred);
+       ret = call_int_hook(file_open, 0, file, cred);
        if (ret)
                return ret;
 
@@ -827,52 +851,49 @@ int security_file_open(struct file *file, const struct cred *cred)
 
 int security_task_create(unsigned long clone_flags)
 {
-       return security_ops->task_create(clone_flags);
+       return call_int_hook(task_create, 0, clone_flags);
 }
 
 void security_task_free(struct task_struct *task)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       yama_task_free(task);
-#endif
-       security_ops->task_free(task);
+       call_void_hook(task_free, task);
 }
 
 int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 {
-       return security_ops->cred_alloc_blank(cred, gfp);
+       return call_int_hook(cred_alloc_blank, 0, cred, gfp);
 }
 
 void security_cred_free(struct cred *cred)
 {
-       security_ops->cred_free(cred);
+       call_void_hook(cred_free, cred);
 }
 
 int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
 {
-       return security_ops->cred_prepare(new, old, gfp);
+       return call_int_hook(cred_prepare, 0, new, old, gfp);
 }
 
 void security_transfer_creds(struct cred *new, const struct cred *old)
 {
-       security_ops->cred_transfer(new, old);
+       call_void_hook(cred_transfer, new, old);
 }
 
 int security_kernel_act_as(struct cred *new, u32 secid)
 {
-       return security_ops->kernel_act_as(new, secid);
+       return call_int_hook(kernel_act_as, 0, new, secid);
 }
 
 int security_kernel_create_files_as(struct cred *new, struct inode *inode)
 {
-       return security_ops->kernel_create_files_as(new, inode);
+       return call_int_hook(kernel_create_files_as, 0, new, inode);
 }
 
 int security_kernel_fw_from_file(struct file *file, char *buf, size_t size)
 {
        int ret;
 
-       ret = security_ops->kernel_fw_from_file(file, buf, size);
+       ret = call_int_hook(kernel_fw_from_file, 0, file, buf, size);
        if (ret)
                return ret;
        return ima_fw_from_file(file, buf, size);
@@ -881,14 +902,14 @@ EXPORT_SYMBOL_GPL(security_kernel_fw_from_file);
 
 int security_kernel_module_request(char *kmod_name)
 {
-       return security_ops->kernel_module_request(kmod_name);
+       return call_int_hook(kernel_module_request, 0, kmod_name);
 }
 
 int security_kernel_module_from_file(struct file *file)
 {
        int ret;
 
-       ret = security_ops->kernel_module_from_file(file);
+       ret = call_int_hook(kernel_module_from_file, 0, file);
        if (ret)
                return ret;
        return ima_module_check(file);
@@ -897,259 +918,269 @@ int security_kernel_module_from_file(struct file *file)
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags)
 {
-       return security_ops->task_fix_setuid(new, old, flags);
+       return call_int_hook(task_fix_setuid, 0, new, old, flags);
 }
 
 int security_task_setpgid(struct task_struct *p, pid_t pgid)
 {
-       return security_ops->task_setpgid(p, pgid);
+       return call_int_hook(task_setpgid, 0, p, pgid);
 }
 
 int security_task_getpgid(struct task_struct *p)
 {
-       return security_ops->task_getpgid(p);
+       return call_int_hook(task_getpgid, 0, p);
 }
 
 int security_task_getsid(struct task_struct *p)
 {
-       return security_ops->task_getsid(p);
+       return call_int_hook(task_getsid, 0, p);
 }
 
 void security_task_getsecid(struct task_struct *p, u32 *secid)
 {
-       security_ops->task_getsecid(p, secid);
+       *secid = 0;
+       call_void_hook(task_getsecid, p, secid);
 }
 EXPORT_SYMBOL(security_task_getsecid);
 
 int security_task_setnice(struct task_struct *p, int nice)
 {
-       return security_ops->task_setnice(p, nice);
+       return call_int_hook(task_setnice, 0, p, nice);
 }
 
 int security_task_setioprio(struct task_struct *p, int ioprio)
 {
-       return security_ops->task_setioprio(p, ioprio);
+       return call_int_hook(task_setioprio, 0, p, ioprio);
 }
 
 int security_task_getioprio(struct task_struct *p)
 {
-       return security_ops->task_getioprio(p);
+       return call_int_hook(task_getioprio, 0, p);
 }
 
 int security_task_setrlimit(struct task_struct *p, unsigned int resource,
                struct rlimit *new_rlim)
 {
-       return security_ops->task_setrlimit(p, resource, new_rlim);
+       return call_int_hook(task_setrlimit, 0, p, resource, new_rlim);
 }
 
 int security_task_setscheduler(struct task_struct *p)
 {
-       return security_ops->task_setscheduler(p);
+       return call_int_hook(task_setscheduler, 0, p);
 }
 
 int security_task_getscheduler(struct task_struct *p)
 {
-       return security_ops->task_getscheduler(p);
+       return call_int_hook(task_getscheduler, 0, p);
 }
 
 int security_task_movememory(struct task_struct *p)
 {
-       return security_ops->task_movememory(p);
+       return call_int_hook(task_movememory, 0, p);
 }
 
 int security_task_kill(struct task_struct *p, struct siginfo *info,
                        int sig, u32 secid)
 {
-       return security_ops->task_kill(p, info, sig, secid);
+       return call_int_hook(task_kill, 0, p, info, sig, secid);
 }
 
 int security_task_wait(struct task_struct *p)
 {
-       return security_ops->task_wait(p);
+       return call_int_hook(task_wait, 0, p);
 }
 
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                         unsigned long arg4, unsigned long arg5)
 {
-#ifdef CONFIG_SECURITY_YAMA_STACKED
-       int rc;
-       rc = yama_task_prctl(option, arg2, arg3, arg4, arg5);
-       if (rc != -ENOSYS)
-               return rc;
-#endif
-       return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
+       int thisrc;
+       int rc = -ENOSYS;
+       struct security_hook_list *hp;
+
+       list_for_each_entry(hp, &security_hook_heads.task_prctl, list) {
+               thisrc = hp->hook.task_prctl(option, arg2, arg3, arg4, arg5);
+               if (thisrc != -ENOSYS) {
+                       rc = thisrc;
+                       if (thisrc != 0)
+                               break;
+               }
+       }
+       return rc;
 }
 
 void security_task_to_inode(struct task_struct *p, struct inode *inode)
 {
-       security_ops->task_to_inode(p, inode);
+       call_void_hook(task_to_inode, p, inode);
 }
 
 int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
 {
-       return security_ops->ipc_permission(ipcp, flag);
+       return call_int_hook(ipc_permission, 0, ipcp, flag);
 }
 
 void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
 {
-       security_ops->ipc_getsecid(ipcp, secid);
+       *secid = 0;
+       call_void_hook(ipc_getsecid, ipcp, secid);
 }
 
 int security_msg_msg_alloc(struct msg_msg *msg)
 {
-       return security_ops->msg_msg_alloc_security(msg);
+       return call_int_hook(msg_msg_alloc_security, 0, msg);
 }
 
 void security_msg_msg_free(struct msg_msg *msg)
 {
-       security_ops->msg_msg_free_security(msg);
+       call_void_hook(msg_msg_free_security, msg);
 }
 
 int security_msg_queue_alloc(struct msg_queue *msq)
 {
-       return security_ops->msg_queue_alloc_security(msq);
+       return call_int_hook(msg_queue_alloc_security, 0, msq);
 }
 
 void security_msg_queue_free(struct msg_queue *msq)
 {
-       security_ops->msg_queue_free_security(msq);
+       call_void_hook(msg_queue_free_security, msq);
 }
 
 int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
 {
-       return security_ops->msg_queue_associate(msq, msqflg);
+       return call_int_hook(msg_queue_associate, 0, msq, msqflg);
 }
 
 int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
 {
-       return security_ops->msg_queue_msgctl(msq, cmd);
+       return call_int_hook(msg_queue_msgctl, 0, msq, cmd);
 }
 
 int security_msg_queue_msgsnd(struct msg_queue *msq,
                               struct msg_msg *msg, int msqflg)
 {
-       return security_ops->msg_queue_msgsnd(msq, msg, msqflg);
+       return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg);
 }
 
 int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
                               struct task_struct *target, long type, int mode)
 {
-       return security_ops->msg_queue_msgrcv(msq, msg, target, type, mode);
+       return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode);
 }
 
 int security_shm_alloc(struct shmid_kernel *shp)
 {
-       return security_ops->shm_alloc_security(shp);
+       return call_int_hook(shm_alloc_security, 0, shp);
 }
 
 void security_shm_free(struct shmid_kernel *shp)
 {
-       security_ops->shm_free_security(shp);
+       call_void_hook(shm_free_security, shp);
 }
 
 int security_shm_associate(struct shmid_kernel *shp, int shmflg)
 {
-       return security_ops->shm_associate(shp, shmflg);
+       return call_int_hook(shm_associate, 0, shp, shmflg);
 }
 
 int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
 {
-       return security_ops->shm_shmctl(shp, cmd);
+       return call_int_hook(shm_shmctl, 0, shp, cmd);
 }
 
 int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
 {
-       return security_ops->shm_shmat(shp, shmaddr, shmflg);
+       return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg);
 }
 
 int security_sem_alloc(struct sem_array *sma)
 {
-       return security_ops->sem_alloc_security(sma);
+       return call_int_hook(sem_alloc_security, 0, sma);
 }
 
 void security_sem_free(struct sem_array *sma)
 {
-       security_ops->sem_free_security(sma);
+       call_void_hook(sem_free_security, sma);
 }
 
 int security_sem_associate(struct sem_array *sma, int semflg)
 {
-       return security_ops->sem_associate(sma, semflg);
+       return call_int_hook(sem_associate, 0, sma, semflg);
 }
 
 int security_sem_semctl(struct sem_array *sma, int cmd)
 {
-       return security_ops->sem_semctl(sma, cmd);
+       return call_int_hook(sem_semctl, 0, sma, cmd);
 }
 
 int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
                        unsigned nsops, int alter)
 {
-       return security_ops->sem_semop(sma, sops, nsops, alter);
+       return call_int_hook(sem_semop, 0, sma, sops, nsops, alter);
 }
 
 void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 {
        if (unlikely(inode && IS_PRIVATE(inode)))
                return;
-       security_ops->d_instantiate(dentry, inode);
+       call_void_hook(d_instantiate, dentry, inode);
 }
 EXPORT_SYMBOL(security_d_instantiate);
 
 int security_getprocattr(struct task_struct *p, char *name, char **value)
 {
-       return security_ops->getprocattr(p, name, value);
+       return call_int_hook(getprocattr, -EINVAL, p, name, value);
 }
 
 int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
 {
-       return security_ops->setprocattr(p, name, value, size);
+       return call_int_hook(setprocattr, -EINVAL, p, name, value, size);
 }
 
 int security_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
-       return security_ops->netlink_send(sk, skb);
+       return call_int_hook(netlink_send, 0, sk, skb);
 }
 
 int security_ismaclabel(const char *name)
 {
-       return security_ops->ismaclabel(name);
+       return call_int_hook(ismaclabel, 0, name);
 }
 EXPORT_SYMBOL(security_ismaclabel);
 
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
-       return security_ops->secid_to_secctx(secid, secdata, seclen);
+       return call_int_hook(secid_to_secctx, -EOPNOTSUPP, secid, secdata,
+                               seclen);
 }
 EXPORT_SYMBOL(security_secid_to_secctx);
 
 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
-       return security_ops->secctx_to_secid(secdata, seclen, secid);
+       *secid = 0;
+       return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid);
 }
 EXPORT_SYMBOL(security_secctx_to_secid);
 
 void security_release_secctx(char *secdata, u32 seclen)
 {
-       security_ops->release_secctx(secdata, seclen);
+       call_void_hook(release_secctx, secdata, seclen);
 }
 EXPORT_SYMBOL(security_release_secctx);
 
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
 {
-       return security_ops->inode_notifysecctx(inode, ctx, ctxlen);
+       return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen);
 }
 EXPORT_SYMBOL(security_inode_notifysecctx);
 
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
 {
-       return security_ops->inode_setsecctx(dentry, ctx, ctxlen);
+       return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen);
 }
 EXPORT_SYMBOL(security_inode_setsecctx);
 
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
 {
-       return security_ops->inode_getsecctx(inode, ctx, ctxlen);
+       return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, ctx, ctxlen);
 }
 EXPORT_SYMBOL(security_inode_getsecctx);
 
@@ -1157,206 +1188,207 @@ EXPORT_SYMBOL(security_inode_getsecctx);
 
 int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
 {
-       return security_ops->unix_stream_connect(sock, other, newsk);
+       return call_int_hook(unix_stream_connect, 0, sock, other, newsk);
 }
 EXPORT_SYMBOL(security_unix_stream_connect);
 
 int security_unix_may_send(struct socket *sock,  struct socket *other)
 {
-       return security_ops->unix_may_send(sock, other);
+       return call_int_hook(unix_may_send, 0, sock, other);
 }
 EXPORT_SYMBOL(security_unix_may_send);
 
 int security_socket_create(int family, int type, int protocol, int kern)
 {
-       return security_ops->socket_create(family, type, protocol, kern);
+       return call_int_hook(socket_create, 0, family, type, protocol, kern);
 }
 
 int security_socket_post_create(struct socket *sock, int family,
                                int type, int protocol, int kern)
 {
-       return security_ops->socket_post_create(sock, family, type,
+       return call_int_hook(socket_post_create, 0, sock, family, type,
                                                protocol, kern);
 }
 
 int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
 {
-       return security_ops->socket_bind(sock, address, addrlen);
+       return call_int_hook(socket_bind, 0, sock, address, addrlen);
 }
 
 int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
 {
-       return security_ops->socket_connect(sock, address, addrlen);
+       return call_int_hook(socket_connect, 0, sock, address, addrlen);
 }
 
 int security_socket_listen(struct socket *sock, int backlog)
 {
-       return security_ops->socket_listen(sock, backlog);
+       return call_int_hook(socket_listen, 0, sock, backlog);
 }
 
 int security_socket_accept(struct socket *sock, struct socket *newsock)
 {
-       return security_ops->socket_accept(sock, newsock);
+       return call_int_hook(socket_accept, 0, sock, newsock);
 }
 
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
-       return security_ops->socket_sendmsg(sock, msg, size);
+       return call_int_hook(socket_sendmsg, 0, sock, msg, size);
 }
 
 int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
                            int size, int flags)
 {
-       return security_ops->socket_recvmsg(sock, msg, size, flags);
+       return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags);
 }
 
 int security_socket_getsockname(struct socket *sock)
 {
-       return security_ops->socket_getsockname(sock);
+       return call_int_hook(socket_getsockname, 0, sock);
 }
 
 int security_socket_getpeername(struct socket *sock)
 {
-       return security_ops->socket_getpeername(sock);
+       return call_int_hook(socket_getpeername, 0, sock);
 }
 
 int security_socket_getsockopt(struct socket *sock, int level, int optname)
 {
-       return security_ops->socket_getsockopt(sock, level, optname);
+       return call_int_hook(socket_getsockopt, 0, sock, level, optname);
 }
 
 int security_socket_setsockopt(struct socket *sock, int level, int optname)
 {
-       return security_ops->socket_setsockopt(sock, level, optname);
+       return call_int_hook(socket_setsockopt, 0, sock, level, optname);
 }
 
 int security_socket_shutdown(struct socket *sock, int how)
 {
-       return security_ops->socket_shutdown(sock, how);
+       return call_int_hook(socket_shutdown, 0, sock, how);
 }
 
 int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
-       return security_ops->socket_sock_rcv_skb(sk, skb);
+       return call_int_hook(socket_sock_rcv_skb, 0, sk, skb);
 }
 EXPORT_SYMBOL(security_sock_rcv_skb);
 
 int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
                                      int __user *optlen, unsigned len)
 {
-       return security_ops->socket_getpeersec_stream(sock, optval, optlen, len);
+       return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock,
+                               optval, optlen, len);
 }
 
 int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
 {
-       return security_ops->socket_getpeersec_dgram(sock, skb, secid);
+       return call_int_hook(socket_getpeersec_dgram, 0, sock, skb, secid);
 }
 EXPORT_SYMBOL(security_socket_getpeersec_dgram);
 
 int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
 {
-       return security_ops->sk_alloc_security(sk, family, priority);
+       return call_int_hook(sk_alloc_security, 0, sk, family, priority);
 }
 
 void security_sk_free(struct sock *sk)
 {
-       security_ops->sk_free_security(sk);
+       call_void_hook(sk_free_security, sk);
 }
 
 void security_sk_clone(const struct sock *sk, struct sock *newsk)
 {
-       security_ops->sk_clone_security(sk, newsk);
+       call_void_hook(sk_clone_security, sk, newsk);
 }
 EXPORT_SYMBOL(security_sk_clone);
 
 void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
 {
-       security_ops->sk_getsecid(sk, &fl->flowi_secid);
+       call_void_hook(sk_getsecid, sk, &fl->flowi_secid);
 }
 EXPORT_SYMBOL(security_sk_classify_flow);
 
 void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
 {
-       security_ops->req_classify_flow(req, fl);
+       call_void_hook(req_classify_flow, req, fl);
 }
 EXPORT_SYMBOL(security_req_classify_flow);
 
 void security_sock_graft(struct sock *sk, struct socket *parent)
 {
-       security_ops->sock_graft(sk, parent);
+       call_void_hook(sock_graft, sk, parent);
 }
 EXPORT_SYMBOL(security_sock_graft);
 
 int security_inet_conn_request(struct sock *sk,
                        struct sk_buff *skb, struct request_sock *req)
 {
-       return security_ops->inet_conn_request(sk, skb, req);
+       return call_int_hook(inet_conn_request, 0, sk, skb, req);
 }
 EXPORT_SYMBOL(security_inet_conn_request);
 
 void security_inet_csk_clone(struct sock *newsk,
                        const struct request_sock *req)
 {
-       security_ops->inet_csk_clone(newsk, req);
+       call_void_hook(inet_csk_clone, newsk, req);
 }
 
 void security_inet_conn_established(struct sock *sk,
                        struct sk_buff *skb)
 {
-       security_ops->inet_conn_established(sk, skb);
+       call_void_hook(inet_conn_established, sk, skb);
 }
 
 int security_secmark_relabel_packet(u32 secid)
 {
-       return security_ops->secmark_relabel_packet(secid);
+       return call_int_hook(secmark_relabel_packet, 0, secid);
 }
 EXPORT_SYMBOL(security_secmark_relabel_packet);
 
 void security_secmark_refcount_inc(void)
 {
-       security_ops->secmark_refcount_inc();
+       call_void_hook(secmark_refcount_inc);
 }
 EXPORT_SYMBOL(security_secmark_refcount_inc);
 
 void security_secmark_refcount_dec(void)
 {
-       security_ops->secmark_refcount_dec();
+       call_void_hook(secmark_refcount_dec);
 }
 EXPORT_SYMBOL(security_secmark_refcount_dec);
 
 int security_tun_dev_alloc_security(void **security)
 {
-       return security_ops->tun_dev_alloc_security(security);
+       return call_int_hook(tun_dev_alloc_security, 0, security);
 }
 EXPORT_SYMBOL(security_tun_dev_alloc_security);
 
 void security_tun_dev_free_security(void *security)
 {
-       security_ops->tun_dev_free_security(security);
+       call_void_hook(tun_dev_free_security, security);
 }
 EXPORT_SYMBOL(security_tun_dev_free_security);
 
 int security_tun_dev_create(void)
 {
-       return security_ops->tun_dev_create();
+       return call_int_hook(tun_dev_create, 0);
 }
 EXPORT_SYMBOL(security_tun_dev_create);
 
 int security_tun_dev_attach_queue(void *security)
 {
-       return security_ops->tun_dev_attach_queue(security);
+       return call_int_hook(tun_dev_attach_queue, 0, security);
 }
 EXPORT_SYMBOL(security_tun_dev_attach_queue);
 
 int security_tun_dev_attach(struct sock *sk, void *security)
 {
-       return security_ops->tun_dev_attach(sk, security);
+       return call_int_hook(tun_dev_attach, 0, sk, security);
 }
 EXPORT_SYMBOL(security_tun_dev_attach);
 
 int security_tun_dev_open(void *security)
 {
-       return security_ops->tun_dev_open(security);
+       return call_int_hook(tun_dev_open, 0, security);
 }
 EXPORT_SYMBOL(security_tun_dev_open);
 
@@ -1368,71 +1400,89 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
                               struct xfrm_user_sec_ctx *sec_ctx,
                               gfp_t gfp)
 {
-       return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx, gfp);
+       return call_int_hook(xfrm_policy_alloc_security, 0, 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 security_ops->xfrm_policy_clone_security(old_ctx, new_ctxp);
+       return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp);
 }
 
 void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
 {
-       security_ops->xfrm_policy_free_security(ctx);
+       call_void_hook(xfrm_policy_free_security, ctx);
 }
 EXPORT_SYMBOL(security_xfrm_policy_free);
 
 int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
 {
-       return security_ops->xfrm_policy_delete_security(ctx);
+       return call_int_hook(xfrm_policy_delete_security, 0, ctx);
 }
 
 int security_xfrm_state_alloc(struct xfrm_state *x,
                              struct xfrm_user_sec_ctx *sec_ctx)
 {
-       return security_ops->xfrm_state_alloc(x, sec_ctx);
+       return call_int_hook(xfrm_state_alloc, 0, 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 security_ops->xfrm_state_alloc_acquire(x, polsec, secid);
+       return call_int_hook(xfrm_state_alloc_acquire, 0, x, polsec, secid);
 }
 
 int security_xfrm_state_delete(struct xfrm_state *x)
 {
-       return security_ops->xfrm_state_delete_security(x);
+       return call_int_hook(xfrm_state_delete_security, 0, x);
 }
 EXPORT_SYMBOL(security_xfrm_state_delete);
 
 void security_xfrm_state_free(struct xfrm_state *x)
 {
-       security_ops->xfrm_state_free_security(x);
+       call_void_hook(xfrm_state_free_security, x);
 }
 
 int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
 {
-       return security_ops->xfrm_policy_lookup(ctx, fl_secid, dir);
+       return call_int_hook(xfrm_policy_lookup, 0, ctx, fl_secid, dir);
 }
 
 int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
                                       struct xfrm_policy *xp,
                                       const struct flowi *fl)
 {
-       return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
+       struct security_hook_list *hp;
+       int rc = 1;
+
+       /*
+        * Since this function is expected to return 0 or 1, the judgment
+        * becomes difficult if multiple LSMs supply this call. Fortunately,
+        * we can use the first LSM's judgment because currently only SELinux
+        * supplies this call.
+        *
+        * For speed optimization, we explicitly break the loop rather than
+        * using the macro
+        */
+       list_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match,
+                               list) {
+               rc = hp->hook.xfrm_state_pol_flow_match(x, xp, fl);
+               break;
+       }
+       return rc;
 }
 
 int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
 {
-       return security_ops->xfrm_decode_session(skb, secid, 1);
+       return call_int_hook(xfrm_decode_session, 0, skb, secid, 1);
 }
 
 void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
 {
-       int rc = security_ops->xfrm_decode_session(skb, &fl->flowi_secid, 0);
+       int rc = call_int_hook(xfrm_decode_session, 0, skb, &fl->flowi_secid,
+                               0);
 
        BUG_ON(rc);
 }
@@ -1445,23 +1495,24 @@ EXPORT_SYMBOL(security_skb_classify_flow);
 int security_key_alloc(struct key *key, const struct cred *cred,
                       unsigned long flags)
 {
-       return security_ops->key_alloc(key, cred, flags);
+       return call_int_hook(key_alloc, 0, key, cred, flags);
 }
 
 void security_key_free(struct key *key)
 {
-       security_ops->key_free(key);
+       call_void_hook(key_free, key);
 }
 
 int security_key_permission(key_ref_t key_ref,
                            const struct cred *cred, unsigned perm)
 {
-       return security_ops->key_permission(key_ref, cred, perm);
+       return call_int_hook(key_permission, 0, key_ref, cred, perm);
 }
 
 int security_key_getsecurity(struct key *key, char **_buffer)
 {
-       return security_ops->key_getsecurity(key, _buffer);
+       *_buffer = NULL;
+       return call_int_hook(key_getsecurity, 0, key, _buffer);
 }
 
 #endif /* CONFIG_KEYS */
@@ -1470,23 +1521,369 @@ int security_key_getsecurity(struct key *key, char **_buffer)
 
 int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
 {
-       return security_ops->audit_rule_init(field, op, rulestr, lsmrule);
+       return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule);
 }
 
 int security_audit_rule_known(struct audit_krule *krule)
 {
-       return security_ops->audit_rule_known(krule);
+       return call_int_hook(audit_rule_known, 0, krule);
 }
 
 void security_audit_rule_free(void *lsmrule)
 {
-       security_ops->audit_rule_free(lsmrule);
+       call_void_hook(audit_rule_free, lsmrule);
 }
 
 int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
                              struct audit_context *actx)
 {
-       return security_ops->audit_rule_match(secid, field, op, lsmrule, actx);
+       return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule,
+                               actx);
 }
+#endif /* CONFIG_AUDIT */
 
+struct security_hook_heads security_hook_heads = {
+       .binder_set_context_mgr =
+               LIST_HEAD_INIT(security_hook_heads.binder_set_context_mgr),
+       .binder_transaction =
+               LIST_HEAD_INIT(security_hook_heads.binder_transaction),
+       .binder_transfer_binder =
+               LIST_HEAD_INIT(security_hook_heads.binder_transfer_binder),
+       .binder_transfer_file =
+               LIST_HEAD_INIT(security_hook_heads.binder_transfer_file),
+
+       .ptrace_access_check =
+               LIST_HEAD_INIT(security_hook_heads.ptrace_access_check),
+       .ptrace_traceme =
+               LIST_HEAD_INIT(security_hook_heads.ptrace_traceme),
+       .capget =       LIST_HEAD_INIT(security_hook_heads.capget),
+       .capset =       LIST_HEAD_INIT(security_hook_heads.capset),
+       .capable =      LIST_HEAD_INIT(security_hook_heads.capable),
+       .quotactl =     LIST_HEAD_INIT(security_hook_heads.quotactl),
+       .quota_on =     LIST_HEAD_INIT(security_hook_heads.quota_on),
+       .syslog =       LIST_HEAD_INIT(security_hook_heads.syslog),
+       .settime =      LIST_HEAD_INIT(security_hook_heads.settime),
+       .vm_enough_memory =
+               LIST_HEAD_INIT(security_hook_heads.vm_enough_memory),
+       .bprm_set_creds =
+               LIST_HEAD_INIT(security_hook_heads.bprm_set_creds),
+       .bprm_check_security =
+               LIST_HEAD_INIT(security_hook_heads.bprm_check_security),
+       .bprm_secureexec =
+               LIST_HEAD_INIT(security_hook_heads.bprm_secureexec),
+       .bprm_committing_creds =
+               LIST_HEAD_INIT(security_hook_heads.bprm_committing_creds),
+       .bprm_committed_creds =
+               LIST_HEAD_INIT(security_hook_heads.bprm_committed_creds),
+       .sb_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.sb_alloc_security),
+       .sb_free_security =
+               LIST_HEAD_INIT(security_hook_heads.sb_free_security),
+       .sb_copy_data = LIST_HEAD_INIT(security_hook_heads.sb_copy_data),
+       .sb_remount =   LIST_HEAD_INIT(security_hook_heads.sb_remount),
+       .sb_kern_mount =
+               LIST_HEAD_INIT(security_hook_heads.sb_kern_mount),
+       .sb_show_options =
+               LIST_HEAD_INIT(security_hook_heads.sb_show_options),
+       .sb_statfs =    LIST_HEAD_INIT(security_hook_heads.sb_statfs),
+       .sb_mount =     LIST_HEAD_INIT(security_hook_heads.sb_mount),
+       .sb_umount =    LIST_HEAD_INIT(security_hook_heads.sb_umount),
+       .sb_pivotroot = LIST_HEAD_INIT(security_hook_heads.sb_pivotroot),
+       .sb_set_mnt_opts =
+               LIST_HEAD_INIT(security_hook_heads.sb_set_mnt_opts),
+       .sb_clone_mnt_opts =
+               LIST_HEAD_INIT(security_hook_heads.sb_clone_mnt_opts),
+       .sb_parse_opts_str =
+               LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str),
+       .dentry_init_security =
+               LIST_HEAD_INIT(security_hook_heads.dentry_init_security),
+#ifdef CONFIG_SECURITY_PATH
+       .path_unlink =  LIST_HEAD_INIT(security_hook_heads.path_unlink),
+       .path_mkdir =   LIST_HEAD_INIT(security_hook_heads.path_mkdir),
+       .path_rmdir =   LIST_HEAD_INIT(security_hook_heads.path_rmdir),
+       .path_mknod =   LIST_HEAD_INIT(security_hook_heads.path_mknod),
+       .path_truncate =
+               LIST_HEAD_INIT(security_hook_heads.path_truncate),
+       .path_symlink = LIST_HEAD_INIT(security_hook_heads.path_symlink),
+       .path_link =    LIST_HEAD_INIT(security_hook_heads.path_link),
+       .path_rename =  LIST_HEAD_INIT(security_hook_heads.path_rename),
+       .path_chmod =   LIST_HEAD_INIT(security_hook_heads.path_chmod),
+       .path_chown =   LIST_HEAD_INIT(security_hook_heads.path_chown),
+       .path_chroot =  LIST_HEAD_INIT(security_hook_heads.path_chroot),
+#endif
+       .inode_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.inode_alloc_security),
+       .inode_free_security =
+               LIST_HEAD_INIT(security_hook_heads.inode_free_security),
+       .inode_init_security =
+               LIST_HEAD_INIT(security_hook_heads.inode_init_security),
+       .inode_create = LIST_HEAD_INIT(security_hook_heads.inode_create),
+       .inode_link =   LIST_HEAD_INIT(security_hook_heads.inode_link),
+       .inode_unlink = LIST_HEAD_INIT(security_hook_heads.inode_unlink),
+       .inode_symlink =
+               LIST_HEAD_INIT(security_hook_heads.inode_symlink),
+       .inode_mkdir =  LIST_HEAD_INIT(security_hook_heads.inode_mkdir),
+       .inode_rmdir =  LIST_HEAD_INIT(security_hook_heads.inode_rmdir),
+       .inode_mknod =  LIST_HEAD_INIT(security_hook_heads.inode_mknod),
+       .inode_rename = LIST_HEAD_INIT(security_hook_heads.inode_rename),
+       .inode_readlink =
+               LIST_HEAD_INIT(security_hook_heads.inode_readlink),
+       .inode_follow_link =
+               LIST_HEAD_INIT(security_hook_heads.inode_follow_link),
+       .inode_permission =
+               LIST_HEAD_INIT(security_hook_heads.inode_permission),
+       .inode_setattr =
+               LIST_HEAD_INIT(security_hook_heads.inode_setattr),
+       .inode_getattr =
+               LIST_HEAD_INIT(security_hook_heads.inode_getattr),
+       .inode_setxattr =
+               LIST_HEAD_INIT(security_hook_heads.inode_setxattr),
+       .inode_post_setxattr =
+               LIST_HEAD_INIT(security_hook_heads.inode_post_setxattr),
+       .inode_getxattr =
+               LIST_HEAD_INIT(security_hook_heads.inode_getxattr),
+       .inode_listxattr =
+               LIST_HEAD_INIT(security_hook_heads.inode_listxattr),
+       .inode_removexattr =
+               LIST_HEAD_INIT(security_hook_heads.inode_removexattr),
+       .inode_need_killpriv =
+               LIST_HEAD_INIT(security_hook_heads.inode_need_killpriv),
+       .inode_killpriv =
+               LIST_HEAD_INIT(security_hook_heads.inode_killpriv),
+       .inode_getsecurity =
+               LIST_HEAD_INIT(security_hook_heads.inode_getsecurity),
+       .inode_setsecurity =
+               LIST_HEAD_INIT(security_hook_heads.inode_setsecurity),
+       .inode_listsecurity =
+               LIST_HEAD_INIT(security_hook_heads.inode_listsecurity),
+       .inode_getsecid =
+               LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
+       .file_permission =
+               LIST_HEAD_INIT(security_hook_heads.file_permission),
+       .file_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.file_alloc_security),
+       .file_free_security =
+               LIST_HEAD_INIT(security_hook_heads.file_free_security),
+       .file_ioctl =   LIST_HEAD_INIT(security_hook_heads.file_ioctl),
+       .mmap_addr =    LIST_HEAD_INIT(security_hook_heads.mmap_addr),
+       .mmap_file =    LIST_HEAD_INIT(security_hook_heads.mmap_file),
+       .file_mprotect =
+               LIST_HEAD_INIT(security_hook_heads.file_mprotect),
+       .file_lock =    LIST_HEAD_INIT(security_hook_heads.file_lock),
+       .file_fcntl =   LIST_HEAD_INIT(security_hook_heads.file_fcntl),
+       .file_set_fowner =
+               LIST_HEAD_INIT(security_hook_heads.file_set_fowner),
+       .file_send_sigiotask =
+               LIST_HEAD_INIT(security_hook_heads.file_send_sigiotask),
+       .file_receive = LIST_HEAD_INIT(security_hook_heads.file_receive),
+       .file_open =    LIST_HEAD_INIT(security_hook_heads.file_open),
+       .task_create =  LIST_HEAD_INIT(security_hook_heads.task_create),
+       .task_free =    LIST_HEAD_INIT(security_hook_heads.task_free),
+       .cred_alloc_blank =
+               LIST_HEAD_INIT(security_hook_heads.cred_alloc_blank),
+       .cred_free =    LIST_HEAD_INIT(security_hook_heads.cred_free),
+       .cred_prepare = LIST_HEAD_INIT(security_hook_heads.cred_prepare),
+       .cred_transfer =
+               LIST_HEAD_INIT(security_hook_heads.cred_transfer),
+       .kernel_act_as =
+               LIST_HEAD_INIT(security_hook_heads.kernel_act_as),
+       .kernel_create_files_as =
+               LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as),
+       .kernel_fw_from_file =
+               LIST_HEAD_INIT(security_hook_heads.kernel_fw_from_file),
+       .kernel_module_request =
+               LIST_HEAD_INIT(security_hook_heads.kernel_module_request),
+       .kernel_module_from_file =
+               LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file),
+       .task_fix_setuid =
+               LIST_HEAD_INIT(security_hook_heads.task_fix_setuid),
+       .task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid),
+       .task_getpgid = LIST_HEAD_INIT(security_hook_heads.task_getpgid),
+       .task_getsid =  LIST_HEAD_INIT(security_hook_heads.task_getsid),
+       .task_getsecid =
+               LIST_HEAD_INIT(security_hook_heads.task_getsecid),
+       .task_setnice = LIST_HEAD_INIT(security_hook_heads.task_setnice),
+       .task_setioprio =
+               LIST_HEAD_INIT(security_hook_heads.task_setioprio),
+       .task_getioprio =
+               LIST_HEAD_INIT(security_hook_heads.task_getioprio),
+       .task_setrlimit =
+               LIST_HEAD_INIT(security_hook_heads.task_setrlimit),
+       .task_setscheduler =
+               LIST_HEAD_INIT(security_hook_heads.task_setscheduler),
+       .task_getscheduler =
+               LIST_HEAD_INIT(security_hook_heads.task_getscheduler),
+       .task_movememory =
+               LIST_HEAD_INIT(security_hook_heads.task_movememory),
+       .task_kill =    LIST_HEAD_INIT(security_hook_heads.task_kill),
+       .task_wait =    LIST_HEAD_INIT(security_hook_heads.task_wait),
+       .task_prctl =   LIST_HEAD_INIT(security_hook_heads.task_prctl),
+       .task_to_inode =
+               LIST_HEAD_INIT(security_hook_heads.task_to_inode),
+       .ipc_permission =
+               LIST_HEAD_INIT(security_hook_heads.ipc_permission),
+       .ipc_getsecid = LIST_HEAD_INIT(security_hook_heads.ipc_getsecid),
+       .msg_msg_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.msg_msg_alloc_security),
+       .msg_msg_free_security =
+               LIST_HEAD_INIT(security_hook_heads.msg_msg_free_security),
+       .msg_queue_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.msg_queue_alloc_security),
+       .msg_queue_free_security =
+               LIST_HEAD_INIT(security_hook_heads.msg_queue_free_security),
+       .msg_queue_associate =
+               LIST_HEAD_INIT(security_hook_heads.msg_queue_associate),
+       .msg_queue_msgctl =
+               LIST_HEAD_INIT(security_hook_heads.msg_queue_msgctl),
+       .msg_queue_msgsnd =
+               LIST_HEAD_INIT(security_hook_heads.msg_queue_msgsnd),
+       .msg_queue_msgrcv =
+               LIST_HEAD_INIT(security_hook_heads.msg_queue_msgrcv),
+       .shm_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.shm_alloc_security),
+       .shm_free_security =
+               LIST_HEAD_INIT(security_hook_heads.shm_free_security),
+       .shm_associate =
+               LIST_HEAD_INIT(security_hook_heads.shm_associate),
+       .shm_shmctl =   LIST_HEAD_INIT(security_hook_heads.shm_shmctl),
+       .shm_shmat =    LIST_HEAD_INIT(security_hook_heads.shm_shmat),
+       .sem_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.sem_alloc_security),
+       .sem_free_security =
+               LIST_HEAD_INIT(security_hook_heads.sem_free_security),
+       .sem_associate =
+               LIST_HEAD_INIT(security_hook_heads.sem_associate),
+       .sem_semctl =   LIST_HEAD_INIT(security_hook_heads.sem_semctl),
+       .sem_semop =    LIST_HEAD_INIT(security_hook_heads.sem_semop),
+       .netlink_send = LIST_HEAD_INIT(security_hook_heads.netlink_send),
+       .d_instantiate =
+               LIST_HEAD_INIT(security_hook_heads.d_instantiate),
+       .getprocattr =  LIST_HEAD_INIT(security_hook_heads.getprocattr),
+       .setprocattr =  LIST_HEAD_INIT(security_hook_heads.setprocattr),
+       .ismaclabel =   LIST_HEAD_INIT(security_hook_heads.ismaclabel),
+       .secid_to_secctx =
+               LIST_HEAD_INIT(security_hook_heads.secid_to_secctx),
+       .secctx_to_secid =
+               LIST_HEAD_INIT(security_hook_heads.secctx_to_secid),
+       .release_secctx =
+               LIST_HEAD_INIT(security_hook_heads.release_secctx),
+       .inode_notifysecctx =
+               LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx),
+       .inode_setsecctx =
+               LIST_HEAD_INIT(security_hook_heads.inode_setsecctx),
+       .inode_getsecctx =
+               LIST_HEAD_INIT(security_hook_heads.inode_getsecctx),
+#ifdef CONFIG_SECURITY_NETWORK
+       .unix_stream_connect =
+               LIST_HEAD_INIT(security_hook_heads.unix_stream_connect),
+       .unix_may_send =
+               LIST_HEAD_INIT(security_hook_heads.unix_may_send),
+       .socket_create =
+               LIST_HEAD_INIT(security_hook_heads.socket_create),
+       .socket_post_create =
+               LIST_HEAD_INIT(security_hook_heads.socket_post_create),
+       .socket_bind =  LIST_HEAD_INIT(security_hook_heads.socket_bind),
+       .socket_connect =
+               LIST_HEAD_INIT(security_hook_heads.socket_connect),
+       .socket_listen =
+               LIST_HEAD_INIT(security_hook_heads.socket_listen),
+       .socket_accept =
+               LIST_HEAD_INIT(security_hook_heads.socket_accept),
+       .socket_sendmsg =
+               LIST_HEAD_INIT(security_hook_heads.socket_sendmsg),
+       .socket_recvmsg =
+               LIST_HEAD_INIT(security_hook_heads.socket_recvmsg),
+       .socket_getsockname =
+               LIST_HEAD_INIT(security_hook_heads.socket_getsockname),
+       .socket_getpeername =
+               LIST_HEAD_INIT(security_hook_heads.socket_getpeername),
+       .socket_getsockopt =
+               LIST_HEAD_INIT(security_hook_heads.socket_getsockopt),
+       .socket_setsockopt =
+               LIST_HEAD_INIT(security_hook_heads.socket_setsockopt),
+       .socket_shutdown =
+               LIST_HEAD_INIT(security_hook_heads.socket_shutdown),
+       .socket_sock_rcv_skb =
+               LIST_HEAD_INIT(security_hook_heads.socket_sock_rcv_skb),
+       .socket_getpeersec_stream =
+               LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_stream),
+       .socket_getpeersec_dgram =
+               LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_dgram),
+       .sk_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.sk_alloc_security),
+       .sk_free_security =
+               LIST_HEAD_INIT(security_hook_heads.sk_free_security),
+       .sk_clone_security =
+               LIST_HEAD_INIT(security_hook_heads.sk_clone_security),
+       .sk_getsecid =  LIST_HEAD_INIT(security_hook_heads.sk_getsecid),
+       .sock_graft =   LIST_HEAD_INIT(security_hook_heads.sock_graft),
+       .inet_conn_request =
+               LIST_HEAD_INIT(security_hook_heads.inet_conn_request),
+       .inet_csk_clone =
+               LIST_HEAD_INIT(security_hook_heads.inet_csk_clone),
+       .inet_conn_established =
+               LIST_HEAD_INIT(security_hook_heads.inet_conn_established),
+       .secmark_relabel_packet =
+               LIST_HEAD_INIT(security_hook_heads.secmark_relabel_packet),
+       .secmark_refcount_inc =
+               LIST_HEAD_INIT(security_hook_heads.secmark_refcount_inc),
+       .secmark_refcount_dec =
+               LIST_HEAD_INIT(security_hook_heads.secmark_refcount_dec),
+       .req_classify_flow =
+               LIST_HEAD_INIT(security_hook_heads.req_classify_flow),
+       .tun_dev_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.tun_dev_alloc_security),
+       .tun_dev_free_security =
+               LIST_HEAD_INIT(security_hook_heads.tun_dev_free_security),
+       .tun_dev_create =
+               LIST_HEAD_INIT(security_hook_heads.tun_dev_create),
+       .tun_dev_attach_queue =
+               LIST_HEAD_INIT(security_hook_heads.tun_dev_attach_queue),
+       .tun_dev_attach =
+               LIST_HEAD_INIT(security_hook_heads.tun_dev_attach),
+       .tun_dev_open = LIST_HEAD_INIT(security_hook_heads.tun_dev_open),
+       .skb_owned_by = LIST_HEAD_INIT(security_hook_heads.skb_owned_by),
+#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+       .xfrm_policy_alloc_security =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_alloc_security),
+       .xfrm_policy_clone_security =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_clone_security),
+       .xfrm_policy_free_security =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_free_security),
+       .xfrm_policy_delete_security =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_delete_security),
+       .xfrm_state_alloc =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc),
+       .xfrm_state_alloc_acquire =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc_acquire),
+       .xfrm_state_free_security =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_state_free_security),
+       .xfrm_state_delete_security =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_state_delete_security),
+       .xfrm_policy_lookup =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_lookup),
+       .xfrm_state_pol_flow_match =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_state_pol_flow_match),
+       .xfrm_decode_session =
+               LIST_HEAD_INIT(security_hook_heads.xfrm_decode_session),
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+#ifdef CONFIG_KEYS
+       .key_alloc =    LIST_HEAD_INIT(security_hook_heads.key_alloc),
+       .key_free =     LIST_HEAD_INIT(security_hook_heads.key_free),
+       .key_permission =
+               LIST_HEAD_INIT(security_hook_heads.key_permission),
+       .key_getsecurity =
+               LIST_HEAD_INIT(security_hook_heads.key_getsecurity),
+#endif /* CONFIG_KEYS */
+#ifdef CONFIG_AUDIT
+       .audit_rule_init =
+               LIST_HEAD_INIT(security_hook_heads.audit_rule_init),
+       .audit_rule_known =
+               LIST_HEAD_INIT(security_hook_heads.audit_rule_known),
+       .audit_rule_match =
+               LIST_HEAD_INIT(security_hook_heads.audit_rule_match),
+       .audit_rule_free =
+               LIST_HEAD_INIT(security_hook_heads.audit_rule_free),
 #endif /* CONFIG_AUDIT */
+};
index ffa5a64..6231081 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/tracehook.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/security.h>
+#include <linux/lsm_hooks.h>
 #include <linux/xattr.h>
 #include <linux/capability.h>
 #include <linux/unistd.h>
@@ -403,6 +403,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
        return sbsec->behavior == SECURITY_FS_USE_XATTR ||
                sbsec->behavior == SECURITY_FS_USE_TRANS ||
                sbsec->behavior == SECURITY_FS_USE_TASK ||
+               sbsec->behavior == SECURITY_FS_USE_NATIVE ||
                /* Special handling. Genfs but also in-core setxattr handler */
                !strcmp(sb->s_type->name, "sysfs") ||
                !strcmp(sb->s_type->name, "pstore") ||
@@ -724,7 +725,12 @@ static int selinux_set_mnt_opts(struct super_block *sb,
        }
 
        if (strcmp(sb->s_type->name, "proc") == 0)
-               sbsec->flags |= SE_SBPROC;
+               sbsec->flags |= SE_SBPROC | SE_SBGENFS;
+
+       if (!strcmp(sb->s_type->name, "debugfs") ||
+           !strcmp(sb->s_type->name, "sysfs") ||
+           !strcmp(sb->s_type->name, "pstore"))
+               sbsec->flags |= SE_SBGENFS;
 
        if (!sbsec->behavior) {
                /*
@@ -1188,8 +1194,6 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
                switch (protocol) {
                case NETLINK_ROUTE:
                        return SECCLASS_NETLINK_ROUTE_SOCKET;
-               case NETLINK_FIREWALL:
-                       return SECCLASS_NETLINK_FIREWALL_SOCKET;
                case NETLINK_SOCK_DIAG:
                        return SECCLASS_NETLINK_TCPDIAG_SOCKET;
                case NETLINK_NFLOG:
@@ -1198,14 +1202,28 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
                        return SECCLASS_NETLINK_XFRM_SOCKET;
                case NETLINK_SELINUX:
                        return SECCLASS_NETLINK_SELINUX_SOCKET;
+               case NETLINK_ISCSI:
+                       return SECCLASS_NETLINK_ISCSI_SOCKET;
                case NETLINK_AUDIT:
                        return SECCLASS_NETLINK_AUDIT_SOCKET;
-               case NETLINK_IP6_FW:
-                       return SECCLASS_NETLINK_IP6FW_SOCKET;
+               case NETLINK_FIB_LOOKUP:
+                       return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
+               case NETLINK_CONNECTOR:
+                       return SECCLASS_NETLINK_CONNECTOR_SOCKET;
+               case NETLINK_NETFILTER:
+                       return SECCLASS_NETLINK_NETFILTER_SOCKET;
                case NETLINK_DNRTMSG:
                        return SECCLASS_NETLINK_DNRT_SOCKET;
                case NETLINK_KOBJECT_UEVENT:
                        return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
+               case NETLINK_GENERIC:
+                       return SECCLASS_NETLINK_GENERIC_SOCKET;
+               case NETLINK_SCSITRANSPORT:
+                       return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
+               case NETLINK_RDMA:
+                       return SECCLASS_NETLINK_RDMA_SOCKET;
+               case NETLINK_CRYPTO:
+                       return SECCLASS_NETLINK_CRYPTO_SOCKET;
                default:
                        return SECCLASS_NETLINK_SOCKET;
                }
@@ -1220,12 +1238,13 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
        return SECCLASS_SOCKET;
 }
 
-#ifdef CONFIG_PROC_FS
-static int selinux_proc_get_sid(struct dentry *dentry,
-                               u16 tclass,
-                               u32 *sid)
+static int selinux_genfs_get_sid(struct dentry *dentry,
+                                u16 tclass,
+                                u16 flags,
+                                u32 *sid)
 {
        int rc;
+       struct super_block *sb = dentry->d_inode->i_sb;
        char *buffer, *path;
 
        buffer = (char *)__get_free_page(GFP_KERNEL);
@@ -1236,26 +1255,20 @@ static int selinux_proc_get_sid(struct dentry *dentry,
        if (IS_ERR(path))
                rc = PTR_ERR(path);
        else {
-               /* each process gets a /proc/PID/ entry. Strip off the
-                * PID part to get a valid selinux labeling.
-                * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
-               while (path[1] >= '0' && path[1] <= '9') {
-                       path[1] = '/';
-                       path++;
+               if (flags & SE_SBPROC) {
+                       /* each process gets a /proc/PID/ entry. Strip off the
+                        * PID part to get a valid selinux labeling.
+                        * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
+                       while (path[1] >= '0' && path[1] <= '9') {
+                               path[1] = '/';
+                               path++;
+                       }
                }
-               rc = security_genfs_sid("proc", path, tclass, sid);
+               rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
        }
        free_page((unsigned long)buffer);
        return rc;
 }
-#else
-static int selinux_proc_get_sid(struct dentry *dentry,
-                               u16 tclass,
-                               u32 *sid)
-{
-       return -EINVAL;
-}
-#endif
 
 /* The inode's security attributes must be initialized before first use. */
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
@@ -1412,7 +1425,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                /* Default to the fs superblock SID. */
                isec->sid = sbsec->sid;
 
-               if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
+               if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
                        /* We must have a dentry to determine the label on
                         * procfs inodes */
                        if (opt_dentry)
@@ -1435,7 +1448,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                        if (!dentry)
                                goto out_unlock;
                        isec->sclass = inode_mode_to_security_class(inode->i_mode);
-                       rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
+                       rc = selinux_genfs_get_sid(dentry, isec->sclass,
+                                                  sbsec->flags, &sid);
                        dput(dentry);
                        if (rc)
                                goto out_unlock;
@@ -1990,12 +2004,6 @@ static int selinux_binder_transfer_file(struct task_struct *from,
 static int selinux_ptrace_access_check(struct task_struct *child,
                                     unsigned int mode)
 {
-       int rc;
-
-       rc = cap_ptrace_access_check(child, mode);
-       if (rc)
-               return rc;
-
        if (mode & PTRACE_MODE_READ) {
                u32 sid = current_sid();
                u32 csid = task_sid(child);
@@ -2007,25 +2015,13 @@ static int selinux_ptrace_access_check(struct task_struct *child,
 
 static int selinux_ptrace_traceme(struct task_struct *parent)
 {
-       int rc;
-
-       rc = cap_ptrace_traceme(parent);
-       if (rc)
-               return rc;
-
        return task_has_perm(parent, current, PROCESS__PTRACE);
 }
 
 static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
                          kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
-       int error;
-
-       error = current_has_perm(target, PROCESS__GETCAP);
-       if (error)
-               return error;
-
-       return cap_capget(target, effective, inheritable, permitted);
+       return current_has_perm(target, PROCESS__GETCAP);
 }
 
 static int selinux_capset(struct cred *new, const struct cred *old,
@@ -2033,13 +2029,6 @@ static int selinux_capset(struct cred *new, const struct cred *old,
                          const kernel_cap_t *inheritable,
                          const kernel_cap_t *permitted)
 {
-       int error;
-
-       error = cap_capset(new, old,
-                                     effective, inheritable, permitted);
-       if (error)
-               return error;
-
        return cred_has_perm(old, new, PROCESS__SETCAP);
 }
 
@@ -2056,12 +2045,6 @@ static int selinux_capset(struct cred *new, const struct cred *old,
 static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
                           int cap, int audit)
 {
-       int rc;
-
-       rc = cap_capable(cred, ns, cap, audit);
-       if (rc)
-               return rc;
-
        return cred_has_capability(cred, cap, audit);
 }
 
@@ -2139,12 +2122,12 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
 {
        int rc, cap_sys_admin = 0;
 
-       rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
-                            SECURITY_CAP_NOAUDIT);
+       rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
+                                       SECURITY_CAP_NOAUDIT);
        if (rc == 0)
                cap_sys_admin = 1;
 
-       return __vm_enough_memory(mm, pages, cap_sys_admin);
+       return cap_sys_admin;
 }
 
 /* binprm security operations */
@@ -2193,10 +2176,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
        struct inode *inode = file_inode(bprm->file);
        int rc;
 
-       rc = cap_bprm_set_creds(bprm);
-       if (rc)
-               return rc;
-
        /* SELinux context only depends on initial program or script and not
         * the script interpreter */
        if (bprm->cred_prepared)
@@ -2320,7 +2299,7 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
                                        PROCESS__NOATSECURE, NULL);
        }
 
-       return (atsecure || cap_bprm_secureexec(bprm));
+       return !!atsecure;
 }
 
 static int match_file(const void *p, struct file *file, unsigned fd)
@@ -2451,10 +2430,12 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
                for (i = 0; i < 3; i++)
                        do_setitimer(i, &itimer, NULL);
                spin_lock_irq(&current->sighand->siglock);
-               if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
-                       __flush_signals(current);
+               if (!fatal_signal_pending(current)) {
+                       flush_sigqueue(&current->pending);
+                       flush_sigqueue(&current->signal->shared_pending);
                        flush_signal_handlers(current, 1);
                        sigemptyset(&current->blocked);
+                       recalc_sigpending();
                }
                spin_unlock_irq(&current->sighand->siglock);
        }
@@ -3144,8 +3125,11 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
         * and lack of permission just means that we fall back to the
         * in-core context value, not a denial.
         */
-       error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
-                               SECURITY_CAP_NOAUDIT);
+       error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
+                           SECURITY_CAP_NOAUDIT);
+       if (!error)
+               error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
+                                           SECURITY_CAP_NOAUDIT);
        if (!error)
                error = security_sid_to_context_force(isec->sid, &context,
                                                      &size);
@@ -3330,12 +3314,7 @@ error:
 
 static int selinux_mmap_addr(unsigned long addr)
 {
-       int rc;
-
-       /* do DAC check on address space usage */
-       rc = cap_mmap_addr(addr);
-       if (rc)
-               return rc;
+       int rc = 0;
 
        if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
                u32 sid = current_sid();
@@ -3651,23 +3630,11 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
 
 static int selinux_task_setnice(struct task_struct *p, int nice)
 {
-       int rc;
-
-       rc = cap_task_setnice(p, nice);
-       if (rc)
-               return rc;
-
        return current_has_perm(p, PROCESS__SETSCHED);
 }
 
 static int selinux_task_setioprio(struct task_struct *p, int ioprio)
 {
-       int rc;
-
-       rc = cap_task_setioprio(p, ioprio);
-       if (rc)
-               return rc;
-
        return current_has_perm(p, PROCESS__SETSCHED);
 }
 
@@ -3693,12 +3660,6 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
 
 static int selinux_task_setscheduler(struct task_struct *p)
 {
-       int rc;
-
-       rc = cap_task_setscheduler(p);
-       if (rc)
-               return rc;
-
        return current_has_perm(p, PROCESS__SETSCHED);
 }
 
@@ -4780,8 +4741,9 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
                if (err == -EINVAL) {
                        printk(KERN_WARNING
                               "SELinux: unrecognized netlink message:"
-                              " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
-                              sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
+                              " protocol=%hu nlmsg_type=%hu sclass=%s\n",
+                              sk->sk_protocol, nlh->nlmsg_type,
+                              secclass_map[sksec->sclass - 1].name);
                        if (!selinux_enforcing || security_get_allow_unknown())
                                err = 0;
                }
@@ -5109,12 +5071,6 @@ static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
 
 static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
-       int err;
-
-       err = cap_netlink_send(sk, skb);
-       if (err)
-               return err;
-
        return selinux_nlmsg_perm(sk, skb);
 }
 
@@ -5852,218 +5808,220 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
 
 #endif
 
-static struct security_operations selinux_ops = {
-       .name =                         "selinux",
-
-       .binder_set_context_mgr =       selinux_binder_set_context_mgr,
-       .binder_transaction =           selinux_binder_transaction,
-       .binder_transfer_binder =       selinux_binder_transfer_binder,
-       .binder_transfer_file =         selinux_binder_transfer_file,
-
-       .ptrace_access_check =          selinux_ptrace_access_check,
-       .ptrace_traceme =               selinux_ptrace_traceme,
-       .capget =                       selinux_capget,
-       .capset =                       selinux_capset,
-       .capable =                      selinux_capable,
-       .quotactl =                     selinux_quotactl,
-       .quota_on =                     selinux_quota_on,
-       .syslog =                       selinux_syslog,
-       .vm_enough_memory =             selinux_vm_enough_memory,
-
-       .netlink_send =                 selinux_netlink_send,
-
-       .bprm_set_creds =               selinux_bprm_set_creds,
-       .bprm_committing_creds =        selinux_bprm_committing_creds,
-       .bprm_committed_creds =         selinux_bprm_committed_creds,
-       .bprm_secureexec =              selinux_bprm_secureexec,
-
-       .sb_alloc_security =            selinux_sb_alloc_security,
-       .sb_free_security =             selinux_sb_free_security,
-       .sb_copy_data =                 selinux_sb_copy_data,
-       .sb_remount =                   selinux_sb_remount,
-       .sb_kern_mount =                selinux_sb_kern_mount,
-       .sb_show_options =              selinux_sb_show_options,
-       .sb_statfs =                    selinux_sb_statfs,
-       .sb_mount =                     selinux_mount,
-       .sb_umount =                    selinux_umount,
-       .sb_set_mnt_opts =              selinux_set_mnt_opts,
-       .sb_clone_mnt_opts =            selinux_sb_clone_mnt_opts,
-       .sb_parse_opts_str =            selinux_parse_opts_str,
-
-       .dentry_init_security =         selinux_dentry_init_security,
-
-       .inode_alloc_security =         selinux_inode_alloc_security,
-       .inode_free_security =          selinux_inode_free_security,
-       .inode_init_security =          selinux_inode_init_security,
-       .inode_create =                 selinux_inode_create,
-       .inode_link =                   selinux_inode_link,
-       .inode_unlink =                 selinux_inode_unlink,
-       .inode_symlink =                selinux_inode_symlink,
-       .inode_mkdir =                  selinux_inode_mkdir,
-       .inode_rmdir =                  selinux_inode_rmdir,
-       .inode_mknod =                  selinux_inode_mknod,
-       .inode_rename =                 selinux_inode_rename,
-       .inode_readlink =               selinux_inode_readlink,
-       .inode_follow_link =            selinux_inode_follow_link,
-       .inode_permission =             selinux_inode_permission,
-       .inode_setattr =                selinux_inode_setattr,
-       .inode_getattr =                selinux_inode_getattr,
-       .inode_setxattr =               selinux_inode_setxattr,
-       .inode_post_setxattr =          selinux_inode_post_setxattr,
-       .inode_getxattr =               selinux_inode_getxattr,
-       .inode_listxattr =              selinux_inode_listxattr,
-       .inode_removexattr =            selinux_inode_removexattr,
-       .inode_getsecurity =            selinux_inode_getsecurity,
-       .inode_setsecurity =            selinux_inode_setsecurity,
-       .inode_listsecurity =           selinux_inode_listsecurity,
-       .inode_getsecid =               selinux_inode_getsecid,
-
-       .file_permission =              selinux_file_permission,
-       .file_alloc_security =          selinux_file_alloc_security,
-       .file_free_security =           selinux_file_free_security,
-       .file_ioctl =                   selinux_file_ioctl,
-       .mmap_file =                    selinux_mmap_file,
-       .mmap_addr =                    selinux_mmap_addr,
-       .file_mprotect =                selinux_file_mprotect,
-       .file_lock =                    selinux_file_lock,
-       .file_fcntl =                   selinux_file_fcntl,
-       .file_set_fowner =              selinux_file_set_fowner,
-       .file_send_sigiotask =          selinux_file_send_sigiotask,
-       .file_receive =                 selinux_file_receive,
-
-       .file_open =                    selinux_file_open,
-
-       .task_create =                  selinux_task_create,
-       .cred_alloc_blank =             selinux_cred_alloc_blank,
-       .cred_free =                    selinux_cred_free,
-       .cred_prepare =                 selinux_cred_prepare,
-       .cred_transfer =                selinux_cred_transfer,
-       .kernel_act_as =                selinux_kernel_act_as,
-       .kernel_create_files_as =       selinux_kernel_create_files_as,
-       .kernel_module_request =        selinux_kernel_module_request,
-       .task_setpgid =                 selinux_task_setpgid,
-       .task_getpgid =                 selinux_task_getpgid,
-       .task_getsid =                  selinux_task_getsid,
-       .task_getsecid =                selinux_task_getsecid,
-       .task_setnice =                 selinux_task_setnice,
-       .task_setioprio =               selinux_task_setioprio,
-       .task_getioprio =               selinux_task_getioprio,
-       .task_setrlimit =               selinux_task_setrlimit,
-       .task_setscheduler =            selinux_task_setscheduler,
-       .task_getscheduler =            selinux_task_getscheduler,
-       .task_movememory =              selinux_task_movememory,
-       .task_kill =                    selinux_task_kill,
-       .task_wait =                    selinux_task_wait,
-       .task_to_inode =                selinux_task_to_inode,
-
-       .ipc_permission =               selinux_ipc_permission,
-       .ipc_getsecid =                 selinux_ipc_getsecid,
-
-       .msg_msg_alloc_security =       selinux_msg_msg_alloc_security,
-       .msg_msg_free_security =        selinux_msg_msg_free_security,
-
-       .msg_queue_alloc_security =     selinux_msg_queue_alloc_security,
-       .msg_queue_free_security =      selinux_msg_queue_free_security,
-       .msg_queue_associate =          selinux_msg_queue_associate,
-       .msg_queue_msgctl =             selinux_msg_queue_msgctl,
-       .msg_queue_msgsnd =             selinux_msg_queue_msgsnd,
-       .msg_queue_msgrcv =             selinux_msg_queue_msgrcv,
-
-       .shm_alloc_security =           selinux_shm_alloc_security,
-       .shm_free_security =            selinux_shm_free_security,
-       .shm_associate =                selinux_shm_associate,
-       .shm_shmctl =                   selinux_shm_shmctl,
-       .shm_shmat =                    selinux_shm_shmat,
-
-       .sem_alloc_security =           selinux_sem_alloc_security,
-       .sem_free_security =            selinux_sem_free_security,
-       .sem_associate =                selinux_sem_associate,
-       .sem_semctl =                   selinux_sem_semctl,
-       .sem_semop =                    selinux_sem_semop,
-
-       .d_instantiate =                selinux_d_instantiate,
-
-       .getprocattr =                  selinux_getprocattr,
-       .setprocattr =                  selinux_setprocattr,
-
-       .ismaclabel =                   selinux_ismaclabel,
-       .secid_to_secctx =              selinux_secid_to_secctx,
-       .secctx_to_secid =              selinux_secctx_to_secid,
-       .release_secctx =               selinux_release_secctx,
-       .inode_notifysecctx =           selinux_inode_notifysecctx,
-       .inode_setsecctx =              selinux_inode_setsecctx,
-       .inode_getsecctx =              selinux_inode_getsecctx,
-
-       .unix_stream_connect =          selinux_socket_unix_stream_connect,
-       .unix_may_send =                selinux_socket_unix_may_send,
-
-       .socket_create =                selinux_socket_create,
-       .socket_post_create =           selinux_socket_post_create,
-       .socket_bind =                  selinux_socket_bind,
-       .socket_connect =               selinux_socket_connect,
-       .socket_listen =                selinux_socket_listen,
-       .socket_accept =                selinux_socket_accept,
-       .socket_sendmsg =               selinux_socket_sendmsg,
-       .socket_recvmsg =               selinux_socket_recvmsg,
-       .socket_getsockname =           selinux_socket_getsockname,
-       .socket_getpeername =           selinux_socket_getpeername,
-       .socket_getsockopt =            selinux_socket_getsockopt,
-       .socket_setsockopt =            selinux_socket_setsockopt,
-       .socket_shutdown =              selinux_socket_shutdown,
-       .socket_sock_rcv_skb =          selinux_socket_sock_rcv_skb,
-       .socket_getpeersec_stream =     selinux_socket_getpeersec_stream,
-       .socket_getpeersec_dgram =      selinux_socket_getpeersec_dgram,
-       .sk_alloc_security =            selinux_sk_alloc_security,
-       .sk_free_security =             selinux_sk_free_security,
-       .sk_clone_security =            selinux_sk_clone_security,
-       .sk_getsecid =                  selinux_sk_getsecid,
-       .sock_graft =                   selinux_sock_graft,
-       .inet_conn_request =            selinux_inet_conn_request,
-       .inet_csk_clone =               selinux_inet_csk_clone,
-       .inet_conn_established =        selinux_inet_conn_established,
-       .secmark_relabel_packet =       selinux_secmark_relabel_packet,
-       .secmark_refcount_inc =         selinux_secmark_refcount_inc,
-       .secmark_refcount_dec =         selinux_secmark_refcount_dec,
-       .req_classify_flow =            selinux_req_classify_flow,
-       .tun_dev_alloc_security =       selinux_tun_dev_alloc_security,
-       .tun_dev_free_security =        selinux_tun_dev_free_security,
-       .tun_dev_create =               selinux_tun_dev_create,
-       .tun_dev_attach_queue =         selinux_tun_dev_attach_queue,
-       .tun_dev_attach =               selinux_tun_dev_attach,
-       .tun_dev_open =                 selinux_tun_dev_open,
+static struct security_hook_list selinux_hooks[] = {
+       LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
+       LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
+       LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
+       LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
+
+       LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
+       LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
+       LSM_HOOK_INIT(capget, selinux_capget),
+       LSM_HOOK_INIT(capset, selinux_capset),
+       LSM_HOOK_INIT(capable, selinux_capable),
+       LSM_HOOK_INIT(quotactl, selinux_quotactl),
+       LSM_HOOK_INIT(quota_on, selinux_quota_on),
+       LSM_HOOK_INIT(syslog, selinux_syslog),
+       LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
+
+       LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
+
+       LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
+       LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
+       LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
+       LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
+
+       LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
+       LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
+       LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
+       LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
+       LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
+       LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
+       LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
+       LSM_HOOK_INIT(sb_mount, selinux_mount),
+       LSM_HOOK_INIT(sb_umount, selinux_umount),
+       LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
+       LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
+       LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
+
+       LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
+
+       LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
+       LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
+       LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
+       LSM_HOOK_INIT(inode_create, selinux_inode_create),
+       LSM_HOOK_INIT(inode_link, selinux_inode_link),
+       LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
+       LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
+       LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
+       LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
+       LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
+       LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
+       LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
+       LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
+       LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
+       LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
+       LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
+       LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
+       LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
+       LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
+       LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
+       LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
+       LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
+       LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
+       LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
+       LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
+
+       LSM_HOOK_INIT(file_permission, selinux_file_permission),
+       LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
+       LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
+       LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
+       LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
+       LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
+       LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
+       LSM_HOOK_INIT(file_lock, selinux_file_lock),
+       LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
+       LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
+       LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
+       LSM_HOOK_INIT(file_receive, selinux_file_receive),
+
+       LSM_HOOK_INIT(file_open, selinux_file_open),
+
+       LSM_HOOK_INIT(task_create, selinux_task_create),
+       LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
+       LSM_HOOK_INIT(cred_free, selinux_cred_free),
+       LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
+       LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
+       LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
+       LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
+       LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
+       LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
+       LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
+       LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
+       LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
+       LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
+       LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
+       LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
+       LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
+       LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
+       LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
+       LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
+       LSM_HOOK_INIT(task_kill, selinux_task_kill),
+       LSM_HOOK_INIT(task_wait, selinux_task_wait),
+       LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
+
+       LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
+       LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
+
+       LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
+       LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
+
+       LSM_HOOK_INIT(msg_queue_alloc_security,
+                       selinux_msg_queue_alloc_security),
+       LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
+       LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
+       LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
+       LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
+       LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
+
+       LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
+       LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
+       LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
+       LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
+       LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
+
+       LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
+       LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
+       LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
+       LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
+       LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
+
+       LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
+
+       LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
+       LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
+
+       LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
+       LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
+       LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
+       LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
+       LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
+       LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
+       LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
+
+       LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
+       LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
+
+       LSM_HOOK_INIT(socket_create, selinux_socket_create),
+       LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
+       LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
+       LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
+       LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
+       LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
+       LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
+       LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
+       LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
+       LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
+       LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
+       LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
+       LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
+       LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
+       LSM_HOOK_INIT(socket_getpeersec_stream,
+                       selinux_socket_getpeersec_stream),
+       LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
+       LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
+       LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
+       LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
+       LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
+       LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
+       LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
+       LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
+       LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
+       LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
+       LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
+       LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
+       LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
+       LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
+       LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
+       LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
+       LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
+       LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
+       LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
-       .xfrm_policy_alloc_security =   selinux_xfrm_policy_alloc,
-       .xfrm_policy_clone_security =   selinux_xfrm_policy_clone,
-       .xfrm_policy_free_security =    selinux_xfrm_policy_free,
-       .xfrm_policy_delete_security =  selinux_xfrm_policy_delete,
-       .xfrm_state_alloc =             selinux_xfrm_state_alloc,
-       .xfrm_state_alloc_acquire =     selinux_xfrm_state_alloc_acquire,
-       .xfrm_state_free_security =     selinux_xfrm_state_free,
-       .xfrm_state_delete_security =   selinux_xfrm_state_delete,
-       .xfrm_policy_lookup =           selinux_xfrm_policy_lookup,
-       .xfrm_state_pol_flow_match =    selinux_xfrm_state_pol_flow_match,
-       .xfrm_decode_session =          selinux_xfrm_decode_session,
+       LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
+       LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
+       LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
+       LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
+       LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
+       LSM_HOOK_INIT(xfrm_state_alloc_acquire,
+                       selinux_xfrm_state_alloc_acquire),
+       LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
+       LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
+       LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
+       LSM_HOOK_INIT(xfrm_state_pol_flow_match,
+                       selinux_xfrm_state_pol_flow_match),
+       LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
 #endif
 
 #ifdef CONFIG_KEYS
-       .key_alloc =                    selinux_key_alloc,
-       .key_free =                     selinux_key_free,
-       .key_permission =               selinux_key_permission,
-       .key_getsecurity =              selinux_key_getsecurity,
+       LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
+       LSM_HOOK_INIT(key_free, selinux_key_free),
+       LSM_HOOK_INIT(key_permission, selinux_key_permission),
+       LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
 #endif
 
 #ifdef CONFIG_AUDIT
-       .audit_rule_init =              selinux_audit_rule_init,
-       .audit_rule_known =             selinux_audit_rule_known,
-       .audit_rule_match =             selinux_audit_rule_match,
-       .audit_rule_free =              selinux_audit_rule_free,
+       LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
+       LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
+       LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
+       LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
 #endif
 };
 
 static __init int selinux_init(void)
 {
-       if (!security_module_enable(&selinux_ops)) {
+       if (!security_module_enable("selinux")) {
                selinux_enabled = 0;
                return 0;
        }
@@ -6085,8 +6043,7 @@ static __init int selinux_init(void)
                                            0, SLAB_PANIC, NULL);
        avc_init();
 
-       if (register_security(&selinux_ops))
-               panic("SELinux: Unable to register with kernel.\n");
+       security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
 
        if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
                panic("SELinux: Unable to register AVC netcache callback\n");
@@ -6214,7 +6171,7 @@ int selinux_disable(void)
        selinux_disabled = 1;
        selinux_enabled = 0;
 
-       reset_security_ops();
+       security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
 
        /* Try to destroy the avc node cache */
        avc_disable();
index eccd61b..5a4eef5 100644 (file)
@@ -2,12 +2,12 @@
     "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append"
 
 #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
-    "rename", "execute", "swapon", "quotaon", "mounton", "audit_access", \
+    "rename", "execute", "quotaon", "mounton", "audit_access", \
     "open", "execmod"
 
 #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \
     "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom",  \
-    "sendto", "recv_msg", "send_msg", "name_bind"
+    "sendto", "name_bind"
 
 #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
            "write", "associate", "unix_read", "unix_write"
@@ -44,7 +44,7 @@ struct security_class_mapping secclass_map[] = {
            "audit_control", "setfcap", NULL } },
        { "filesystem",
          { "mount", "remount", "unmount", "getattr",
-           "relabelfrom", "relabelto", "transition", "associate", "quotamod",
+           "relabelfrom", "relabelto", "associate", "quotamod",
            "quotaget", NULL } },
        { "file",
          { COMMON_FILE_PERMS,
@@ -67,7 +67,7 @@ struct security_class_mapping secclass_map[] = {
          { COMMON_SOCK_PERMS, NULL } },
        { "tcp_socket",
          { COMMON_SOCK_PERMS,
-           "connectto", "newconn", "acceptfrom", "node_bind", "name_connect",
+           "node_bind", "name_connect",
            NULL } },
        { "udp_socket",
          { COMMON_SOCK_PERMS,
@@ -76,13 +76,9 @@ struct security_class_mapping secclass_map[] = {
          { COMMON_SOCK_PERMS,
            "node_bind", NULL } },
        { "node",
-         { "tcp_recv", "tcp_send", "udp_recv", "udp_send",
-           "rawip_recv", "rawip_send", "enforce_dest",
-           "dccp_recv", "dccp_send", "recvfrom", "sendto", NULL } },
+         { "recvfrom", "sendto", NULL } },
        { "netif",
-         {  "tcp_recv", "tcp_send", "udp_recv", "udp_send",
-            "rawip_recv", "rawip_send", "dccp_recv", "dccp_send",
-            "ingress", "egress", NULL } },
+         { "ingress", "egress", NULL } },
        { "netlink_socket",
          { COMMON_SOCK_PERMS, NULL } },
        { "packet_socket",
@@ -90,11 +86,9 @@ struct security_class_mapping secclass_map[] = {
        { "key_socket",
          { COMMON_SOCK_PERMS, NULL } },
        { "unix_stream_socket",
-         { COMMON_SOCK_PERMS, "connectto", "newconn", "acceptfrom", NULL
-         } },
+         { COMMON_SOCK_PERMS, "connectto", NULL } },
        { "unix_dgram_socket",
-         { COMMON_SOCK_PERMS, NULL
-         } },
+         { COMMON_SOCK_PERMS, NULL } },
        { "sem",
          { COMMON_IPC_PERMS, NULL } },
        { "msg", { "send", "receive", NULL } },
@@ -107,9 +101,6 @@ struct security_class_mapping secclass_map[] = {
        { "netlink_route_socket",
          { COMMON_SOCK_PERMS,
            "nlmsg_read", "nlmsg_write", NULL } },
-       { "netlink_firewall_socket",
-         { COMMON_SOCK_PERMS,
-           "nlmsg_read", "nlmsg_write", NULL } },
        { "netlink_tcpdiag_socket",
          { COMMON_SOCK_PERMS,
            "nlmsg_read", "nlmsg_write", NULL } },
@@ -120,19 +111,32 @@ struct security_class_mapping secclass_map[] = {
            "nlmsg_read", "nlmsg_write", NULL } },
        { "netlink_selinux_socket",
          { COMMON_SOCK_PERMS, NULL } },
+       { "netlink_iscsi_socket",
+         { COMMON_SOCK_PERMS, NULL } },
        { "netlink_audit_socket",
          { COMMON_SOCK_PERMS,
            "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv",
            "nlmsg_tty_audit", NULL } },
-       { "netlink_ip6fw_socket",
-         { COMMON_SOCK_PERMS,
-           "nlmsg_read", "nlmsg_write", NULL } },
+       { "netlink_fib_lookup_socket",
+         { COMMON_SOCK_PERMS, NULL } },
+       { "netlink_connector_socket",
+         { COMMON_SOCK_PERMS, NULL } },
+       { "netlink_netfilter_socket",
+         { COMMON_SOCK_PERMS, NULL } },
        { "netlink_dnrt_socket",
          { COMMON_SOCK_PERMS, NULL } },
        { "association",
          { "sendto", "recvfrom", "setcontext", "polmatch", NULL } },
        { "netlink_kobject_uevent_socket",
          { COMMON_SOCK_PERMS, NULL } },
+       { "netlink_generic_socket",
+         { COMMON_SOCK_PERMS, NULL } },
+       { "netlink_scsitransport_socket",
+         { COMMON_SOCK_PERMS, NULL } },
+       { "netlink_rdma_socket",
+         { COMMON_SOCK_PERMS, NULL } },
+       { "netlink_crypto_socket",
+         { COMMON_SOCK_PERMS, NULL } },
        { "appletalk_socket",
          { COMMON_SOCK_PERMS, NULL } },
        { "packet",
index d1e0b23..36993ad 100644 (file)
@@ -56,6 +56,7 @@
 /* Non-mount related flags */
 #define SE_SBINITIALIZED       0x0100
 #define SE_SBPROC              0x0200
+#define SE_SBGENFS             0x0400
 
 #define CONTEXT_STR    "context="
 #define FSCONTEXT_STR  "fscontext="
index 49eada6..244e035 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/capability.h>
 #include <linux/spinlock.h>
-#include <linux/security.h>
+#include <linux/lsm_hooks.h>
 #include <linux/in.h>
 #include <net/netlabel.h>
 #include <linux/list.h>
@@ -138,6 +138,11 @@ struct smk_port_label {
        struct smack_known      *smk_out;       /* outgoing label */
 };
 
+struct smack_onlycap {
+       struct list_head        list;
+       struct smack_known      *smk_label;
+};
+
 /*
  * Mount options
  */
@@ -249,6 +254,7 @@ int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
 struct smack_known *smk_import_entry(const char *, int);
 void smk_insert_entry(struct smack_known *skp);
 struct smack_known *smk_find_entry(const char *);
+int smack_privileged(int cap);
 
 /*
  * Shared data.
@@ -257,7 +263,6 @@ extern int smack_enabled;
 extern int smack_cipso_direct;
 extern int smack_cipso_mapped;
 extern struct smack_known *smack_net_ambient;
-extern struct smack_known *smack_onlycap;
 extern struct smack_known *smack_syslog_label;
 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
 extern struct smack_known *smack_unconfined;
@@ -276,7 +281,8 @@ extern struct mutex smack_known_lock;
 extern struct list_head smack_known_list;
 extern struct list_head smk_netlbladdr_list;
 
-extern struct security_operations smack_ops;
+extern struct mutex     smack_onlycap_lock;
+extern struct list_head smack_onlycap_list;
 
 #define SMACK_HASH_SLOTS 16
 extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
@@ -334,21 +340,6 @@ static inline struct smack_known *smk_of_current(void)
 }
 
 /*
- * Is the task privileged and allowed to be privileged
- * by the onlycap rule.
- */
-static inline int smack_privileged(int cap)
-{
-       struct smack_known *skp = smk_of_current();
-
-       if (!capable(cap))
-               return 0;
-       if (smack_onlycap == NULL || smack_onlycap == skp)
-               return 1;
-       return 0;
-}
-
-/*
  * logging functions
  */
 #define SMACK_AUDIT_DENIED 0x1
index 0f410fc..00f6b38 100644 (file)
@@ -425,7 +425,7 @@ void smk_insert_entry(struct smack_known *skp)
  * @string: a text string that might be a Smack label
  *
  * Returns a pointer to the entry in the label list that
- * matches the passed string.
+ * matches the passed string or NULL if not found.
  */
 struct smack_known *smk_find_entry(const char *string)
 {
@@ -448,7 +448,7 @@ struct smack_known *smk_find_entry(const char *string)
  * @string: a text string that might contain a Smack label
  * @len: the maximum size, or zero if it is NULL terminated.
  *
- * Returns a pointer to the clean label, or NULL
+ * Returns a pointer to the clean label or an error code.
  */
 char *smk_parse_smack(const char *string, int len)
 {
@@ -464,7 +464,7 @@ char *smk_parse_smack(const char *string, int len)
         * including /smack/cipso and /smack/cipso2
         */
        if (string[0] == '-')
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        for (i = 0; i < len; i++)
                if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
@@ -472,11 +472,13 @@ char *smk_parse_smack(const char *string, int len)
                        break;
 
        if (i == 0 || i >= SMK_LONGLABEL)
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        smack = kzalloc(i + 1, GFP_KERNEL);
-       if (smack != NULL)
-               strncpy(smack, string, i);
+       if (smack == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       strncpy(smack, string, i);
 
        return smack;
 }
@@ -523,7 +525,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
  * @len: the maximum size, or zero if it is NULL terminated.
  *
  * Returns a pointer to the entry in the label list that
- * matches the passed string, adding it if necessary.
+ * matches the passed string, adding it if necessary,
+ * or an error code.
  */
 struct smack_known *smk_import_entry(const char *string, int len)
 {
@@ -533,8 +536,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
        int rc;
 
        smack = smk_parse_smack(string, len);
-       if (smack == NULL)
-               return NULL;
+       if (IS_ERR(smack))
+               return ERR_CAST(smack);
 
        mutex_lock(&smack_known_lock);
 
@@ -543,8 +546,10 @@ struct smack_known *smk_import_entry(const char *string, int len)
                goto freeout;
 
        skp = kzalloc(sizeof(*skp), GFP_KERNEL);
-       if (skp == NULL)
+       if (skp == NULL) {
+               skp = ERR_PTR(-ENOMEM);
                goto freeout;
+       }
 
        skp->smk_known = smack;
        skp->smk_secid = smack_next_secid++;
@@ -577,7 +582,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
         * smk_netlbl_mls failed.
         */
        kfree(skp);
-       skp = NULL;
+       skp = ERR_PTR(rc);
 freeout:
        kfree(smack);
 unlockout:
@@ -612,3 +617,44 @@ struct smack_known *smack_from_secid(const u32 secid)
        rcu_read_unlock();
        return &smack_known_invalid;
 }
+
+/*
+ * Unless a process is running with one of these labels
+ * even having CAP_MAC_OVERRIDE isn't enough to grant
+ * privilege to violate MAC policy. If no labels are
+ * designated (the empty list case) capabilities apply to
+ * everyone.
+ */
+LIST_HEAD(smack_onlycap_list);
+DEFINE_MUTEX(smack_onlycap_lock);
+
+/*
+ * Is the task privileged and allowed to be privileged
+ * by the onlycap rule.
+ *
+ * Returns 1 if the task is allowed to be privileged, 0 if it's not.
+ */
+int smack_privileged(int cap)
+{
+       struct smack_known *skp = smk_of_current();
+       struct smack_onlycap *sop;
+
+       if (!capable(cap))
+               return 0;
+
+       rcu_read_lock();
+       if (list_empty(&smack_onlycap_list)) {
+               rcu_read_unlock();
+               return 1;
+       }
+
+       list_for_each_entry_rcu(sop, &smack_onlycap_list, list) {
+               if (sop->smk_label == skp) {
+                       rcu_read_unlock();
+                       return 1;
+               }
+       }
+       rcu_read_unlock();
+
+       return 0;
+}
index b644757..a143328 100644 (file)
@@ -245,8 +245,8 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
  * @ip: a pointer to the inode
  * @dp: a pointer to the dentry
  *
- * Returns a pointer to the master list entry for the Smack label
- * or NULL if there was no label to fetch.
+ * Returns a pointer to the master list entry for the Smack label,
+ * NULL if there was no label to fetch, or an error code.
  */
 static struct smack_known *smk_fetch(const char *name, struct inode *ip,
                                        struct dentry *dp)
@@ -256,14 +256,18 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
        struct smack_known *skp = NULL;
 
        if (ip->i_op->getxattr == NULL)
-               return NULL;
+               return ERR_PTR(-EOPNOTSUPP);
 
        buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
        if (buffer == NULL)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
-       if (rc > 0)
+       if (rc < 0)
+               skp = ERR_PTR(rc);
+       else if (rc == 0)
+               skp = NULL;
+       else
                skp = smk_import_entry(buffer, rc);
 
        kfree(buffer);
@@ -436,17 +440,11 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,
  */
 static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
 {
-       int rc;
        struct smack_known *skp;
 
-       rc = cap_ptrace_access_check(ctp, mode);
-       if (rc != 0)
-               return rc;
-
        skp = smk_of_task_struct(ctp);
 
-       rc = smk_ptrace_rule_check(current, skp, mode, __func__);
-       return rc;
+       return smk_ptrace_rule_check(current, skp, mode, __func__);
 }
 
 /**
@@ -462,10 +460,6 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
        int rc;
        struct smack_known *skp;
 
-       rc = cap_ptrace_traceme(ptp);
-       if (rc != 0)
-               return rc;
-
        skp = smk_of_task(current_security());
 
        rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
@@ -615,40 +609,44 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
                if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
                        op += strlen(SMK_FSHAT);
                        skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_hat = skp;
-                               specified = 1;
-                       }
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_hat = skp;
+                       specified = 1;
+
                } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
                        op += strlen(SMK_FSFLOOR);
                        skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_floor = skp;
-                               specified = 1;
-                       }
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_floor = skp;
+                       specified = 1;
+
                } else if (strncmp(op, SMK_FSDEFAULT,
                                   strlen(SMK_FSDEFAULT)) == 0) {
                        op += strlen(SMK_FSDEFAULT);
                        skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_default = skp;
-                               specified = 1;
-                       }
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_default = skp;
+                       specified = 1;
+
                } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
                        op += strlen(SMK_FSROOT);
                        skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_root = skp;
-                               specified = 1;
-                       }
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_root = skp;
+                       specified = 1;
+
                } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) {
                        op += strlen(SMK_FSTRANS);
                        skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_root = skp;
-                               transmute = 1;
-                               specified = 1;
-                       }
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_root = skp;
+                       transmute = 1;
+                       specified = 1;
                }
        }
 
@@ -721,10 +719,6 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
        struct inode_smack *isp;
        int rc;
 
-       rc = cap_bprm_set_creds(bprm);
-       if (rc != 0)
-               return rc;
-
        if (bprm->cred_prepared)
                return 0;
 
@@ -779,12 +773,11 @@ static void smack_bprm_committing_creds(struct linux_binprm *bprm)
 static int smack_bprm_secureexec(struct linux_binprm *bprm)
 {
        struct task_smack *tsp = current_security();
-       int ret = cap_bprm_secureexec(bprm);
 
-       if (!ret && (tsp->smk_task != tsp->smk_forked))
-               ret = 1;
+       if (tsp->smk_task != tsp->smk_forked)
+               return 1;
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -1133,7 +1126,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
 
        if (rc == 0 && check_import) {
                skp = size ? smk_import_entry(value, size) : NULL;
-               if (skp == NULL || (check_star &&
+               if (IS_ERR(skp))
+                       rc = PTR_ERR(skp);
+               else if (skp == NULL || (check_star &&
                    (skp == &smack_known_star || skp == &smack_known_web)))
                        rc = -EINVAL;
        }
@@ -1173,19 +1168,19 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
 
        if (strcmp(name, XATTR_NAME_SMACK) == 0) {
                skp = smk_import_entry(value, size);
-               if (skp != NULL)
+               if (!IS_ERR(skp))
                        isp->smk_inode = skp;
                else
                        isp->smk_inode = &smack_known_invalid;
        } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
                skp = smk_import_entry(value, size);
-               if (skp != NULL)
+               if (!IS_ERR(skp))
                        isp->smk_task = skp;
                else
                        isp->smk_task = &smack_known_invalid;
        } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
                skp = smk_import_entry(value, size);
-               if (skp != NULL)
+               if (!IS_ERR(skp))
                        isp->smk_mmap = skp;
                else
                        isp->smk_mmap = &smack_known_invalid;
@@ -1673,6 +1668,9 @@ static int smack_file_receive(struct file *file)
        struct smk_audit_info ad;
        struct inode *inode = file_inode(file);
 
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
+
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
        smk_ad_setfield_u_fs_path(&ad, file->f_path);
        /*
@@ -1934,12 +1932,7 @@ static void smack_task_getsecid(struct task_struct *p, u32 *secid)
  */
 static int smack_task_setnice(struct task_struct *p, int nice)
 {
-       int rc;
-
-       rc = cap_task_setnice(p, nice);
-       if (rc == 0)
-               rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
-       return rc;
+       return smk_curacc_on_task(p, MAY_WRITE, __func__);
 }
 
 /**
@@ -1951,12 +1944,7 @@ static int smack_task_setnice(struct task_struct *p, int nice)
  */
 static int smack_task_setioprio(struct task_struct *p, int ioprio)
 {
-       int rc;
-
-       rc = cap_task_setioprio(p, ioprio);
-       if (rc == 0)
-               rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
-       return rc;
+       return smk_curacc_on_task(p, MAY_WRITE, __func__);
 }
 
 /**
@@ -1980,12 +1968,7 @@ static int smack_task_getioprio(struct task_struct *p)
  */
 static int smack_task_setscheduler(struct task_struct *p)
 {
-       int rc;
-
-       rc = cap_task_setscheduler(p);
-       if (rc == 0)
-               rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
-       return rc;
+       return smk_curacc_on_task(p, MAY_WRITE, __func__);
 }
 
 /**
@@ -2430,8 +2413,8 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
                return -EINVAL;
 
        skp = smk_import_entry(value, size);
-       if (skp == NULL)
-               return -EINVAL;
+       if (IS_ERR(skp))
+               return PTR_ERR(skp);
 
        if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
                nsp->smk_inode = skp;
@@ -3204,7 +3187,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                 */
                dp = dget(opt_dentry);
                skp = smk_fetch(XATTR_NAME_SMACK, inode, dp);
-               if (skp != NULL)
+               if (!IS_ERR_OR_NULL(skp))
                        final = skp;
 
                /*
@@ -3241,11 +3224,14 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                 * Don't let the exec or mmap label be "*" or "@".
                 */
                skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
-               if (skp == &smack_known_star || skp == &smack_known_web)
+               if (IS_ERR(skp) || skp == &smack_known_star ||
+                   skp == &smack_known_web)
                        skp = NULL;
                isp->smk_task = skp;
+
                skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
-               if (skp == &smack_known_star || skp == &smack_known_web)
+               if (IS_ERR(skp) || skp == &smack_known_star ||
+                   skp == &smack_known_web)
                        skp = NULL;
                isp->smk_mmap = skp;
 
@@ -3329,8 +3315,8 @@ static int smack_setprocattr(struct task_struct *p, char *name,
                return -EINVAL;
 
        skp = smk_import_entry(value, size);
-       if (skp == NULL)
-               return -EINVAL;
+       if (IS_ERR(skp))
+               return PTR_ERR(skp);
 
        /*
         * No process is ever allowed the web ("@") label.
@@ -4105,8 +4091,10 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
                return -EINVAL;
 
        skp = smk_import_entry(rulestr, 0);
-       if (skp)
-               *rule = skp->smk_known;
+       if (IS_ERR(skp))
+               return PTR_ERR(skp);
+
+       *rule = skp->smk_known;
 
        return 0;
 }
@@ -4266,147 +4254,145 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
        return 0;
 }
 
-struct security_operations smack_ops = {
-       .name =                         "smack",
-
-       .ptrace_access_check =          smack_ptrace_access_check,
-       .ptrace_traceme =               smack_ptrace_traceme,
-       .syslog =                       smack_syslog,
-
-       .sb_alloc_security =            smack_sb_alloc_security,
-       .sb_free_security =             smack_sb_free_security,
-       .sb_copy_data =                 smack_sb_copy_data,
-       .sb_kern_mount =                smack_sb_kern_mount,
-       .sb_statfs =                    smack_sb_statfs,
-
-       .bprm_set_creds =               smack_bprm_set_creds,
-       .bprm_committing_creds =        smack_bprm_committing_creds,
-       .bprm_secureexec =              smack_bprm_secureexec,
-
-       .inode_alloc_security =         smack_inode_alloc_security,
-       .inode_free_security =          smack_inode_free_security,
-       .inode_init_security =          smack_inode_init_security,
-       .inode_link =                   smack_inode_link,
-       .inode_unlink =                 smack_inode_unlink,
-       .inode_rmdir =                  smack_inode_rmdir,
-       .inode_rename =                 smack_inode_rename,
-       .inode_permission =             smack_inode_permission,
-       .inode_setattr =                smack_inode_setattr,
-       .inode_getattr =                smack_inode_getattr,
-       .inode_setxattr =               smack_inode_setxattr,
-       .inode_post_setxattr =          smack_inode_post_setxattr,
-       .inode_getxattr =               smack_inode_getxattr,
-       .inode_removexattr =            smack_inode_removexattr,
-       .inode_getsecurity =            smack_inode_getsecurity,
-       .inode_setsecurity =            smack_inode_setsecurity,
-       .inode_listsecurity =           smack_inode_listsecurity,
-       .inode_getsecid =               smack_inode_getsecid,
-
-       .file_permission =              smack_file_permission,
-       .file_alloc_security =          smack_file_alloc_security,
-       .file_free_security =           smack_file_free_security,
-       .file_ioctl =                   smack_file_ioctl,
-       .file_lock =                    smack_file_lock,
-       .file_fcntl =                   smack_file_fcntl,
-       .mmap_file =                    smack_mmap_file,
-       .mmap_addr =                    cap_mmap_addr,
-       .file_set_fowner =              smack_file_set_fowner,
-       .file_send_sigiotask =          smack_file_send_sigiotask,
-       .file_receive =                 smack_file_receive,
-
-       .file_open =                    smack_file_open,
-
-       .cred_alloc_blank =             smack_cred_alloc_blank,
-       .cred_free =                    smack_cred_free,
-       .cred_prepare =                 smack_cred_prepare,
-       .cred_transfer =                smack_cred_transfer,
-       .kernel_act_as =                smack_kernel_act_as,
-       .kernel_create_files_as =       smack_kernel_create_files_as,
-       .task_setpgid =                 smack_task_setpgid,
-       .task_getpgid =                 smack_task_getpgid,
-       .task_getsid =                  smack_task_getsid,
-       .task_getsecid =                smack_task_getsecid,
-       .task_setnice =                 smack_task_setnice,
-       .task_setioprio =               smack_task_setioprio,
-       .task_getioprio =               smack_task_getioprio,
-       .task_setscheduler =            smack_task_setscheduler,
-       .task_getscheduler =            smack_task_getscheduler,
-       .task_movememory =              smack_task_movememory,
-       .task_kill =                    smack_task_kill,
-       .task_wait =                    smack_task_wait,
-       .task_to_inode =                smack_task_to_inode,
-
-       .ipc_permission =               smack_ipc_permission,
-       .ipc_getsecid =                 smack_ipc_getsecid,
-
-       .msg_msg_alloc_security =       smack_msg_msg_alloc_security,
-       .msg_msg_free_security =        smack_msg_msg_free_security,
-
-       .msg_queue_alloc_security =     smack_msg_queue_alloc_security,
-       .msg_queue_free_security =      smack_msg_queue_free_security,
-       .msg_queue_associate =          smack_msg_queue_associate,
-       .msg_queue_msgctl =             smack_msg_queue_msgctl,
-       .msg_queue_msgsnd =             smack_msg_queue_msgsnd,
-       .msg_queue_msgrcv =             smack_msg_queue_msgrcv,
-
-       .shm_alloc_security =           smack_shm_alloc_security,
-       .shm_free_security =            smack_shm_free_security,
-       .shm_associate =                smack_shm_associate,
-       .shm_shmctl =                   smack_shm_shmctl,
-       .shm_shmat =                    smack_shm_shmat,
-
-       .sem_alloc_security =           smack_sem_alloc_security,
-       .sem_free_security =            smack_sem_free_security,
-       .sem_associate =                smack_sem_associate,
-       .sem_semctl =                   smack_sem_semctl,
-       .sem_semop =                    smack_sem_semop,
-
-       .d_instantiate =                smack_d_instantiate,
-
-       .getprocattr =                  smack_getprocattr,
-       .setprocattr =                  smack_setprocattr,
-
-       .unix_stream_connect =          smack_unix_stream_connect,
-       .unix_may_send =                smack_unix_may_send,
-
-       .socket_post_create =           smack_socket_post_create,
+struct security_hook_list smack_hooks[] = {
+       LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
+       LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
+       LSM_HOOK_INIT(syslog, smack_syslog),
+
+       LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
+       LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
+       LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
+       LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount),
+       LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
+
+       LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
+       LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds),
+       LSM_HOOK_INIT(bprm_secureexec, smack_bprm_secureexec),
+
+       LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security),
+       LSM_HOOK_INIT(inode_free_security, smack_inode_free_security),
+       LSM_HOOK_INIT(inode_init_security, smack_inode_init_security),
+       LSM_HOOK_INIT(inode_link, smack_inode_link),
+       LSM_HOOK_INIT(inode_unlink, smack_inode_unlink),
+       LSM_HOOK_INIT(inode_rmdir, smack_inode_rmdir),
+       LSM_HOOK_INIT(inode_rename, smack_inode_rename),
+       LSM_HOOK_INIT(inode_permission, smack_inode_permission),
+       LSM_HOOK_INIT(inode_setattr, smack_inode_setattr),
+       LSM_HOOK_INIT(inode_getattr, smack_inode_getattr),
+       LSM_HOOK_INIT(inode_setxattr, smack_inode_setxattr),
+       LSM_HOOK_INIT(inode_post_setxattr, smack_inode_post_setxattr),
+       LSM_HOOK_INIT(inode_getxattr, smack_inode_getxattr),
+       LSM_HOOK_INIT(inode_removexattr, smack_inode_removexattr),
+       LSM_HOOK_INIT(inode_getsecurity, smack_inode_getsecurity),
+       LSM_HOOK_INIT(inode_setsecurity, smack_inode_setsecurity),
+       LSM_HOOK_INIT(inode_listsecurity, smack_inode_listsecurity),
+       LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid),
+
+       LSM_HOOK_INIT(file_permission, smack_file_permission),
+       LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security),
+       LSM_HOOK_INIT(file_free_security, smack_file_free_security),
+       LSM_HOOK_INIT(file_ioctl, smack_file_ioctl),
+       LSM_HOOK_INIT(file_lock, smack_file_lock),
+       LSM_HOOK_INIT(file_fcntl, smack_file_fcntl),
+       LSM_HOOK_INIT(mmap_file, smack_mmap_file),
+       LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
+       LSM_HOOK_INIT(file_set_fowner, smack_file_set_fowner),
+       LSM_HOOK_INIT(file_send_sigiotask, smack_file_send_sigiotask),
+       LSM_HOOK_INIT(file_receive, smack_file_receive),
+
+       LSM_HOOK_INIT(file_open, smack_file_open),
+
+       LSM_HOOK_INIT(cred_alloc_blank, smack_cred_alloc_blank),
+       LSM_HOOK_INIT(cred_free, smack_cred_free),
+       LSM_HOOK_INIT(cred_prepare, smack_cred_prepare),
+       LSM_HOOK_INIT(cred_transfer, smack_cred_transfer),
+       LSM_HOOK_INIT(kernel_act_as, smack_kernel_act_as),
+       LSM_HOOK_INIT(kernel_create_files_as, smack_kernel_create_files_as),
+       LSM_HOOK_INIT(task_setpgid, smack_task_setpgid),
+       LSM_HOOK_INIT(task_getpgid, smack_task_getpgid),
+       LSM_HOOK_INIT(task_getsid, smack_task_getsid),
+       LSM_HOOK_INIT(task_getsecid, smack_task_getsecid),
+       LSM_HOOK_INIT(task_setnice, smack_task_setnice),
+       LSM_HOOK_INIT(task_setioprio, smack_task_setioprio),
+       LSM_HOOK_INIT(task_getioprio, smack_task_getioprio),
+       LSM_HOOK_INIT(task_setscheduler, smack_task_setscheduler),
+       LSM_HOOK_INIT(task_getscheduler, smack_task_getscheduler),
+       LSM_HOOK_INIT(task_movememory, smack_task_movememory),
+       LSM_HOOK_INIT(task_kill, smack_task_kill),
+       LSM_HOOK_INIT(task_wait, smack_task_wait),
+       LSM_HOOK_INIT(task_to_inode, smack_task_to_inode),
+
+       LSM_HOOK_INIT(ipc_permission, smack_ipc_permission),
+       LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid),
+
+       LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security),
+       LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security),
+
+       LSM_HOOK_INIT(msg_queue_alloc_security, smack_msg_queue_alloc_security),
+       LSM_HOOK_INIT(msg_queue_free_security, smack_msg_queue_free_security),
+       LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate),
+       LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl),
+       LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd),
+       LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv),
+
+       LSM_HOOK_INIT(shm_alloc_security, smack_shm_alloc_security),
+       LSM_HOOK_INIT(shm_free_security, smack_shm_free_security),
+       LSM_HOOK_INIT(shm_associate, smack_shm_associate),
+       LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl),
+       LSM_HOOK_INIT(shm_shmat, smack_shm_shmat),
+
+       LSM_HOOK_INIT(sem_alloc_security, smack_sem_alloc_security),
+       LSM_HOOK_INIT(sem_free_security, smack_sem_free_security),
+       LSM_HOOK_INIT(sem_associate, smack_sem_associate),
+       LSM_HOOK_INIT(sem_semctl, smack_sem_semctl),
+       LSM_HOOK_INIT(sem_semop, smack_sem_semop),
+
+       LSM_HOOK_INIT(d_instantiate, smack_d_instantiate),
+
+       LSM_HOOK_INIT(getprocattr, smack_getprocattr),
+       LSM_HOOK_INIT(setprocattr, smack_setprocattr),
+
+       LSM_HOOK_INIT(unix_stream_connect, smack_unix_stream_connect),
+       LSM_HOOK_INIT(unix_may_send, smack_unix_may_send),
+
+       LSM_HOOK_INIT(socket_post_create, smack_socket_post_create),
 #ifndef CONFIG_SECURITY_SMACK_NETFILTER
-       .socket_bind =                  smack_socket_bind,
+       LSM_HOOK_INIT(socket_bind, smack_socket_bind),
 #endif /* CONFIG_SECURITY_SMACK_NETFILTER */
-       .socket_connect =               smack_socket_connect,
-       .socket_sendmsg =               smack_socket_sendmsg,
-       .socket_sock_rcv_skb =          smack_socket_sock_rcv_skb,
-       .socket_getpeersec_stream =     smack_socket_getpeersec_stream,
-       .socket_getpeersec_dgram =      smack_socket_getpeersec_dgram,
-       .sk_alloc_security =            smack_sk_alloc_security,
-       .sk_free_security =             smack_sk_free_security,
-       .sock_graft =                   smack_sock_graft,
-       .inet_conn_request =            smack_inet_conn_request,
-       .inet_csk_clone =               smack_inet_csk_clone,
+       LSM_HOOK_INIT(socket_connect, smack_socket_connect),
+       LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg),
+       LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb),
+       LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream),
+       LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
+       LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
+       LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+       LSM_HOOK_INIT(sock_graft, smack_sock_graft),
+       LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
+       LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
 
  /* key management security hooks */
 #ifdef CONFIG_KEYS
-       .key_alloc =                    smack_key_alloc,
-       .key_free =                     smack_key_free,
-       .key_permission =               smack_key_permission,
-       .key_getsecurity =              smack_key_getsecurity,
+       LSM_HOOK_INIT(key_alloc, smack_key_alloc),
+       LSM_HOOK_INIT(key_free, smack_key_free),
+       LSM_HOOK_INIT(key_permission, smack_key_permission),
+       LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity),
 #endif /* CONFIG_KEYS */
 
  /* Audit hooks */
 #ifdef CONFIG_AUDIT
-       .audit_rule_init =              smack_audit_rule_init,
-       .audit_rule_known =             smack_audit_rule_known,
-       .audit_rule_match =             smack_audit_rule_match,
-       .audit_rule_free =              smack_audit_rule_free,
+       LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init),
+       LSM_HOOK_INIT(audit_rule_known, smack_audit_rule_known),
+       LSM_HOOK_INIT(audit_rule_match, smack_audit_rule_match),
+       LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free),
 #endif /* CONFIG_AUDIT */
 
-       .ismaclabel =                   smack_ismaclabel,
-       .secid_to_secctx =              smack_secid_to_secctx,
-       .secctx_to_secid =              smack_secctx_to_secid,
-       .release_secctx =               smack_release_secctx,
-       .inode_notifysecctx =           smack_inode_notifysecctx,
-       .inode_setsecctx =              smack_inode_setsecctx,
-       .inode_getsecctx =              smack_inode_getsecctx,
+       LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
+       LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
+       LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
+       LSM_HOOK_INIT(release_secctx, smack_release_secctx),
+       LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx),
+       LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),
+       LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx),
 };
 
 
@@ -4451,7 +4437,7 @@ static __init int smack_init(void)
        struct cred *cred;
        struct task_smack *tsp;
 
-       if (!security_module_enable(&smack_ops))
+       if (!security_module_enable("smack"))
                return 0;
 
        smack_enabled = 1;
@@ -4481,8 +4467,7 @@ static __init int smack_init(void)
        /*
         * Register with LSM
         */
-       if (register_security(&smack_ops))
-               panic("smack: Unable to register with kernel.\n");
+       security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks));
 
        return 0;
 }
index d968298..5e0a64e 100644 (file)
@@ -87,16 +87,6 @@ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
  */
 int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
 
-/*
- * Unless a process is running with this label even
- * having CAP_MAC_OVERRIDE isn't enough to grant
- * privilege to violate MAC policy. If no label is
- * designated (the NULL case) capabilities apply to
- * everyone. It is expected that the hat (^) label
- * will be used if any label is used.
- */
-struct smack_known *smack_onlycap;
-
 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
 /*
  * Allow one label to be unconfined. This is for
@@ -338,8 +328,7 @@ static int smk_perm_from_str(const char *string)
  * @import: if non-zero, import labels
  * @len: label length limit
  *
- * Returns 0 on success, -EINVAL on failure and -ENOENT when either subject
- * or object is missing.
+ * Returns 0 on success, appropriate error code on failure.
  */
 static int smk_fill_rule(const char *subject, const char *object,
                                const char *access1, const char *access2,
@@ -351,16 +340,16 @@ static int smk_fill_rule(const char *subject, const char *object,
 
        if (import) {
                rule->smk_subject = smk_import_entry(subject, len);
-               if (rule->smk_subject == NULL)
-                       return -EINVAL;
+               if (IS_ERR(rule->smk_subject))
+                       return PTR_ERR(rule->smk_subject);
 
                rule->smk_object = smk_import_entry(object, len);
-               if (rule->smk_object == NULL)
-                       return -EINVAL;
+               if (IS_ERR(rule->smk_object))
+                       return PTR_ERR(rule->smk_object);
        } else {
                cp = smk_parse_smack(subject, len);
-               if (cp == NULL)
-                       return -EINVAL;
+               if (IS_ERR(cp))
+                       return PTR_ERR(cp);
                skp = smk_find_entry(cp);
                kfree(cp);
                if (skp == NULL)
@@ -368,8 +357,8 @@ static int smk_fill_rule(const char *subject, const char *object,
                rule->smk_subject = skp;
 
                cp = smk_parse_smack(object, len);
-               if (cp == NULL)
-                       return -EINVAL;
+               if (IS_ERR(cp))
+                       return PTR_ERR(cp);
                skp = smk_find_entry(cp);
                kfree(cp);
                if (skp == NULL)
@@ -412,7 +401,7 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
  * @import: if non-zero, import labels
  * @tokens: numer of substrings expected in data
  *
- * Returns number of processed bytes on success, -1 on failure.
+ * Returns number of processed bytes on success, -ERRNO on failure.
  */
 static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
                                int import, int tokens)
@@ -431,7 +420,7 @@ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
 
                if (data[cnt] == '\0')
                        /* Unexpected end of data */
-                       return -1;
+                       return -EINVAL;
 
                tok[i] = data + cnt;
 
@@ -529,14 +518,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
        while (cnt < count) {
                if (format == SMK_FIXED24_FMT) {
                        rc = smk_parse_rule(data, &rule, 1);
-                       if (rc != 0) {
-                               rc = -EINVAL;
+                       if (rc < 0)
                                goto out;
-                       }
                        cnt = count;
                } else {
                        rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
-                       if (rc <= 0) {
+                       if (rc < 0)
+                               goto out;
+                       if (rc == 0) {
                                rc = -EINVAL;
                                goto out;
                        }
@@ -567,23 +556,17 @@ static void *smk_seq_start(struct seq_file *s, loff_t *pos,
                                struct list_head *head)
 {
        struct list_head *list;
+       int i = *pos;
+
+       rcu_read_lock();
+       for (list = rcu_dereference(list_next_rcu(head));
+               list != head;
+               list = rcu_dereference(list_next_rcu(list))) {
+               if (i-- == 0)
+                       return list;
+       }
 
-       /*
-        * This is 0 the first time through.
-        */
-       if (s->index == 0)
-               s->private = head;
-
-       if (s->private == NULL)
-               return NULL;
-
-       list = s->private;
-       if (list_empty(list))
-               return NULL;
-
-       if (s->index == 0)
-               return list->next;
-       return list;
+       return NULL;
 }
 
 static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
@@ -591,17 +574,15 @@ static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
 {
        struct list_head *list = v;
 
-       if (list_is_last(list, head)) {
-               s->private = NULL;
-               return NULL;
-       }
-       s->private = list->next;
-       return list->next;
+       ++*pos;
+       list = rcu_dereference(list_next_rcu(list));
+
+       return (list == head) ? NULL : list;
 }
 
 static void smk_seq_stop(struct seq_file *s, void *v)
 {
-       /* No-op */
+       rcu_read_unlock();
 }
 
 static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
@@ -661,7 +642,7 @@ static int load_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
        struct smack_master_list *smlp =
-                list_entry(list, struct smack_master_list, list);
+               list_entry_rcu(list, struct smack_master_list, list);
 
        smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
 
@@ -809,7 +790,7 @@ static int cipso_seq_show(struct seq_file *s, void *v)
 {
        struct list_head  *list = v;
        struct smack_known *skp =
-                list_entry(list, struct smack_known, list);
+               list_entry_rcu(list, struct smack_known, list);
        struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
        char sep = '/';
        int i;
@@ -915,8 +896,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
        mutex_lock(&smack_cipso_lock);
 
        skp = smk_import_entry(rule, 0);
-       if (skp == NULL)
+       if (IS_ERR(skp)) {
+               rc = PTR_ERR(skp);
                goto out;
+       }
 
        if (format == SMK_FIXED24_FMT)
                rule += SMK_LABELLEN;
@@ -998,7 +981,7 @@ static int cipso2_seq_show(struct seq_file *s, void *v)
 {
        struct list_head  *list = v;
        struct smack_known *skp =
-                list_entry(list, struct smack_known, list);
+               list_entry_rcu(list, struct smack_known, list);
        struct netlbl_lsm_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
        char sep = '/';
        int i;
@@ -1082,7 +1065,7 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
        struct smk_netlbladdr *skp =
-                        list_entry(list, struct smk_netlbladdr, list);
+                       list_entry_rcu(list, struct smk_netlbladdr, list);
        unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
        int maskn;
        u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
@@ -1237,8 +1220,8 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
         */
        if (smack[0] != '-') {
                skp = smk_import_entry(smack, 0);
-               if (skp == NULL) {
-                       rc = -EINVAL;
+               if (IS_ERR(skp)) {
+                       rc = PTR_ERR(skp);
                        goto free_out;
                }
        } else {
@@ -1619,8 +1602,8 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
        }
 
        skp = smk_import_entry(data, count);
-       if (skp == NULL) {
-               rc = -EINVAL;
+       if (IS_ERR(skp)) {
+               rc = PTR_ERR(skp);
                goto out;
        }
 
@@ -1643,34 +1626,79 @@ static const struct file_operations smk_ambient_ops = {
        .llseek         = default_llseek,
 };
 
-/**
- * smk_read_onlycap - read() for smackfs/onlycap
- * @filp: file pointer, not actually used
- * @buf: where to put the result
- * @cn: maximum to send along
- * @ppos: where to start
- *
- * Returns number of bytes read or error code, as appropriate
+/*
+ * Seq_file operations for /smack/onlycap
  */
-static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
-                               size_t cn, loff_t *ppos)
+static void *onlycap_seq_start(struct seq_file *s, loff_t *pos)
 {
-       char *smack = "";
-       ssize_t rc = -EINVAL;
-       int asize;
+       return smk_seq_start(s, pos, &smack_onlycap_list);
+}
 
-       if (*ppos != 0)
-               return 0;
+static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       return smk_seq_next(s, v, pos, &smack_onlycap_list);
+}
 
-       if (smack_onlycap != NULL)
-               smack = smack_onlycap->smk_known;
+static int onlycap_seq_show(struct seq_file *s, void *v)
+{
+       struct list_head *list = v;
+       struct smack_onlycap *sop =
+               list_entry_rcu(list, struct smack_onlycap, list);
 
-       asize = strlen(smack) + 1;
+       seq_puts(s, sop->smk_label->smk_known);
+       seq_putc(s, ' ');
 
-       if (cn >= asize)
-               rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
+       return 0;
+}
 
-       return rc;
+static const struct seq_operations onlycap_seq_ops = {
+       .start = onlycap_seq_start,
+       .next  = onlycap_seq_next,
+       .show  = onlycap_seq_show,
+       .stop  = smk_seq_stop,
+};
+
+static int smk_open_onlycap(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &onlycap_seq_ops);
+}
+
+/**
+ * smk_list_swap_rcu - swap public list with a private one in RCU-safe way
+ * The caller must hold appropriate mutex to prevent concurrent modifications
+ * to the public list.
+ * Private list is assumed to be not accessible to other threads yet.
+ *
+ * @public: public list
+ * @private: private list
+ */
+static void smk_list_swap_rcu(struct list_head *public,
+                             struct list_head *private)
+{
+       struct list_head *first, *last;
+
+       if (list_empty(public)) {
+               list_splice_init_rcu(private, public, synchronize_rcu);
+       } else {
+               /* Remember public list before replacing it */
+               first = public->next;
+               last = public->prev;
+
+               /* Publish private list in place of public in RCU-safe way */
+               private->prev->next = public;
+               private->next->prev = public;
+               rcu_assign_pointer(public->next, private->next);
+               public->prev = private->prev;
+
+               synchronize_rcu();
+
+               /* When all readers are done with the old public list,
+                * attach it in place of private */
+               private->next = first;
+               private->prev = last;
+               first->prev = private;
+               last->next = private;
+       }
 }
 
 /**
@@ -1686,47 +1714,79 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
        char *data;
-       struct smack_known *skp = smk_of_task(current->cred->security);
+       char *data_parse;
+       char *tok;
+       struct smack_known *skp;
+       struct smack_onlycap *sop;
+       struct smack_onlycap *sop2;
+       LIST_HEAD(list_tmp);
        int rc = count;
 
        if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
-       /*
-        * This can be done using smk_access() but is done
-        * explicitly for clarity. The smk_access() implementation
-        * would use smk_access(smack_onlycap, MAY_WRITE)
-        */
-       if (smack_onlycap != NULL && smack_onlycap != skp)
-               return -EPERM;
-
        data = kzalloc(count + 1, GFP_KERNEL);
        if (data == NULL)
                return -ENOMEM;
 
+       if (copy_from_user(data, buf, count) != 0) {
+               kfree(data);
+               return -EFAULT;
+       }
+
+       data_parse = data;
+       while ((tok = strsep(&data_parse, " ")) != NULL) {
+               if (!*tok)
+                       continue;
+
+               skp = smk_import_entry(tok, 0);
+               if (IS_ERR(skp)) {
+                       rc = PTR_ERR(skp);
+                       break;
+               }
+
+               sop = kzalloc(sizeof(*sop), GFP_KERNEL);
+               if (sop == NULL) {
+                       rc = -ENOMEM;
+                       break;
+               }
+
+               sop->smk_label = skp;
+               list_add_rcu(&sop->list, &list_tmp);
+       }
+       kfree(data);
+
        /*
-        * Should the null string be passed in unset the onlycap value.
-        * This seems like something to be careful with as usually
-        * smk_import only expects to return NULL for errors. It
-        * is usually the case that a nullstring or "\n" would be
-        * bad to pass to smk_import but in fact this is useful here.
+        * Clear the smack_onlycap on invalid label errors. This means
+        * that we can pass a null string to unset the onlycap value.
         *
-        * smk_import will also reject a label beginning with '-',
+        * Importing will also reject a label beginning with '-',
         * so "-usecapabilities" will also work.
+        *
+        * But do so only on invalid label, not on system errors.
+        * The invalid label must be first to count as clearing attempt.
         */
-       if (copy_from_user(data, buf, count) != 0)
-               rc = -EFAULT;
-       else
-               smack_onlycap = smk_import_entry(data, count);
+       if (rc == -EINVAL && list_empty(&list_tmp))
+               rc = count;
+
+       if (rc >= 0) {
+               mutex_lock(&smack_onlycap_lock);
+               smk_list_swap_rcu(&smack_onlycap_list, &list_tmp);
+               mutex_unlock(&smack_onlycap_lock);
+       }
+
+       list_for_each_entry_safe(sop, sop2, &list_tmp, list)
+               kfree(sop);
 
-       kfree(data);
        return rc;
 }
 
 static const struct file_operations smk_onlycap_ops = {
-       .read           = smk_read_onlycap,
+       .open           = smk_open_onlycap,
+       .read           = seq_read,
        .write          = smk_write_onlycap,
-       .llseek         = default_llseek,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
 };
 
 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
@@ -1773,6 +1833,7 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
                                        size_t count, loff_t *ppos)
 {
        char *data;
+       struct smack_known *skp;
        int rc = count;
 
        if (!smack_privileged(CAP_MAC_ADMIN))
@@ -1782,21 +1843,31 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
        if (data == NULL)
                return -ENOMEM;
 
+       if (copy_from_user(data, buf, count) != 0) {
+               rc = -EFAULT;
+               goto freeout;
+       }
+
        /*
-        * Should the null string be passed in unset the unconfined value.
-        * This seems like something to be careful with as usually
-        * smk_import only expects to return NULL for errors. It
-        * is usually the case that a nullstring or "\n" would be
-        * bad to pass to smk_import but in fact this is useful here.
+        * Clear the smack_unconfined on invalid label errors. This means
+        * that we can pass a null string to unset the unconfined value.
         *
-        * smk_import will also reject a label beginning with '-',
+        * Importing will also reject a label beginning with '-',
         * so "-confine" will also work.
+        *
+        * But do so only on invalid label, not on system errors.
         */
-       if (copy_from_user(data, buf, count) != 0)
-               rc = -EFAULT;
-       else
-               smack_unconfined = smk_import_entry(data, count);
+       skp = smk_import_entry(data, count);
+       if (PTR_ERR(skp) == -EINVAL)
+               skp = NULL;
+       else if (IS_ERR(skp)) {
+               rc = PTR_ERR(skp);
+               goto freeout;
+       }
 
+       smack_unconfined = skp;
+
+freeout:
        kfree(data);
        return rc;
 }
@@ -1895,7 +1966,7 @@ static int load_self_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
        struct smack_rule *srp =
-                list_entry(list, struct smack_rule, list);
+               list_entry_rcu(list, struct smack_rule, list);
 
        smk_rule_show(s, srp, SMK_LABELLEN);
 
@@ -1980,7 +2051,7 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
                res = smk_access(rule.smk_subject, rule.smk_object,
                                 rule.smk_access1, NULL);
        else if (res != -ENOENT)
-               return -EINVAL;
+               return res;
 
        /*
         * smk_access() can return a value > 0 in the "bringup" case.
@@ -2024,7 +2095,7 @@ static int load2_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
        struct smack_master_list *smlp =
-                list_entry(list, struct smack_master_list, list);
+               list_entry_rcu(list, struct smack_master_list, list);
 
        smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
 
@@ -2101,7 +2172,7 @@ static int load_self2_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
        struct smack_rule *srp =
-                list_entry(list, struct smack_rule, list);
+               list_entry_rcu(list, struct smack_rule, list);
 
        smk_rule_show(s, srp, SMK_LONGLABEL);
 
@@ -2182,8 +2253,8 @@ static const struct file_operations smk_access2_ops = {
 static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       char *data = NULL;
-       const char *cp = NULL;
+       char *data;
+       const char *cp;
        struct smack_known *skp;
        struct smack_rule *sp;
        struct list_head *rule_list;
@@ -2205,18 +2276,18 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
 
        if (copy_from_user(data, buf, count) != 0) {
                rc = -EFAULT;
-               goto free_out;
+               goto out_data;
        }
 
        cp = smk_parse_smack(data, count);
-       if (cp == NULL) {
-               rc = -EINVAL;
-               goto free_out;
+       if (IS_ERR(cp)) {
+               rc = PTR_ERR(cp);
+               goto out_data;
        }
 
        skp = smk_find_entry(cp);
        if (skp == NULL)
-               goto free_out;
+               goto out_cp;
 
        rule_list = &skp->smk_rules;
        rule_lock = &skp->smk_rules_lock;
@@ -2228,9 +2299,11 @@ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
 
        mutex_unlock(rule_lock);
 
-free_out:
-       kfree(data);
+out_cp:
        kfree(cp);
+out_data:
+       kfree(data);
+
        return rc;
 }
 
@@ -2341,10 +2414,10 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
                rc = -EFAULT;
        else {
                skp = smk_import_entry(data, count);
-               if (skp == NULL)
-                       rc = -EINVAL;
+               if (IS_ERR(skp))
+                       rc = PTR_ERR(skp);
                else
-                       smack_syslog_label = smk_import_entry(data, count);
+                       smack_syslog_label = skp;
        }
 
        kfree(data);
@@ -2547,7 +2620,7 @@ static int __init init_smk_fs(void)
        int err;
        int rc;
 
-       if (!security_module_enable(&smack_ops))
+       if (!security_module_enable("smack"))
                return 0;
 
        err = smk_init_sysfs();
index 57c88d5..cbf3df4 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
-#include <linux/security.h>
+#include <linux/lsm_hooks.h>
 #include "common.h"
 
 /**
@@ -72,12 +72,6 @@ static void tomoyo_cred_free(struct cred *cred)
  */
 static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
 {
-       int rc;
-
-       rc = cap_bprm_set_creds(bprm);
-       if (rc)
-               return rc;
-
        /*
         * Do only if this function is called for the first time of an execve
         * operation.
@@ -502,36 +496,35 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
  * tomoyo_security_ops is a "struct security_operations" which is used for
  * registering TOMOYO.
  */
-static struct security_operations tomoyo_security_ops = {
-       .name                = "tomoyo",
-       .cred_alloc_blank    = tomoyo_cred_alloc_blank,
-       .cred_prepare        = tomoyo_cred_prepare,
-       .cred_transfer       = tomoyo_cred_transfer,
-       .cred_free           = tomoyo_cred_free,
-       .bprm_set_creds      = tomoyo_bprm_set_creds,
-       .bprm_check_security = tomoyo_bprm_check_security,
-       .file_fcntl          = tomoyo_file_fcntl,
-       .file_open           = tomoyo_file_open,
-       .path_truncate       = tomoyo_path_truncate,
-       .path_unlink         = tomoyo_path_unlink,
-       .path_mkdir          = tomoyo_path_mkdir,
-       .path_rmdir          = tomoyo_path_rmdir,
-       .path_symlink        = tomoyo_path_symlink,
-       .path_mknod          = tomoyo_path_mknod,
-       .path_link           = tomoyo_path_link,
-       .path_rename         = tomoyo_path_rename,
-       .inode_getattr       = tomoyo_inode_getattr,
-       .file_ioctl          = tomoyo_file_ioctl,
-       .path_chmod          = tomoyo_path_chmod,
-       .path_chown          = tomoyo_path_chown,
-       .path_chroot         = tomoyo_path_chroot,
-       .sb_mount            = tomoyo_sb_mount,
-       .sb_umount           = tomoyo_sb_umount,
-       .sb_pivotroot        = tomoyo_sb_pivotroot,
-       .socket_bind         = tomoyo_socket_bind,
-       .socket_connect      = tomoyo_socket_connect,
-       .socket_listen       = tomoyo_socket_listen,
-       .socket_sendmsg      = tomoyo_socket_sendmsg,
+static struct security_hook_list tomoyo_hooks[] = {
+       LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank),
+       LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
+       LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer),
+       LSM_HOOK_INIT(cred_free, tomoyo_cred_free),
+       LSM_HOOK_INIT(bprm_set_creds, tomoyo_bprm_set_creds),
+       LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security),
+       LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl),
+       LSM_HOOK_INIT(file_open, tomoyo_file_open),
+       LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate),
+       LSM_HOOK_INIT(path_unlink, tomoyo_path_unlink),
+       LSM_HOOK_INIT(path_mkdir, tomoyo_path_mkdir),
+       LSM_HOOK_INIT(path_rmdir, tomoyo_path_rmdir),
+       LSM_HOOK_INIT(path_symlink, tomoyo_path_symlink),
+       LSM_HOOK_INIT(path_mknod, tomoyo_path_mknod),
+       LSM_HOOK_INIT(path_link, tomoyo_path_link),
+       LSM_HOOK_INIT(path_rename, tomoyo_path_rename),
+       LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr),
+       LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl),
+       LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod),
+       LSM_HOOK_INIT(path_chown, tomoyo_path_chown),
+       LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot),
+       LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount),
+       LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount),
+       LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot),
+       LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind),
+       LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect),
+       LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen),
+       LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg),
 };
 
 /* Lock for GC. */
@@ -546,11 +539,10 @@ static int __init tomoyo_init(void)
 {
        struct cred *cred = (struct cred *) current_cred();
 
-       if (!security_module_enable(&tomoyo_security_ops))
+       if (!security_module_enable("tomoyo"))
                return 0;
        /* register ourselves with the security framework */
-       if (register_security(&tomoyo_security_ops))
-               panic("Failure registering TOMOYO Linux");
+       security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks));
        printk(KERN_INFO "TOMOYO Linux initialized\n");
        cred->security = &tomoyo_kernel_domain;
        tomoyo_mm_init();
index 24aae2a..9ed3250 100644 (file)
@@ -12,7 +12,7 @@
  *
  */
 
-#include <linux/security.h>
+#include <linux/lsm_hooks.h>
 #include <linux/sysctl.h>
 #include <linux/ptrace.h>
 #include <linux/prctl.h>
@@ -154,13 +154,9 @@ void yama_task_free(struct task_struct *task)
 int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                           unsigned long arg4, unsigned long arg5)
 {
-       int rc;
+       int rc = -ENOSYS;
        struct task_struct *myself = current;
 
-       rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
-       if (rc != -ENOSYS)
-               return rc;
-
        switch (option) {
        case PR_SET_PTRACER:
                /* Since a thread can call prctl(), find the group leader
@@ -279,17 +275,10 @@ static int ptracer_exception_found(struct task_struct *tracer,
  *
  * Returns 0 if following the ptrace is allowed, -ve on error.
  */
-int yama_ptrace_access_check(struct task_struct *child,
+static int yama_ptrace_access_check(struct task_struct *child,
                                    unsigned int mode)
 {
-       int rc;
-
-       /* If standard caps disallows it, so does Yama.  We should
-        * only tighten restrictions further.
-        */
-       rc = cap_ptrace_access_check(child, mode);
-       if (rc)
-               return rc;
+       int rc = 0;
 
        /* require ptrace target be a child of ptracer on attach */
        if (mode == PTRACE_MODE_ATTACH) {
@@ -335,14 +324,7 @@ int yama_ptrace_access_check(struct task_struct *child,
  */
 int yama_ptrace_traceme(struct task_struct *parent)
 {
-       int rc;
-
-       /* If standard caps disallows it, so does Yama.  We should
-        * only tighten restrictions further.
-        */
-       rc = cap_ptrace_traceme(parent);
-       if (rc)
-               return rc;
+       int rc = 0;
 
        /* Only disallow PTRACE_TRACEME on more aggressive settings. */
        switch (ptrace_scope) {
@@ -364,16 +346,17 @@ int yama_ptrace_traceme(struct task_struct *parent)
        return rc;
 }
 
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-static struct security_operations yama_ops = {
-       .name =                 "yama",
-
-       .ptrace_access_check =  yama_ptrace_access_check,
-       .ptrace_traceme =       yama_ptrace_traceme,
-       .task_prctl =           yama_task_prctl,
-       .task_free =            yama_task_free,
+static struct security_hook_list yama_hooks[] = {
+       LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
+       LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
+       LSM_HOOK_INIT(task_prctl, yama_task_prctl),
+       LSM_HOOK_INIT(task_free, yama_task_free),
 };
-#endif
+
+void __init yama_add_hooks(void)
+{
+       security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks));
+}
 
 #ifdef CONFIG_SYSCTL
 static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -418,16 +401,13 @@ static struct ctl_table yama_sysctl_table[] = {
 static __init int yama_init(void)
 {
 #ifndef CONFIG_SECURITY_YAMA_STACKED
-       if (!security_module_enable(&yama_ops))
+       /*
+        * If yama is being stacked this is already taken care of.
+        */
+       if (!security_module_enable("yama"))
                return 0;
 #endif
-
-       printk(KERN_INFO "Yama: becoming mindful.\n");
-
-#ifndef CONFIG_SECURITY_YAMA_STACKED
-       if (register_security(&yama_ops))
-               panic("Yama: kernel registration failed.\n");
-#endif
+       pr_info("Yama: becoming mindful.\n");
 
 #ifdef CONFIG_SYSCTL
        if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))