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         | 15 +++++++++++----
 include/linux/ima.h                   |  2 +-
 security/integrity/ima/ima.h          |  2 +-
 security/integrity/ima/ima_appraise.c |  5 -----
 security/integrity/ima/ima_main.c     |  2 +-
 security/integrity/ima/ima_policy.c   | 23 +++++++++++------------
 security/integrity/integrity.h        | 11 ++++-------
 7 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8524450..dcd902f 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>
 
@@ -305,11 +306,17 @@ static int fw_read_file_contents(struct file *file, 
struct firmware_buf *fw_buf)
        buf = vmalloc(size);
        if (!buf)
                return -ENOMEM;
-       rc = kernel_read(file, 0, buf, size);
-       if (rc != size) {
-               if (rc > 0)
-                       rc = -EIO;
+
+       rc = ima_read_and_process_file(file, FIRMWARE_CHECK, buf, size);
+       if (rc == -EIO)
                goto fail;
+       else if (rc != -EOPNOTSUPP) {
+               rc = kernel_read(file, 0, buf, size);
+               if (rc != size) {
+                       if (rc > 0)
+                               rc = -EIO;
+                       goto fail;
+               }
        }
        rc = security_kernel_fw_from_file(file, buf, size);
        if (rc)
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 5d83ecf..7bd4e07 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -13,7 +13,7 @@
 #include <linux/fs.h>
 struct linux_binprm;
 
-enum ima_read_hooks { KEXEC_CHECK = 1, INITRAMFS_CHECK, IMA_MAX_READ_CHECK};
+enum ima_read_hooks { KEXEC_CHECK = 1, INITRAMFS_CHECK, FIRMWARE_CHECK, 
IMA_MAX_READ_CHECK};
 
 #ifdef CONFIG_IMA
 extern int ima_bprm_check(struct linux_binprm *bprm);
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 8dc9077..548b258 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -160,7 +160,7 @@ void ima_free_template_entry(struct ima_template_entry 
*entry);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
 /* IMA policy related functions */
-enum ima_hooks { FILE_CHECK = IMA_MAX_READ_CHECK, MMAP_CHECK, BPRM_CHECK, 
MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR};
+enum ima_hooks { FILE_CHECK = IMA_MAX_READ_CHECK, MMAP_CHECK, BPRM_CHECK, 
MODULE_CHECK, POST_SETATTR};
 
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
                     int flags);
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index e58df45..b83049b 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -77,7 +77,6 @@ enum integrity_status ima_get_cache_status(struct 
integrity_iint_cache *iint,
        case MODULE_CHECK:
                return iint->ima_module_status;
        case FIRMWARE_CHECK:
-               return iint->ima_firmware_status;
        case KEXEC_CHECK:
        case INITRAMFS_CHECK:
                return iint->ima_read_status;
@@ -101,8 +100,6 @@ static void ima_set_cache_status(struct 
integrity_iint_cache *iint,
                iint->ima_module_status = status;
                break;
        case FIRMWARE_CHECK:
-               iint->ima_firmware_status = status;
-               break;
        case KEXEC_CHECK:
        case INITRAMFS_CHECK:
                iint->ima_read_status = status;
@@ -127,8 +124,6 @@ static void ima_cache_flags(struct integrity_iint_cache 
*iint, int func)
                iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED);
                break;
        case FIRMWARE_CHECK:
-               iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED);
-               break;
        case KEXEC_CHECK:
        case INITRAMFS_CHECK:
                iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED);
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index b8b0b8c..f9206cd 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -375,7 +375,7 @@ int ima_fw_from_file(struct file *file, char *buf, size_t 
size)
                        return -EACCES; /* INTEGRITY_UNKNOWN */
                return 0;
        }
-       return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, NULL, 0);
+       return 0;
 }
 
 static int __init init_ima(void)
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 6fe0ab9..a65cb2a 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[] = {
@@ -305,7 +305,6 @@ static int get_subaction(struct ima_rule_entry *rule, int 
func)
        case MODULE_CHECK:
                return IMA_MODULE_APPRAISE;
        case FIRMWARE_CHECK:
-               return IMA_FIRMWARE_APPRAISE;
        case KEXEC_CHECK:
        case INITRAMFS_CHECK:
                return IMA_READ_APPRAISE;
@@ -603,8 +602,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;
@@ -614,6 +611,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)
@@ -770,7 +769,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);
@@ -857,8 +856,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[] = {
@@ -866,10 +865,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)
@@ -943,9 +942,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;
@@ -957,6 +953,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..e6c37a4 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