diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2014-07-22 10:39:48 -0400 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2014-07-25 14:47:46 -0400 |
commit | 5a9196d715607f76d6b7d96a0970d6065335e62b (patch) | |
tree | df323588d1026b947e489c5fb9c83299dbcb9689 /security | |
parent | 6593d9245bc66e6e3cf4ba6d365a7833110c1402 (diff) |
ima: add support for measuring and appraising firmware
The "security: introduce kernel_fw_from_file hook" patch defined a
new security hook to evaluate any loaded firmware that wasn't built
into the kernel.
This patch defines ima_fw_from_file(), which is called from the new
security hook, to measure and/or appraise the loaded firmware's
integrity.
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/ima/ima.h | 3 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 8 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 11 | ||||
-rw-r--r-- | security/integrity/ima/ima_policy.c | 7 | ||||
-rw-r--r-- | security/integrity/integrity.h | 9 | ||||
-rw-r--r-- | security/security.c | 7 |
6 files changed, 41 insertions, 4 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index c42056edfc97..57da4bd7ba0c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -158,7 +158,7 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | |||
158 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | 158 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); |
159 | 159 | ||
160 | /* IMA policy related functions */ | 160 | /* IMA policy related functions */ |
161 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, POST_SETATTR }; | 161 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; |
162 | 162 | ||
163 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | 163 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, |
164 | int flags); | 164 | int flags); |
@@ -171,6 +171,7 @@ void ima_delete_rules(void); | |||
171 | #define IMA_APPRAISE_ENFORCE 0x01 | 171 | #define IMA_APPRAISE_ENFORCE 0x01 |
172 | #define IMA_APPRAISE_FIX 0x02 | 172 | #define IMA_APPRAISE_FIX 0x02 |
173 | #define IMA_APPRAISE_MODULES 0x04 | 173 | #define IMA_APPRAISE_MODULES 0x04 |
174 | #define IMA_APPRAISE_FIRMWARE 0x08 | ||
174 | 175 | ||
175 | #ifdef CONFIG_IMA_APPRAISE | 176 | #ifdef CONFIG_IMA_APPRAISE |
176 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 177 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 59ac90275070..86bfd5c5df85 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
@@ -75,6 +75,8 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, | |||
75 | return iint->ima_bprm_status; | 75 | return iint->ima_bprm_status; |
76 | case MODULE_CHECK: | 76 | case MODULE_CHECK: |
77 | return iint->ima_module_status; | 77 | return iint->ima_module_status; |
78 | case FIRMWARE_CHECK: | ||
79 | return iint->ima_firmware_status; | ||
78 | case FILE_CHECK: | 80 | case FILE_CHECK: |
79 | default: | 81 | default: |
80 | return iint->ima_file_status; | 82 | return iint->ima_file_status; |
@@ -94,6 +96,9 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, | |||
94 | case MODULE_CHECK: | 96 | case MODULE_CHECK: |
95 | iint->ima_module_status = status; | 97 | iint->ima_module_status = status; |
96 | break; | 98 | break; |
99 | case FIRMWARE_CHECK: | ||
100 | iint->ima_firmware_status = status; | ||
101 | break; | ||
97 | case FILE_CHECK: | 102 | case FILE_CHECK: |
98 | default: | 103 | default: |
99 | iint->ima_file_status = status; | 104 | iint->ima_file_status = status; |
@@ -113,6 +118,9 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func) | |||
113 | case MODULE_CHECK: | 118 | case MODULE_CHECK: |
114 | iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); | 119 | iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); |
115 | break; | 120 | break; |
121 | case FIRMWARE_CHECK: | ||
122 | iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED); | ||
123 | break; | ||
116 | case FILE_CHECK: | 124 | case FILE_CHECK: |
117 | default: | 125 | default: |
118 | iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); | 126 | iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 0d696431209c..2917f980bf30 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -319,6 +319,17 @@ int ima_module_check(struct file *file) | |||
319 | return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); | 319 | return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); |
320 | } | 320 | } |
321 | 321 | ||
322 | int ima_fw_from_file(struct file *file, char *buf, size_t size) | ||
323 | { | ||
324 | if (!file) { | ||
325 | if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && | ||
326 | (ima_appraise & IMA_APPRAISE_ENFORCE)) | ||
327 | return -EACCES; /* INTEGRITY_UNKNOWN */ | ||
328 | return 0; | ||
329 | } | ||
330 | return process_measurement(file, NULL, MAY_EXEC, FIRMWARE_CHECK); | ||
331 | } | ||
332 | |||
322 | static int __init init_ima(void) | 333 | static int __init init_ima(void) |
323 | { | 334 | { |
324 | int error; | 335 | int error; |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index cea84d8bd7be..07099a8bc283 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
@@ -84,6 +84,7 @@ static struct ima_rule_entry default_rules[] = { | |||
84 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID, | 84 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID, |
85 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | 85 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, |
86 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, | 86 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, |
87 | {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | static struct ima_rule_entry default_appraise_rules[] = { | 90 | static struct ima_rule_entry default_appraise_rules[] = { |
@@ -241,6 +242,8 @@ static int get_subaction(struct ima_rule_entry *rule, int func) | |||
241 | return IMA_BPRM_APPRAISE; | 242 | return IMA_BPRM_APPRAISE; |
242 | case MODULE_CHECK: | 243 | case MODULE_CHECK: |
243 | return IMA_MODULE_APPRAISE; | 244 | return IMA_MODULE_APPRAISE; |
245 | case FIRMWARE_CHECK: | ||
246 | return IMA_FIRMWARE_APPRAISE; | ||
244 | case FILE_CHECK: | 247 | case FILE_CHECK: |
245 | default: | 248 | default: |
246 | return IMA_FILE_APPRAISE; | 249 | return IMA_FILE_APPRAISE; |
@@ -486,6 +489,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
486 | entry->func = FILE_CHECK; | 489 | entry->func = FILE_CHECK; |
487 | else if (strcmp(args[0].from, "MODULE_CHECK") == 0) | 490 | else if (strcmp(args[0].from, "MODULE_CHECK") == 0) |
488 | entry->func = MODULE_CHECK; | 491 | entry->func = MODULE_CHECK; |
492 | else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0) | ||
493 | entry->func = FIRMWARE_CHECK; | ||
489 | else if ((strcmp(args[0].from, "FILE_MMAP") == 0) | 494 | else if ((strcmp(args[0].from, "FILE_MMAP") == 0) |
490 | || (strcmp(args[0].from, "MMAP_CHECK") == 0)) | 495 | || (strcmp(args[0].from, "MMAP_CHECK") == 0)) |
491 | entry->func = MMAP_CHECK; | 496 | entry->func = MMAP_CHECK; |
@@ -636,6 +641,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
636 | result = -EINVAL; | 641 | result = -EINVAL; |
637 | else if (entry->func == MODULE_CHECK) | 642 | else if (entry->func == MODULE_CHECK) |
638 | ima_appraise |= IMA_APPRAISE_MODULES; | 643 | ima_appraise |= IMA_APPRAISE_MODULES; |
644 | else if (entry->func == FIRMWARE_CHECK) | ||
645 | ima_appraise |= IMA_APPRAISE_FIRMWARE; | ||
639 | audit_log_format(ab, "res=%d", !result); | 646 | audit_log_format(ab, "res=%d", !result); |
640 | audit_log_end(ab); | 647 | audit_log_end(ab); |
641 | return result; | 648 | return result; |
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 09c440d9aaee..19b8e314ca96 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
@@ -46,10 +46,14 @@ | |||
46 | #define IMA_BPRM_APPRAISED 0x00002000 | 46 | #define IMA_BPRM_APPRAISED 0x00002000 |
47 | #define IMA_MODULE_APPRAISE 0x00004000 | 47 | #define IMA_MODULE_APPRAISE 0x00004000 |
48 | #define IMA_MODULE_APPRAISED 0x00008000 | 48 | #define IMA_MODULE_APPRAISED 0x00008000 |
49 | #define IMA_FIRMWARE_APPRAISE 0x00010000 | ||
50 | #define IMA_FIRMWARE_APPRAISED 0x00020000 | ||
49 | #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ | 51 | #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ |
50 | IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE) | 52 | IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \ |
53 | IMA_FIRMWARE_APPRAISE) | ||
51 | #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ | 54 | #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ |
52 | IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED) | 55 | IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \ |
56 | IMA_FIRMWARE_APPRAISED) | ||
53 | 57 | ||
54 | enum evm_ima_xattr_type { | 58 | enum evm_ima_xattr_type { |
55 | IMA_XATTR_DIGEST = 0x01, | 59 | IMA_XATTR_DIGEST = 0x01, |
@@ -104,6 +108,7 @@ struct integrity_iint_cache { | |||
104 | enum integrity_status ima_mmap_status:4; | 108 | enum integrity_status ima_mmap_status:4; |
105 | enum integrity_status ima_bprm_status:4; | 109 | enum integrity_status ima_bprm_status:4; |
106 | enum integrity_status ima_module_status:4; | 110 | enum integrity_status ima_module_status:4; |
111 | enum integrity_status ima_firmware_status:4; | ||
107 | enum integrity_status evm_status:4; | 112 | enum integrity_status evm_status:4; |
108 | struct ima_digest_data *ima_hash; | 113 | struct ima_digest_data *ima_hash; |
109 | }; | 114 | }; |
diff --git a/security/security.c b/security/security.c index 35d37d0f0d49..e41b1a8d7644 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -847,7 +847,12 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
847 | 847 | ||
848 | int security_kernel_fw_from_file(struct file *file, char *buf, size_t size) | 848 | int security_kernel_fw_from_file(struct file *file, char *buf, size_t size) |
849 | { | 849 | { |
850 | return security_ops->kernel_fw_from_file(file, buf, size); | 850 | int ret; |
851 | |||
852 | ret = security_ops->kernel_fw_from_file(file, buf, size); | ||
853 | if (ret) | ||
854 | return ret; | ||
855 | return ima_fw_from_file(file, buf, size); | ||
851 | } | 856 | } |
852 | EXPORT_SYMBOL_GPL(security_kernel_fw_from_file); | 857 | EXPORT_SYMBOL_GPL(security_kernel_fw_from_file); |
853 | 858 | ||