summaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_api.c
diff options
context:
space:
mode:
authorDmitry Kasatkin <d.kasatkin@samsung.com>2013-04-25 10:44:04 +0300
committerMimi Zohar <zohar@linux.vnet.ibm.com>2013-10-25 17:17:00 -0400
commita35c3fb6490cc1d3446e4781693408100113c4fb (patch)
tree03234f8b7ebaf3cb98bf77f999b8a5284d4dadbc /security/integrity/ima/ima_api.c
parentb1aaab22e263d0cca1effe319b7d2bf895444219 (diff)
ima: use dynamically allocated hash storage
For each inode in the IMA policy, an iint is allocated. To support larger hash digests, the iint digest size changed from 20 bytes to the maximum supported hash digest size. Instead of allocating the maximum size, which most likely is not needed, this patch dynamically allocates the needed hash storage. Changelog: - fix krealloc bug Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Diffstat (limited to 'security/integrity/ima/ima_api.c')
-rw-r--r--security/integrity/ima/ima_api.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1dba98e2d7e..5a7942e2081 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -44,7 +44,10 @@ int ima_store_template(struct ima_template_entry *entry,
const char *op = "add_template_measure";
const char *audit_cause = "hashing_error";
int result;
- struct ima_digest_data hash;
+ struct {
+ struct ima_digest_data hdr;
+ char digest[IMA_MAX_DIGEST_SIZE];
+ } hash;
memset(entry->digest, 0, sizeof(entry->digest));
entry->template_name = IMA_TEMPLATE_NAME;
@@ -52,14 +55,14 @@ int ima_store_template(struct ima_template_entry *entry,
if (!violation) {
result = ima_calc_buffer_hash(&entry->template,
- entry->template_len, &hash);
+ entry->template_len, &hash.hdr);
if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
entry->template_name, op,
audit_cause, result, 0);
return result;
}
- memcpy(entry->digest, hash.digest, hash.length);
+ memcpy(entry->digest, hash.hdr.digest, hash.hdr.length);
}
result = ima_add_template_entry(entry, violation, op, inode);
return result;
@@ -146,6 +149,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
struct inode *inode = file_inode(file);
const char *filename = file->f_dentry->d_name.name;
int result = 0;
+ struct {
+ struct ima_digest_data hdr;
+ char digest[IMA_MAX_DIGEST_SIZE];
+ } hash;
if (xattr_value)
*xattr_len = ima_read_xattr(file->f_dentry, xattr_value);
@@ -154,16 +161,23 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
u64 i_version = file_inode(file)->i_version;
/* use default hash algorithm */
- iint->ima_hash.algo = ima_hash_algo;
+ hash.hdr.algo = ima_hash_algo;
if (xattr_value)
- ima_get_hash_algo(*xattr_value, *xattr_len,
- &iint->ima_hash);
+ ima_get_hash_algo(*xattr_value, *xattr_len, &hash.hdr);
- result = ima_calc_file_hash(file, &iint->ima_hash);
+ result = ima_calc_file_hash(file, &hash.hdr);
if (!result) {
- iint->version = i_version;
- iint->flags |= IMA_COLLECTED;
+ int length = sizeof(hash.hdr) + hash.hdr.length;
+ void *tmpbuf = krealloc(iint->ima_hash, length,
+ GFP_NOFS);
+ if (tmpbuf) {
+ iint->ima_hash = tmpbuf;
+ memcpy(iint->ima_hash, &hash, length);
+ iint->version = i_version;
+ iint->flags |= IMA_COLLECTED;
+ } else
+ result = -ENOMEM;
}
}
if (result)
@@ -208,21 +222,24 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
return;
}
memset(&entry->template, 0, sizeof(entry->template));
- if (iint->ima_hash.algo != ima_hash_algo) {
- struct ima_digest_data hash;
+ if (iint->ima_hash->algo != ima_hash_algo) {
+ struct {
+ struct ima_digest_data hdr;
+ char digest[IMA_MAX_DIGEST_SIZE];
+ } hash;
- hash.algo = ima_hash_algo;
- result = ima_calc_file_hash(file, &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.digest,
- hash.length);
+ memcpy(entry->template.digest, hash.hdr.digest,
+ hash.hdr.length);
} else
- memcpy(entry->template.digest, iint->ima_hash.digest,
- iint->ima_hash.length);
+ 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);
@@ -238,14 +255,14 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename)
{
struct audit_buffer *ab;
- char hash[(iint->ima_hash.length * 2) + 1];
+ char hash[(iint->ima_hash->length * 2) + 1];
int i;
if (iint->flags & IMA_AUDITED)
return;
- for (i = 0; i < iint->ima_hash.length; i++)
- hex_byte_pack(hash + (i * 2), iint->ima_hash.digest[i]);
+ for (i = 0; i < iint->ima_hash->length; i++)
+ hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]);
hash[i * 2] = '\0';
ab = audit_log_start(current->audit_context, GFP_KERNEL,