aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Jung Bauermann <bauerman@linux.ibm.com>2019-06-27 22:19:32 -0400
committerMimi Zohar <zohar@linux.ibm.com>2019-08-05 18:40:25 -0400
commit3878d505aa718bcc7b1eb4089ab9b9fb27dee957 (patch)
tree94bf31dc35114d22a2c87906106074cdcb4bd021
parent15588227e086ec662d59df144e48af82e3e592f1 (diff)
ima: Define ima-modsig template
Define new "d-modsig" template field which holds the digest that is expected to match the one contained in the modsig, and also new "modsig" template field which holds the appended file signature. Add a new "ima-modsig" defined template descriptor with the new fields as well as the ones from the "ima-sig" descriptor. Change ima_store_measurement() to accept a struct modsig * argument so that it can be passed along to the templates via struct ima_event_data. Suggested-by: Mimi Zohar <zohar@linux.ibm.com> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
-rw-r--r--Documentation/security/IMA-templates.rst3
-rw-r--r--security/integrity/ima/ima.h20
-rw-r--r--security/integrity/ima/ima_api.c5
-rw-r--r--security/integrity/ima/ima_main.c2
-rw-r--r--security/integrity/ima/ima_modsig.c19
-rw-r--r--security/integrity/ima/ima_policy.c41
-rw-r--r--security/integrity/ima/ima_template.c7
-rw-r--r--security/integrity/ima/ima_template_lib.c64
-rw-r--r--security/integrity/ima/ima_template_lib.h4
9 files changed, 159 insertions, 6 deletions
diff --git a/Documentation/security/IMA-templates.rst b/Documentation/security/IMA-templates.rst
index 3d1cca287aa4..c5a8432972ef 100644
--- a/Documentation/security/IMA-templates.rst
+++ b/Documentation/security/IMA-templates.rst
@@ -68,8 +68,10 @@ descriptors by adding their identifier to the format string
68 - 'd-ng': the digest of the event, calculated with an arbitrary hash 68 - 'd-ng': the digest of the event, calculated with an arbitrary hash
69 algorithm (field format: [<hash algo>:]digest, where the digest 69 algorithm (field format: [<hash algo>:]digest, where the digest
70 prefix is shown only if the hash algorithm is not SHA1 or MD5); 70 prefix is shown only if the hash algorithm is not SHA1 or MD5);
71 - 'd-modsig': the digest of the event without the appended modsig;
71 - 'n-ng': the name of the event, without size limitations; 72 - 'n-ng': the name of the event, without size limitations;
72 - 'sig': the file signature; 73 - 'sig': the file signature;
74 - 'modsig' the appended file signature;
73 - 'buf': the buffer data that was used to generate the hash without size limitations; 75 - 'buf': the buffer data that was used to generate the hash without size limitations;
74 76
75 77
@@ -79,6 +81,7 @@ Below, there is the list of defined template descriptors:
79 - "ima-ng" (default): its format is ``d-ng|n-ng``; 81 - "ima-ng" (default): its format is ``d-ng|n-ng``;
80 - "ima-sig": its format is ``d-ng|n-ng|sig``; 82 - "ima-sig": its format is ``d-ng|n-ng|sig``;
81 - "ima-buf": its format is ``d-ng|n-ng|buf``; 83 - "ima-buf": its format is ``d-ng|n-ng|buf``;
84 - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
82 85
83 86
84Use 87Use
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 0bc764c80327..cfc8b0887776 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -60,6 +60,7 @@ struct ima_event_data {
60 const unsigned char *filename; 60 const unsigned char *filename;
61 struct evm_ima_xattr_data *xattr_value; 61 struct evm_ima_xattr_data *xattr_value;
62 int xattr_len; 62 int xattr_len;
63 const struct modsig *modsig;
63 const char *violation; 64 const char *violation;
64 const void *buf; 65 const void *buf;
65 int buf_len; 66 int buf_len;
@@ -211,7 +212,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
211void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, 212void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
212 const unsigned char *filename, 213 const unsigned char *filename,
213 struct evm_ima_xattr_data *xattr_value, 214 struct evm_ima_xattr_data *xattr_value,
214 int xattr_len, int pcr, 215 int xattr_len, const struct modsig *modsig, int pcr,
215 struct ima_template_desc *template_desc); 216 struct ima_template_desc *template_desc);
216void ima_audit_measurement(struct integrity_iint_cache *iint, 217void ima_audit_measurement(struct integrity_iint_cache *iint,
217 const unsigned char *filename); 218 const unsigned char *filename);
@@ -312,6 +313,10 @@ bool ima_hook_supports_modsig(enum ima_hooks func);
312int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, 313int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
313 struct modsig **modsig); 314 struct modsig **modsig);
314void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size); 315void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size);
316int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
317 const u8 **digest, u32 *digest_size);
318int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
319 u32 *data_len);
315void ima_free_modsig(struct modsig *modsig); 320void ima_free_modsig(struct modsig *modsig);
316#else 321#else
317static inline bool ima_hook_supports_modsig(enum ima_hooks func) 322static inline bool ima_hook_supports_modsig(enum ima_hooks func)
@@ -330,6 +335,19 @@ static inline void ima_collect_modsig(struct modsig *modsig, const void *buf,
330{ 335{
331} 336}
332 337
338static inline int ima_get_modsig_digest(const struct modsig *modsig,
339 enum hash_algo *algo, const u8 **digest,
340 u32 *digest_size)
341{
342 return -EOPNOTSUPP;
343}
344
345static inline int ima_get_raw_modsig(const struct modsig *modsig,
346 const void **data, u32 *data_len)
347{
348 return -EOPNOTSUPP;
349}
350
333static inline void ima_free_modsig(struct modsig *modsig) 351static inline void ima_free_modsig(struct modsig *modsig)
334{ 352{
335} 353}
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index ff8b7fb03ea0..ca930e2ebc2c 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -288,7 +288,7 @@ out:
288void ima_store_measurement(struct integrity_iint_cache *iint, 288void ima_store_measurement(struct integrity_iint_cache *iint,
289 struct file *file, const unsigned char *filename, 289 struct file *file, const unsigned char *filename,
290 struct evm_ima_xattr_data *xattr_value, 290 struct evm_ima_xattr_data *xattr_value,
291 int xattr_len, int pcr, 291 int xattr_len, const struct modsig *modsig, int pcr,
292 struct ima_template_desc *template_desc) 292 struct ima_template_desc *template_desc)
293{ 293{
294 static const char op[] = "add_template_measure"; 294 static const char op[] = "add_template_measure";
@@ -300,7 +300,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
300 .file = file, 300 .file = file,
301 .filename = filename, 301 .filename = filename,
302 .xattr_value = xattr_value, 302 .xattr_value = xattr_value,
303 .xattr_len = xattr_len }; 303 .xattr_len = xattr_len,
304 .modsig = modsig };
304 int violation = 0; 305 int violation = 0;
305 306
306 if (iint->measured_pcrs & (0x1 << pcr)) 307 if (iint->measured_pcrs & (0x1 << pcr))
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 7c8d92cf2755..c87645c2c4c0 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -323,7 +323,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
323 323
324 if (action & IMA_MEASURE) 324 if (action & IMA_MEASURE)
325 ima_store_measurement(iint, file, pathname, 325 ima_store_measurement(iint, file, pathname,
326 xattr_value, xattr_len, pcr, 326 xattr_value, xattr_len, modsig, pcr,
327 template_desc); 327 template_desc);
328 if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { 328 if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
329 inode_lock(inode); 329 inode_lock(inode);
diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c
index 257387ce3b70..c412e31d1714 100644
--- a/security/integrity/ima/ima_modsig.c
+++ b/security/integrity/ima/ima_modsig.c
@@ -138,6 +138,25 @@ int ima_modsig_verify(struct key *keyring, const struct modsig *modsig)
138 VERIFYING_MODULE_SIGNATURE, NULL, NULL); 138 VERIFYING_MODULE_SIGNATURE, NULL, NULL);
139} 139}
140 140
141int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
142 const u8 **digest, u32 *digest_size)
143{
144 *algo = modsig->hash_algo;
145 *digest = modsig->digest;
146 *digest_size = modsig->digest_size;
147
148 return 0;
149}
150
151int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
152 u32 *data_len)
153{
154 *data = &modsig->raw_pkcs7;
155 *data_len = modsig->raw_pkcs7_len;
156
157 return 0;
158}
159
141void ima_free_modsig(struct modsig *modsig) 160void ima_free_modsig(struct modsig *modsig)
142{ 161{
143 if (!modsig) 162 if (!modsig)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 873dd7edaa78..4badc4fcda98 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -6,6 +6,9 @@
6 * ima_policy.c 6 * ima_policy.c
7 * - initialize default measure policy rules 7 * - initialize default measure policy rules
8 */ 8 */
9
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
9#include <linux/init.h> 12#include <linux/init.h>
10#include <linux/list.h> 13#include <linux/list.h>
11#include <linux/fs.h> 14#include <linux/fs.h>
@@ -845,6 +848,38 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
845 ima_log_string_op(ab, key, value, NULL); 848 ima_log_string_op(ab, key, value, NULL);
846} 849}
847 850
851/*
852 * Validating the appended signature included in the measurement list requires
853 * the file hash calculated without the appended signature (i.e., the 'd-modsig'
854 * field). Therefore, notify the user if they have the 'modsig' field but not
855 * the 'd-modsig' field in the template.
856 */
857static void check_template_modsig(const struct ima_template_desc *template)
858{
859#define MSG "template with 'modsig' field also needs 'd-modsig' field\n"
860 bool has_modsig, has_dmodsig;
861 static bool checked;
862 int i;
863
864 /* We only need to notify the user once. */
865 if (checked)
866 return;
867
868 has_modsig = has_dmodsig = false;
869 for (i = 0; i < template->num_fields; i++) {
870 if (!strcmp(template->fields[i]->field_id, "modsig"))
871 has_modsig = true;
872 else if (!strcmp(template->fields[i]->field_id, "d-modsig"))
873 has_dmodsig = true;
874 }
875
876 if (has_modsig && !has_dmodsig)
877 pr_notice(MSG);
878
879 checked = true;
880#undef MSG
881}
882
848static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) 883static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
849{ 884{
850 struct audit_buffer *ab; 885 struct audit_buffer *ab;
@@ -1187,6 +1222,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
1187 else if (entry->action == APPRAISE) 1222 else if (entry->action == APPRAISE)
1188 temp_ima_appraise |= ima_appraise_flag(entry->func); 1223 temp_ima_appraise |= ima_appraise_flag(entry->func);
1189 1224
1225 if (!result && entry->flags & IMA_MODSIG_ALLOWED) {
1226 template_desc = entry->template ? entry->template :
1227 ima_template_desc_current();
1228 check_template_modsig(template_desc);
1229 }
1230
1190 audit_log_format(ab, "res=%d", !result); 1231 audit_log_format(ab, "res=%d", !result);
1191 audit_log_end(ab); 1232 audit_log_end(ab);
1192 return result; 1233 return result;
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index cb349d7b2601..88d494ca6248 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -23,6 +23,7 @@ static struct ima_template_desc builtin_templates[] = {
23 {.name = "ima-ng", .fmt = "d-ng|n-ng"}, 23 {.name = "ima-ng", .fmt = "d-ng|n-ng"},
24 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, 24 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
25 {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"}, 25 {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"},
26 {.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"},
26 {.name = "", .fmt = ""}, /* placeholder for a custom format */ 27 {.name = "", .fmt = ""}, /* placeholder for a custom format */
27}; 28};
28 29
@@ -42,6 +43,10 @@ static const struct ima_template_field supported_fields[] = {
42 .field_show = ima_show_template_sig}, 43 .field_show = ima_show_template_sig},
43 {.field_id = "buf", .field_init = ima_eventbuf_init, 44 {.field_id = "buf", .field_init = ima_eventbuf_init,
44 .field_show = ima_show_template_buf}, 45 .field_show = ima_show_template_buf},
46 {.field_id = "d-modsig", .field_init = ima_eventdigest_modsig_init,
47 .field_show = ima_show_template_digest_ng},
48 {.field_id = "modsig", .field_init = ima_eventmodsig_init,
49 .field_show = ima_show_template_sig},
45}; 50};
46 51
47/* 52/*
@@ -49,7 +54,7 @@ static const struct ima_template_field supported_fields[] = {
49 * need to be accounted for since they shouldn't be defined in the same template 54 * need to be accounted for since they shouldn't be defined in the same template
50 * description as 'd-ng' and 'n-ng' respectively. 55 * description as 'd-ng' and 'n-ng' respectively.
51 */ 56 */
52#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf") 57#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig")
53 58
54static struct ima_template_desc *ima_template; 59static struct ima_template_desc *ima_template;
55 60
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 2fb9a10bc6b7..32ae05d88257 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -225,7 +225,8 @@ int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
225 return 0; 225 return 0;
226} 226}
227 227
228static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, 228static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
229 u8 hash_algo,
229 struct ima_field_data *field_data) 230 struct ima_field_data *field_data)
230{ 231{
231 /* 232 /*
@@ -328,6 +329,41 @@ out:
328 hash_algo, field_data); 329 hash_algo, field_data);
329} 330}
330 331
332/*
333 * This function writes the digest of the file which is expected to match the
334 * digest contained in the file's appended signature.
335 */
336int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
337 struct ima_field_data *field_data)
338{
339 enum hash_algo hash_algo;
340 const u8 *cur_digest;
341 u32 cur_digestsize;
342
343 if (!event_data->modsig)
344 return 0;
345
346 if (event_data->violation) {
347 /* Recording a violation. */
348 hash_algo = HASH_ALGO_SHA1;
349 cur_digest = NULL;
350 cur_digestsize = 0;
351 } else {
352 int rc;
353
354 rc = ima_get_modsig_digest(event_data->modsig, &hash_algo,
355 &cur_digest, &cur_digestsize);
356 if (rc)
357 return rc;
358 else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0)
359 /* There was some error collecting the digest. */
360 return -EINVAL;
361 }
362
363 return ima_eventdigest_init_common(cur_digest, cur_digestsize,
364 hash_algo, field_data);
365}
366
331static int ima_eventname_init_common(struct ima_event_data *event_data, 367static int ima_eventname_init_common(struct ima_event_data *event_data,
332 struct ima_field_data *field_data, 368 struct ima_field_data *field_data,
333 bool size_limit) 369 bool size_limit)
@@ -406,3 +442,29 @@ int ima_eventbuf_init(struct ima_event_data *event_data,
406 event_data->buf_len, DATA_FMT_HEX, 442 event_data->buf_len, DATA_FMT_HEX,
407 field_data); 443 field_data);
408} 444}
445
446/*
447 * ima_eventmodsig_init - include the appended file signature as part of the
448 * template data
449 */
450int ima_eventmodsig_init(struct ima_event_data *event_data,
451 struct ima_field_data *field_data)
452{
453 const void *data;
454 u32 data_len;
455 int rc;
456
457 if (!event_data->modsig)
458 return 0;
459
460 /*
461 * modsig is a runtime structure containing pointers. Get its raw data
462 * instead.
463 */
464 rc = ima_get_raw_modsig(event_data->modsig, &data, &data_len);
465 if (rc)
466 return rc;
467
468 return ima_write_template_field_data(data, data_len, DATA_FMT_HEX,
469 field_data);
470}
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
index 652aa5de81ef..9a88c79a7a61 100644
--- a/security/integrity/ima/ima_template_lib.h
+++ b/security/integrity/ima/ima_template_lib.h
@@ -36,10 +36,14 @@ int ima_eventname_init(struct ima_event_data *event_data,
36 struct ima_field_data *field_data); 36 struct ima_field_data *field_data);
37int ima_eventdigest_ng_init(struct ima_event_data *event_data, 37int ima_eventdigest_ng_init(struct ima_event_data *event_data,
38 struct ima_field_data *field_data); 38 struct ima_field_data *field_data);
39int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
40 struct ima_field_data *field_data);
39int ima_eventname_ng_init(struct ima_event_data *event_data, 41int ima_eventname_ng_init(struct ima_event_data *event_data,
40 struct ima_field_data *field_data); 42 struct ima_field_data *field_data);
41int ima_eventsig_init(struct ima_event_data *event_data, 43int ima_eventsig_init(struct ima_event_data *event_data,
42 struct ima_field_data *field_data); 44 struct ima_field_data *field_data);
43int ima_eventbuf_init(struct ima_event_data *event_data, 45int ima_eventbuf_init(struct ima_event_data *event_data,
44 struct ima_field_data *field_data); 46 struct ima_field_data *field_data);
47int ima_eventmodsig_init(struct ima_event_data *event_data,
48 struct ima_field_data *field_data);
45#endif /* __LINUX_IMA_TEMPLATE_LIB_H */ 49#endif /* __LINUX_IMA_TEMPLATE_LIB_H */