summaryrefslogtreecommitdiff
path: root/security/integrity/ima
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-09-08 01:01:14 -0300
commite5fd91f1ef340da553f7a79da9540c3db711c937 (patch)
treeb11842027dc6641da63f4bcc524f8678263304a3 /security/integrity/ima
parent2a9b0348e685a63d97486f6749622b61e9e3292f (diff)
Linux-libre 4.2-gnu
Diffstat (limited to 'security/integrity/ima')
-rw-r--r--security/integrity/ima/ima.h27
-rw-r--r--security/integrity/ima/ima_api.c20
-rw-r--r--security/integrity/ima/ima_appraise.c8
-rw-r--r--security/integrity/ima/ima_crypto.c2
-rw-r--r--security/integrity/ima/ima_init.c13
-rw-r--r--security/integrity/ima/ima_main.c5
-rw-r--r--security/integrity/ima/ima_template_lib.c71
-rw-r--r--security/integrity/ima/ima_template_lib.h22
8 files changed, 76 insertions, 92 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index fc56d4dfa..e2a60c30d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -52,6 +52,16 @@ extern int ima_used_chip;
extern int ima_hash_algo;
extern int ima_appraise;
+/* IMA event related data */
+struct ima_event_data {
+ struct integrity_iint_cache *iint;
+ struct file *file;
+ const unsigned char *filename;
+ struct evm_ima_xattr_data *xattr_value;
+ int xattr_len;
+ const char *violation;
+};
+
/* IMA template field data definition */
struct ima_field_data {
u8 *data;
@@ -61,12 +71,10 @@ struct ima_field_data {
/* IMA template field definition */
struct ima_template_field {
const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN];
- int (*field_init) (struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value,
- int xattr_len, struct ima_field_data *field_data);
- void (*field_show) (struct seq_file *m, enum ima_show_type show,
- struct ima_field_data *field_data);
+ int (*field_init)(struct ima_event_data *event_data,
+ struct ima_field_data *field_data);
+ void (*field_show)(struct seq_file *m, enum ima_show_type show,
+ struct ima_field_data *field_data);
};
/* IMA template descriptor definition */
@@ -103,6 +111,7 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
struct ima_digest_data *hash);
int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
void ima_add_violation(struct file *file, const unsigned char *filename,
+ struct integrity_iint_cache *iint,
const char *op, const char *cause);
int ima_init_crypto(void);
void ima_putc(struct seq_file *m, void *data, int datalen);
@@ -140,10 +149,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
int xattr_len);
void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename);
-int ima_alloc_init_template(struct integrity_iint_cache *iint,
- struct file *file, const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value,
- int xattr_len, struct ima_template_entry **entry);
+int ima_alloc_init_template(struct ima_event_data *event_data,
+ struct ima_template_entry **entry);
int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode, const unsigned char *filename);
void ima_free_template_entry(struct ima_template_entry *entry);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index b8a27c505..1d950fbb2 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -37,10 +37,8 @@ void ima_free_template_entry(struct ima_template_entry *entry)
/*
* 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 evm_ima_xattr_data *xattr_value,
- int xattr_len, struct ima_template_entry **entry)
+int ima_alloc_init_template(struct ima_event_data *event_data,
+ struct ima_template_entry **entry)
{
struct ima_template_desc *template_desc = ima_template_desc_current();
int i, result = 0;
@@ -55,8 +53,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
struct ima_template_field *field = template_desc->fields[i];
u32 len;
- result = field->field_init(iint, file, filename,
- xattr_value, xattr_len,
+ result = field->field_init(event_data,
&((*entry)->template_data[i]));
if (result != 0)
goto out;
@@ -129,18 +126,20 @@ int ima_store_template(struct ima_template_entry *entry,
* value is invalidated.
*/
void ima_add_violation(struct file *file, const unsigned char *filename,
+ struct integrity_iint_cache *iint,
const char *op, const char *cause)
{
struct ima_template_entry *entry;
struct inode *inode = file_inode(file);
+ struct ima_event_data event_data = {iint, file, filename, NULL, 0,
+ cause};
int violation = 1;
int result;
/* can overflow, only indicator */
atomic_long_inc(&ima_htable.violations);
- result = ima_alloc_init_template(NULL, file, filename,
- NULL, 0, &entry);
+ result = ima_alloc_init_template(&event_data, &entry);
if (result < 0) {
result = -ENOMEM;
goto err_out;
@@ -267,13 +266,14 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
int result = -ENOMEM;
struct inode *inode = file_inode(file);
struct ima_template_entry *entry;
+ struct ima_event_data event_data = {iint, file, filename, xattr_value,
+ xattr_len, NULL};
int violation = 0;
if (iint->flags & IMA_MEASURED)
return;
- result = ima_alloc_init_template(iint, file, filename,
- xattr_value, xattr_len, &entry);
+ result = ima_alloc_init_template(&event_data, &entry);
if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
op, audit_cause, result, 0);
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 4df493e4b..1873b5536 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -378,10 +378,14 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
result = ima_protect_xattr(dentry, xattr_name, xattr_value,
xattr_value_len);
if (result == 1) {
+ bool digsig;
+
if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
return -EINVAL;
- ima_reset_appraise_flags(d_backing_inode(dentry),
- (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
+ digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
+ if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE))
+ return -EPERM;
+ ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
result = 0;
}
return result;
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 686355fea..e24121afb 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -55,7 +55,7 @@ static int param_set_bufsize(const char *val, const struct kernel_param *kp)
return 0;
}
-static struct kernel_param_ops param_ops_bufsize = {
+static const struct kernel_param_ops param_ops_bufsize = {
.set = param_set_bufsize,
.get = param_get_uint,
};
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 5e4c29d17..e600cadd2 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -24,12 +24,6 @@
#include <crypto/hash_info.h>
#include "ima.h"
-#ifdef CONFIG_IMA_X509_PATH
-#define IMA_X509_PATH CONFIG_IMA_X509_PATH
-#else
-#define IMA_X509_PATH "/etc/keys/x509_ima.der"
-#endif
-
/* name for boot aggregate entry */
static const char *boot_aggregate_name = "boot_aggregate";
int ima_used_chip;
@@ -55,6 +49,8 @@ static int __init ima_add_boot_aggregate(void)
const char *audit_cause = "ENOMEM";
struct ima_template_entry *entry;
struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
+ struct ima_event_data event_data = {iint, NULL, boot_aggregate_name,
+ NULL, 0, NULL};
int result = -ENOMEM;
int violation = 0;
struct {
@@ -76,8 +72,7 @@ static int __init ima_add_boot_aggregate(void)
}
}
- result = ima_alloc_init_template(iint, NULL, boot_aggregate_name,
- NULL, 0, &entry);
+ result = ima_alloc_init_template(&event_data, &entry);
if (result < 0) {
audit_cause = "alloc_entry";
goto err_out;
@@ -103,7 +98,7 @@ void __init ima_load_x509(void)
int unset_flags = ima_policy_flag & IMA_APPRAISE;
ima_policy_flag &= ~unset_flags;
- integrity_load_x509(INTEGRITY_KEYRING_IMA, IMA_X509_PATH);
+ integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
ima_policy_flag |= unset_flags;
}
#endif
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index eeee00dce..c21f09bf8 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -106,9 +106,10 @@ static void ima_rdwr_violation_check(struct file *file,
*pathname = ima_d_path(&file->f_path, pathbuf);
if (send_tomtou)
- ima_add_violation(file, *pathname, "invalid_pcr", "ToMToU");
+ ima_add_violation(file, *pathname, iint,
+ "invalid_pcr", "ToMToU");
if (send_writers)
- ima_add_violation(file, *pathname,
+ ima_add_violation(file, *pathname, iint,
"invalid_pcr", "open_writers");
}
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 61fbd0c0d..2934e3d37 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -196,9 +196,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
/*
* This function writes the digest of an event (with size limit).
*/
-int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventdigest_init(struct ima_event_data *event_data,
struct ima_field_data *field_data)
{
struct {
@@ -212,25 +210,25 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
memset(&hash, 0, sizeof(hash));
- if (!iint) /* recording a violation. */
+ if (event_data->violation) /* recording a violation. */
goto out;
- if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) {
- cur_digest = iint->ima_hash->digest;
- cur_digestsize = iint->ima_hash->length;
+ if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) {
+ cur_digest = event_data->iint->ima_hash->digest;
+ cur_digestsize = event_data->iint->ima_hash->length;
goto out;
}
- if (!file) /* missing info to re-calculate the digest */
+ if (!event_data->file) /* missing info to re-calculate the digest */
return -EINVAL;
- inode = file_inode(file);
+ inode = file_inode(event_data->file);
hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
ima_hash_algo : HASH_ALGO_SHA1;
- result = ima_calc_file_hash(file, &hash.hdr);
+ result = ima_calc_file_hash(event_data->file, &hash.hdr);
if (result) {
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
- filename, "collect_data",
+ event_data->filename, "collect_data",
"failed", result, 0);
return result;
}
@@ -244,48 +242,43 @@ out:
/*
* This function writes the digest of an event (without size limit).
*/
-int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
- struct file *file, const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value,
- int xattr_len, struct ima_field_data *field_data)
+int ima_eventdigest_ng_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data)
{
u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1;
u32 cur_digestsize = 0;
- /* If iint is NULL, we are recording a violation. */
- if (!iint)
+ if (event_data->violation) /* recording a violation. */
goto out;
- cur_digest = iint->ima_hash->digest;
- cur_digestsize = iint->ima_hash->length;
+ cur_digest = event_data->iint->ima_hash->digest;
+ cur_digestsize = event_data->iint->ima_hash->length;
- hash_algo = iint->ima_hash->algo;
+ hash_algo = event_data->iint->ima_hash->algo;
out:
return ima_eventdigest_init_common(cur_digest, cur_digestsize,
hash_algo, field_data);
}
-static int ima_eventname_init_common(struct integrity_iint_cache *iint,
- struct file *file,
- const unsigned char *filename,
+static int ima_eventname_init_common(struct ima_event_data *event_data,
struct ima_field_data *field_data,
bool size_limit)
{
const char *cur_filename = NULL;
u32 cur_filename_len = 0;
- BUG_ON(filename == NULL && file == NULL);
+ BUG_ON(event_data->filename == NULL && event_data->file == NULL);
- if (filename) {
- cur_filename = filename;
- cur_filename_len = strlen(filename);
+ if (event_data->filename) {
+ cur_filename = event_data->filename;
+ cur_filename_len = strlen(event_data->filename);
if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
goto out;
}
- if (file) {
- cur_filename = file->f_path.dentry->d_name.name;
+ if (event_data->file) {
+ cur_filename = event_data->file->f_path.dentry->d_name.name;
cur_filename_len = strlen(cur_filename);
} else
/*
@@ -301,36 +294,30 @@ out:
/*
* This function writes the name of an event (with size limit).
*/
-int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventname_init(struct ima_event_data *event_data,
struct ima_field_data *field_data)
{
- return ima_eventname_init_common(iint, file, filename,
- field_data, true);
+ return ima_eventname_init_common(event_data, field_data, true);
}
/*
* This function writes the name of an event (without size limit).
*/
-int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventname_ng_init(struct ima_event_data *event_data,
struct ima_field_data *field_data)
{
- return ima_eventname_init_common(iint, file, filename,
- field_data, false);
+ return ima_eventname_init_common(event_data, field_data, false);
}
/*
* ima_eventsig_init - include the file signature as part of the template data
*/
-int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventsig_init(struct ima_event_data *event_data,
struct ima_field_data *field_data)
{
enum data_formats fmt = DATA_FMT_HEX;
+ struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
+ int xattr_len = event_data->xattr_len;
int rc = 0;
if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
index 63f6b52cb..c344530c1 100644
--- a/security/integrity/ima/ima_template_lib.h
+++ b/security/integrity/ima/ima_template_lib.h
@@ -26,24 +26,14 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data);
void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data);
-int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventdigest_init(struct ima_event_data *event_data,
struct ima_field_data *field_data);
-int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventname_init(struct ima_event_data *event_data,
struct ima_field_data *field_data);
-int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
- struct file *file, const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value,
- int xattr_len, struct ima_field_data *field_data);
-int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventdigest_ng_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data);
+int ima_eventname_ng_init(struct ima_event_data *event_data,
struct ima_field_data *field_data);
-int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
- const unsigned char *filename,
- struct evm_ima_xattr_data *xattr_value, int xattr_len,
+int ima_eventsig_init(struct ima_event_data *event_data,
struct ima_field_data *field_data);
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */