summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-01-21 19:54:32 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2025-01-21 19:54:32 -0800
commit0ca0cf9f8cb16e3850e5242d68a1825d286e6a68 (patch)
tree1888053b0c78962a204856e08a83be7fbf757c9c
parent7dd457a2fd78f3dd39aad4579d13e9eed2effbca (diff)
parent4785ed362a24d4f37ee0eb4403f587fee886f8da (diff)
downloadlinux-0ca0cf9f8cb16e3850e5242d68a1825d286e6a68.tar.gz
linux-0ca0cf9f8cb16e3850e5242d68a1825d286e6a68.tar.bz2
linux-0ca0cf9f8cb16e3850e5242d68a1825d286e6a68.zip
Merge tag 'integrity-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar: "There's just a couple of changes: two kernel messages addressed, a measurement policy collision addressed, and one policy cleanup. Please note that the contents of the IMA measurement list is potentially affected. The builtin tmpfs IMA policy rule change might introduce additional measurements, while detecting a reboot might eliminate some measurements" * tag 'integrity-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: ima: ignore suffixed policy rule comments ima: limit the builtin 'tcb' dont_measure tmpfs policy rule ima: kexec: silence RCU list traversal warning ima: Suspend PCR extends and log appends when rebooting
-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;