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