--- v3
+++ v5
@@ -1,138 +1,65 @@
-In preparation for serializing the binary_runtime_measurements, this patch
-maintains the amount of memory required.
+Measurements carried across kexec need to be added to the IMA
+measurement list, but should not prevent measurements of the newly
+booted kernel from being added to the measurement list. This patch
+adds support for allowing duplicate measurements.
-Changelog v3:
-- include the ima_kexec_hdr size in the binary_runtime_measurement size.
+The "boot_aggregate" measurement entry is the delimiter between soft
+boots.
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
- security/integrity/ima/Kconfig | 12 +++++++++
- security/integrity/ima/ima.h | 1 +
- security/integrity/ima/ima_queue.c | 53 ++++++++++++++++++++++++++++++++++++--
- 3 files changed, 64 insertions(+), 2 deletions(-)
+ security/integrity/ima/ima_queue.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
-diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
-index 5487827..1c5a1c2 100644
---- a/security/integrity/ima/Kconfig
-+++ b/security/integrity/ima/Kconfig
-@@ -27,6 +27,18 @@ config IMA
- to learn more about IMA.
- If unsure, say N.
-
-+config IMA_KEXEC
-+ bool "Enable carrying the IMA measurement list across a soft boot"
-+ depends on IMA && TCG_TPM && KEXEC_FILE
-+ default n
-+ help
-+ TPM PCRs are only reset on a hard reboot. In order to validate
-+ a TPM's quote after a soft boot, the IMA measurement list of the
-+ running kernel must be saved and restored on boot.
-+
-+ Depending on the IMA policy, the measurement list can grow to
-+ be very large.
-+
- config IMA_MEASURE_PCR_IDX
- int
- depends on IMA
-diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
-index e7b3755..f9cd08e 100644
---- a/security/integrity/ima/ima.h
-+++ b/security/integrity/ima/ima.h
-@@ -133,6 +133,7 @@ void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
- struct ima_template_desc *ima_template_desc_current(void);
- int ima_restore_measurement_entry(struct ima_template_entry *entry);
- int ima_restore_measurement_list(loff_t bufsize, void *buf);
-+unsigned long ima_get_binary_runtime_size(void);
- int ima_init_template(void);
-
- #ifdef CONFIG_KEXEC_FILE
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
-index 12d1b04..3a3cc2a 100644
+index 4b1bb77..12d1b04 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
-@@ -29,6 +29,11 @@
- #define AUDIT_CAUSE_LEN_MAX 32
-
- LIST_HEAD(ima_measurements); /* list of all measurements */
-+#ifdef CONFIG_IMA_KEXEC
-+static unsigned long binary_runtime_size;
-+#else
-+static unsigned long binary_runtime_size = ULONG_MAX;
-+#endif
-
- /* key: inode (before secure-hashing a file) */
- struct ima_h_table ima_htable = {
-@@ -64,6 +69,24 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
- return ret;
+@@ -65,11 +65,12 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
}
-+/*
-+ * Calculate the memory required for serializing a single
-+ * binary_runtime_measurement list entry, which contains a
-+ * couple of variable length fields (e.g template name and data).
-+ */
-+static int get_binary_runtime_size(struct ima_template_entry *entry)
-+{
-+ int size = 0;
-+
-+ size += sizeof(u32); /* pcr */
-+ size += sizeof(entry->digest);
-+ size += sizeof(int); /* template name size field */
-+ size += strlen(entry->template_desc->name);
-+ size += sizeof(entry->template_data_len);
-+ size += entry->template_data_len;
-+ return size;
-+}
-+
/* ima_add_template_entry helper function:
- * - Add template entry to the measurement list and hash table, for
- * all entries except those carried across kexec.
-@@ -90,9 +113,30 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
- key = ima_hash_key(entry->digest);
- hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
- }
-+
-+ if (binary_runtime_size != ULONG_MAX) {
-+ int size;
-+
-+ size = get_binary_runtime_size(entry);
-+ binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
-+ binary_runtime_size + size : ULONG_MAX;
+- * - Add template entry to measurement list and hash table.
++ * - Add template entry to the measurement list and hash table, for
++ * all entries except those carried across kexec.
+ *
+ * (Called with ima_extend_list_mutex held.)
+ */
+-static int ima_add_digest_entry(struct ima_template_entry *entry)
++static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
+ {
+ struct ima_queue_entry *qe;
+ unsigned int key;
+@@ -85,8 +86,10 @@ static int ima_add_digest_entry(struct ima_template_entry *entry)
+ list_add_tail_rcu(&qe->later, &ima_measurements);
+
+ atomic_long_inc(&ima_htable.len);
+- key = ima_hash_key(entry->digest);
+- hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
++ if (flags) {
++ key = ima_hash_key(entry->digest);
++ hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+ }
return 0;
}
-+/*
-+ * Return the amount of memory required for serializing the
-+ * entire binary_runtime_measurement list, including the ima_kexec_hdr
-+ * structure.
-+ */
-+unsigned long ima_get_binary_runtime_size(void)
-+{
-+ if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
-+ return ULONG_MAX;
-+ else
-+ return binary_runtime_size + sizeof(struct ima_kexec_hdr);
-+};
-+
- static int ima_pcr_extend(const u8 *hash, int pcr)
- {
+@@ -126,7 +129,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
+ }
+ }
+
+- result = ima_add_digest_entry(entry);
++ result = ima_add_digest_entry(entry, 1);
+ if (result < 0) {
+ audit_cause = "ENOMEM";
+ audit_info = 0;
+@@ -155,7 +158,7 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry)
int result = 0;
-@@ -106,8 +150,13 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
+
+ mutex_lock(&ima_extend_list_mutex);
+- result = ima_add_digest_entry(entry);
++ result = ima_add_digest_entry(entry, 0);
+ mutex_unlock(&ima_extend_list_mutex);
return result;
}
-
--/* Add template entry to the measurement list and hash table,
-- * and extend the pcr.
-+/*
-+ * Add template entry to the measurement list and hash table, and
-+ * extend the pcr.
-+ *
-+ * On systems which support carrying the IMA measurement list across
-+ * kexec, maintain the total memory size required for serializing the
-+ * binary_runtime_measurements.
- */
- int ima_add_template_entry(struct ima_template_entry *entry, int violation,
- const char *op, struct inode *inode,
--
2.1.0