summaryrefslogtreecommitdiffstats
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.c88
1 files changed, 60 insertions, 28 deletions
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index a0fe5041310a..29dd43de823a 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -24,6 +24,62 @@
static const char *IMA_TEMPLATE_NAME = "ima";
/*
+ * ima_alloc_init_template - create and initialize a new template entry
+ */
+int ima_alloc_init_template(struct integrity_iint_cache *iint,
+ struct file *file, const unsigned char *filename,
+ struct ima_template_entry **entry)
+{
+ struct ima_template_entry *e;
+ int result = 0;
+
+ e = kzalloc(sizeof(**entry), GFP_NOFS);
+ if (!e)
+ return -ENOMEM;
+
+ memset(&(e)->template, 0, sizeof(e->template));
+ if (!iint) /* IMA measurement violation entry */
+ goto out;
+
+ if (iint->ima_hash->algo != ima_hash_algo) {
+ struct inode *inode;
+ struct {
+ struct ima_digest_data hdr;
+ char digest[IMA_MAX_DIGEST_SIZE];
+ } hash;
+
+ if (!file) {
+ result = -EINVAL;
+ goto out_free;
+ }
+
+ inode = file_inode(file);
+ hash.hdr.algo = ima_hash_algo;
+ hash.hdr.length = SHA1_DIGEST_SIZE;
+ result = ima_calc_file_hash(file, &hash.hdr);
+ if (result) {
+ integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
+ filename, "collect_data",
+ "failed", result, 0);
+ goto out_free;
+ } else
+ memcpy(e->template.digest, hash.hdr.digest,
+ hash.hdr.length);
+ } else
+ memcpy(e->template.digest, iint->ima_hash->digest,
+ iint->ima_hash->length);
+out:
+ strcpy(e->template.file_name,
+ (strlen(filename) > IMA_EVENT_NAME_LEN_MAX && file != NULL) ?
+ file->f_dentry->d_name.name : filename);
+ *entry = e;
+ return 0;
+out_free:
+ kfree(e);
+ return result;
+}
+
+/*
* ima_store_template - store ima template measurements
*
* Calculate the hash of a template entry, add the template entry
@@ -90,13 +146,11 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
/* can overflow, only indicator */
atomic_long_inc(&ima_htable.violations);
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
+ result = ima_alloc_init_template(NULL, file, filename, &entry);
+ if (result < 0) {
result = -ENOMEM;
goto err_out;
}
- memset(&entry->template, 0, sizeof(entry->template));
- strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
result = ima_store_template(entry, violation, inode, filename);
if (result < 0)
kfree(entry);
@@ -220,34 +274,12 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
if (iint->flags & IMA_MEASURED)
return;
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
+ result = ima_alloc_init_template(iint, file, filename, &entry);
+ if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
op, audit_cause, result, 0);
return;
}
- memset(&entry->template, 0, sizeof(entry->template));
- if (iint->ima_hash->algo != ima_hash_algo) {
- struct {
- struct ima_digest_data hdr;
- char digest[IMA_MAX_DIGEST_SIZE];
- } hash;
-
- hash.hdr.algo = ima_hash_algo;
- result = ima_calc_file_hash(file, &hash.hdr);
- if (result)
- integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
- filename, "collect_data", "failed",
- result, 0);
- else
- memcpy(entry->template.digest, hash.hdr.digest,
- hash.hdr.length);
- } else
- memcpy(entry->template.digest, iint->ima_hash->digest,
- iint->ima_hash->length);
- strcpy(entry->template.file_name,
- (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
- file->f_dentry->d_name.name : filename);
result = ima_store_template(entry, violation, inode, filename);
if (!result || result == -EEXIST)