Instead of reading the firmware twice, once for measuring/appraising
the firmware and again reading the file contents into memory, this
patch reads the firmware once.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 drivers/base/firmware_class.c         |  5 +++++
 include/linux/ima.h                   |  1 +
 security/integrity/ima/ima.h          |  1 -
 security/integrity/ima/ima_appraise.c |  8 --------
 security/integrity/ima/ima_main.c     |  2 +-
 security/integrity/ima/ima_policy.c   | 24 +++++++++++-------------
 security/integrity/integrity.h        | 11 ++++-------
 7 files changed, 22 insertions(+), 30 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8524450..3ca96a6 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -29,6 +29,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/ima.h>
 
 #include <generated/utsrelease.h>
 
@@ -311,6 +312,10 @@ static int fw_read_file_contents(struct file *file, struct 
firmware_buf *fw_buf)
                        rc = -EIO;
                goto fail;
        }
+       rc = ima_hash_and_process_file(file, buf, size, FIRMWARE_CHECK);
+       if (rc)
+               goto fail;
+
        rc = security_kernel_fw_from_file(file, buf, size);
        if (rc)
                goto fail;
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 020de0f..c40fb3d 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -16,6 +16,7 @@ struct linux_binprm;
 enum ima_read_hooks {
        KEXEC_CHECK = 1,
        INITRAMFS_CHECK,
+       FIRMWARE_CHECK,
        IMA_MAX_READ_CHECK
 };
 
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index fa801fa..7fb0ab7 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -165,7 +165,6 @@ enum ima_hooks {
        MMAP_CHECK,
        BPRM_CHECK,
        MODULE_CHECK,
-       FIRMWARE_CHECK,
        POST_SETATTR
 };
 
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 3adf937..57b1ad1 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -76,8 +76,6 @@ enum integrity_status ima_get_cache_status(struct 
integrity_iint_cache *iint,
                return iint->ima_bprm_status;
        case MODULE_CHECK:
                return iint->ima_module_status;
-       case FIRMWARE_CHECK:
-               return iint->ima_firmware_status;
        case KEXEC_CHECK ... IMA_MAX_READ_CHECK - 1:
                return iint->ima_read_status;
        case FILE_CHECK:
@@ -99,9 +97,6 @@ static void ima_set_cache_status(struct integrity_iint_cache 
*iint,
        case MODULE_CHECK:
                iint->ima_module_status = status;
                break;
-       case FIRMWARE_CHECK:
-               iint->ima_firmware_status = status;
-               break;
        case KEXEC_CHECK ... IMA_MAX_READ_CHECK - 1:
                iint->ima_read_status = status;
                break;
@@ -124,9 +119,6 @@ static void ima_cache_flags(struct integrity_iint_cache 
*iint, int func)
        case MODULE_CHECK:
                iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED);
                break;
-       case FIRMWARE_CHECK:
-               iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED);
-               break;
        case KEXEC_CHECK ... IMA_MAX_READ_CHECK - 1:
                break;
        case FILE_CHECK:
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index cd9c576..c55ee06 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -345,7 +345,7 @@ int ima_fw_from_file(struct file *file, char *buf, size_t 
size)
                        return -EACCES; /* INTEGRITY_UNKNOWN */
                return 0;
        }
