From 78bb5d0b4fe1988ae1a2a0cad0776134846414bd Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Fri, 3 Oct 2014 14:40:18 +0300 Subject: ima: report policy load status Audit messages are rate limited, often causing the policy update info to not be visible. Report policy loading status also using pr_info. Changes in v2: * reporting moved to ima_release_policy to notice parsing errors * reporting both completed and failed status Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar --- security/integrity/ima/ima_fs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'security/integrity/ima/ima_fs.c') diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index da92fcc08d15..16d85273d408 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -311,6 +311,8 @@ static int ima_open_policy(struct inode *inode, struct file *filp) */ static int ima_release_policy(struct inode *inode, struct file *file) { + pr_info("IMA: policy update %s\n", + valid_policy ? "completed" : "failed"); if (!valid_policy) { ima_delete_rules(); valid_policy = 1; -- cgit v1.2.3 From 0716abbb58e3c47e04354c2502083854f49c34e5 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Fri, 3 Oct 2014 14:40:21 +0300 Subject: ima: use atomic bit operations to protect policy update interface The current implementation uses an atomic counter to provide exclusive access to the sysfs 'policy' entry to update the IMA policy. While it is highly unlikely, the usage of a counter might potentially allow another process to overflow the counter, open the interface and insert additional rules into the policy being loaded. This patch replaces using an atomic counter with atomic bit operations which is more reliable and a widely used method to provide exclusive access. As bit operation keep the interface locked after successful update, it makes it unnecessary to verify if the default policy was set or not during parsing and interface closing. This patch also removes that code. Changes in v3: * move audit log message to ima_relead_policy() to report successful and unsuccessful result * unnecessary comment removed Changes in v2: * keep interface locked after successful policy load as in original design * remove sysfs entry as in original design Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar --- security/integrity/ima/ima_fs.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'security/integrity/ima/ima_fs.c') diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 16d85273d408..973b5683a92e 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -288,7 +288,12 @@ static struct dentry *runtime_measurements_count; static struct dentry *violations; static struct dentry *ima_policy; -static atomic_t policy_opencount = ATOMIC_INIT(1); +enum ima_fs_flags { + IMA_FS_BUSY, +}; + +static unsigned long ima_fs_flags; + /* * ima_open_policy: sequentialize access to the policy file */ @@ -297,9 +302,9 @@ 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)) return -EACCES; - if (atomic_dec_and_test(&policy_opencount)) - return 0; - return -EBUSY; + if (test_and_set_bit(IMA_FS_BUSY, &ima_fs_flags)) + return -EBUSY; + return 0; } /* @@ -311,12 +316,16 @@ static int ima_open_policy(struct inode *inode, struct file *filp) */ static int ima_release_policy(struct inode *inode, struct file *file) { - pr_info("IMA: policy update %s\n", - valid_policy ? "completed" : "failed"); + const char *cause = valid_policy ? "completed" : "failed"; + + pr_info("IMA: policy update %s\n", cause); + integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, + "policy_update", cause, !valid_policy, 0); + if (!valid_policy) { ima_delete_rules(); valid_policy = 1; - atomic_set(&policy_opencount, 1); + clear_bit(IMA_FS_BUSY, &ima_fs_flags); return 0; } ima_update_policy(); -- cgit v1.2.3 From 7dbdb4206bd69bf518fd76e01f4c5c64cda96455 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Mon, 13 Oct 2014 14:08:39 +0200 Subject: ima: display template format in meas. list if template name length is zero With the introduction of the 'ima_template_fmt' kernel cmdline parameter, a user can define a new template descriptor with custom format. However, in this case, userspace tools will be unable to parse the measurements list because the new template is unknown. For this reason, this patch modifies the current IMA behavior to display in the list the template format instead of the name (only if the length of the latter is zero) so that a tool can extract needed information if it can handle listed fields. This patch also correctly displays the error log message in ima_init_template() if the selected template cannot be initialized. Changelog: - v3: - check the first byte of 'e->template_desc->name' instead of using strlen() in ima_fs.c (suggested by Mimi Zohar) - v2: - print the template format in ima_init_template(), if the selected template is custom (Roberto Sassu) - v1: - fixed patch description (Roberto Sassu, suggested by Mimi Zohar) - set 'template_name' variable in ima_fs.c only once (Roberto Sassu, suggested by Mimi Zohar) Signed-off-by: Roberto Sassu Signed-off-by: Mimi Zohar --- security/integrity/ima/ima_fs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'security/integrity/ima/ima_fs.c') diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 973b5683a92e..461215e5fd31 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -118,6 +118,7 @@ static int ima_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; + char *template_name; int namelen; u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; bool is_ima_template = false; @@ -128,6 +129,9 @@ static int ima_measurements_show(struct seq_file *m, void *v) if (e == NULL) return -1; + template_name = (e->template_desc->name[0] != '\0') ? + e->template_desc->name : e->template_desc->fmt; + /* * 1st: PCRIndex * PCR used is always the same (config option) in @@ -139,14 +143,14 @@ static int ima_measurements_show(struct seq_file *m, void *v) ima_putc(m, e->digest, TPM_DIGEST_SIZE); /* 3rd: template name size */ - namelen = strlen(e->template_desc->name); + namelen = strlen(template_name); ima_putc(m, &namelen, sizeof(namelen)); /* 4th: template name */ - ima_putc(m, e->template_desc->name, namelen); + ima_putc(m, template_name, namelen); /* 5th: template length (except for 'ima' template) */ - if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) + if (strcmp(template_name, IMA_TEMPLATE_IMA_NAME) == 0) is_ima_template = true; if (!is_ima_template) @@ -200,6 +204,7 @@ 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; + char *template_name; int i; /* get entry */ @@ -207,6 +212,9 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v) if (e == NULL) return -1; + template_name = (e->template_desc->name[0] != '\0') ? + e->template_desc->name : e->template_desc->fmt; + /* 1st: PCR used (config option) */ seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX); @@ -214,7 +222,7 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v) ima_print_digest(m, e->digest, TPM_DIGEST_SIZE); /* 3th: template name */ - seq_printf(m, " %s", e->template_desc->name); + seq_printf(m, " %s", template_name); /* 4th: template specific data */ for (i = 0; i < e->template_desc->num_fields; i++) { -- cgit v1.2.3