Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jul 2019 03:28:59 +0000 (20:28 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jul 2019 03:28:59 +0000 (20:28 -0700)
Pull integrity updates from Mimi Zohar:
 "Bug fixes, code clean up, and new features:

   - IMA policy rules can be defined in terms of LSM labels, making the
     IMA policy dependent on LSM policy label changes, in particular LSM
     label deletions. The new environment, in which IMA-appraisal is
     being used, frequently updates the LSM policy and permits LSM label
     deletions.

   - Prevent an mmap'ed shared file opened for write from also being
     mmap'ed execute. In the long term, making this and other similar
     changes at the VFS layer would be preferable.

   - The IMA per policy rule template format support is needed for a
     couple of new/proposed features (eg. kexec boot command line
     measurement, appended signatures, and VFS provided file hashes).

   - Other than the "boot-aggregate" record in the IMA measuremeent
     list, all other measurements are of file data. Measuring and
     storing the kexec boot command line in the IMA measurement list is
     the first buffer based measurement included in the measurement
     list"

* 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity:
  integrity: Introduce struct evm_xattr
  ima: Update MAX_TEMPLATE_NAME_LEN to fit largest reasonable definition
  KEXEC: Call ima_kexec_cmdline to measure the boot command line args
  IMA: Define a new template field buf
  IMA: Define a new hook to measure the kexec boot command line arguments
  IMA: support for per policy rule template formats
  integrity: Fix __integrity_init_keyring() section mismatch
  ima: Use designated initializers for struct ima_event_data
  ima: use the lsm policy update notifier
  LSM: switch to blocking policy update notifiers
  x86/ima: fix the Kconfig dependency for IMA_ARCH_POLICY
  ima: Make arch_policy_entry static
  ima: prevent a file already mmap'ed write to be mmap'ed execute
  x86/ima: check EFI SetupMode too

23 files changed:
Documentation/ABI/testing/ima_policy
Documentation/security/IMA-templates.rst
arch/x86/kernel/ima_arch.c
drivers/infiniband/core/device.c
include/linux/ima.h
include/linux/security.h
kernel/kexec_file.c
security/integrity/digsig.c
security/integrity/evm/evm_main.c
security/integrity/ima/Kconfig
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_appraise.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/integrity/ima/ima_template.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/selinuxfs.c

index 74c6702de74e24369bc4d3e314d534898052ec2b..fc376a3239083550a278411ce542badc37643b80 100644 (file)
@@ -24,11 +24,11 @@ Description:
                                [euid=] [fowner=] [fsname=]]
                        lsm:    [[subj_user=] [subj_role=] [subj_type=]
                                 [obj_user=] [obj_role=] [obj_type=]]
-                       option: [[appraise_type=]] [permit_directio]
-
+                       option: [[appraise_type=]] [template=] [permit_directio]
                base:   func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
                                [FIRMWARE_CHECK]
                                [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
+                               [KEXEC_CMDLINE]
                        mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
                               [[^]MAY_EXEC]
                        fsmagic:= hex value
@@ -38,6 +38,8 @@ Description:
                        fowner:= decimal value
                lsm:    are LSM specific
                option: appraise_type:= [imasig]
+                       template:= name of a defined IMA template type
+                       (eg, ima-ng). Only valid when action is "measure".
                        pcr:= decimal value
 
                default policy:
index 2cd0e273cc9aa024ed738acf997dc404f0ba77dd..3d1cca287aa4b21ebe839571b7b111c0adb32f8e 100644 (file)
@@ -69,15 +69,16 @@ descriptors by adding their identifier to the format string
    algorithm (field format: [<hash algo>:]digest, where the digest
    prefix is shown only if the hash algorithm is not SHA1 or MD5);
  - 'n-ng': the name of the event, without size limitations;
- - 'sig': the file signature.
+ - 'sig': the file signature;
+ - 'buf': the buffer data that was used to generate the hash without size limitations;
 
 
 Below, there is the list of defined template descriptors:
 
  - "ima": its format is ``d|n``;
  - "ima-ng" (default): its format is ``d-ng|n-ng``;
- - "ima-sig": its format is ``d-ng|n-ng|sig``.
-
+ - "ima-sig": its format is ``d-ng|n-ng|sig``;
+ - "ima-buf": its format is ``d-ng|n-ng|buf``;
 
 
 Use
index 64b973f0e98523628d7239a98c5c8b64fc5c8f9f..4c407833facab7b7d8866de965e6c465313a0520 100644 (file)
@@ -11,10 +11,11 @@ extern struct boot_params boot_params;
 static enum efi_secureboot_mode get_sb_mode(void)
 {
        efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
+       efi_char16_t efi_SetupMode_name[] = L"SecureBoot";
        efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
        efi_status_t status;
        unsigned long size;
-       u8 secboot;
+       u8 secboot, setupmode;
 
        size = sizeof(secboot);
 
@@ -36,7 +37,14 @@ static enum efi_secureboot_mode get_sb_mode(void)
                return efi_secureboot_mode_unknown;
        }
 
-       if (secboot == 0) {
+       size = sizeof(setupmode);
+       status = efi.get_variable(efi_SetupMode_name, &efi_variable_guid,
+                                 NULL, &size, &setupmode);
+
+       if (status != EFI_SUCCESS)      /* ignore unknown SetupMode */
+               setupmode = 0;
+
+       if (secboot == 0 || setupmode == 1) {
                pr_info("ima: secureboot mode disabled\n");
                return efi_secureboot_mode_disabled;
        }
index d020bb4d03d5c946f9e3d0ca9af928395a7b3f2f..3352a107b4a36756518087eef46615b55372e2a0 100644 (file)
@@ -2520,7 +2520,7 @@ static int __init ib_core_init(void)
                goto err_mad;
        }
 
-       ret = register_lsm_notifier(&ibdev_lsm_nb);
+       ret = register_blocking_lsm_notifier(&ibdev_lsm_nb);
        if (ret) {
                pr_warn("Couldn't register LSM notifier. ret %d\n", ret);
                goto err_sa;
@@ -2539,7 +2539,7 @@ static int __init ib_core_init(void)
        return 0;
 
 err_compat:
-       unregister_lsm_notifier(&ibdev_lsm_nb);
+       unregister_blocking_lsm_notifier(&ibdev_lsm_nb);
 err_sa:
        ib_sa_cleanup();
 err_mad:
@@ -2565,7 +2565,7 @@ static void __exit ib_core_cleanup(void)
        nldev_exit();
        rdma_nl_unregister(RDMA_NL_LS);
        unregister_pernet_device(&rdma_dev_net_ops);
-       unregister_lsm_notifier(&ibdev_lsm_nb);
+       unregister_blocking_lsm_notifier(&ibdev_lsm_nb);
        ib_sa_cleanup();
        ib_mad_cleanup();
        addr_cleanup();
index 00036d2f57c30824aad747469f4d640dfd0d6857..a20ad398d260189e6eb9238abc5a1c65a85d81bf 100644 (file)
@@ -23,6 +23,7 @@ extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
 extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
                              enum kernel_read_file_id id);
 extern void ima_post_path_mknod(struct dentry *dentry);
+extern void ima_kexec_cmdline(const void *buf, int size);
 
 #ifdef CONFIG_IMA_KEXEC
 extern void ima_add_kexec_buffer(struct kimage *image);
@@ -89,6 +90,7 @@ static inline void ima_post_path_mknod(struct dentry *dentry)
        return;
 }
 
