aboutsummaryrefslogtreecommitdiff
path: root/security/integrity/ima/ima_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima/ima_fs.c')
-rw-r--r--security/integrity/ima/ima_fs.c158
1 files changed, 80 insertions, 78 deletions
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 6bfc7eaebfd..da92fcc08d1 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -16,6 +16,7 @@
* current measurement list and IMA statistics
*/
#include <linux/fcntl.h>
+#include <linux/slab.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/rculist.h>
@@ -43,8 +44,9 @@ static ssize_t ima_show_htable_violations(struct file *filp,
return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
}
-static struct file_operations ima_htable_violations_ops = {
- .read = ima_show_htable_violations
+static const struct file_operations ima_htable_violations_ops = {
+ .read = ima_show_htable_violations,
+ .llseek = generic_file_llseek,
};
static ssize_t ima_show_measurements_count(struct file *filp,
@@ -55,8 +57,9 @@ static ssize_t ima_show_measurements_count(struct file *filp,
}
-static struct file_operations ima_measurements_count_ops = {
- .read = ima_show_measurements_count
+static const struct file_operations ima_measurements_count_ops = {
+ .read = ima_show_measurements_count,
+ .llseek = generic_file_llseek,
};
/* returns pointer to hlist_node */
@@ -85,8 +88,7 @@ static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
* against concurrent list-extension
*/
rcu_read_lock();
- qe = list_entry_rcu(qe->later.next,
- struct ima_queue_entry, later);
+ qe = list_entry_rcu(qe->later.next, struct ima_queue_entry, later);
rcu_read_unlock();
(*pos)++;
@@ -97,7 +99,7 @@ static void ima_measurements_stop(struct seq_file *m, void *v)
{
}
-static void ima_putc(struct seq_file *m, void *data, int datalen)
+void ima_putc(struct seq_file *m, void *data, int datalen)
{
while (datalen--)
seq_putc(m, *(char *)data++);
@@ -108,6 +110,7 @@ static void ima_putc(struct seq_file *m, void *data, int datalen)
* char[20]=template digest
* 32bit-le=template name size
* char[n]=template name
+ * [eventdata length]
* eventdata[n]=template specific data
*/
static int ima_measurements_show(struct seq_file *m, void *v)
@@ -117,6 +120,8 @@ static int ima_measurements_show(struct seq_file *m, void *v)
struct ima_template_entry *e;
int namelen;
u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+ bool is_ima_template = false;
+ int i;
/* get entry */
e = qe->entry;
@@ -128,25 +133,41 @@ static int ima_measurements_show(struct seq_file *m, void *v)
* PCR used is always the same (config option) in
* little-endian format
*/
- ima_putc(m, &pcr, sizeof pcr);
+ ima_putc(m, &pcr, sizeof(pcr));
/* 2nd: template digest */
- ima_putc(m, e->digest, IMA_DIGEST_SIZE);
+ ima_putc(m, e->digest, TPM_DIGEST_SIZE);
/* 3rd: template name size */
- namelen = strlen(e->template_name);
- ima_putc(m, &namelen, sizeof namelen);
+ namelen = strlen(e->template_desc->name);
+ ima_putc(m, &namelen, sizeof(namelen));
/* 4th: template name */
- ima_putc(m, (void *)e->template_name, namelen);
-
- /* 5th: template specific data */
- ima_template_show(m, (struct ima_template_data *)&e->template,
- IMA_SHOW_BINARY);
+ ima_putc(m, e->template_desc->name, namelen);
+
+ /* 5th: template length (except for 'ima' template) */
+ if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0)
+ is_ima_template = true;
+
+ if (!is_ima_template)
+ ima_putc(m, &e->template_data_len,
+ sizeof(e->template_data_len));
+
+ /* 6th: template specific data */
+ for (i = 0; i < e->template_desc->num_fields; i++) {
+ enum ima_show_type show = IMA_SHOW_BINARY;
+ struct ima_template_field *field = e->template_desc->fields[i];
+
+ if (is_ima_template && strcmp(field->field_id, "d") == 0)
+ show = IMA_SHOW_BINARY_NO_FIELD_LEN;
+ if (is_ima_template && strcmp(field->field_id, "n") == 0)
+ show = IMA_SHOW_BINARY_OLD_STRING_FMT;
+ field->field_show(m, show, &e->template_data[i]);
+ }
return 0;
}
-static struct seq_operations ima_measurments_seqops = {
+static const struct seq_operations ima_measurments_seqops = {
.start = ima_measurements_start,
.next = ima_measurements_next,
.stop = ima_measurements_stop,
@@ -158,48 +179,28 @@ static int ima_measurements_open(struct inode *inode, struct file *file)
return seq_open(file, &ima_measurments_seqops);
}
-static struct file_operations ima_measurements_ops = {
+static const struct file_operations ima_measurements_ops = {
.open = ima_measurements_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
-static void ima_print_digest(struct seq_file *m, u8 *digest)
+void ima_print_digest(struct seq_file *m, u8 *digest, int size)
{
int i;
- for (i = 0; i < IMA_DIGEST_SIZE; i++)
+ for (i = 0; i < size; i++)
seq_printf(m, "%02x", *(digest + i));
}
-void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
-{
- struct ima_template_data *entry = e;
- int namelen;
-
- switch (show) {
- case IMA_SHOW_ASCII:
- ima_print_digest(m, entry->digest);
- seq_printf(m, " %s\n", entry->file_name);
- break;
- case IMA_SHOW_BINARY:
- ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
-
- namelen = strlen(entry->file_name);
- ima_putc(m, &namelen, sizeof namelen);
- ima_putc(m, entry->file_name, namelen);
- default:
- break;
- }
-}
-
/* print in ascii */
static int ima_ascii_measurements_show(struct seq_file *m, void *v)
{
/* the list never shrinks, so we don't need a lock here */
struct ima_queue_entry *qe = v;
struct ima_template_entry *e;
+ int i;
/* get entry */
e = qe->entry;
@@ -210,18 +211,25 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
/* 2nd: SHA1 template hash */
- ima_print_digest(m, e->digest);
+ ima_print_digest(m, e->digest, TPM_DIGEST_SIZE);
/* 3th: template name */
- seq_printf(m, " %s ", e->template_name);
+ seq_printf(m, " %s", e->template_desc->name);
/* 4th: template specific data */
- ima_template_show(m, (struct ima_template_data *)&e->template,
- IMA_SHOW_ASCII);
+ for (i = 0; i < e->template_desc->num_fields; i++) {
+ seq_puts(m, " ");
+ if (e->template_data[i].len == 0)
+ continue;
+
+ e->template_desc->fields[i]->field_show(m, IMA_SHOW_ASCII,
+ &e->template_data[i]);
+ }
+ seq_puts(m, "\n");
return 0;
}
-static struct seq_operations ima_ascii_measurements_seqops = {
+static const struct seq_operations ima_ascii_measurements_seqops = {
.start = ima_measurements_start,
.next = ima_measurements_next,
.stop = ima_measurements_stop,
@@ -233,7 +241,7 @@ static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
return seq_open(file, &ima_ascii_measurements_seqops);
}
-static struct file_operations ima_ascii_measurements_ops = {
+static const struct file_operations ima_ascii_measurements_ops = {
.open = ima_ascii_measurements_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -243,32 +251,34 @@ static struct file_operations ima_ascii_measurements_ops = {
static ssize_t ima_write_policy(struct file *file, const char __user *buf,
size_t datalen, loff_t *ppos)
{
- char *data;
- int rc;
+ char *data = NULL;
+ ssize_t result;
if (datalen >= PAGE_SIZE)
- return -ENOMEM;
- if (*ppos != 0) {
- /* No partial writes. */
- return -EINVAL;
- }
+ datalen = PAGE_SIZE - 1;
+
+ /* No partial writes. */
+ result = -EINVAL;
+ if (*ppos != 0)
+ goto out;
+
+ result = -ENOMEM;
data = kmalloc(datalen + 1, GFP_KERNEL);
if (!data)
- return -ENOMEM;
+ goto out;
- if (copy_from_user(data, buf, datalen)) {
- kfree(data);
- return -EFAULT;
- }
*(data + datalen) = '\0';
- rc = ima_parse_add_rule(data);
- if (rc < 0) {
- datalen = -EINVAL;
- valid_policy = 0;
- }
+ result = -EFAULT;
+ if (copy_from_user(data, buf, datalen))
+ goto out;
+
+ result = ima_parse_add_rule(data);
+out:
+ if (result < 0)
+ valid_policy = 0;
kfree(data);
- return datalen;
+ return result;
}
static struct dentry *ima_dir;
@@ -282,7 +292,7 @@ static atomic_t policy_opencount = ATOMIC_INIT(1);
/*
* ima_open_policy: sequentialize access to the policy file
*/
-int ima_open_policy(struct inode * inode, struct file * filp)
+static int ima_open_policy(struct inode *inode, struct file *filp)
{
/* No point in being allowed to open it if you aren't going to write */
if (!(filp->f_flags & O_WRONLY))
@@ -313,10 +323,11 @@ static int ima_release_policy(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations ima_measure_policy_ops = {
+static const struct file_operations ima_measure_policy_ops = {
.open = ima_open_policy,
.write = ima_write_policy,
- .release = ima_release_policy
+ .release = ima_release_policy,
+ .llseek = generic_file_llseek,
};
int __init ima_fs_init(void)
@@ -361,20 +372,11 @@ int __init ima_fs_init(void)
return 0;
out:
- securityfs_remove(runtime_measurements_count);
- securityfs_remove(ascii_runtime_measurements);
- securityfs_remove(binary_runtime_measurements);
- securityfs_remove(ima_dir);
- securityfs_remove(ima_policy);
- return -1;
-}
-
-void __exit ima_fs_cleanup(void)
-{
securityfs_remove(violations);
securityfs_remove(runtime_measurements_count);
securityfs_remove(ascii_runtime_measurements);
securityfs_remove(binary_runtime_measurements);
securityfs_remove(ima_dir);
securityfs_remove(ima_policy);
+ return -1;
}