summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima.h1
-rw-r--r--security/integrity/ima/ima_init.c2
-rw-r--r--security/integrity/ima/ima_kexec.c3
-rw-r--r--security/integrity/ima/ima_policy.c5
-rw-r--r--security/integrity/ima/ima_queue.c44
5 files changed, 52 insertions, 3 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c0d3b716d11f..24d09ea91b87 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -278,6 +278,7 @@ unsigned long ima_get_binary_runtime_size(void);
int ima_init_template(void);
void ima_init_template_list(void);
int __init ima_init_digests(void);
+void __init ima_init_reboot_notifier(void);
int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
void *lsm_data);
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 4e208239a40e..a2f34f2d8ad7 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -152,6 +152,8 @@ int __init ima_init(void)
ima_init_key_queue();
+ ima_init_reboot_notifier();
+
ima_measure_critical_data("kernel_info", "kernel_version",
UTS_RELEASE, strlen(UTS_RELEASE), false,
NULL, 0);
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 52e00332defe..9d45f4d26f73 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -37,7 +37,8 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
memset(&khdr, 0, sizeof(khdr));
khdr.version = 1;
- list_for_each_entry_rcu(qe, &ima_measurements, later) {
+ /* This is an append-only list, no need to hold the RCU read lock */
+ list_for_each_entry_rcu(qe, &ima_measurements, later, true) {
if (file.count < file.size) {
khdr.count++;
ima_measurements_show(&file, qe);
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 21a8e54c383f..128fab897930 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -148,7 +148,8 @@ static struct ima_rule_entry dont_measure_rules[] __ro_after_init = {
{.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
- {.action = DONT_MEASURE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
+ {.action = DONT_MEASURE, .fsmagic = TMPFS_MAGIC, .func = FILE_CHECK,
+ .flags = IMA_FSMAGIC | IMA_FUNC},
{.action = DONT_MEASURE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
@@ -1431,7 +1432,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
int token;
unsigned long lnum;
- if (result < 0)
+ if (result < 0 || *p == '#') /* ignore suffixed comment */
break;
if ((*p == '\0') || (*p == ' ') || (*p == '\t'))
continue;
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 532da87ce519..83d53824aa98 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -16,6 +16,7 @@
*/
#include <linux/rculist.h>
+#include <linux/reboot.h>
#include <linux/slab.h>
#include "ima.h"
@@ -44,6 +45,12 @@ struct ima_h_table ima_htable = {
*/
static DEFINE_MUTEX(ima_extend_list_mutex);
+/*
+ * Used internally by the kernel to suspend measurements.
+ * Protected by ima_extend_list_mutex.
+ */
+static bool ima_measurements_suspended;
+
/* lookup up the digest value in the hash table, and return the entry */
static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
int pcr)
@@ -168,6 +175,18 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
int result = 0, tpmresult = 0;
mutex_lock(&ima_extend_list_mutex);
+
+ /*
+ * Avoid appending to the measurement log when the TPM subsystem has
+ * been shut down while preparing for system reboot.
+ */
+ if (ima_measurements_suspended) {
+ audit_cause = "measurements_suspended";
+ audit_info = 0;
+ result = -ENODEV;
+ goto out;
+ }
+
if (!violation && !IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)) {
if (ima_lookup_digest_entry(digest, entry->pcr)) {
audit_cause = "hash_exists";
@@ -211,6 +230,31 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry)
return result;
}
+static void ima_measurements_suspend(void)
+{
+ mutex_lock(&ima_extend_list_mutex);
+ ima_measurements_suspended = true;
+ mutex_unlock(&ima_extend_list_mutex);
+}
+
+static int ima_reboot_notifier(struct notifier_block *nb,
+ unsigned long action,
+ void *data)
+{
+ ima_measurements_suspend();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ima_reboot_nb = {
+ .notifier_call = ima_reboot_notifier,
+};
+
+void __init ima_init_reboot_notifier(void)
+{
+ register_reboot_notifier(&ima_reboot_nb);
+}
+
int __init ima_init_digests(void)
{
u16 digest_size;