+static inline void ima_kexec_cmdline(const void *buf, int size) {}
 #endif /* CONFIG_IMA */
 
 #ifndef CONFIG_IMA_KEXEC
index 659071c2e57c63a950e4a7c92e2c8c238296d34e..5f7441abbf4291129fa2cb0dbe1daf1c9c51f057 100644 (file)
@@ -189,9 +189,9 @@ static inline const char *kernel_load_data_id_str(enum kernel_load_data_id id)
 
 #ifdef CONFIG_SECURITY
 
-int call_lsm_notifier(enum lsm_event event, void *data);
-int register_lsm_notifier(struct notifier_block *nb);
-int unregister_lsm_notifier(struct notifier_block *nb);
+int call_blocking_lsm_notifier(enum lsm_event event, void *data);
+int register_blocking_lsm_notifier(struct notifier_block *nb);
+int unregister_blocking_lsm_notifier(struct notifier_block *nb);
 
 /* prototypes */
 extern int security_init(void);
@@ -394,17 +394,17 @@ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
 #else /* CONFIG_SECURITY */
 
-static inline int call_lsm_notifier(enum lsm_event event, void *data)
+static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
 {
        return 0;
 }
 
-static inline int register_lsm_notifier(struct notifier_block *nb)
+static inline int register_blocking_lsm_notifier(struct notifier_block *nb)
 {
        return 0;
 }
 
-static inline  int unregister_lsm_notifier(struct notifier_block *nb)
+static inline  int unregister_blocking_lsm_notifier(struct notifier_block *nb)
 {
        return 0;
 }
index ef7b951a808703eff4d2ae9c798792c400c80f72..b8cc032d5620115547d38428a767dd2d40c6523b 100644 (file)
@@ -196,9 +196,6 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
                return ret;
        image->kernel_buf_len = size;
 
-       /* IMA needs to pass the measurement list to the next kernel. */
-       ima_add_kexec_buffer(image);
-
        /* Call arch image probe handlers */
        ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
                                            image->kernel_buf_len);
@@ -239,8 +236,14 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
                        ret = -EINVAL;
                        goto out;
                }
+
+               ima_kexec_cmdline(image->cmdline_buf,
+                                 image->cmdline_buf_len - 1);
        }
 
+       /* IMA needs to pass the measurement list to the next kernel. */
+       ima_add_kexec_buffer(image);
+
        /* Call arch image load handlers */
        ldata = arch_kexec_kernel_image_load(image);
 
index ceb10553a6ba64a093a747bf1f5f1605ba9fecf6..f9f3c8ffe7864e1f9b6441f0e6c1aa3cabdfc322 100644 (file)
@@ -70,8 +70,9 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
        return -EOPNOTSUPP;
 }
 