-       return process_measurement(file, NULL, 0, MAY_EXEC, FIRMWARE_CHECK, 0);
+       return 0;
 }
 
 /**
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 26e24df..6ac25c5 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -102,7 +102,7 @@ static struct ima_rule_entry original_measurement_rules[] = 
{
        {.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},
+       {.action = MEASURE, .read_func = FIRMWARE_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_measurement_rules[] = {
@@ -115,7 +115,7 @@ static struct ima_rule_entry default_measurement_rules[] = {
        {.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},
+       {.action = MEASURE, .read_func = FIRMWARE_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_appraise_rules[] = {
@@ -304,8 +304,6 @@ static int get_subaction(struct ima_rule_entry *rule, int 
func)
                return IMA_BPRM_APPRAISE;
        case MODULE_CHECK:
                return IMA_MODULE_APPRAISE;
-       case FIRMWARE_CHECK:
-               return IMA_FIRMWARE_APPRAISE;
        case KEXEC_CHECK ... IMA_MAX_READ_CHECK - 1:
                return IMA_READ_APPRAISE;
        case FILE_CHECK:
@@ -601,8 +599,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
                                entry->func = FILE_CHECK;
                        else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
                                entry->func = MODULE_CHECK;
-                       else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0)
-                               entry->func = FIRMWARE_CHECK;
                        else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
                                || (strcmp(args[0].from, "MMAP_CHECK") == 0))
                                entry->func = MMAP_CHECK;
@@ -612,6 +608,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
                                entry->read_func = KEXEC_CHECK;
                        else if (strcmp(args[0].from, "INITRAMFS_CHECK") == 0)
                                entry->read_func = INITRAMFS_CHECK;
+                       else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0)
+                               entry->read_func = FIRMWARE_CHECK;
                        else
                                result = -EINVAL;
                        if (!result)
@@ -768,7 +766,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
                result = -EINVAL;
        else if (entry->func == MODULE_CHECK)
                temp_ima_appraise |= IMA_APPRAISE_MODULES;
-       else if (entry->func == FIRMWARE_CHECK)
+       else if (entry->read_func == FIRMWARE_CHECK)
                temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
        audit_log_format(ab, "res=%d", !result);
        audit_log_end(ab);
@@ -855,8 +853,8 @@ static char *mask_tokens[] = {
 
 enum {
        func_file = 0, func_mmap, func_bprm,
-       func_module, func_firmware, func_post,
-       func_kexec, func_initramfs
+       func_module, func_post,
+       func_kexec, func_initramfs, func_firmware
 };
 
 static char *func_tokens[] = {
@@ -864,10 +862,10 @@ static char *func_tokens[] = {
        "MMAP_CHECK",
        "BPRM_CHECK",
        "MODULE_CHECK",
-       "FIRMWARE_CHECK",
        "POST_SETATTR",
        "KEXEC_CHECK",
        "INITRAMFS_CHECK",
+       "FIRMWARE_CHECK"
 };
 
 void *ima_policy_start(struct seq_file *m, loff_t *pos)
@@ -941,9 +939,6 @@ int ima_policy_show(struct seq_file *m, void *v)
                case MODULE_CHECK:
                        seq_printf(m, pt(Opt_func), ft(func_module));
                        break;
-               case FIRMWARE_CHECK:
-                       seq_printf(m, pt(Opt_func), ft(func_firmware));
-                       break;
                case POST_SETATTR:
                        seq_printf(m, pt(Opt_func), ft(func_post));
                        break;
@@ -955,6 +950,9 @@ int ima_policy_show(struct seq_file *m, void *v)
                        case INITRAMFS_CHECK:
                                seq_printf(m, pt(Opt_func), ft(func_initramfs));
                                break;
+                       case FIRMWARE_CHECK:
+                               seq_printf(m, pt(Opt_func), ft(func_firmware));
+                               break;
                        default:
                                snprintf(tbuf, sizeof(tbuf), "%d", entry->func);
                                seq_printf(m, pt(Opt_func), tbuf);
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 645d5be..164bbf6 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -47,16 +47,14 @@
 #define IMA_BPRM_APPRAISED     0x00002000
 #define IMA_MODULE_APPRAISE    0x00004000
 #define IMA_MODULE_APPRAISED   0x00008000
-#define IMA_FIRMWARE_APPRAISE  0x00010000
-#define IMA_FIRMWARE_APPRAISED 0x00020000
-#define IMA_READ_APPRAISE      0x00040000
-#define IMA_READ_APPRAISED     0x00080000
+#define IMA_READ_APPRAISE      0x00010000
+#define IMA_READ_APPRAISED     0x00020000
 #define IMA_APPRAISE_SUBMASK   (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \
                                 IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \
-                                IMA_FIRMWARE_APPRAISE | IMA_READ_APPRAISE)
+                                IMA_READ_APPRAISE)
 #define IMA_APPRAISED_SUBMASK  (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \
                                 IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \
-                                IMA_FIRMWARE_APPRAISED | IMA_READ_APPRAISED)
+                                IMA_READ_APPRAISED)
 
 enum evm_ima_xattr_type {
        IMA_XATTR_DIGEST = 0x01,
@@ -112,7 +110,6 @@ struct integrity_iint_cache {
        enum integrity_status ima_mmap_status:4;
        enum integrity_status ima_bprm_status:4;
        enum integrity_status ima_module_status:4;
-       enum integrity_status ima_firmware_status:4;
        enum integrity_status ima_read_status:4;
        enum integrity_status evm_status:4;
        struct ima_digest_data *ima_hash;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to