aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima/ima_api.c')
-rw-r--r--security/integrity/ima/ima_api.c154
1 files changed, 117 insertions, 37 deletions
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1c03e8f1e0e1..c38bbce8c6a6 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -18,9 +18,59 @@
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/xattr.h> 19#include <linux/xattr.h>
20#include <linux/evm.h> 20#include <linux/evm.h>
21#include <crypto/hash_info.h>
21#include "ima.h" 22#include "ima.h"
22 23
23static const char *IMA_TEMPLATE_NAME = "ima"; 24/*
25 * ima_free_template_entry - free an existing template entry
26 */
27void ima_free_template_entry(struct ima_template_entry *entry)
28{
29 int i;
30
31 for (i = 0; i < entry->template_desc->num_fields; i++)
32 kfree(entry->template_data[i].data);
33
34 kfree(entry);
35}
36
37/*
38 * ima_alloc_init_template - create and initialize a new template entry
39 */
40int ima_alloc_init_template(struct integrity_iint_cache *iint,
41 struct file *file, const unsigned char *filename,
42 struct evm_ima_xattr_data *xattr_value,
43 int xattr_len, struct ima_template_entry **entry)
44{
45 struct ima_template_desc *template_desc = ima_template_desc_current();
46 int i, result = 0;
47
48 *entry = kzalloc(sizeof(**entry) + template_desc->num_fields *
49 sizeof(struct ima_field_data), GFP_NOFS);
50 if (!*entry)
51 return -ENOMEM;
52
53 (*entry)->template_desc = template_desc;
54 for (i = 0; i < template_desc->num_fields; i++) {
55 struct ima_template_field *field = template_desc->fields[i];
56 u32 len;
57
58 result = field->field_init(iint, file, filename,
59 xattr_value, xattr_len,
60 &((*entry)->template_data[i]));
61 if (result != 0)
62 goto out;
63
64 len = (*entry)->template_data[i].len;
65 (*entry)->template_data_len += sizeof(len);
66 (*entry)->template_data_len += len;
67 }
68 return 0;
69out:
70 ima_free_template_entry(*entry);
71 *entry = NULL;
72 return result;
73}
24 74
25/* 75/*
26 * ima_store_template - store ima template measurements 76 * ima_store_template - store ima template measurements
@@ -39,28 +89,35 @@ static const char *IMA_TEMPLATE_NAME = "ima";
39 * Returns 0 on success, error code otherwise 89 * Returns 0 on success, error code otherwise
40 */ 90 */
41int ima_store_template(struct ima_template_entry *entry, 91int ima_store_template(struct ima_template_entry *entry,
42 int violation, struct inode *inode) 92 int violation, struct inode *inode,
93 const unsigned char *filename)
43{ 94{
44 const char *op = "add_template_measure"; 95 const char *op = "add_template_measure";
45 const char *audit_cause = "hashing_error"; 96 const char *audit_cause = "hashing_error";
97 char *template_name = entry->template_desc->name;
46 int result; 98 int result;
47 99 struct {
48 memset(entry->digest, 0, sizeof(entry->digest)); 100 struct ima_digest_data hdr;
49 entry->template_name = IMA_TEMPLATE_NAME; 101 char digest[TPM_DIGEST_SIZE];
50 entry->template_len = sizeof(entry->template); 102 } hash;
51 103
52 if (!violation) { 104 if (!violation) {
53 result = ima_calc_buffer_hash(&entry->template, 105 int num_fields = entry->template_desc->num_fields;
54 entry->template_len, 106
55 entry->digest); 107 /* this function uses default algo */
108 hash.hdr.algo = HASH_ALGO_SHA1;
109 result = ima_calc_field_array_hash(&entry->template_data[0],
110 entry->template_desc,
111 num_fields, &hash.hdr);
56 if (result < 0) { 112 if (result < 0) {
57 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, 113 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
58 entry->template_name, op, 114 template_name, op,
59 audit_cause, result, 0); 115 audit_cause, result, 0);
60 return result; 116 return result;
61 } 117 }
118 memcpy(entry->digest, hash.hdr.digest, hash.hdr.length);
62 } 119 }
63 result = ima_add_template_entry(entry, violation, op, inode); 120 result = ima_add_template_entry(entry, violation, op, inode, filename);
64 return result; 121 return result;
65} 122}
66 123
@@ -71,26 +128,26 @@ int ima_store_template(struct ima_template_entry *entry,
71 * By extending the PCR with 0xFF's instead of with zeroes, the PCR 128 * By extending the PCR with 0xFF's instead of with zeroes, the PCR
72 * value is invalidated. 129 * value is invalidated.
73 */ 130 */
74void ima_add_violation(struct inode *inode, const unsigned char *filename, 131void ima_add_violation(struct file *file, const unsigned char *filename,
75 const char *op, const char *cause) 132 const char *op, const char *cause)
76{ 133{
77 struct ima_template_entry *entry; 134 struct ima_template_entry *entry;
135 struct inode *inode = file->f_dentry->d_inode;
78 int violation = 1; 136 int violation = 1;
79 int result; 137 int result;
80 138
81 /* can overflow, only indicator */ 139 /* can overflow, only indicator */
82 atomic_long_inc(&ima_htable.violations); 140 atomic_long_inc(&ima_htable.violations);
83 141
84 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 142 result = ima_alloc_init_template(NULL, file, filename,
85 if (!entry) { 143 NULL, 0, &entry);
144 if (result < 0) {
86 result = -ENOMEM; 145 result = -ENOMEM;
87 goto err_out; 146 goto err_out;
88 } 147 }
89 memset(&entry->template, 0, sizeof(entry->template)); 148 result = ima_store_template(entry, violation, inode, filename);
90 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
91 result = ima_store_template(entry, violation, inode);
92 if (result < 0) 149 if (result < 0)
93 kfree(entry); 150 ima_free_template_entry(entry);
94err_out: 151err_out:
95 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, 152 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
96 op, cause, result, 0); 153 op, cause, result, 0);
@@ -138,20 +195,42 @@ int ima_must_measure(struct inode *inode, int mask, int function)
138 * Return 0 on success, error code otherwise 195 * Return 0 on success, error code otherwise
139 */ 196 */
140int ima_collect_measurement(struct integrity_iint_cache *iint, 197int ima_collect_measurement(struct integrity_iint_cache *iint,
141 struct file *file) 198 struct file *file,
199 struct evm_ima_xattr_data **xattr_value,
200 int *xattr_len)
142{ 201{
143 struct inode *inode = file_inode(file); 202 struct inode *inode = file_inode(file);
144 const char *filename = file->f_dentry->d_name.name; 203 const char *filename = file->f_dentry->d_name.name;
145 int result = 0; 204 int result = 0;
205 struct {
206 struct ima_digest_data hdr;
207 char digest[IMA_MAX_DIGEST_SIZE];
208 } hash;
209
210 if (xattr_value)
211 *xattr_len = ima_read_xattr(file->f_dentry, xattr_value);
146 212
147 if (!(iint->flags & IMA_COLLECTED)) { 213 if (!(iint->flags & IMA_COLLECTED)) {
148 u64 i_version = file_inode(file)->i_version; 214 u64 i_version = file_inode(file)->i_version;
149 215
150 iint->ima_xattr.type = IMA_XATTR_DIGEST; 216 /* use default hash algorithm */
151 result = ima_calc_file_hash(file, iint->ima_xattr.digest); 217 hash.hdr.algo = ima_hash_algo;
218
219 if (xattr_value)
220 ima_get_hash_algo(*xattr_value, *xattr_len, &hash.hdr);
221
222 result = ima_calc_file_hash(file, &hash.hdr);
152 if (!result) { 223 if (!result) {
153 iint->version = i_version; 224 int length = sizeof(hash.hdr) + hash.hdr.length;
154 iint->flags |= IMA_COLLECTED; 225 void *tmpbuf = krealloc(iint->ima_hash, length,
226 GFP_NOFS);
227 if (tmpbuf) {
228 iint->ima_hash = tmpbuf;
229 memcpy(iint->ima_hash, &hash, length);
230 iint->version = i_version;
231 iint->flags |= IMA_COLLECTED;
232 } else
233 result = -ENOMEM;
155 } 234 }
156 } 235 }
157 if (result) 236 if (result)
@@ -177,7 +256,9 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
177 * Must be called with iint->mutex held. 256 * Must be called with iint->mutex held.
178 */ 257 */
179void ima_store_measurement(struct integrity_iint_cache *iint, 258void ima_store_measurement(struct integrity_iint_cache *iint,
180 struct file *file, const unsigned char *filename) 259 struct file *file, const unsigned char *filename,
260 struct evm_ima_xattr_data *xattr_value,
261 int xattr_len)
181{ 262{
182 const char *op = "add_template_measure"; 263 const char *op = "add_template_measure";
183 const char *audit_cause = "ENOMEM"; 264 const char *audit_cause = "ENOMEM";
@@ -189,37 +270,35 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
189 if (iint->flags & IMA_MEASURED) 270 if (iint->flags & IMA_MEASURED)
190 return; 271 return;
191 272
192 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 273 result = ima_alloc_init_template(iint, file, filename,
193 if (!entry) { 274 xattr_value, xattr_len, &entry);
275 if (result < 0) {
194 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, 276 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
195 op, audit_cause, result, 0); 277 op, audit_cause, result, 0);
196 return; 278 return;
197 } 279 }
198 memset(&entry->template, 0, sizeof(entry->template));
199 memcpy(entry->template.digest, iint->ima_xattr.digest, IMA_DIGEST_SIZE);
200 strcpy(entry->template.file_name,
201 (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
202 file->f_dentry->d_name.name : filename);
203 280
204 result = ima_store_template(entry, violation, inode); 281 result = ima_store_template(entry, violation, inode, filename);
205 if (!result || result == -EEXIST) 282 if (!result || result == -EEXIST)
206 iint->flags |= IMA_MEASURED; 283 iint->flags |= IMA_MEASURED;
207 if (result < 0) 284 if (result < 0)
208 kfree(entry); 285 ima_free_template_entry(entry);
209} 286}
210 287
211void ima_audit_measurement(struct integrity_iint_cache *iint, 288void ima_audit_measurement(struct integrity_iint_cache *iint,
212 const unsigned char *filename) 289 const unsigned char *filename)
213{ 290{
214 struct audit_buffer *ab; 291 struct audit_buffer *ab;
215 char hash[(IMA_DIGEST_SIZE * 2) + 1]; 292 char hash[(iint->ima_hash->length * 2) + 1];
293 const char *algo_name = hash_algo_name[iint->ima_hash->algo];
294 char algo_hash[sizeof(hash) + strlen(algo_name) + 2];
216 int i; 295 int i;
217 296
218 if (iint->flags & IMA_AUDITED) 297 if (iint->flags & IMA_AUDITED)
219 return; 298 return;
220 299
221 for (i = 0; i < IMA_DIGEST_SIZE; i++) 300 for (i = 0; i < iint->ima_hash->length; i++)
222 hex_byte_pack(hash + (i * 2), iint->ima_xattr.digest[i]); 301 hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]);
223 hash[i * 2] = '\0'; 302 hash[i * 2] = '\0';
224 303
225 ab = audit_log_start(current->audit_context, GFP_KERNEL, 304 ab = audit_log_start(current->audit_context, GFP_KERNEL,
@@ -230,7 +309,8 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
230 audit_log_format(ab, "file="); 309 audit_log_format(ab, "file=");
231 audit_log_untrustedstring(ab, filename); 310 audit_log_untrustedstring(ab, filename);
232 audit_log_format(ab, " hash="); 311 audit_log_format(ab, " hash=");
233 audit_log_untrustedstring(ab, hash); 312 snprintf(algo_hash, sizeof(algo_hash), "%s:%s", algo_name, hash);
313 audit_log_untrustedstring(ab, algo_hash);
234 314
235 audit_log_task_info(ab, current); 315 audit_log_task_info(ab, current);
236 audit_log_end(ab); 316 audit_log_end(ab);