-static int __integrity_init_keyring(const unsigned int id, struct key_acl *acl,
-                                   struct key_restriction *restriction)
+static int __init __integrity_init_keyring(const unsigned int id,
+                                          struct key_acl *acl,
+                                          struct key_restriction *restriction)
 {
        const struct cred *cred = current_cred();
        int err = 0;
index 5bbd8b4dc29a66e0d8d0754557adf062b1fa3da1..f9a81b187fae9d1a8aea498cf790f5a08d306c35 100644 (file)
@@ -166,7 +166,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
        /* check value type */
        switch (xattr_data->type) {
        case EVM_XATTR_HMAC:
-               if (xattr_len != sizeof(struct evm_ima_xattr_data)) {
+               if (xattr_len != sizeof(struct evm_xattr)) {
                        evm_status = INTEGRITY_FAIL;
                        goto out;
                }
@@ -176,7 +176,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
                                   xattr_value_len, &digest);
                if (rc)
                        break;
-               rc = crypto_memneq(xattr_data->digest, digest.digest,
+               rc = crypto_memneq(xattr_data->data, digest.digest,
                                   SHA1_DIGEST_SIZE);
                if (rc)
                        rc = -EINVAL;
@@ -520,7 +520,7 @@ int evm_inode_init_security(struct inode *inode,
                                 const struct xattr *lsm_xattr,
                                 struct xattr *evm_xattr)
 {
-       struct evm_ima_xattr_data *xattr_data;
+       struct evm_xattr *xattr_data;
        int rc;
 
        if (!evm_key_loaded() || !evm_protected_xattr(lsm_xattr->name))
@@ -530,7 +530,7 @@ int evm_inode_init_security(struct inode *inode,
        if (!xattr_data)
                return -ENOMEM;
 
-       xattr_data->type = EVM_XATTR_HMAC;
+       xattr_data->data.type = EVM_XATTR_HMAC;
        rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
        if (rc < 0)
                goto out;
index 2692c7358c2c3027edc7eee2b8c795828448fa77..2ced99dde694806f96db3e85bc9204ebec7847a4 100644 (file)
@@ -160,7 +160,8 @@ config IMA_APPRAISE
 
 config IMA_ARCH_POLICY
         bool "Enable loading an IMA architecture specific policy"
-        depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
+        depends on (KEXEC_VERIFY_SIG && IMA) || IMA_APPRAISE \
+                  && INTEGRITY_ASYMMETRIC_KEYS
         default n
         help
           This option enables loading an IMA architecture specific policy
index ca10917b5f89ac2b322ea99c98f411a775ee8959..011b91c79351cdc4a765a6c475887bd30c298e50 100644 (file)
@@ -61,6 +61,8 @@ struct ima_event_data {
        struct evm_ima_xattr_data *xattr_value;
        int xattr_len;
        const char *violation;
+       const void *buf;
+       int buf_len;
 };
 
 /* IMA template field data definition */
@@ -142,7 +144,11 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
 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, u32 size);
+int template_desc_init_fields(const char *template_fmt,
+                             const struct ima_template_field ***fields,
+                             int *num_fields);
 struct ima_template_desc *ima_template_desc_current(void);
+struct ima_template_desc *lookup_template_desc(const char *name);
 int ima_restore_measurement_entry(struct ima_template_entry *entry);
 int ima_restore_measurement_list(loff_t bufsize, void *buf);
 int ima_measurements_show(struct seq_file *m, void *v);
@@ -150,6 +156,8 @@ unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
 void ima_init_template_list(void);
 int __init ima_init_digests(void);
+int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
+                         void *lsm_data);
 
 /*
  * used to protect h_table and sha_table
@@ -180,6 +188,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
        hook(KEXEC_KERNEL_CHECK)        \
        hook(KEXEC_INITRAMFS_CHECK)     \
        hook(POLICY_CHECK)              \
+       hook(KEXEC_CMDLINE)             \
        hook(MAX_CHECK)
 #define __ima_hook_enumify(ENUM)       ENUM,
 
@@ -189,7 +198,8 @@ enum ima_hooks {
 
 /* LIM API function definitions */
 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
-                  int mask, enum ima_hooks func, int *pcr);
+                  int mask, enum ima_hooks func, int *pcr,
+                  struct ima_template_desc **template_desc);
 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
                            struct file *file, void *buf, loff_t size,
@@ -197,11 +207,13 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
                           const unsigned char *filename,
                           struct evm_ima_xattr_data *xattr_value,
-                          int xattr_len, int pcr);
+                          int xattr_len, int pcr,
+                          struct ima_template_desc *template_desc);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
                           const unsigned char *filename);
 int ima_alloc_init_template(struct ima_event_data *event_data,
-                           struct ima_template_entry **entry);
+                           struct ima_template_entry **entry,
+                           struct ima_template_desc *template_desc);
 int ima_store_template(struct ima_template_entry *entry, int violation,
                       struct inode *inode,
                       const unsigned char *filename, int pcr);
@@ -210,7 +222,8 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
 
 /* IMA policy related functions */
 int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
-                    enum ima_hooks func, int mask, int flags, int *pcr);
+                    enum ima_hooks func, int mask, int flags, int *pcr,
+                    struct ima_template_desc **template_desc);
 void ima_init_policy(void);
 void ima_update_policy(void);
 void ima_update_policy_flag(void);
