summary refs log tree commit diff
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)