aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorRoberto Sassu <roberto.sassu@polito.it>2013-06-07 06:16:33 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2013-10-25 17:17:06 -0400
commita71dc65d30a472409f05d247f4eab91b14acf2f5 (patch)
tree0d0798a7a40af5db7d44608de1f64ca872bfaf1c /security
parent4d7aeee73f5304bf195aa2904f8eb1d7b2e8fe52 (diff)
ima: switch to new template management mechanism
This patch performs the switch to the new template mechanism by modifying the functions ima_alloc_init_template(), ima_measurements_show() and ima_ascii_measurements_show(). The old function ima_template_show() was removed as it is no longer needed. Also, if the template descriptor used to generate a measurement entry is not 'ima', the whole length of field data stored for an entry is provided before the data itself through the binary_runtime_measurement interface. Changelog: - unnecessary to use strncmp() (Mimi Zohar) - create new variable 'field' in ima_alloc_init_template() (Roberto Sassu) - use GFP_NOFS flag in ima_alloc_init_template() (Roberto Sassu) - new variable 'num_fields' in ima_store_template() (Roberto Sassu, proposed by Mimi Zohar) - rename ima_calc_buffer_hash/template_hash() to ima_calc_field_array_hash(), something more generic (Mimi, requested by Dmitry) - sparse error fix - Fengguang Wu - fix lindent warnings - always include the field length in the template data length - include the template field length variable size in the template data length - include both the template field data and field length in the template digest calculation. Simplifies verifying the template digest. (Mimi) Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima.h19
-rw-r--r--security/integrity/ima/ima_api.c75
-rw-r--r--security/integrity/ima/ima_crypto.c34
-rw-r--r--security/integrity/ima/ima_fs.c54
-rw-r--r--security/integrity/ima/ima_template.c22
5 files changed, 107 insertions, 97 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index e1f081d65dbf..72d013e190b1 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -72,17 +72,11 @@ struct ima_template_desc {
72 struct ima_template_field **fields; 72 struct ima_template_field **fields;
73}; 73};
74 74
75/* IMA inode template definition */
76struct ima_template_data {
77 u8 digest[IMA_DIGEST_SIZE]; /* sha1/md5 measurement hash */
78 char file_name[IMA_EVENT_NAME_LEN_MAX + 1]; /* name + \0 */
79};
80
81struct ima_template_entry { 75struct ima_template_entry {
82 u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */ 76 u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
83 const char *template_name; 77 struct ima_template_desc *template_desc; /* template descriptor */
84 int template_len; 78 u32 template_data_len;
85 struct ima_template_data template; 79 struct ima_field_data template_data[0]; /* template related data */
86}; 80};
87 81
88struct ima_queue_entry { 82struct ima_queue_entry {
@@ -102,14 +96,16 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
102 const char *op, struct inode *inode, 96 const char *op, struct inode *inode,
103 const unsigned char *filename); 97 const unsigned char *filename);
104int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); 98int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
105int ima_calc_buffer_hash(const void *data, int len, 99int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
106 struct ima_digest_data *hash); 100 struct ima_digest_data *hash);
107int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); 101int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
108void ima_add_violation(struct file *file, const unsigned char *filename, 102void ima_add_violation(struct file *file, const unsigned char *filename,
109 const char *op, const char *cause); 103 const char *op, const char *cause);
110int ima_init_crypto(void); 104int ima_init_crypto(void);
111void ima_putc(struct seq_file *m, void *data, int datalen); 105void ima_putc(struct seq_file *m, void *data, int datalen);
112void ima_print_digest(struct seq_file *m, u8 *digest, int size); 106void ima_print_digest(struct seq_file *m, u8 *digest, int size);
107struct ima_template_desc *ima_template_desc_current(void);
108int ima_init_template(void);
113 109
114int ima_init_template(void); 110int ima_init_template(void);
115 111
@@ -146,7 +142,6 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
146 struct ima_template_entry **entry); 142 struct ima_template_entry **entry);
147int ima_store_template(struct ima_template_entry *entry, int violation, 143int ima_store_template(struct ima_template_entry *entry, int violation,
148 struct inode *inode, const unsigned char *filename); 144 struct inode *inode, const unsigned char *filename);
149void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
150const char *ima_d_path(struct path *path, char **pathbuf); 145const char *ima_d_path(struct path *path, char **pathbuf);
151 146
152/* rbtree tree calls to lookup, insert, delete 147/* rbtree tree calls to lookup, insert, delete
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 29dd43de823a..baa348179527 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -21,8 +21,6 @@
21#include <crypto/hash_info.h> 21#include <crypto/hash_info.h>
22#include "ima.h" 22#include "ima.h"
23 23
24static const char *IMA_TEMPLATE_NAME = "ima";
25
26/* 24/*
27 * ima_alloc_init_template - create and initialize a new template entry 25 * ima_alloc_init_template - create and initialize a new template entry
28 */ 26 */
@@ -30,52 +28,32 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
30 struct file *file, const unsigned char *filename, 28 struct file *file, const unsigned char *filename,
31 struct ima_template_entry **entry) 29 struct ima_template_entry **entry)
32{ 30{
33 struct ima_template_entry *e; 31 struct ima_template_desc *template_desc = ima_template_desc_current();
34 int result = 0; 32 int i, result = 0;
35 33
36 e = kzalloc(sizeof(**entry), GFP_NOFS); 34 *entry = kzalloc(sizeof(**entry) + template_desc->num_fields *
37 if (!e) 35 sizeof(struct ima_field_data), GFP_NOFS);
36 if (!*entry)
38 return -ENOMEM; 37 return -ENOMEM;
39 38
40 memset(&(e)->template, 0, sizeof(e->template)); 39 for (i = 0; i < template_desc->num_fields; i++) {
41 if (!iint) /* IMA measurement violation entry */ 40 struct ima_template_field *field = template_desc->fields[i];
42 goto out; 41 u32 len;
43
44 if (iint->ima_hash->algo != ima_hash_algo) {
45 struct inode *inode;
46 struct {
47 struct ima_digest_data hdr;
48 char digest[IMA_MAX_DIGEST_SIZE];
49 } hash;
50 42
51 if (!file) { 43 result = field->field_init(iint, file, filename,
52 result = -EINVAL; 44 &((*entry)->template_data[i]));
53 goto out_free; 45 if (result != 0)
54 } 46 goto out;
55 47
56 inode = file_inode(file); 48 len = (*entry)->template_data[i].len;
57 hash.hdr.algo = ima_hash_algo; 49 (*entry)->template_data_len += sizeof(len);
58 hash.hdr.length = SHA1_DIGEST_SIZE; 50 (*entry)->template_data_len += len;
59 result = ima_calc_file_hash(file, &hash.hdr); 51 }
60 if (result) { 52 (*entry)->template_desc = template_desc;
61 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
62 filename, "collect_data",
63 "failed", result, 0);
64 goto out_free;
65 } else
66 memcpy(e->template.digest, hash.hdr.digest,
67 hash.hdr.length);
68 } else
69 memcpy(e->template.digest, iint->ima_hash->digest,
70 iint->ima_hash->length);
71out:
72 strcpy(e->template.file_name,
73 (strlen(filename) > IMA_EVENT_NAME_LEN_MAX && file != NULL) ?
74 file->f_dentry->d_name.name : filename);
75 *entry = e;
76 return 0; 53 return 0;
77out_free: 54out:
78 kfree(e); 55 kfree(*entry);
56 *entry = NULL;
79 return result; 57 return result;
80} 58}
81 59
@@ -101,24 +79,23 @@ int ima_store_template(struct ima_template_entry *entry,
101{ 79{
102 const char *op = "add_template_measure"; 80 const char *op = "add_template_measure";
103 const char *audit_cause = "hashing_error"; 81 const char *audit_cause = "hashing_error";
82 char *template_name = entry->template_desc->name;
104 int result; 83 int result;
105 struct { 84 struct {
106 struct ima_digest_data hdr; 85 struct ima_digest_data hdr;
107 char digest[TPM_DIGEST_SIZE]; 86 char digest[TPM_DIGEST_SIZE];
108 } hash; 87 } hash;
109 88
110 memset(entry->digest, 0, sizeof(entry->digest));
111 entry->template_name = IMA_TEMPLATE_NAME;
112 entry->template_len = sizeof(entry->template);
113
114 if (!violation) { 89 if (!violation) {
90 int num_fields = entry->template_desc->num_fields;
91
115 /* this function uses default algo */ 92 /* this function uses default algo */
116 hash.hdr.algo = HASH_ALGO_SHA1; 93 hash.hdr.algo = HASH_ALGO_SHA1;
117 result = ima_calc_buffer_hash(&entry->template, 94 result = ima_calc_field_array_hash(&entry->template_data[0],
118 entry->template_len, &hash.hdr); 95 num_fields, &hash.hdr);
119 if (result < 0) { 96 if (result < 0) {
120 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, 97 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
121 entry->template_name, op, 98 template_name, op,
122 audit_cause, result, 0); 99 audit_cause, result, 0);
123 return result; 100 return result;
124 } 101 }
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 22be23f13b3d..676e0292dfec 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -137,26 +137,46 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
137} 137}
138 138
139/* 139/*
140 * Calculate the hash of a given buffer 140 * Calculate the hash of template data
141 */ 141 */
142static int ima_calc_buffer_hash_tfm(const void *buf, int len, 142static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
143 struct ima_digest_data *hash, 143 int num_fields,
144 struct crypto_shash *tfm) 144 struct ima_digest_data *hash,
145 struct crypto_shash *tfm)
145{ 146{
146 struct { 147 struct {
147 struct shash_desc shash; 148 struct shash_desc shash;
148 char ctx[crypto_shash_descsize(tfm)]; 149 char ctx[crypto_shash_descsize(tfm)];
149 } desc; 150 } desc;
151 int rc, i;
150 152
151 desc.shash.tfm = tfm; 153 desc.shash.tfm = tfm;
152 desc.shash.flags = 0; 154 desc.shash.flags = 0;
153 155
154 hash->length = crypto_shash_digestsize(tfm); 156 hash->length = crypto_shash_digestsize(tfm);
155 157
156 return crypto_shash_digest(&desc.shash, buf, len, hash->digest); 158 rc = crypto_shash_init(&desc.shash);
159 if (rc != 0)
160 return rc;
161
162 for (i = 0; i < num_fields; i++) {
163 rc = crypto_shash_update(&desc.shash,
164 (const u8 *) &field_data[i].len,
165 sizeof(field_data[i].len));
166 rc = crypto_shash_update(&desc.shash, field_data[i].data,
167 field_data[i].len);
168 if (rc)
169 break;
170 }
171
172 if (!rc)
173 rc = crypto_shash_final(&desc.shash, hash->digest);
174
175 return rc;
157} 176}
158 177
159int ima_calc_buffer_hash(const void *buf, int len, struct ima_digest_data *hash) 178int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
179 struct ima_digest_data *hash)
160{ 180{
161 struct crypto_shash *tfm; 181 struct crypto_shash *tfm;
162 int rc; 182 int rc;
@@ -165,7 +185,7 @@ int ima_calc_buffer_hash(const void *buf, int len, struct ima_digest_data *hash)
165 if (IS_ERR(tfm)) 185 if (IS_ERR(tfm))
166 return PTR_ERR(tfm); 186 return PTR_ERR(tfm);
167 187
168 rc = ima_calc_buffer_hash_tfm(buf, len, hash, tfm); 188 rc = ima_calc_field_array_hash_tfm(field_data, num_fields, hash, tfm);
169 189
170 ima_free_tfm(tfm); 190 ima_free_tfm(tfm);
171 191
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 414862e1904b..d47a7c86a21d 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -110,6 +110,7 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
110 * char[20]=template digest 110 * char[20]=template digest
111 * 32bit-le=template name size 111 * 32bit-le=template name size
112 * char[n]=template name 112 * char[n]=template name
113 * [eventdata length]
113 * eventdata[n]=template specific data 114 * eventdata[n]=template specific data
114 */ 115 */
115static int ima_measurements_show(struct seq_file *m, void *v) 116static int ima_measurements_show(struct seq_file *m, void *v)
@@ -119,6 +120,7 @@ static int ima_measurements_show(struct seq_file *m, void *v)
119 struct ima_template_entry *e; 120 struct ima_template_entry *e;
120 int namelen; 121 int namelen;
121 u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; 122 u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
123 int i;
122 124
123 /* get entry */ 125 /* get entry */
124 e = qe->entry; 126 e = qe->entry;
@@ -136,15 +138,22 @@ static int ima_measurements_show(struct seq_file *m, void *v)
136 ima_putc(m, e->digest, TPM_DIGEST_SIZE); 138 ima_putc(m, e->digest, TPM_DIGEST_SIZE);
137 139
138 /* 3rd: template name size */ 140 /* 3rd: template name size */
139 namelen = strlen(e->template_name); 141 namelen = strlen(e->template_desc->name);
140 ima_putc(m, &namelen, sizeof namelen); 142 ima_putc(m, &namelen, sizeof namelen);
141 143
142 /* 4th: template name */ 144 /* 4th: template name */
143 ima_putc(m, (void *)e->template_name, namelen); 145 ima_putc(m, e->template_desc->name, namelen);
146
147 /* 5th: template length (except for 'ima' template) */
148 if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
149 ima_putc(m, &e->template_data_len,
150 sizeof(e->template_data_len));
144 151
145 /* 5th: template specific data */ 152 /* 6th: template specific data */
146 ima_template_show(m, (struct ima_template_data *)&e->template, 153 for (i = 0; i < e->template_desc->num_fields; i++) {
147 IMA_SHOW_BINARY); 154 e->template_desc->fields[i]->field_show(m, IMA_SHOW_BINARY,
155 &e->template_data[i]);
156 }
148 return 0; 157 return 0;
149} 158}
150 159
@@ -175,33 +184,13 @@ void ima_print_digest(struct seq_file *m, u8 *digest, int size)
175 seq_printf(m, "%02x", *(digest + i)); 184 seq_printf(m, "%02x", *(digest + i));
176} 185}
177 186
178void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
179{
180 struct ima_template_data *entry = e;
181 int namelen;
182
183 switch (show) {
184 case IMA_SHOW_ASCII:
185 ima_print_digest(m, entry->digest, IMA_DIGEST_SIZE);
186 seq_printf(m, " %s\n", entry->file_name);
187 break;
188 case IMA_SHOW_BINARY:
189 ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
190
191 namelen = strlen(entry->file_name);
192 ima_putc(m, &namelen, sizeof namelen);
193 ima_putc(m, entry->file_name, namelen);
194 default:
195 break;
196 }
197}
198
199/* print in ascii */ 187/* print in ascii */
200static int ima_ascii_measurements_show(struct seq_file *m, void *v) 188static int ima_ascii_measurements_show(struct seq_file *m, void *v)
201{ 189{
202 /* the list never shrinks, so we don't need a lock here */ 190 /* the list never shrinks, so we don't need a lock here */
203 struct ima_queue_entry *qe = v; 191 struct ima_queue_entry *qe = v;
204 struct ima_template_entry *e; 192 struct ima_template_entry *e;
193 int i;
205 194
206 /* get entry */ 195 /* get entry */
207 e = qe->entry; 196 e = qe->entry;
@@ -215,11 +204,18 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
215 ima_print_digest(m, e->digest, TPM_DIGEST_SIZE); 204 ima_print_digest(m, e->digest, TPM_DIGEST_SIZE);
216 205
217 /* 3th: template name */ 206 /* 3th: template name */
218 seq_printf(m, " %s ", e->template_name); 207 seq_printf(m, " %s", e->template_desc->name);
219 208
220 /* 4th: template specific data */ 209 /* 4th: template specific data */
221 ima_template_show(m, (struct ima_template_data *)&e->template, 210 for (i = 0; i < e->template_desc->num_fields; i++) {
222 IMA_SHOW_ASCII); 211 seq_puts(m, " ");
212 if (e->template_data[i].len == 0)
213 continue;
214
215 e->template_desc->fields[i]->field_show(m, IMA_SHOW_ASCII,
216 &e->template_data[i]);
217 }
218 seq_puts(m, "\n");
223 return 0; 219 return 0;
224} 220}
225 221
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index bf38d1af3cfd..1c4cf194592c 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -31,6 +31,20 @@ static struct ima_template_field supported_fields[] = {
31 .field_show = ima_show_template_string}, 31 .field_show = ima_show_template_string},
32}; 32};
33 33
34static struct ima_template_desc *ima_template;
35
36static struct ima_template_desc *lookup_template_desc(const char *name)
37{
38 int i;
39
40 for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
41 if (strcmp(defined_templates[i].name, name) == 0)
42 return defined_templates + i;
43 }
44
45 return NULL;
46}
47
34static struct ima_template_field *lookup_template_field(const char *field_id) 48static struct ima_template_field *lookup_template_field(const char *field_id)
35{ 49{
36 int i; 50 int i;
@@ -110,6 +124,14 @@ static int init_defined_templates(void)
110 return result; 124 return result;
111} 125}
112 126
127struct ima_template_desc *ima_template_desc_current(void)
128{
129 if (!ima_template)
130 ima_template = lookup_template_desc(IMA_TEMPLATE_IMA_NAME);
131
132 return ima_template;
133}
134
113int ima_init_template(void) 135int ima_init_template(void)
114{ 136{
115 int result; 137 int result;