index 35c129cbb7e9bf9357d963c73e134f98b1a1c1dc..f614e22bf39f47134c5124ce0d003ce5343abcbf 100644 (file)
@@ -34,11 +34,17 @@ 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 ima_event_data *event_data,
-                           struct ima_template_entry **entry)
+                           struct ima_template_entry **entry,
+                           struct ima_template_desc *desc)
 {
-       struct ima_template_desc *template_desc = ima_template_desc_current();
+       struct ima_template_desc *template_desc;
        int i, result = 0;
 
+       if (desc)
+               template_desc = desc;
+       else
+               template_desc = ima_template_desc_current();
+
        *entry = kzalloc(sizeof(**entry) + template_desc->num_fields *
                         sizeof(struct ima_field_data), GFP_NOFS);
        if (!*entry)
@@ -129,15 +135,17 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
 {
        struct ima_template_entry *entry;
        struct inode *inode = file_inode(file);
-       struct ima_event_data event_data = {iint, file, filename, NULL, 0,
-                                           cause};
+       struct ima_event_data event_data = { .iint = iint,
+                                            .file = file,
+                                            .filename = filename,
+                                            .violation = cause };
        int violation = 1;
        int result;
 
        /* can overflow, only indicator */
        atomic_long_inc(&ima_htable.violations);
 
-       result = ima_alloc_init_template(&event_data, &entry);
+       result = ima_alloc_init_template(&event_data, &entry, NULL);
        if (result < 0) {
                result = -ENOMEM;
                goto err_out;
@@ -160,11 +168,13 @@ err_out:
  *        MAY_APPEND)
  * @func: caller identifier
  * @pcr: pointer filled in if matched measure policy sets pcr=
+ * @template_desc: pointer filled in if matched measure policy sets template=
  *
  * The policy is defined in terms of keypairs:
  *             subj=, obj=, type=, func=, mask=, fsmagic=
  *     subj,obj, and type: are LSM specific.
  *     func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
+ *     | KEXEC_CMDLINE
  *     mask: contains the permission mask
  *     fsmagic: hex value
  *
@@ -172,13 +182,15 @@ err_out:
  *
  */
 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
-                  int mask, enum ima_hooks func, int *pcr)
+                  int mask, enum ima_hooks func, int *pcr,
+                  struct ima_template_desc **template_desc)
 {
        int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
 
        flags &= ima_policy_flag;
 
-       return ima_match_policy(inode, cred, secid, func, mask, flags, pcr);
+       return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
+                               template_desc);
 }
 
 /*
@@ -273,21 +285,25 @@ out:
 void ima_store_measurement(struct integrity_iint_cache *iint,
                           struct file *file, const unsigned char *filename,
                           struct evm_ima_xattr_data *xattr_value,
-                          int xattr_len, int pcr)
+                          int xattr_len, int pcr,
+                          struct ima_template_desc *template_desc)
 {
        static const char op[] = "add_template_measure";
        static const char audit_cause[] = "ENOMEM";
        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};
+       struct ima_event_data event_data = { .iint = iint,
+                                            .file = file,
+                                            .filename = filename,
+                                            .xattr_value = xattr_value,
+                                            .xattr_len = xattr_len };
        int violation = 0;
 
        if (iint->measured_pcrs & (0x1 << pcr))
                return;
 
-       result = ima_alloc_init_template(&event_data, &entry);
+       result = ima_alloc_init_template(&event_data, &entry, template_desc);
        if (result < 0) {
                integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
                                    op, audit_cause, result, 0);
index f0cd67cab6aa2506ce094131f10cfc2bb28235b7..89b83194d1dc4813ec57160ab817b24ac84571e3 100644 (file)
@@ -54,7 +54,7 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
 
        security_task_getsecid(current, &secid);
        return ima_match_policy(inode, current_cred(), secid, func, mask,
-                               IMA_APPRAISE | IMA_HASH, NULL);
+                               IMA_APPRAISE | IMA_HASH, NULL, NULL);
 }
 
 static int ima_fix_xattr(struct dentry *dentry,
@@ -165,7 +165,8 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
                return sig->hash_algo;
                break;
        case IMA_XATTR_DIGEST_NG:
-               ret = xattr_value->digest[0];
+               /* first byte contains algorithm id */
+               ret = xattr_value->data[0];
                if (ret < HASH_ALGO__LAST)
                        return ret;
                break;
@@ -173,7 +174,7 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
                /* this is for backward compatibility */
                if (xattr_len == 21) {
                        unsigned int zero = 0;
-                       if (!memcmp(&xattr_value->digest[16], &zero, 4))
+                       if (!memcmp(&xattr_value->data[16], &zero, 4))
                                return HASH_ALGO_MD5;
                        else
                                return HASH_ALGO_SHA1;
@@ -272,7 +273,7 @@ int ima_appraise_measurement(enum ima_hooks func,
                        /* xattr length may be longer. md5 hash in previous
                           version occupied 20 bytes in xattr, instead of 16
                         */
-                       rc = memcmp(&xattr_value->digest[hash_start],
+                       rc = memcmp(&xattr_value->data[hash_start],
                                    iint->ima_hash->digest,
                                    iint->ima_hash->length);
                else
index 1e47c1026471656336b6fcb1f81b483c1c7c78d8..5d55ade5f3b9aca42fe6187b931cd1e50f449426 100644 (file)
@@ -45,8 +45,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};
+       struct ima_event_data event_data = { .iint = iint,
+                                            .filename = boot_aggregate_name };
        int result = -ENOMEM;
        int violation = 0;
        struct {
@@ -68,7 +68,7 @@ static int __init ima_add_boot_aggregate(void)
                }
        }
 
-       result = ima_alloc_init_template(&event_data, &entry);
+       result = ima_alloc_init_template(&event_data, &entry, NULL);
        if (result < 0) {
                audit_cause = "alloc_entry";
                goto err_out;
index f556e6c18f9b6ed376333dea73b2921efd00c976..584019728660a906867be32f342d605d4fb52ab0 100644 (file)
@@ -39,6 +39,10 @@ int ima_appraise;
 int ima_hash_algo = HASH_ALGO_SHA1;
 static int hash_setup_done;
 
+static struct notifier_block ima_lsm_policy_notifier = {
+       .notifier_call = ima_lsm_policy_change,
+};
+
 static int __init hash_setup(char *str)
 {
        struct ima_template_desc *template_desc = ima_template_desc_current();
@@ -68,6 +72,27 @@ out:
 }
 __setup("ima_hash=", hash_setup);
 
+/* Prevent mmap'ing a file execute that is already mmap'ed write */
+static int mmap_violation_check(enum ima_hooks func, struct file *file,
+                               char **pathbuf, const char **pathname,
+                               char *filename)
+{
+       struct inode *inode;
+       int rc = 0;
+
+       if ((func == MMAP_CHECK) && mapping_writably_mapped(file->f_mapping)) {
+               rc = -ETXTBSY;
+               inode = file_inode(file);
+
+               if (!*pathbuf)  /* ima_rdwr_violation possibly pre-fetched */
+                       *pathname = ima_d_path(&file->f_path, pathbuf,
+                                              filename);
+               integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, *pathname,
+                                   "mmap_file", "mmapped_writers", rc, 0);
+       }
+       return rc;
+}
+
 /*
  * ima_rdwr_violation_check
  *
@@ -170,7 +195,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
 {
        struct inode *inode = file_inode(file);
        struct integrity_iint_cache *iint = NULL;
-       struct ima_template_desc *template_desc;
+       struct ima_template_desc *template_desc = NULL;
        char *pathbuf = NULL;
        char filename[NAME_MAX];
        const char *pathname = NULL;
@@ -188,7 +213,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
         * bitmask based on the appraise/audit/measurement policy.
         * Included is the appraise submask.
         */
-       action = ima_get_action(inode, cred, secid, mask, func, &pcr);
+       action = ima_get_action(inode, cred, secid, mask, func, &pcr,
+                               &template_desc);
        violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
                           (ima_policy_flag & IMA_MEASURE));
        if (!action && !violation_check)
