aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima
diff options
context:
space:
mode:
authorRoberto Sassu <roberto.sassu@polito.it>2013-06-07 06:16:32 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2013-10-25 17:17:05 -0400
commit4d7aeee73f5304bf195aa2904f8eb1d7b2e8fe52 (patch)
tree5cc0bb30f81dab7a981c1f640fb668932a7c32c2 /security/integrity/ima
parent3ce1217d6cd5dfa82a9db5c2a999cc1bb01490d9 (diff)
ima: define new template ima-ng and template fields d-ng and n-ng
This patch adds support for the new template 'ima-ng', whose format is defined as 'd-ng|n-ng'. These new field definitions remove the size limitations of the original 'ima' template. Further, the 'd-ng' field prefixes the inode digest with the hash algorithim, when displaying the new larger digest sizes. Change log: - scripts/Lindent fixes - Mimi - "always true comparison" - reported by Fengguang Wu, resolved Dmitry - initialize hash_algo variable to HASH_ALGO__LAST - always prefix digest with hash algorithm - Mimi Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Diffstat (limited to 'security/integrity/ima')
-rw-r--r--security/integrity/ima/ima_template.c7
-rw-r--r--security/integrity/ima/ima_template_lib.c152
-rw-r--r--security/integrity/ima/ima_template_lib.h8
3 files changed, 150 insertions, 17 deletions
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index 810042264396..bf38d1af3cfd 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -16,7 +16,8 @@
16#include "ima_template_lib.h" 16#include "ima_template_lib.h"
17 17
18static struct ima_template_desc defined_templates[] = { 18static struct ima_template_desc defined_templates[] = {
19 {.name = IMA_TEMPLATE_IMA_NAME,.fmt = IMA_TEMPLATE_IMA_FMT}, 19 {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
20 {.name = "ima-ng",.fmt = "d-ng|n-ng"},
20}; 21};
21 22
22static struct ima_template_field supported_fields[] = { 23static struct ima_template_field supported_fields[] = {
@@ -24,6 +25,10 @@ static struct ima_template_field supported_fields[] = {
24 .field_show = ima_show_template_digest}, 25 .field_show = ima_show_template_digest},
25 {.field_id = "n",.field_init = ima_eventname_init, 26 {.field_id = "n",.field_init = ima_eventname_init,
26 .field_show = ima_show_template_string}, 27 .field_show = ima_show_template_string},
28 {.field_id = "d-ng",.field_init = ima_eventdigest_ng_init,
29 .field_show = ima_show_template_digest_ng},
30 {.field_id = "n-ng",.field_init = ima_eventname_ng_init,
31 .field_show = ima_show_template_string},
27}; 32};
28 33
29static struct ima_template_field *lookup_template_field(const char *field_id) 34static struct ima_template_field *lookup_template_field(const char *field_id)
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index e13fc7c04ebc..7d841448f246 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -12,9 +12,25 @@
12 * File: ima_template_lib.c 12 * File: ima_template_lib.c
13 * Library of supported template fields. 13 * Library of supported template fields.
14 */ 14 */
15#include <crypto/hash_info.h>
16
15#include "ima_template_lib.h" 17#include "ima_template_lib.h"
16 18
17enum data_formats { DATA_FMT_DIGEST = 0, DATA_FMT_EVENT_NAME, DATA_FMT_STRING }; 19static bool ima_template_hash_algo_allowed(u8 algo)
20{
21 if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5)
22 return true;
23
24 return false;
25}
26
27enum data_formats {
28 DATA_FMT_DIGEST = 0,
29 DATA_FMT_DIGEST_WITH_ALGO,
30 DATA_FMT_EVENT_NAME,
31 DATA_FMT_STRING
32};
33
18static int ima_write_template_field_data(const void *data, const u32 datalen, 34static int ima_write_template_field_data(const void *data, const u32 datalen,
19 enum data_formats datafmt, 35 enum data_formats datafmt,
20 struct ima_field_data *field_data) 36 struct ima_field_data *field_data)
@@ -62,12 +78,22 @@ static void ima_show_template_data_ascii(struct seq_file *m,
62 enum data_formats datafmt, 78 enum data_formats datafmt,
63 struct ima_field_data *field_data) 79 struct ima_field_data *field_data)
64{ 80{
81 u8 *buf_ptr = field_data->data, buflen = field_data->len;
82
65 switch (datafmt) { 83 switch (datafmt) {
84 case DATA_FMT_DIGEST_WITH_ALGO:
85 buf_ptr = strnchr(field_data->data, buflen, ':');
86 if (buf_ptr != field_data->data)
87 seq_printf(m, "%s", field_data->data);
88
89 /* skip ':' and '\0' */
90 buf_ptr += 2;
91 buflen -= buf_ptr - field_data->data;
66 case DATA_FMT_DIGEST: 92 case DATA_FMT_DIGEST:
67 ima_print_digest(m, field_data->data, field_data->len); 93 ima_print_digest(m, buf_ptr, buflen);
68 break; 94 break;
69 case DATA_FMT_STRING: 95 case DATA_FMT_STRING:
70 seq_printf(m, "%s", field_data->data); 96 seq_printf(m, "%s", buf_ptr);
71 break; 97 break;
72 default: 98 default:
73 break; 99 break;
@@ -108,14 +134,59 @@ void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
108 ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data); 134 ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data);
109} 135}
110 136
137void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
138 struct ima_field_data *field_data)
139{
140 ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO,
141 field_data);
142}
143
111void ima_show_template_string(struct seq_file *m, enum ima_show_type show, 144void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
112 struct ima_field_data *field_data) 145 struct ima_field_data *field_data)
113{ 146{
114 ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); 147 ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
115} 148}
116 149
150static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
151 struct ima_field_data *field_data,
152 bool size_limit)
153{
154 /*
155 * digest formats:
156 * - DATA_FMT_DIGEST: digest
157 * - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest,
158 * where <hash algo> is provided if the hash algoritm is not
159 * SHA1 or MD5
160 */
161 u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 };
162 enum data_formats fmt = DATA_FMT_DIGEST;
163 u32 offset = 0;
164
165 if (!size_limit) {
166 fmt = DATA_FMT_DIGEST_WITH_ALGO;
167 if (hash_algo < HASH_ALGO__LAST)
168 offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1,
169 "%s", hash_algo_name[hash_algo]);
170 buffer[offset] = ':';
171 offset += 2;
172 }
173
174 if (digest)
175 memcpy(buffer + offset, digest, digestsize);
176 else
177 /*
178 * If digest is NULL, the event being recorded is a violation.
179 * Make room for the digest by increasing the offset of
180 * IMA_DIGEST_SIZE.
181 */
182 offset += IMA_DIGEST_SIZE;
183
184 return ima_write_template_field_data(buffer, offset + digestsize,
185 fmt, field_data);
186}
187
117/* 188/*
118 * This function writes the digest of an event. 189 * This function writes the digest of an event (with size limit).
119 */ 190 */
120int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, 191int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
121 const unsigned char *filename, 192 const unsigned char *filename,
@@ -125,8 +196,8 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
125 struct ima_digest_data hdr; 196 struct ima_digest_data hdr;
126 char digest[IMA_MAX_DIGEST_SIZE]; 197 char digest[IMA_MAX_DIGEST_SIZE];
127 } hash; 198 } hash;
128 u8 *cur_digest = hash.hdr.digest; 199 u8 *cur_digest = NULL;
129 u32 cur_digestsize = IMA_DIGEST_SIZE; 200 u32 cur_digestsize = 0;
130 struct inode *inode; 201 struct inode *inode;
131 int result; 202 int result;
132 203
@@ -135,7 +206,7 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
135 if (!iint) /* recording a violation. */ 206 if (!iint) /* recording a violation. */
136 goto out; 207 goto out;
137 208
138 if (iint->ima_hash->algo == ima_hash_algo) { 209 if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) {
139 cur_digest = iint->ima_hash->digest; 210 cur_digest = iint->ima_hash->digest;
140 cur_digestsize = iint->ima_hash->length; 211 cur_digestsize = iint->ima_hash->length;
141 goto out; 212 goto out;
@@ -145,7 +216,8 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
145 return -EINVAL; 216 return -EINVAL;
146 217
147 inode = file_inode(file); 218 inode = file_inode(file);
148 hash.hdr.algo = ima_hash_algo; 219 hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
220 ima_hash_algo : HASH_ALGO_SHA1;
149 result = ima_calc_file_hash(file, &hash.hdr); 221 result = ima_calc_file_hash(file, &hash.hdr);
150 if (result) { 222 if (result) {
151 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 223 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
@@ -153,20 +225,46 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
153 "failed", result, 0); 225 "failed", result, 0);
154 return result; 226 return result;
155 } 227 }
228 cur_digest = hash.hdr.digest;
229 cur_digestsize = hash.hdr.length;
156out: 230out:
157 return ima_write_template_field_data(cur_digest, cur_digestsize, 231 return ima_eventdigest_init_common(cur_digest, cur_digestsize, -1,
158 DATA_FMT_DIGEST, field_data); 232 field_data, true);
159} 233}
160 234
161/* 235/*
162 * This function writes the name of an event. 236 * This function writes the digest of an event (without size limit).
163 */ 237 */
164int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, 238int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
165 const unsigned char *filename, 239 struct file *file, const unsigned char *filename,
166 struct ima_field_data *field_data) 240 struct ima_field_data *field_data)
241{
242 u8 *cur_digest = NULL, hash_algo = HASH_ALGO__LAST;
243 u32 cur_digestsize = 0;
244
245 /* If iint is NULL, we are recording a violation. */
246 if (!iint)
247 goto out;
248
249 cur_digest = iint->ima_hash->digest;
250 cur_digestsize = iint->ima_hash->length;
251
252 hash_algo = iint->ima_hash->algo;
253out:
254 return ima_eventdigest_init_common(cur_digest, cur_digestsize,
255 hash_algo, field_data, false);
256}
257
258static int ima_eventname_init_common(struct integrity_iint_cache *iint,
259 struct file *file,
260 const unsigned char *filename,
261 struct ima_field_data *field_data,
262 bool size_limit)
167{ 263{
168 const char *cur_filename = NULL; 264 const char *cur_filename = NULL;
169 u32 cur_filename_len = 0; 265 u32 cur_filename_len = 0;
266 enum data_formats fmt = size_limit ?
267 DATA_FMT_EVENT_NAME : DATA_FMT_STRING;
170 268
171 BUG_ON(filename == NULL && file == NULL); 269 BUG_ON(filename == NULL && file == NULL);
172 270
@@ -174,7 +272,7 @@ int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
174 cur_filename = filename; 272 cur_filename = filename;
175 cur_filename_len = strlen(filename); 273 cur_filename_len = strlen(filename);
176 274
177 if (cur_filename_len <= IMA_EVENT_NAME_LEN_MAX) 275 if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
178 goto out; 276 goto out;
179 } 277 }
180 278
@@ -189,5 +287,27 @@ int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
189 cur_filename_len = IMA_EVENT_NAME_LEN_MAX; 287 cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
190out: 288out:
191 return ima_write_template_field_data(cur_filename, cur_filename_len, 289 return ima_write_template_field_data(cur_filename, cur_filename_len,
192 DATA_FMT_EVENT_NAME, field_data); 290 fmt, field_data);
291}
292
293/*
294 * This function writes the name of an event (with size limit).
295 */
296int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
297 const unsigned char *filename,
298 struct ima_field_data *field_data)
299{
300 return ima_eventname_init_common(iint, file, filename,
301 field_data, true);
302}
303
304/*
305 * This function writes the name of an event (without size limit).
306 */
307int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
308 const unsigned char *filename,
309 struct ima_field_data *field_data)
310{
311 return ima_eventname_init_common(iint, file, filename,
312 field_data, false);
193} 313}
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
index 2cecc83a928d..16c5e7810234 100644
--- a/security/integrity/ima/ima_template_lib.h
+++ b/security/integrity/ima/ima_template_lib.h
@@ -20,6 +20,8 @@
20 20
21void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, 21void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
22 struct ima_field_data *field_data); 22 struct ima_field_data *field_data);
23void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
24 struct ima_field_data *field_data);
23void ima_show_template_string(struct seq_file *m, enum ima_show_type show, 25void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
24 struct ima_field_data *field_data); 26 struct ima_field_data *field_data);
25int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, 27int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
@@ -28,4 +30,10 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
28int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, 30int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
29 const unsigned char *filename, 31 const unsigned char *filename,
30 struct ima_field_data *field_data); 32 struct ima_field_data *field_data);
33int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
34 struct file *file, const unsigned char *filename,
35 struct ima_field_data *field_data);
36int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
37 const unsigned char *filename,
38 struct ima_field_data *field_data);
31#endif /* __LINUX_IMA_TEMPLATE_LIB_H */ 39#endif /* __LINUX_IMA_TEMPLATE_LIB_H */