diff options
author | Roberto Sassu <roberto.sassu@polito.it> | 2013-06-07 06:16:32 -0400 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2013-10-25 17:17:05 -0400 |
commit | 4d7aeee73f5304bf195aa2904f8eb1d7b2e8fe52 (patch) | |
tree | 5cc0bb30f81dab7a981c1f640fb668932a7c32c2 /security/integrity/ima | |
parent | 3ce1217d6cd5dfa82a9db5c2a999cc1bb01490d9 (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.c | 7 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 152 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.h | 8 |
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 | ||
18 | static struct ima_template_desc defined_templates[] = { | 18 | static 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 | ||
22 | static struct ima_template_field supported_fields[] = { | 23 | static 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 | ||
29 | static struct ima_template_field *lookup_template_field(const char *field_id) | 34 | static 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 | ||
17 | enum data_formats { DATA_FMT_DIGEST = 0, DATA_FMT_EVENT_NAME, DATA_FMT_STRING }; | 19 | static 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 | |||
27 | enum data_formats { | ||
28 | DATA_FMT_DIGEST = 0, | ||
29 | DATA_FMT_DIGEST_WITH_ALGO, | ||
30 | DATA_FMT_EVENT_NAME, | ||
31 | DATA_FMT_STRING | ||
32 | }; | ||
33 | |||
18 | static int ima_write_template_field_data(const void *data, const u32 datalen, | 34 | static 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 | ||
137 | void 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 | |||
111 | void ima_show_template_string(struct seq_file *m, enum ima_show_type show, | 144 | void 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 | ||
150 | static 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 | */ |
120 | int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, | 191 | int 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; | ||
156 | out: | 230 | out: |
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 | */ |
164 | int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, | 238 | int 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; | ||
253 | out: | ||
254 | return ima_eventdigest_init_common(cur_digest, cur_digestsize, | ||
255 | hash_algo, field_data, false); | ||
256 | } | ||
257 | |||
258 | static 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; |
190 | out: | 288 | out: |
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 | */ | ||
296 | int 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 | */ | ||
307 | int 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 | ||
21 | void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, | 21 | void 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); |
23 | void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, | ||
24 | struct ima_field_data *field_data); | ||
23 | void ima_show_template_string(struct seq_file *m, enum ima_show_type show, | 25 | void 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); |
25 | int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, | 27 | int 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, | |||
28 | int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, | 30 | int 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); |
33 | int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, | ||
34 | struct file *file, const unsigned char *filename, | ||
35 | struct ima_field_data *field_data); | ||
36 | int 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 */ |