@@ -266,12 +292,15 @@ static int process_measurement(struct file *file, const struct cred *cred,
 
        /* Nothing to do, just return existing appraised status */
        if (!action) {
-               if (must_appraise)
-                       rc = ima_get_cache_status(iint, func);
+               if (must_appraise) {
+                       rc = mmap_violation_check(func, file, &pathbuf,
+                                                 &pathname, filename);
+                       if (!rc)
+                               rc = ima_get_cache_status(iint, func);
+               }
                goto out_locked;
        }
 
-       template_desc = ima_template_desc_current();
        if ((action & IMA_APPRAISE_SUBMASK) ||
                    strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
                /* read 'security.ima' */
@@ -288,12 +317,16 @@ static int process_measurement(struct file *file, const struct cred *cred,
 
        if (action & IMA_MEASURE)
                ima_store_measurement(iint, file, pathname,
-                                     xattr_value, xattr_len, pcr);
+                                     xattr_value, xattr_len, pcr,
+                                     template_desc);
        if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
                inode_lock(inode);
                rc = ima_appraise_measurement(func, iint, file, pathname,
                                              xattr_value, xattr_len);
                inode_unlock(inode);
+               if (!rc)
+                       rc = mmap_violation_check(func, file, &pathbuf,
+                                                 &pathname, filename);
        }
        if (action & IMA_AUDIT)
                ima_audit_measurement(iint, pathname);
@@ -572,6 +605,80 @@ int ima_load_data(enum kernel_load_data_id id)
        return 0;
 }
 
+/*
+ * process_buffer_measurement - Measure the buffer to ima log.
+ * @buf: pointer to the buffer that needs to be added to the log.
+ * @size: size of buffer(in bytes).
+ * @eventname: event name to be used for the buffer entry.
+ * @cred: a pointer to a credentials structure for user validation.
+ * @secid: the secid of the task to be validated.
+ *
+ * Based on policy, the buffer is measured into the ima log.
+ */
+static void process_buffer_measurement(const void *buf, int size,
+                                      const char *eventname,
+                                      const struct cred *cred, u32 secid)
+{
+       int ret = 0;
+       struct ima_template_entry *entry = NULL;
+       struct integrity_iint_cache iint = {};
+       struct ima_event_data event_data = {.iint = &iint,
+                                           .filename = eventname,
+                                           .buf = buf,
+                                           .buf_len = size};
+       struct ima_template_desc *template_desc = NULL;
+       struct {
+               struct ima_digest_data hdr;
+               char digest[IMA_MAX_DIGEST_SIZE];
+       } hash = {};
+       int violation = 0;
+       int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+       int action = 0;
+
+       action = ima_get_action(NULL, cred, secid, 0, KEXEC_CMDLINE, &pcr,
+                               &template_desc);
+       if (!(action & IMA_MEASURE))
+               return;
+
+       iint.ima_hash = &hash.hdr;
+       iint.ima_hash->algo = ima_hash_algo;
+       iint.ima_hash->length = hash_digest_size[ima_hash_algo];
+
+       ret = ima_calc_buffer_hash(buf, size, iint.ima_hash);
+       if (ret < 0)
+               goto out;
+
+       ret = ima_alloc_init_template(&event_data, &entry, template_desc);
+       if (ret < 0)
+               goto out;
+
+       ret = ima_store_template(entry, violation, NULL, buf, pcr);
+
+       if (ret < 0)
+               ima_free_template_entry(entry);
+
+out:
+       return;
+}
+
+/**
+ * ima_kexec_cmdline - measure kexec cmdline boot args
+ * @buf: pointer to buffer
+ * @size: size of buffer
+ *
+ * Buffers can only be measured, not appraised.
+ */
+void ima_kexec_cmdline(const void *buf, int size)
+{
+       u32 secid;
+
+       if (buf && size != 0) {
+               security_task_getsecid(current, &secid);
+               process_buffer_measurement(buf, size, "kexec-cmdline",
+                                          current_cred(), secid);
+       }
+}
+
 static int __init init_ima(void)
 {
        int error;
@@ -589,6 +696,10 @@ static int __init init_ima(void)
                error = ima_init();
        }
 
+       error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier);
+       if (error)
+               pr_warn("Couldn't register LSM notifier, error %d\n", error);
+
        if (!error)
                ima_update_policy_flag();
 
index 7b53f2ca58e285f75c21286e7e405f118117fe7b..6df7f641ff66658e7793185a51c04862e7100728 100644 (file)
@@ -76,6 +76,7 @@ struct ima_rule_entry {
                int type;       /* audit type */
        } lsm[MAX_LSM_RULES];
        char *fsname;
+       struct ima_template_desc *template;
 };
 
 /*
@@ -195,7 +196,7 @@ static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
 };
 
 /* An array of architecture specific rules */
-struct ima_rule_entry *arch_policy_entry __ro_after_init;
+static struct ima_rule_entry *arch_policy_entry __ro_after_init;
 
 static LIST_HEAD(ima_default_rules);
 static LIST_HEAD(ima_policy_rules);
@@ -245,31 +246,113 @@ static int __init default_appraise_policy_setup(char *str)
 }
 __setup("ima_appraise_tcb", default_appraise_policy_setup);
 
+static void ima_lsm_free_rule(struct ima_rule_entry *entry)
+{
+       int i;
+
+       for (i = 0; i < MAX_LSM_RULES; i++) {
+               kfree(entry->lsm[i].rule);
+               kfree(entry->lsm[i].args_p);
+       }
+       kfree(entry);
+}
+
+static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
+{
+       struct ima_rule_entry *nentry;
+       int i, result;
+
+       nentry = kmalloc(sizeof(*nentry), GFP_KERNEL);
+       if (!nentry)
+               return NULL;
+
+       /*
+        * Immutable elements are copied over as pointers and data; only
+        * lsm rules can change
+        */
+       memcpy(nentry, entry, sizeof(*nentry));
+       memset(nentry->lsm, 0, FIELD_SIZEOF(struct ima_rule_entry, lsm));
+
+       for (i = 0; i < MAX_LSM_RULES; i++) {
+               if (!entry->lsm[i].rule)
+                       continue;
+
+               nentry->lsm[i].type = entry->lsm[i].type;
+               nentry->lsm[i].args_p = kstrdup(entry->lsm[i].args_p,
+                                               GFP_KERNEL);
+               if (!nentry->lsm[i].args_p)
+                       goto out_err;
+
+               result = security_filter_rule_init(nentry->lsm[i].type,
+                                                  Audit_equal,
+                                                  nentry->lsm[i].args_p,
+                                                  &nentry->lsm[i].rule);
+               if (result == -EINVAL)
+                       pr_warn("ima: rule for LSM \'%d\' is undefined\n",
+                               entry->lsm[i].type);
+       }
+       return nentry;
+
+out_err:
+       ima_lsm_free_rule(nentry);
+       return NULL;
+}
+
+static int ima_lsm_update_rule(struct ima_rule_entry *entry)
+{
+       struct ima_rule_entry *nentry;
+
+       nentry = ima_lsm_copy_rule(entry);
+       if (!nentry)
+               return -ENOMEM;
+
+       list_replace_rcu(&entry->list, &nentry->list);
+       synchronize_rcu();
+       ima_lsm_free_rule(entry);
+
+       return 0;
+}
+
 /*
  * The LSM policy can be reloaded, leaving the IMA LSM based rules referring
  * to the old, stale LSM policy.  Update the IMA LSM based rules to reflect
- * the reloaded LSM policy.  We assume the rules still exist; and BUG_ON() if
- * they don't.
+ * the reloaded LSM policy.
  */
 static void ima_lsm_update_rules(void)
 {
-       struct ima_rule_entry *entry;
-       int result;
-       int i;
+       struct ima_rule_entry *entry, *e;
+       int i, result, needs_update;
 
-       list_for_each_entry(entry, &ima_policy_rules, list) {
+       list_for_each_entry_safe(entry, e, &ima_policy_rules, list) {
+               needs_update = 0;
                for (i = 0; i < MAX_LSM_RULES; i++) {
-                       if (!entry->lsm[i].rule)
-                               continue;
-                       result = security_filter_rule_init(entry->lsm[i].type,
-                                                          Audit_equal,
-                                                          entry->lsm[i].args_p,
-                                                          &entry->lsm[i].rule);
-                       BUG_ON(!entry->lsm[i].rule);
+                       if (entry->lsm[i].rule) {
+                               needs_update = 1;
+                               break;
+                       }
+               }
+               if (!needs_update)
+                       continue;
+
+               result = ima_lsm_update_rule(entry);
+               if (result) {
+                       pr_err("ima: lsm rule update error %d\n",
+                               result);
+                       return;
                }
        }
 }
 
+int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
+                         void *lsm_data)
+{
+       if (event != LSM_POLICY_CHANGE)
+               return NOTIFY_DONE;
+
+       ima_lsm_update_rules();
+       return NOTIFY_OK;
+}
+
 /**
  * ima_match_rules - determine whether an inode matches the measure rule.
  * @rule: a pointer to a rule
@@ -287,6 +370,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
 {
        int i;
 
+       if (func == KEXEC_CMDLINE) {
+               if ((rule->flags & IMA_FUNC) && (rule->func == func))
+                       return true;
+               return false;
+       }
        if ((rule->flags & IMA_FUNC) &&
            (rule->func != func && func != POST_SETATTR))
                return false;
@@ -323,11 +411,10 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
        for (i = 0; i < MAX_LSM_RULES; i++) {
                int rc = 0;
                u32 osid;
-               int retried = 0;
 
                if (!rule->lsm[i].rule)
                        continue;
-retry:
+
                switch (i) {
                case LSM_OBJ_USER:
                case LSM_OBJ_ROLE:
@@ -348,11 +435,6 @@ retry:
                default:
                        break;
                }
-               if ((rc < 0) && (!retried)) {
-                       retried = 1;
-                       ima_lsm_update_rules();
-                       goto retry;
-               }
                if (!rc)
                        return false;
        }
@@ -393,6 +475,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
  * @func: IMA hook identifier
  * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
  * @pcr: set the pcr to extend
+ * @template_desc: the template that should be used for this rule
  *
  * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
  * conditions.
@@ -402,7 +485,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
  * than writes so ima_match_policy() is classical RCU candidate.
  */
 int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
-                    enum ima_hooks func, int mask, int flags, int *pcr)
+                    enum ima_hooks func, int mask, int flags, int *pcr,
+                    struct ima_template_desc **template_desc)
 {
        struct ima_rule_entry *entry;
        int action = 0, actmask = flags | (flags << 1);
@@ -434,6 +518,11 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
                if ((pcr) && (entry->flags & IMA_PCR))
                        *pcr = entry->pcr;
 
+               if (template_desc && entry->template)
+                       *template_desc = entry->template;
+               else if (template_desc)
+                       *template_desc = ima_template_desc_current();
+
                if (!actmask)
                        break;
        }
@@ -672,7 +761,7 @@ enum {
        Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
        Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
        Opt_appraise_type, Opt_permit_directio,
-       Opt_pcr, Opt_err
+       Opt_pcr, Opt_template, Opt_err
 };
 
 static const match_table_t policy_tokens = {
@@ -706,6 +795,7 @@ static const match_table_t policy_tokens = {
        {Opt_appraise_type, "appraise_type=%s"},
        {Opt_permit_directio, "permit_directio"},
        {Opt_pcr, "pcr=%s"},
+       {Opt_template, "template=%s"},
        {Opt_err, NULL}
 };
 
@@ -759,6 +849,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
        char *from;
        char *p;
        bool uid_token;
+       struct ima_template_desc *template_desc;
        int result = 0;
 
        ab = integrity_audit_log_start(audit_context(), GFP_KERNEL,
@@ -866,6 +957,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                                entry->func = KEXEC_INITRAMFS_CHECK;
                        else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
                                entry->func = POLICY_CHECK;
+                       else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0)
+                               entry->func = KEXEC_CMDLINE;
                        else
                                result = -EINVAL;
                        if (!result)
@@ -1054,6 +1147,28 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                        else
                                entry->flags |= IMA_PCR;
 
+                       break;
+               case Opt_template:
+                       ima_log_string(ab, "template", args[0].from);
+                       if (entry->action != MEASURE) {
+                               result = -EINVAL;
+                               break;
+                       }
+                       template_desc = lookup_template_desc(args[0].from);
+                       if (!template_desc || entry->template) {
+                               result = -EINVAL;
+                               break;
+                       }
+
+                       /*
+                        * template_desc_init_fields() does nothing if
+                        * the template is already initialised, so
+                        * it's safe to do this unconditionally
+                        */
+                       template_desc_init_fields(template_desc->fmt,
+                                                &(template_desc->fields),
+                                                &(template_desc->num_fields));
+                       entry->template = template_desc;
                        break;
                case Opt_err:
                        ima_log_string(ab, "UNKNOWN", p);
@@ -1330,6 +1445,8 @@ int ima_policy_show(struct seq_file *m, void *v)
                        }
                }
        }
+       if (entry->template)
+               seq_printf(m, "template=%s ", entry->template->name);
        if (entry->flags & IMA_DIGSIG_REQUIRED)
                seq_puts(m, "appraise_type=imasig ");
        if (entry->flags & IMA_PERMIT_DIRECTIO)
index f4354c267396b0709093687a93500c055dea255b..cb349d7b26015906c198dc4cc8650e63002a0919 100644 (file)
@@ -22,6 +22,7 @@ static struct ima_template_desc builtin_templates[] = {
        {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
        {.name = "ima-ng", .fmt = "d-ng|n-ng"},
        {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
+       {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"},
        {.name = "", .fmt = ""},        /* placeholder for a custom format */
 };
 
@@ -39,14 +40,18 @@ static const struct ima_template_field supported_fields[] = {
         .field_show = ima_show_template_string},
        {.field_id = "sig", .field_init = ima_eventsig_init,
         .field_show = ima_show_template_sig},
+       {.field_id = "buf", .field_init = ima_eventbuf_init,
+        .field_show = ima_show_template_buf},
 };
-#define MAX_TEMPLATE_NAME_LEN 15
+
+/*
+ * Used when restoring measurements carried over from a kexec. 'd' and 'n' don't
+ * need to be accounted for since they shouldn't be defined in the same template
+ * description as 'd-ng' and 'n-ng' respectively.
+ */
+#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf")
 
 static struct ima_template_desc *ima_template;
-static struct ima_template_desc *lookup_template_desc(const char *name);
-static int template_desc_init_fields(const char *template_fmt,
-                                    const struct ima_template_field ***fields,
-                                    int *num_fields);
 
 static int __init ima_template_setup(char *str)
 {
@@ -104,7 +109,7 @@ static int __init ima_template_fmt_setup(char *str)
 }
 __setup("ima_template_fmt=", ima_template_fmt_setup);
 
-static struct ima_template_desc *lookup_template_desc(const char *name)
+struct ima_template_desc *lookup_template_desc(const char *name)
 {
        struct ima_template_desc *template_desc;
        int found = 0;
@@ -149,9 +154,9 @@ static int template_fmt_size(const char *template_fmt)
        return j + 1;
 }
 
-static int template_desc_init_fields(const char *template_fmt,
-                                    const struct ima_template_field ***fields,
-                                    int *num_fields)
+int template_desc_init_fields(const char *template_fmt,
+                             const struct ima_template_field ***fields,
+                             int *num_fields)
 {
        const char *template_fmt_ptr;
        const struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];
index 9fe0ef7f91e2e0db14613cf5865062f6cca71ec4..2fb9a10bc6b7f3fb311dbc646035f5c96a09e07f 100644 (file)
@@ -158,6 +158,12 @@ void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
        ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
 }
 
+void ima_show_template_buf(struct seq_file *m, enum ima_show_type show,
+                          struct ima_field_data *field_data)
+{
+       ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
+}
+
 /**
  * ima_parse_buf() - Parses lengths and data from an input buffer
  * @bufstartp:       Buffer start address.
@@ -385,3 +391,18 @@ int ima_eventsig_init(struct ima_event_data *event_data,
        return ima_write_template_field_data(xattr_value, event_data->xattr_len,
                                             DATA_FMT_HEX, field_data);
 }
+
+/*
+ *  ima_eventbuf_init - include the buffer(kexec-cmldine) as part of the
+ *  template data.
+ */
+int ima_eventbuf_init(struct ima_event_data *event_data,
+                     struct ima_field_data *field_data)
+{
+       if ((!event_data->buf) || (event_data->buf_len == 0))
+               return 0;
+
+       return ima_write_template_field_data(event_data->buf,
+                                            event_data->buf_len, DATA_FMT_HEX,
+                                            field_data);
+}
index e515955456a3393422811152a1f52bdb0cc2f640..652aa5de81ef1a59807c5e4587052f8c7ba92b6d 100644 (file)
@@ -25,6 +25,8 @@ 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);
+void ima_show_template_buf(struct seq_file *m, enum ima_show_type show,
+                          struct ima_field_data *field_data);
 int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
                  int maxfields, struct ima_field_data *fields, int *curfields,
                  unsigned long *len_mask, int enforce_mask, char *bufname);
@@ -38,4 +40,6 @@ int ima_eventname_ng_init(struct ima_event_data *event_data,
                          struct ima_field_data *field_data);
 int ima_eventsig_init(struct ima_event_data *event_data,
                      struct ima_field_data *field_data);
+int ima_eventbuf_init(struct ima_event_data *event_data,
+                     struct ima_field_data *field_data);
 #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
index 45f4aef83e29e89576221e18e4ec7b09d0f66c20..875c6a7a5af1a63113e838d86caa7112274cd77a 100644 (file)
@@ -76,6 +76,12 @@ enum evm_ima_xattr_type {
 
 struct evm_ima_xattr_data {
        u8 type;
+       u8 data[];
+} __packed;
+
+/* Only used in the EVM HMAC code. */
+struct evm_xattr {
+       struct evm_ima_xattr_data data;
        u8 digest[SHA1_DIGEST_SIZE];
 } __packed;
 
index f493db0bf62a9c51361b3d4d3c7b025a9d11f38b..250ee2d76406d76b5746259fe76dbbed9f51f13b 100644 (file)
@@ -35,7 +35,7 @@
 #define LSM_COUNT (__end_lsm_info - __start_lsm_info)
 
 struct security_hook_heads security_hook_heads __lsm_ro_after_init;
-static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
+static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
 
 static struct kmem_cache *lsm_file_cache;
 static struct kmem_cache *lsm_inode_cache;
@@ -426,23 +426,26 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
                panic("%s - Cannot get early memory.\n", __func__);
 }
 
-int call_lsm_notifier(enum lsm_event event, void *data)
+int call_blocking_lsm_notifier(enum lsm_event event, void *data)
 {
-       return atomic_notifier_call_chain(&lsm_notifier_chain, event, data);
+       return blocking_notifier_call_chain(&blocking_lsm_notifier_chain,
+                                           event, data);
 }
-EXPORT_SYMBOL(call_lsm_notifier);
+EXPORT_SYMBOL(call_blocking_lsm_notifier);
 
-int register_lsm_notifier(struct notifier_block *nb)
+int register_blocking_lsm_notifier(struct notifier_block *nb)
 {
-       return atomic_notifier_chain_register(&lsm_notifier_chain, nb);
+       return blocking_notifier_chain_register(&blocking_lsm_notifier_chain,
+                                               nb);
 }
-EXPORT_SYMBOL(register_lsm_notifier);
+EXPORT_SYMBOL(register_blocking_lsm_notifier);
 
-int unregister_lsm_notifier(struct notifier_block *nb)
+int unregister_blocking_lsm_notifier(struct notifier_block *nb)
 {
-       return atomic_notifier_chain_unregister(&lsm_notifier_chain, nb);
+       return blocking_notifier_chain_unregister(&blocking_lsm_notifier_chain,
+                                                 nb);
 }
-EXPORT_SYMBOL(unregister_lsm_notifier);
+EXPORT_SYMBOL(unregister_blocking_lsm_notifier);
 
 /**
  * lsm_cred_alloc - allocate a composite cred blob
index 4ed83d869084830c3ca19a1392d538247c842785..4bef86ed463b5c42b420dc105c6b7c4a3628aaae 100644 (file)
@@ -194,7 +194,7 @@ static int selinux_lsm_notifier_avc_callback(u32 event)
 {
        if (event == AVC_CALLBACK_RESET) {
                sel_ib_pkey_flush();
-               call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
+               call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
        }
 
        return 0;
index 1884f34bb9832eff210065e9043207755f3f98d8..6f195c7915de0c14ae39fabea3a406f1800e3a32 100644 (file)
@@ -178,7 +178,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
                selnl_notify_setenforce(new_value);
                selinux_status_update_setenforce(state, new_value);
                if (!new_value)
-                       call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
+                       call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
        }
        length = count;
 out: